# email addresses.
#
-Aaron Todd <github@opprobrio.us>
Aaron Power <theaaronepower@gmail.com> Erin Power <xampprocky@gmail.com>
+Aaron Todd <github@opprobrio.us>
Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com>
Adolfo Ochagavía <aochagavia92@gmail.com>
Adrien Tétar <adri-from-59@hotmail.fr>
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> arielb1 <arielb1@mail.tau.ac.il>
Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org>
Aydin Kim <ladinjin@hanmail.net> aydin.kim <aydin.kim@samsung.com>
-Bastian Kauschke <bastian_kauschke@hotmail.de>
Barosl Lee <vcs@barosl.com> Barosl LEE <github@barosl.com>
+Bastian Kauschke <bastian_kauschke@hotmail.de>
Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com>
Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@bsago.me>
Ben Sago <ogham@users.noreply.github.com> Ben S <ogham@users.noreply.github.com>
Brian Dawn <brian.t.dawn@gmail.com>
Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com>
Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> <193874+carols10cents@users.noreply.github.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> <carol.nichols@gmail.com>
Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com>
-Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <carol.nichols@gmail.com>
Carol Willing <carolcode@willingconsulting.com>
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
Chris Pressey <cpressey@gmail.com>
Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
-Christian Poveda <christianpoveda@protonmail.com> <z1mvader@protonmail.com>
Christian Poveda <christianpoveda@protonmail.com> <cn.poveda.ruiz@gmail.com>
+Christian Poveda <christianpoveda@protonmail.com> <z1mvader@protonmail.com>
Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
Clinton Ryan <clint.ryan3@gmail.com>
Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net>
Cyryl Płotnicki <cyplo@cyplo.net>
Damien Schoof <damien.schoof@gmail.com>
-Daniel Ramos <dan@daramos.com>
Daniel J Rollins <drollins@financialforce.com>
+Daniel Ramos <dan@daramos.com>
David Klein <david.klein@baesystemsdetica.com>
David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
David Ross <daboross@daboross.net>
Dylan Braithwaite <dylanbraithwaite1@gmail.com> <mail@dylanb.me>
Dzmitry Malyshau <kvarkus@gmail.com>
E. Dunham <edunham@mozilla.com> edunham <edunham@mozilla.com>
+Eduard-Mihai Burtescu <edy.burt@gmail.com>
Eduardo Bautista <me@eduardobautista.com> <=>
Eduardo Bautista <me@eduardobautista.com> <mail@eduardobautista.com>
-Eduard-Mihai Burtescu <edy.burt@gmail.com>
Elliott Slaughter <elliottslaughter@gmail.com> <eslaughter@mozilla.com>
Elly Fong-Jones <elly@leptoquark.net>
Eric Holk <eric.holk@gmail.com> <eholk@cs.indiana.edu>
Eric Holmes <eric@ejholmes.net>
Eric Reed <ecreed@cs.washington.edu> <ereed@mozilla.com>
Erick Tryzelaar <erick.tryzelaar@gmail.com> <etryzelaar@iqt.org>
-Esteban Küber <esteban@kuber.com.ar> <estebank@users.noreply.github.com>
Esteban Küber <esteban@kuber.com.ar> <esteban@commure.com>
+Esteban Küber <esteban@kuber.com.ar> <estebank@users.noreply.github.com>
Esteban Küber <esteban@kuber.com.ar> <github@kuber.com.ar>
Evgeny Sologubov
Falco Hirschenberger <falco.hirschenberger@gmail.com> <hirschen@itwm.fhg.de>
Ilyong Cho <ilyoan@gmail.com>
Ivan Ivaschenko <defuz.net@gmail.com>
J. J. Weber <jjweber@gmail.com>
+Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
-Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com>
James Miller <bladeon@gmail.com> <james@aatch.net>
James Perry <james.austin.perry@gmail.com>
Jihyun Yu <j.yu@navercorp.com> <yjh0502@gmail.com>
Jihyun Yu <j.yu@navercorp.com> jihyun <jihyun@nablecomm.com>
Jihyun Yu <j.yu@navercorp.com> Jihyun Yu <jihyun@nclab.kaist.ac.kr>
+João Oliveira <hello@jxs.pt> joaoxsouls <joaoxsouls@gmail.com>
Johann Hofmann <git@johann-hofmann.com> Johann <git@johann-hofmann.com>
John Clements <clements@racket-lang.org> <clements@brinckerhoff.org>
John Hodge <acessdev@gmail.com> John Hodge <tpg@mutabah.net>
Jonathan Turner <probata@hotmail.com>
Jorge Aparicio <japaric@linux.com> <japaricious@gmail.com>
Joseph Martin <pythoner6@gmail.com>
-João Oliveira <hello@jxs.pt> joaoxsouls <joaoxsouls@gmail.com>
+Joseph T. Lyons <JosephTLyons@gmail.com> <josephtlyons@gmail.com>
+Joseph T. Lyons <JosephTLyons@gmail.com> <JosephTLyons@users.noreply.github.com>
Junyoung Cho <june0.cho@samsung.com>
Jyun-Yan You <jyyou.tw@gmail.com> <jyyou@cs.nctu.edu.tw>
Kang Seonghoon <kang.seonghoon@mearie.org> <public+git@mearie.org>
Luke Metz <luke.metz@students.olin.edu>
Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca>
Luqman Aden <me@luqman.ca> <laden@mozilla.com>
-NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
-NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm+github@gmail.com>
Marcell Pardavi <marcell.pardavi@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew>
Mark Rousskov <mark.simulacrum@gmail.com>
Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com>
Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm+github@gmail.com>
Nathan West <Lucretiel@gmail.com> <lucretiel@gmail.com>
Nathan Wilson <wilnathan@gmail.com>
Nathaniel Herman <nherman@post.harvard.edu> Nathaniel Herman <nherman@college.harvard.edu>
Neil Pankey <npankey@gmail.com> <neil@wire.im>
-Nicole Mazzuca <npmazzuca@gmail.com>
Nick Platt <platt.nicholas@gmail.com>
+Nicole Mazzuca <npmazzuca@gmail.com>
Nif Ward <nif.ward@gmail.com>
Oliver Schneider <oliver.schneider@kit.edu> oli-obk <github6541940@oli-obk.de>
Oliver Schneider <oliver.schneider@kit.edu> Oliver 'ker' Schneider <rust19446194516@oli-obk.de>
Tim Joseph Dumol <tim@timdumol.com>
Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com>
Ty Overby <ty@pre-alpha.com>
-Ulrik Sverdrup <bluss@users.noreply.github.com> bluss <bluss>
Ulrik Sverdrup <bluss@users.noreply.github.com> bluss <bluss@users.noreply.github.com>
+Ulrik Sverdrup <bluss@users.noreply.github.com> bluss <bluss>
Ulrik Sverdrup <bluss@users.noreply.github.com> Ulrik Sverdrup <root@localhost>
Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Vadim Petrochenkov <vadim.petrochenkov@gmail.com> petrochenkov <vadim.petrochenkov@gmail.com>
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "pulldown-cmark"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "pulldown-cmark"
-version = "0.5.0"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
dependencies = [
"minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synstructure"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "unicase"
-version = "2.3.0"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum proptest 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24f5844db2f839e97e3021980975f6ebf8691d9b9b2ca67ed3feb38dc3edb52c"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
-"checksum pulldown-cmark 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d1b74cc784b038a9921fd1a48310cc2e238101aa8ae0b94201e2d85121dd68b5"
-"checksum pulldown-cmark 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "157737d41407de9c5e0563a991d085117d60ae729af2cc1bf28d6dfbc97bcc1f"
+"checksum pulldown-cmark 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "051e60ace841b3bfecd402fe5051c06cb3bec4a6e6fdd060a37aa8eb829a1db3"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
+"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2"
"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
-"checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd"
+"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
})
}
+ /// Similar to `compiler`, except handles the full-bootstrap option to
+ /// silently use the stage1 compiler instead of a stage2 compiler if one is
+ /// requested.
+ ///
+ /// Note that this does *not* have the side effect of creating
+ /// `compiler(stage, host)`, unlike `compiler` above which does have such
+ /// a side effect. The returned compiler here can only be used to compile
+ /// new artifacts, it can't be used to rely on the presence of a particular
+ /// sysroot.
+ ///
+ /// See `force_use_stage1` for documentation on what each argument is.
+ pub fn compiler_for(
+ &self,
+ stage: u32,
+ host: Interned<String>,
+ target: Interned<String>,
+ ) -> Compiler {
+ if self.build.force_use_stage1(Compiler { stage, host }, target) {
+ self.compiler(1, self.config.build)
+ } else {
+ self.compiler(stage, host)
+ }
+ }
+
pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
self.ensure(compile::Sysroot { compiler })
}
// This is for the original compiler, but if we're forced to use stage 1, then
// std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
// we copy the libs forward.
- let cmp = if self.force_use_stage1(compiler, target) {
- self.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let cmp = self.compiler_for(compiler.stage, compiler.host, target);
let libstd_stamp = match cmd {
"check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target),
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
- &[dist::Docs { stage: 2, host: a },]
+ &[dist::Docs { host: a },]
);
assert_eq!(
first(builder.cache.all::<dist::Mingw>()),
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},]
);
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
&[
- dist::Docs { stage: 2, host: a },
- dist::Docs { stage: 2, host: b },
+ dist::Docs { host: a },
+ dist::Docs { host: b },
]
);
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
&[
- dist::Docs { stage: 2, host: a },
- dist::Docs { stage: 2, host: b },
+ dist::Docs { host: a },
+ dist::Docs { host: b },
]
);
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: b,
},
]
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
+ #[test]
+ fn dist_only_cross_host() {
+ let a = INTERNER.intern_str("A");
+ let b = INTERNER.intern_str("B");
+ let mut build = Build::new(configure(&["B"], &[]));
+ build.config.docs = false;
+ build.config.extended = true;
+ build.hosts = vec![b];
+ let mut builder = Builder::new(&build);
+ builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+ assert_eq!(
+ first(builder.cache.all::<dist::Rustc>()),
+ &[
+ dist::Rustc {
+ compiler: Compiler { host: b, stage: 2 }
+ },
+ ]
+ );
+ assert_eq!(
+ first(builder.cache.all::<compile::Rustc>()),
+ &[
+ compile::Rustc {
+ compiler: Compiler { host: a, stage: 0 },
+ target: a,
+ },
+ compile::Rustc {
+ compiler: Compiler { host: a, stage: 1 },
+ target: b,
+ },
+ ]
+ );
+ }
+
#[test]
fn dist_with_targets_and_hosts() {
let build = Build::new(configure(&["B"], &["C"]));
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
&[
- dist::Docs { stage: 2, host: a },
- dist::Docs { stage: 2, host: b },
- dist::Docs { stage: 2, host: c },
+ dist::Docs { host: a },
+ dist::Docs { host: b },
+ dist::Docs { host: c },
]
);
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: b,
},
dist::Std {
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
&[
- dist::Docs { stage: 2, host: a },
- dist::Docs { stage: 2, host: b },
- dist::Docs { stage: 2, host: c },
+ dist::Docs { host: a },
+ dist::Docs { host: b },
+ dist::Docs { host: c },
]
);
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: b,
},
dist::Std {
assert_eq!(
first(builder.cache.all::<dist::Docs>()),
&[
- dist::Docs { stage: 2, host: a },
- dist::Docs { stage: 2, host: b },
+ dist::Docs { host: a },
+ dist::Docs { host: b },
]
);
assert_eq!(
first(builder.cache.all::<dist::Std>()),
&[
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: a,
},
dist::Std {
- compiler: Compiler { host: a, stage: 2 },
+ compiler: Compiler { host: a, stage: 1 },
target: b,
},
]
compiler: Compiler { host: a, stage: 1 },
target: b,
},
- compile::Test {
- compiler: Compiler { host: a, stage: 2 },
- target: b,
- },
]
);
assert_eq!(
compiler: Compiler { host: b, stage: 2 },
target: a,
},
- compile::Rustc {
- compiler: Compiler { host: a, stage: 0 },
- target: b,
- },
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
compiler: Compiler { host: b, stage: 2 },
target: a,
},
- compile::Test {
- compiler: Compiler { host: a, stage: 0 },
- target: b,
- },
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
compile::Assemble {
target_compiler: Compiler { host: a, stage: 1 },
},
- compile::Assemble {
- target_compiler: Compiler { host: b, stage: 1 },
- },
compile::Assemble {
target_compiler: Compiler { host: a, stage: 2 },
},
compiler: Compiler { host: a, stage: 1 },
target: a,
},
- compile::Rustc {
- compiler: Compiler { host: a, stage: 0 },
- target: b,
- },
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
compiler: Compiler { host: b, stage: 2 },
target: a,
},
- compile::Test {
- compiler: Compiler { host: a, stage: 0 },
- target: b,
- },
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
builder.ensure(StartupObjects { compiler, target });
- if builder.force_use_stage1(compiler, target) {
- let from = builder.compiler(1, builder.config.build);
+ let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+ if compiler_to_use != compiler {
builder.ensure(Std {
- compiler: from,
+ compiler: compiler_to_use,
target,
});
- builder.info(&format!("Uplifting stage1 std ({} -> {})", from.host, target));
+ builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target));
// Even if we're not building std this stage, the new sysroot must
// still contain the third party objects needed by various targets.
copy_third_party_objects(builder, &compiler, target);
builder.ensure(StdLink {
- compiler: from,
+ compiler: compiler_to_use,
target_compiler: compiler,
target,
});
return;
}
- if builder.force_use_stage1(compiler, target) {
+ let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+ if compiler_to_use != compiler {
builder.ensure(Test {
- compiler: builder.compiler(1, builder.config.build),
+ compiler: compiler_to_use,
target,
});
builder.info(
&format!("Uplifting stage1 test ({} -> {})", builder.config.build, target));
builder.ensure(TestLink {
- compiler: builder.compiler(1, builder.config.build),
+ compiler: compiler_to_use,
target_compiler: compiler,
target,
});
return;
}
- if builder.force_use_stage1(compiler, target) {
+ let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+ if compiler_to_use != compiler {
builder.ensure(Rustc {
- compiler: builder.compiler(1, builder.config.build),
+ compiler: compiler_to_use,
target,
});
builder.info(&format!("Uplifting stage1 rustc ({} -> {})",
builder.config.build, target));
builder.ensure(RustcLink {
- compiler: builder.compiler(1, builder.config.build),
+ compiler: compiler_to_use,
target_compiler: compiler,
target,
});
return;
}
- if builder.force_use_stage1(compiler, target) {
+ let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
+ if compiler_to_use != compiler {
builder.ensure(CodegenBackend {
- compiler: builder.compiler(1, builder.config.build),
+ compiler: compiler_to_use,
target,
backend,
});
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Docs {
- pub stage: u32,
pub host: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Docs {
- stage: run.builder.top_stage,
host: run.target,
});
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustcDocs {
- pub stage: u32,
pub host: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(RustcDocs {
- stage: run.builder.top_stage,
host: run.target,
});
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Std {
- compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Analysis {
- compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
+ // Find the actual compiler (handling the full bootstrap option) which
+ // produced the save-analysis data because that data isn't copied
+ // through the sysroot uplifting.
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
builder.ensure(Std { compiler, target });
- // Package save-analysis from stage1 if not doing a full bootstrap, as the
- // stage2 artifacts is simply copied from stage1 in that case.
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler.clone()
- };
-
let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
let src = builder.stage_out(compiler, Mode::Std)
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Cargo {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
- let stage = self.stage;
+ let compiler = self.compiler;
let target = self.target;
- builder.info(&format!("Dist cargo stage{} ({})", stage, target));
+ builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
let src = builder.src.join("src/tools/cargo");
let etc = src.join("src/etc");
let release_num = builder.release_num("cargo");
// Prepare the image directory
builder.create_dir(&image.join("share/zsh/site-functions"));
builder.create_dir(&image.join("etc/bash_completion.d"));
- let cargo = builder.ensure(tool::Cargo {
- compiler: builder.compiler(stage, builder.config.build),
- target
- });
+ let cargo = builder.ensure(tool::Cargo { compiler, target });
builder.install(&cargo, &image.join("bin"), 0o755);
for man in t!(etc.join("man").read_dir()) {
let man = t!(man);
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rls {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- let stage = self.stage;
+ let compiler = self.compiler;
let target = self.target;
assert!(builder.config.extended);
- builder.info(&format!("Dist RLS stage{} ({})", stage, target));
+ builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target));
let src = builder.src.join("src/tools/rls");
let release_num = builder.release_num("rls");
let name = pkgname(builder, "rls");
// We expect RLS to build, because we've exited this step above if tool
// state for RLS isn't testing.
let rls = builder.ensure(tool::Rls {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new(),
}).or_else(|| { missing_tool("RLS", builder.build.config.missing_tools); None })?;
builder.install(&rls, &image.join("bin"), 0o755);
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Clippy {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Clippy {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- let stage = self.stage;
+ let compiler = self.compiler;
let target = self.target;
assert!(builder.config.extended);
- builder.info(&format!("Dist clippy stage{} ({})", stage, target));
+ builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
let src = builder.src.join("src/tools/clippy");
let release_num = builder.release_num("clippy");
let name = pkgname(builder, "clippy");
// We expect clippy to build, because we've exited this step above if tool
// state for clippy isn't testing.
let clippy = builder.ensure(tool::Clippy {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new(),
}).or_else(|| { missing_tool("clippy", builder.build.config.missing_tools); None })?;
let cargoclippy = builder.ensure(tool::CargoClippy {
- compiler: builder.compiler(stage, builder.config.build),
+ compiler,
target, extra_features: Vec::new()
}).or_else(|| { missing_tool("cargo clippy", builder.build.config.missing_tools); None })?;
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Miri {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Miri {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- let stage = self.stage;
+ let compiler = self.compiler;
let target = self.target;
assert!(builder.config.extended);
- builder.info(&format!("Dist miri stage{} ({})", stage, target));
+ builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
let src = builder.src.join("src/tools/miri");
let release_num = builder.release_num("miri");
let name = pkgname(builder, "miri");
// We expect miri to build, because we've exited this step above if tool
// state for miri isn't testing.
let miri = builder.ensure(tool::Miri {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new(),
}).or_else(|| { missing_tool("miri", builder.build.config.missing_tools); None })?;
let cargomiri = builder.ensure(tool::CargoMiri {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new()
}).or_else(|| { missing_tool("cargo miri", builder.build.config.missing_tools); None })?;
builder.install(&miri, &image.join("bin"), 0o755);
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustfmt {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Rustfmt {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler_for(
+ run.builder.top_stage,
+ run.builder.config.build,
+ run.target,
+ ),
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- let stage = self.stage;
+ let compiler = self.compiler;
let target = self.target;
- builder.info(&format!("Dist Rustfmt stage{} ({})", stage, target));
+ builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
let src = builder.src.join("src/tools/rustfmt");
let release_num = builder.release_num("rustfmt");
let name = pkgname(builder, "rustfmt");
// Prepare the image directory
let rustfmt = builder.ensure(tool::Rustfmt {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new(),
}).or_else(|| { missing_tool("Rustfmt", builder.build.config.missing_tools); None })?;
let cargofmt = builder.ensure(tool::Cargofmt {
- compiler: builder.compiler(stage, builder.config.build),
- target, extra_features: Vec::new()
+ compiler,
+ target,
+ extra_features: Vec::new(),
}).or_else(|| { missing_tool("Cargofmt", builder.build.config.missing_tools); None })?;
builder.install(&rustfmt, &image.join("bin"), 0o755);
/// Creates a combined installer for the specified target in the provided stage.
fn run(self, builder: &Builder<'_>) {
- let stage = self.stage;
let target = self.target;
+ let stage = self.stage;
+ let compiler = builder.compiler_for(self.stage, self.host, self.target);
- builder.info(&format!("Dist extended stage{} ({})", stage, target));
+ builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
let rustc_installer = builder.ensure(Rustc {
compiler: builder.compiler(stage, target),
});
- let cargo_installer = builder.ensure(Cargo { stage, target });
- let rustfmt_installer = builder.ensure(Rustfmt { stage, target });
- let rls_installer = builder.ensure(Rls { stage, target });
- let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
- let clippy_installer = builder.ensure(Clippy { stage, target });
- let miri_installer = builder.ensure(Miri { stage, target });
+ let cargo_installer = builder.ensure(Cargo { compiler, target });
+ let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
+ let rls_installer = builder.ensure(Rls { compiler, target });
+ let llvm_tools_installer = builder.ensure(LlvmTools { target });
+ let clippy_installer = builder.ensure(Clippy { compiler, target });
+ let miri_installer = builder.ensure(Miri { compiler, target });
let lldb_installer = builder.ensure(Lldb { target });
let mingw_installer = builder.ensure(Mingw { host: target });
- let analysis_installer = builder.ensure(Analysis {
- compiler: builder.compiler(stage, self.host),
- target
- });
+ let analysis_installer = builder.ensure(Analysis { compiler, target });
- let docs_installer = builder.ensure(Docs { stage, host: target, });
+ let docs_installer = builder.ensure(Docs { host: target, });
let std_installer = builder.ensure(Std {
- compiler: builder.compiler(stage, self.host),
+ compiler: builder.compiler(stage, target),
target,
});
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct LlvmTools {
- pub stage: u32,
pub target: Interned<String>,
}
fn make_run(run: RunConfig<'_>) {
run.builder.ensure(LlvmTools {
- stage: run.builder.top_stage,
target: run.target,
});
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- let stage = self.stage;
let target = self.target;
assert!(builder.config.extended);
/* run only if llvm-config isn't used */
if let Some(config) = builder.config.target_config.get(&target) {
if let Some(ref _s) = config.llvm_config {
- builder.info(&format!("Skipping LlvmTools stage{} ({}): external LLVM",
- stage, target));
+ builder.info(&format!("Skipping LlvmTools ({}): external LLVM",
+ target));
return None;
}
}
- builder.info(&format!("Dist LlvmTools stage{} ({})", stage, target));
+ builder.info(&format!("Dist LlvmTools ({})", target));
let src = builder.src.join("src/llvm-project/llvm");
let name = pkgname(builder, "llvm-tools");
builder.info(&format!("Documenting stage{} std ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
- let compiler = builder.compiler(stage, builder.config.build);
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let compiler = builder.compiler_for(stage, builder.config.build, target);
builder.ensure(compile::Std { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Std)
builder.info(&format!("Documenting stage{} test ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
- let compiler = builder.compiler(stage, builder.config.build);
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let compiler = builder.compiler_for(stage, builder.config.build, target);
// Build libstd docs so that we generate relative links
builder.ensure(Std { stage, target });
builder.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target));
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
- let compiler = builder.compiler(stage, builder.config.build);
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let compiler = builder.compiler_for(stage, builder.config.build, target);
// Build libstd docs so that we generate relative links
builder.ensure(Std { stage, target });
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
- let compiler = builder.compiler(stage, builder.config.build);
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let compiler = builder.compiler_for(stage, builder.config.build, target);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/librustdoc docs disabled");
// Build cargo command.
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
- cargo.env("RUSTDOCFLAGS", "--document-private-items");
+ cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
compile::rustc_cargo(builder, &mut cargo);
// Only include compiler crates, no dependencies of those, such as `libc`.
t!(fs::create_dir_all(&out));
// Get the correct compiler for this stage.
- let compiler = builder.compiler(stage, builder.config.build);
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler
- };
+ let compiler = builder.compiler_for(stage, builder.config.build, target);
if !builder.config.compiler_docs {
builder.info("\tskipping - compiler/librustdoc docs disabled");
use std::env;
use std::fs;
-use std::path::{Path, PathBuf, Component};
+use std::path::{Component, Path, PathBuf};
use std::process::Command;
use build_helper::t;
use crate::dist::{self, pkgname, sanitize_sh, tmpdir};
+use crate::Compiler;
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
package: &str,
name: &str,
stage: u32,
- host: Option<Interned<String>>
+ host: Option<Interned<String>>,
) {
builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
$(
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $name {
- pub stage: u32,
+ pub compiler: Compiler,
pub target: Interned<String>,
- pub host: Interned<String>,
}
impl $name {
fn make_run(run: RunConfig<'_>) {
run.builder.ensure($name {
- stage: run.builder.top_stage,
+ compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
target: run.target,
- host: run.builder.config.build,
});
}
install!((self, builder, _config),
Docs, "src/doc", _config.docs, only_hosts: false, {
- builder.ensure(dist::Docs { stage: self.stage, host: self.target });
- install_docs(builder, self.stage, self.target);
+ builder.ensure(dist::Docs { host: self.target });
+ install_docs(builder, self.compiler.stage, self.target);
};
Std, "src/libstd", true, only_hosts: true, {
for target in &builder.targets {
builder.ensure(dist::Std {
- compiler: builder.compiler(self.stage, self.host),
+ compiler: self.compiler,
target: *target
});
- install_std(builder, self.stage, *target);
+ install_std(builder, self.compiler.stage, *target);
}
};
Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
- builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
- install_cargo(builder, self.stage, self.target);
+ builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
+ install_cargo(builder, self.compiler.stage, self.target);
};
Rls, "rls", Self::should_build(_config), only_hosts: true, {
- if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() ||
+ if builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }).is_some() ||
Self::should_install(builder) {
- install_rls(builder, self.stage, self.target);
+ install_rls(builder, self.compiler.stage, self.target);
} else {
- builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target));
+ builder.info(
+ &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
+ );
}
};
Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
- if builder.ensure(dist::Clippy { stage: self.stage, target: self.target }).is_some() ||
- Self::should_install(builder) {
- install_clippy(builder, self.stage, self.target);
+ if builder.ensure(dist::Clippy {
+ compiler: self.compiler,
+ target: self.target,
+ }).is_some() || Self::should_install(builder) {
+ install_clippy(builder, self.compiler.stage, self.target);
} else {
- builder.info(&format!("skipping Install clippy stage{} ({})", self.stage, self.target));
+ builder.info(
+ &format!("skipping Install clippy stage{} ({})", self.compiler.stage, self.target),
+ );
}
};
Miri, "miri", Self::should_build(_config), only_hosts: true, {
- if builder.ensure(dist::Miri { stage: self.stage, target: self.target }).is_some() ||
+ if builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }).is_some() ||
Self::should_install(builder) {
- install_miri(builder, self.stage, self.target);
+ install_miri(builder, self.compiler.stage, self.target);
} else {
- builder.info(&format!("skipping Install miri stage{} ({})", self.stage, self.target));
+ builder.info(
+ &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
+ );
}
};
Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
- if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
- Self::should_install(builder) {
- install_rustfmt(builder, self.stage, self.target);
+ if builder.ensure(dist::Rustfmt {
+ compiler: self.compiler,
+ target: self.target
+ }).is_some() || Self::should_install(builder) {
+ install_rustfmt(builder, self.compiler.stage, self.target);
} else {
builder.info(
- &format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target));
+ &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
+ );
}
};
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
builder.ensure(dist::Analysis {
- compiler: builder.compiler(self.stage, self.host),
+ compiler: self.compiler,
target: self.target
});
- install_analysis(builder, self.stage, self.target);
+ install_analysis(builder, self.compiler.stage, self.target);
};
Rustc, "src/librustc", true, only_hosts: true, {
builder.ensure(dist::Rustc {
- compiler: builder.compiler(self.stage, self.target),
+ compiler: self.compiler,
});
- install_rustc(builder, self.stage, self.target);
+ install_rustc(builder, self.compiler.stage, self.target);
};
);
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let config = &run.builder.config;
- let cond = config.extended &&
- config.tools.as_ref().map_or(true, |t| t.contains("src"));
+ let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src"));
run.path("src").default_condition(cond)
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Src {
- stage: run.builder.top_stage,
- });
+ run.builder.ensure(Src { stage: run.builder.top_stage });
}
fn run(self, builder: &Builder<'_>) {
builder.ensure(compile::Test { compiler, target });
builder.ensure(RemoteCopyLibs { compiler, target });
- // If we're not doing a full bootstrap but we're testing a stage2 version of
- // libstd, then what we're actually testing is the libstd produced in
- // stage1. Reflect that here by updating the compiler that we're working
- // with automatically.
- let compiler = if builder.force_use_stage1(compiler, target) {
- builder.compiler(1, compiler.host)
- } else {
- compiler.clone()
- };
+ // If we're not doing a full bootstrap but we're testing a stage2
+ // version of libstd, then what we're actually testing is the libstd
+ // produced in stage1. Reflect that here by updating the compiler that
+ // we're working with automatically.
+ let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
match mode {
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
- // Cargo depends on procedural macros, which requires a full host
- // compiler to be available, so we need to depend on that.
- builder.ensure(compile::Rustc {
+ // Cargo depends on procedural macros, so make sure the host
+ // libstd/libproc_macro is available.
+ builder.ensure(compile::Test {
compiler: self.compiler,
target: builder.config.build,
});
tool_extended!((self, builder),
Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {};
CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", {
- // Clippy depends on procedural macros (serde), which requires a full host
- // compiler to be available, so we need to depend on that.
- builder.ensure(compile::Rustc {
+ // Clippy depends on procedural macros, so make sure that's built for
+ // the compiler itself.
+ builder.ensure(compile::Test {
compiler: self.compiler,
target: builder.config.build,
});
};
Clippy, clippy, "src/tools/clippy", "clippy-driver", {
- // Clippy depends on procedural macros (serde), which requires a full host
- // compiler to be available, so we need to depend on that.
- builder.ensure(compile::Rustc {
+ // Clippy depends on procedural macros, so make sure that's built for
+ // the compiler itself.
+ builder.ensure(compile::Test {
compiler: self.compiler,
target: builder.config.build,
});
};
Miri, miri, "src/tools/miri", "miri", {};
CargoMiri, miri, "src/tools/miri", "cargo-miri", {
- // Miri depends on procedural macros (serde), which requires a full host
- // compiler to be available, so we need to depend on that.
- builder.ensure(compile::Rustc {
+ // Miri depends on procedural macros, so make sure that's built for
+ // the compiler itself.
+ builder.ensure(compile::Test {
compiler: self.compiler,
target: builder.config.build,
});
if clippy.is_some() {
self.extra_features.push("clippy".to_owned());
}
- // RLS depends on procedural macros, which requires a full host
- // compiler to be available, so we need to depend on that.
- builder.ensure(compile::Rustc {
+ // RLS depends on procedural macros, so make sure that's built for
+ // the compiler itself.
+ builder.ensure(compile::Test {
compiler: self.compiler,
target: builder.config.build,
});
+++ /dev/null
-# `borrow_state`
-
-The tracking issue for this feature is: [#27733]
-
-[#27733]: https://github.com/rust-lang/rust/issues/27733
-
-------------------------
use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
use core::marker::{self, Unpin, Unsize, PhantomData};
-use core::mem::{self, align_of_val, forget, size_of_val};
+use core::mem::{self, align_of, align_of_val, forget, size_of_val};
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
use core::pin::Pin;
use core::ptr::{self, NonNull};
/// ```
#[stable(feature = "rc_raw", since = "1.17.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
- // Align the unsized value to the end of the RcBox.
- // Because it is ?Sized, it will always be the last field in memory.
- let align = align_of_val(&*ptr);
- let layout = Layout::new::<RcBox<()>>();
- let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
+ let offset = data_offset(ptr);
// Reverse the offset to find the original RcBox.
let fake_ptr = ptr as *mut RcBox<T>;
ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
}
}
+
+ /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
+ ///
+ /// It is up to the caller to ensure that the object is still alive when accessing it through
+ /// the pointer.
+ ///
+ /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::rc::{Rc, Weak};
+ /// use std::ptr;
+ ///
+ /// let strong = Rc::new(42);
+ /// let weak = Rc::downgrade(&strong);
+ /// // Both point to the same object
+ /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
+ /// // The strong here keeps it alive, so we can still access the object.
+ /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
+ ///
+ /// drop(strong);
+ /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
+ /// // undefined behaviour.
+ /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
+ /// ```
+ ///
+ /// [`null`]: ../../std/ptr/fn.null.html
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub fn as_raw(this: &Self) -> *const T {
+ match this.inner() {
+ None => ptr::null(),
+ Some(inner) => {
+ let offset = data_offset_sized::<T>();
+ let ptr = inner as *const RcBox<T>;
+ // Note: while the pointer we create may already point to dropped value, the
+ // allocation still lives (it must hold the weak point as long as we are alive).
+ // Therefore, the offset is OK to do, it won't get out of the allocation.
+ let ptr = unsafe { (ptr as *const u8).offset(offset) };
+ ptr as *const T
+ }
+ }
+ }
+
+ /// Consumes the `Weak<T>` and turns it into a raw pointer.
+ ///
+ /// This converts the weak pointer into a raw pointer, preserving the original weak count. It
+ /// can be turned back into the `Weak<T>` with [`from_raw`].
+ ///
+ /// The same restrictions of accessing the target of the pointer as with
+ /// [`as_raw`] apply.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::rc::{Rc, Weak};
+ ///
+ /// let strong = Rc::new(42);
+ /// let weak = Rc::downgrade(&strong);
+ /// let raw = Weak::into_raw(weak);
+ ///
+ /// assert_eq!(1, Rc::weak_count(&strong));
+ /// assert_eq!(42, unsafe { *raw });
+ ///
+ /// drop(unsafe { Weak::from_raw(raw) });
+ /// assert_eq!(0, Rc::weak_count(&strong));
+ /// ```
+ ///
+ /// [`from_raw`]: struct.Weak.html#method.from_raw
+ /// [`as_raw`]: struct.Weak.html#method.as_raw
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub fn into_raw(this: Self) -> *const T {
+ let result = Self::as_raw(&this);
+ mem::forget(this);
+ result
+ }
+
+ /// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>`.
+ ///
+ /// This can be used to safely get a strong reference (by calling [`upgrade`]
+ /// later) or to deallocate the weak count by dropping the `Weak<T>`.
+ ///
+ /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
+ /// returned.
+ ///
+ /// # Safety
+ ///
+ /// The pointer must represent one valid weak count. In other words, it must point to `T` which
+ /// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
+ /// 0. It is allowed for the strong count to be 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::rc::{Rc, Weak};
+ ///
+ /// let strong = Rc::new(42);
+ ///
+ /// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
+ /// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
+ ///
+ /// assert_eq!(2, Rc::weak_count(&strong));
+ ///
+ /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
+ /// assert_eq!(1, Rc::weak_count(&strong));
+ ///
+ /// drop(strong);
+ ///
+ /// // Decrement the last weak count.
+ /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
+ /// ```
+ ///
+ /// [`null`]: ../../std/ptr/fn.null.html
+ /// [`into_raw`]: struct.Weak.html#method.into_raw
+ /// [`upgrade`]: struct.Weak.html#method.upgrade
+ /// [`Rc`]: struct.Rc.html
+ /// [`Weak`]: struct.Weak.html
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub unsafe fn from_raw(ptr: *const T) -> Self {
+ if ptr.is_null() {
+ Self::new()
+ } else {
+ // See Rc::from_raw for details
+ let offset = data_offset(ptr);
+ let fake_ptr = ptr as *mut RcBox<T>;
+ let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
+ Weak {
+ ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
+ }
+ }
+ }
}
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Rc<T> { }
+
+unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
+ // Align the unsized value to the end of the RcBox.
+ // Because it is ?Sized, it will always be the last field in memory.
+ let align = align_of_val(&*ptr);
+ let layout = Layout::new::<RcBox<()>>();
+ (layout.size() + layout.padding_needed_for(align)) as isize
+}
+
+/// Computes the offset of the data field within ArcInner.
+///
+/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
+fn data_offset_sized<T>() -> isize {
+ let align = align_of::<T>();
+ let layout = Layout::new::<RcBox<()>>();
+ (layout.size() + layout.padding_needed_for(align)) as isize
+}
// `core::slice::SliceExt` - we need to supply these functions for the
// `test_permutations` test
mod hack {
- use core::mem;
-
use crate::boxed::Box;
use crate::vec::Vec;
#[cfg(test)]
use crate::string::ToString;
- pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> {
+ pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> {
unsafe {
- let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len());
- mem::forget(b);
+ let len = b.len();
+ let b = Box::into_raw(b);
+ let xs = Vec::from_raw_parts(b as *mut T, len, len);
xs
}
}
use core::fmt;
use core::cmp::{self, Ordering};
use core::intrinsics::abort;
-use core::mem::{self, align_of_val, size_of_val};
+use core::mem::{self, align_of, align_of_val, size_of_val};
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
use core::pin::Pin;
use core::ptr::{self, NonNull};
/// ```
#[stable(feature = "rc_raw", since = "1.17.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
- // Align the unsized value to the end of the ArcInner.
- // Because it is ?Sized, it will always be the last field in memory.
- let align = align_of_val(&*ptr);
- let layout = Layout::new::<ArcInner<()>>();
- let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
+ let offset = data_offset(ptr);
// Reverse the offset to find the original ArcInner.
let fake_ptr = ptr as *mut ArcInner<T>;
ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
}
}
+
+ /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
+ ///
+ /// It is up to the caller to ensure that the object is still alive when accessing it through
+ /// the pointer.
+ ///
+ /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::sync::{Arc, Weak};
+ /// use std::ptr;
+ ///
+ /// let strong = Arc::new(42);
+ /// let weak = Arc::downgrade(&strong);
+ /// // Both point to the same object
+ /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
+ /// // The strong here keeps it alive, so we can still access the object.
+ /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
+ ///
+ /// drop(strong);
+ /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
+ /// // undefined behaviour.
+ /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
+ /// ```
+ ///
+ /// [`null`]: ../../std/ptr/fn.null.html
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub fn as_raw(this: &Self) -> *const T {
+ match this.inner() {
+ None => ptr::null(),
+ Some(inner) => {
+ let offset = data_offset_sized::<T>();
+ let ptr = inner as *const ArcInner<T>;
+ // Note: while the pointer we create may already point to dropped value, the
+ // allocation still lives (it must hold the weak point as long as we are alive).
+ // Therefore, the offset is OK to do, it won't get out of the allocation.
+ let ptr = unsafe { (ptr as *const u8).offset(offset) };
+ ptr as *const T
+ }
+ }
+ }
+
+ /// Consumes the `Weak<T>` and turns it into a raw pointer.
+ ///
+ /// This converts the weak pointer into a raw pointer, preserving the original weak count. It
+ /// can be turned back into the `Weak<T>` with [`from_raw`].
+ ///
+ /// The same restrictions of accessing the target of the pointer as with
+ /// [`as_raw`] apply.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::sync::{Arc, Weak};
+ ///
+ /// let strong = Arc::new(42);
+ /// let weak = Arc::downgrade(&strong);
+ /// let raw = Weak::into_raw(weak);
+ ///
+ /// assert_eq!(1, Arc::weak_count(&strong));
+ /// assert_eq!(42, unsafe { *raw });
+ ///
+ /// drop(unsafe { Weak::from_raw(raw) });
+ /// assert_eq!(0, Arc::weak_count(&strong));
+ /// ```
+ ///
+ /// [`from_raw`]: struct.Weak.html#method.from_raw
+ /// [`as_raw`]: struct.Weak.html#method.as_raw
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub fn into_raw(this: Self) -> *const T {
+ let result = Self::as_raw(&this);
+ mem::forget(this);
+ result
+ }
+
+ /// Converts a raw pointer previously created by [`into_raw`] back into
+ /// `Weak<T>`.
+ ///
+ /// This can be used to safely get a strong reference (by calling [`upgrade`]
+ /// later) or to deallocate the weak count by dropping the `Weak<T>`.
+ ///
+ /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
+ /// returned.
+ ///
+ /// # Safety
+ ///
+ /// The pointer must represent one valid weak count. In other words, it must point to `T` which
+ /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
+ /// 0. It is allowed for the strong count to be 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(weak_into_raw)]
+ ///
+ /// use std::sync::{Arc, Weak};
+ ///
+ /// let strong = Arc::new(42);
+ ///
+ /// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
+ /// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
+ ///
+ /// assert_eq!(2, Arc::weak_count(&strong));
+ ///
+ /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
+ /// assert_eq!(1, Arc::weak_count(&strong));
+ ///
+ /// drop(strong);
+ ///
+ /// // Decrement the last weak count.
+ /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
+ /// ```
+ ///
+ /// [`null`]: ../../std/ptr/fn.null.html
+ /// [`into_raw`]: struct.Weak.html#method.into_raw
+ /// [`upgrade`]: struct.Weak.html#method.upgrade
+ /// [`Weak`]: struct.Weak.html
+ /// [`Arc`]: struct.Arc.html
+ #[unstable(feature = "weak_into_raw", issue = "60728")]
+ pub unsafe fn from_raw(ptr: *const T) -> Self {
+ if ptr.is_null() {
+ Self::new()
+ } else {
+ // See Arc::from_raw for details
+ let offset = data_offset(ptr);
+ let fake_ptr = ptr as *mut ArcInner<T>;
+ let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
+ Weak {
+ ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
+ }
+ }
+ }
}
impl<T: ?Sized> Weak<T> {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Arc<T> { }
+
+/// Computes the offset of the data field within ArcInner.
+unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
+ // Align the unsized value to the end of the ArcInner.
+ // Because it is ?Sized, it will always be the last field in memory.
+ let align = align_of_val(&*ptr);
+ let layout = Layout::new::<ArcInner<()>>();
+ (layout.size() + layout.padding_needed_for(align)) as isize
+}
+
+/// Computes the offset of the data field within ArcInner.
+///
+/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
+fn data_offset_sized<T>() -> isize {
+ let align = align_of::<T>();
+ let layout = Layout::new::<ArcInner<()>>();
+ (layout.size() + layout.padding_needed_for(align)) as isize
+}
/// # Examples
///
/// ```
- /// #![feature(borrow_state)]
/// use std::cell::RefCell;
///
/// let c = RefCell::new(5);
/// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
/// }
/// ```
- #[unstable(feature = "borrow_state", issue = "27733")]
+ #[stable(feature = "borrow_state", since = "1.37.0")]
#[inline]
pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
if !is_writing(self.borrow.get()) {
/// Adds a `usize`, returning `None` on overflow.
fn add_usize(&self, n: usize) -> Option<Self>;
+
+ /// Subtracts a `usize`, returning `None` on underflow.
+ fn sub_usize(&self, n: usize) -> Option<Self> {
+ // this default implementation makes the addition of `sub_usize` a non-breaking change
+ let _ = n;
+ unimplemented!()
+ }
}
// These are still macro-generated because the integer literals resolve to different types.
}
}
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn sub_usize(&self, n: usize) -> Option<Self> {
+ match <$t>::try_from(n) {
+ Ok(n_as_t) => self.checked_sub(n_as_t),
+ Err(_) => None,
+ }
+ }
+
step_identical_methods!();
}
)*)
}
}
+ #[inline]
+ #[allow(unreachable_patterns)]
+ fn sub_usize(&self, n: usize) -> Option<Self> {
+ match <$unsigned>::try_from(n) {
+ Ok(n_as_unsigned) => {
+ // Wrapping in unsigned space handles cases like
+ // `80_i8.sub_usize(200) == Some(-120_i8)`,
+ // even though 200_usize is out of range for i8.
+ let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t;
+ if wrapped <= *self {
+ Some(wrapped)
+ } else {
+ None // Subtraction underflowed
+ }
+ }
+ Err(_) => None,
+ }
+ }
+
step_identical_methods!();
}
)*)
ResultShunt::process(iter, |i| i.product())
}
}
+
+/// An iterator adapter that produces output as long as the underlying
+/// iterator produces `Option::Some` values.
+struct OptionShunt<I> {
+ iter: I,
+ exited_early: bool,
+}
+
+impl<I, T> OptionShunt<I>
+where
+ I: Iterator<Item = Option<T>>,
+{
+ /// Process the given iterator as if it yielded a `T` instead of a
+ /// `Option<T>`. Any `None` value will stop the inner iterator and
+ /// the overall result will be a `None`.
+ pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
+ where
+ F: FnMut(&mut Self) -> U,
+ {
+ let mut shunt = OptionShunt::new(iter);
+ let value = f(shunt.by_ref());
+ shunt.reconstruct(value)
+ }
+
+ fn new(iter: I) -> Self {
+ OptionShunt {
+ iter,
+ exited_early: false,
+ }
+ }
+
+ /// Consume the adapter and rebuild a `Option` value.
+ fn reconstruct<U>(self, val: U) -> Option<U> {
+ if self.exited_early {
+ None
+ } else {
+ Some(val)
+ }
+ }
+}
+
+impl<I, T> Iterator for OptionShunt<I>
+where
+ I: Iterator<Item = Option<T>>,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.iter.next() {
+ Some(Some(v)) => Some(v),
+ Some(None) => {
+ self.exited_early = true;
+ None
+ }
+ None => None,
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ if self.exited_early {
+ (0, Some(0))
+ } else {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+ }
+}
+
+#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
+impl<T, U> Sum<Option<U>> for Option<T>
+where
+ T: Sum<U>,
+{
+ /// Takes each element in the `Iterator`: if it is a `None`, no further
+ /// elements are taken, and the `None` is returned. Should no `None` occur,
+ /// the sum of all elements is returned.
+ ///
+ /// # Examples
+ ///
+ /// This sums up the position of the character 'a' in a vector of strings,
+ /// if a word did not have the character 'a' the operation returns `None`:
+ ///
+ /// ```
+ /// let words = vec!["have", "a", "great", "day"];
+ /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
+ /// assert_eq!(total, Some(5));
+ /// ```
+ fn sum<I>(iter: I) -> Option<T>
+ where
+ I: Iterator<Item = Option<U>>,
+ {
+ OptionShunt::process(iter, |i| i.sum())
+ }
+}
+
+#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
+impl<T, U> Product<Option<U>> for Option<T>
+where
+ T: Product<U>,
+{
+ /// Takes each element in the `Iterator`: if it is a `None`, no further
+ /// elements are taken, and the `None` is returned. Should no `None` occur,
+ /// the product of all elements is returned.
+ fn product<I>(iter: I) -> Option<T>
+ where
+ I: Iterator<Item = Option<U>>,
+ {
+ OptionShunt::process(iter, |i| i.product())
+ }
+}
+++ /dev/null
-//! Basic functions for dealing with memory.
-//!
-//! This module contains functions for querying the size and alignment of
-//! types, initializing and manipulating memory.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use crate::clone;
-use crate::cmp;
-use crate::fmt;
-use crate::hash;
-use crate::intrinsics;
-use crate::marker::{Copy, PhantomData, Sized};
-use crate::ptr;
-use crate::ops::{Deref, DerefMut};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(inline)]
-pub use crate::intrinsics::transmute;
-
-/// Takes ownership and "forgets" about the value **without running its destructor**.
-///
-/// Any resources the value manages, such as heap memory or a file handle, will linger
-/// forever in an unreachable state. However, it does not guarantee that pointers
-/// to this memory will remain valid.
-///
-/// * If you want to leak memory, see [`Box::leak`][leak].
-/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
-/// * If you want to dispose of a value properly, running its destructor, see
-/// [`mem::drop`][drop].
-///
-/// # Safety
-///
-/// `forget` is not marked as `unsafe`, because Rust's safety guarantees
-/// do not include a guarantee that destructors will always run. For example,
-/// a program can create a reference cycle using [`Rc`][rc], or call
-/// [`process::exit`][exit] to exit without running destructors. Thus, allowing
-/// `mem::forget` from safe code does not fundamentally change Rust's safety
-/// guarantees.
-///
-/// That said, leaking resources such as memory or I/O objects is usually undesirable,
-/// so `forget` is only recommended for specialized use cases like those shown below.
-///
-/// Because forgetting a value is allowed, any `unsafe` code you write must
-/// allow for this possibility. You cannot return a value and expect that the
-/// caller will necessarily run the value's destructor.
-///
-/// [rc]: ../../std/rc/struct.Rc.html
-/// [exit]: ../../std/process/fn.exit.html
-///
-/// # Examples
-///
-/// Leak an I/O object, never closing the file:
-///
-/// ```no_run
-/// use std::mem;
-/// use std::fs::File;
-///
-/// let file = File::open("foo.txt").unwrap();
-/// mem::forget(file);
-/// ```
-///
-/// The practical use cases for `forget` are rather specialized and mainly come
-/// up in unsafe or FFI code.
-///
-/// [drop]: fn.drop.html
-/// [uninit]: fn.uninitialized.html
-/// [clone]: ../clone/trait.Clone.html
-/// [swap]: fn.swap.html
-/// [box]: ../../std/boxed/struct.Box.html
-/// [leak]: ../../std/boxed/struct.Box.html#method.leak
-/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
-/// [ub]: ../../reference/behavior-considered-undefined.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn forget<T>(t: T) {
- ManuallyDrop::new(t);
-}
-
-/// Like [`forget`], but also accepts unsized values.
-///
-/// This function is just a shim intended to be removed when the `unsized_locals` feature gets
-/// stabilized.
-///
-/// [`forget`]: fn.forget.html
-#[inline]
-#[unstable(feature = "forget_unsized", issue = "0")]
-pub fn forget_unsized<T: ?Sized>(t: T) {
- unsafe { intrinsics::forget(t) }
-}
-
-/// Returns the size of a type in bytes.
-///
-/// More specifically, this is the offset in bytes between successive elements
-/// in an array with that item type including alignment padding. Thus, for any
-/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`.
-///
-/// In general, the size of a type is not stable across compilations, but
-/// specific types such as primitives are.
-///
-/// The following table gives the size for primitives.
-///
-/// Type | size_of::\<Type>()
-/// ---- | ---------------
-/// () | 0
-/// bool | 1
-/// u8 | 1
-/// u16 | 2
-/// u32 | 4
-/// u64 | 8
-/// u128 | 16
-/// i8 | 1
-/// i16 | 2
-/// i32 | 4
-/// i64 | 8
-/// i128 | 16
-/// f32 | 4
-/// f64 | 8
-/// char | 4
-///
-/// Furthermore, `usize` and `isize` have the same size.
-///
-/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have
-/// the same size. If `T` is Sized, all of those types have the same size as `usize`.
-///
-/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
-/// have the same size. Likewise for `*const T` and `*mut T`.
-///
-/// # Size of `#[repr(C)]` items
-///
-/// The `C` representation for items has a defined layout. With this layout,
-/// the size of items is also stable as long as all fields have a stable size.
-///
-/// ## Size of Structs
-///
-/// For `structs`, the size is determined by the following algorithm.
-///
-/// For each field in the struct ordered by declaration order:
-///
-/// 1. Add the size of the field.
-/// 2. Round up the current size to the nearest multiple of the next field's [alignment].
-///
-/// Finally, round the size of the struct to the nearest multiple of its [alignment].
-/// The alignment of the struct is usually the largest alignment of all its
-/// fields; this can be changed with the use of `repr(align(N))`.
-///
-/// Unlike `C`, zero sized structs are not rounded up to one byte in size.
-///
-/// ## Size of Enums
-///
-/// Enums that carry no data other than the discriminant have the same size as C enums
-/// on the platform they are compiled for.
-///
-/// ## Size of Unions
-///
-/// The size of a union is the size of its largest field.
-///
-/// Unlike `C`, zero sized unions are not rounded up to one byte in size.
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// // Some primitives
-/// assert_eq!(4, mem::size_of::<i32>());
-/// assert_eq!(8, mem::size_of::<f64>());
-/// assert_eq!(0, mem::size_of::<()>());
-///
-/// // Some arrays
-/// assert_eq!(8, mem::size_of::<[i32; 2]>());
-/// assert_eq!(12, mem::size_of::<[i32; 3]>());
-/// assert_eq!(0, mem::size_of::<[i32; 0]>());
-///
-///
-/// // Pointer size equality
-/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>());
-/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>());
-/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
-/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
-/// ```
-///
-/// Using `#[repr(C)]`.
-///
-/// ```
-/// use std::mem;
-///
-/// #[repr(C)]
-/// struct FieldStruct {
-/// first: u8,
-/// second: u16,
-/// third: u8
-/// }
-///
-/// // The size of the first field is 1, so add 1 to the size. Size is 1.
-/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
-/// // The size of the second field is 2, so add 2 to the size. Size is 4.
-/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
-/// // The size of the third field is 1, so add 1 to the size. Size is 5.
-/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its
-/// // fields is 2), so add 1 to the size for padding. Size is 6.
-/// assert_eq!(6, mem::size_of::<FieldStruct>());
-///
-/// #[repr(C)]
-/// struct TupleStruct(u8, u16, u8);
-///
-/// // Tuple structs follow the same rules.
-/// assert_eq!(6, mem::size_of::<TupleStruct>());
-///
-/// // Note that reordering the fields can lower the size. We can remove both padding bytes
-/// // by putting `third` before `second`.
-/// #[repr(C)]
-/// struct FieldStructOptimized {
-/// first: u8,
-/// third: u8,
-/// second: u16
-/// }
-///
-/// assert_eq!(4, mem::size_of::<FieldStructOptimized>());
-///
-/// // Union size is the size of the largest field.
-/// #[repr(C)]
-/// union ExampleUnion {
-/// smaller: u8,
-/// larger: u16
-/// }
-///
-/// assert_eq!(2, mem::size_of::<ExampleUnion>());
-/// ```
-///
-/// [alignment]: ./fn.align_of.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_promotable]
-pub const fn size_of<T>() -> usize {
- intrinsics::size_of::<T>()
-}
-
-/// Returns the size of the pointed-to value in bytes.
-///
-/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no
-/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object],
-/// then `size_of_val` can be used to get the dynamically-known size.
-///
-/// [slice]: ../../std/primitive.slice.html
-/// [trait object]: ../../book/ch17-02-trait-objects.html
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// assert_eq!(4, mem::size_of_val(&5i32));
-///
-/// let x: [u8; 13] = [0; 13];
-/// let y: &[u8] = &x;
-/// assert_eq!(13, mem::size_of_val(y));
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
- unsafe { intrinsics::size_of_val(val) }
-}
-
-/// Returns the [ABI]-required minimum alignment of a type.
-///
-/// Every reference to a value of the type `T` must be a multiple of this number.
-///
-/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
-///
-/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
-///
-/// # Examples
-///
-/// ```
-/// # #![allow(deprecated)]
-/// use std::mem;
-///
-/// assert_eq!(4, mem::min_align_of::<i32>());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
-pub fn min_align_of<T>() -> usize {
- intrinsics::min_align_of::<T>()
-}
-
-/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
-///
-/// Every reference to a value of the type `T` must be a multiple of this number.
-///
-/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
-///
-/// # Examples
-///
-/// ```
-/// # #![allow(deprecated)]
-/// use std::mem;
-///
-/// assert_eq!(4, mem::min_align_of_val(&5i32));
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
-pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
- unsafe { intrinsics::min_align_of_val(val) }
-}
-
-/// Returns the [ABI]-required minimum alignment of a type.
-///
-/// Every reference to a value of the type `T` must be a multiple of this number.
-///
-/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
-///
-/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// assert_eq!(4, mem::align_of::<i32>());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_promotable]
-pub const fn align_of<T>() -> usize {
- intrinsics::min_align_of::<T>()
-}
-
-/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
-///
-/// Every reference to a value of the type `T` must be a multiple of this number.
-///
-/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// assert_eq!(4, mem::align_of_val(&5i32));
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
- unsafe { intrinsics::min_align_of_val(val) }
-}
-
-/// Returns `true` if dropping values of type `T` matters.
-///
-/// This is purely an optimization hint, and may be implemented conservatively:
-/// it may return `true` for types that don't actually need to be dropped.
-/// As such always returning `true` would be a valid implementation of
-/// this function. However if this function actually returns `false`, then you
-/// can be certain dropping `T` has no side effect.
-///
-/// Low level implementations of things like collections, which need to manually
-/// drop their data, should use this function to avoid unnecessarily
-/// trying to drop all their contents when they are destroyed. This might not
-/// make a difference in release builds (where a loop that has no side-effects
-/// is easily detected and eliminated), but is often a big win for debug builds.
-///
-/// Note that `ptr::drop_in_place` already performs this check, so if your workload
-/// can be reduced to some small number of drop_in_place calls, using this is
-/// unnecessary. In particular note that you can drop_in_place a slice, and that
-/// will do a single needs_drop check for all the values.
-///
-/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
-/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
-/// values one at a time and should use this API.
-///
-///
-/// # Examples
-///
-/// Here's an example of how a collection might make use of needs_drop:
-///
-/// ```
-/// use std::{mem, ptr};
-///
-/// pub struct MyCollection<T> {
-/// # data: [T; 1],
-/// /* ... */
-/// }
-/// # impl<T> MyCollection<T> {
-/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data }
-/// # fn free_buffer(&mut self) {}
-/// # }
-///
-/// impl<T> Drop for MyCollection<T> {
-/// fn drop(&mut self) {
-/// unsafe {
-/// // drop the data
-/// if mem::needs_drop::<T>() {
-/// for x in self.iter_mut() {
-/// ptr::drop_in_place(x);
-/// }
-/// }
-/// self.free_buffer();
-/// }
-/// }
-/// }
-/// ```
-#[inline]
-#[stable(feature = "needs_drop", since = "1.21.0")]
-pub const fn needs_drop<T>() -> bool {
- intrinsics::needs_drop::<T>()
-}
-
-/// Creates a value whose bytes are all zero.
-///
-/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
-/// It is useful for FFI sometimes, but should generally be avoided.
-///
-/// There is no guarantee that an all-zero byte-pattern represents a valid value of
-/// some type `T`. For example, the all-zero byte-pattern is not a valid value
-/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
-/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
-/// that there always is a valid value in a variable it considers initialized.
-///
-/// [zeroed]: union.MaybeUninit.html#method.zeroed
-/// [ub]: ../../reference/behavior-considered-undefined.html
-/// [inv]: union.MaybeUninit.html#initialization-invariant
-///
-/// # Examples
-///
-/// Correct usage of this function: initializing an integer with zero.
-///
-/// ```
-/// use std::mem;
-///
-/// let x: i32 = unsafe { mem::zeroed() };
-/// assert_eq!(0, x);
-/// ```
-///
-/// *Incorrect* usage of this function: initializing a reference with zero.
-///
-/// ```no_run
-/// use std::mem;
-///
-/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn zeroed<T>() -> T {
- intrinsics::panic_if_uninhabited::<T>();
- intrinsics::init()
-}
-
-/// Bypasses Rust's normal memory-initialization checks by pretending to
-/// produce a value of type `T`, while doing nothing at all.
-///
-/// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead.
-///
-/// The reason for deprecation is that the function basically cannot be used
-/// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
-/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
-/// undefined behavior for returning a `bool` that is not definitely either `true`
-/// or `false`. Worse, truly uninitialized memory like what gets returned here
-/// is special in that the compiler knows that it does not have a fixed value.
-/// This makes it undefined behavior to have uninitialized data in a variable even
-/// if that variable has an integer type.
-/// (Notice that the rules around uninitialized integers are not finalized yet, but
-/// until they are, it is advisable to avoid them.)
-///
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-/// [inv]: union.MaybeUninit.html#initialization-invariant
-#[inline]
-#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn uninitialized<T>() -> T {
- intrinsics::panic_if_uninhabited::<T>();
- intrinsics::uninit()
-}
-
-/// Swaps the values at two mutable locations, without deinitializing either one.
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// let mut x = 5;
-/// let mut y = 42;
-///
-/// mem::swap(&mut x, &mut y);
-///
-/// assert_eq!(42, x);
-/// assert_eq!(5, y);
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn swap<T>(x: &mut T, y: &mut T) {
- unsafe {
- ptr::swap_nonoverlapping_one(x, y);
- }
-}
-
-/// Moves `src` into the referenced `dest`, returning the previous `dest` value.
-///
-/// Neither value is dropped.
-///
-/// # Examples
-///
-/// A simple example:
-///
-/// ```
-/// use std::mem;
-///
-/// let mut v: Vec<i32> = vec![1, 2];
-///
-/// let old_v = mem::replace(&mut v, vec![3, 4, 5]);
-/// assert_eq!(vec![1, 2], old_v);
-/// assert_eq!(vec![3, 4, 5], v);
-/// ```
-///
-/// `replace` allows consumption of a struct field by replacing it with another value.
-/// Without `replace` you can run into issues like these:
-///
-/// ```compile_fail,E0507
-/// struct Buffer<T> { buf: Vec<T> }
-///
-/// impl<T> Buffer<T> {
-/// fn get_and_reset(&mut self) -> Vec<T> {
-/// // error: cannot move out of dereference of `&mut`-pointer
-/// let buf = self.buf;
-/// self.buf = Vec::new();
-/// buf
-/// }
-/// }
-/// ```
-///
-/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
-/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
-/// `self`, allowing it to be returned:
-///
-/// ```
-/// # #![allow(dead_code)]
-/// use std::mem;
-///
-/// # struct Buffer<T> { buf: Vec<T> }
-/// impl<T> Buffer<T> {
-/// fn get_and_reset(&mut self) -> Vec<T> {
-/// mem::replace(&mut self.buf, Vec::new())
-/// }
-/// }
-/// ```
-///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn replace<T>(dest: &mut T, mut src: T) -> T {
- swap(dest, &mut src);
- src
-}
-
-/// Disposes of a value.
-///
-/// This does call the argument's implementation of [`Drop`][drop].
-///
-/// This effectively does nothing for types which implement `Copy`, e.g.
-/// integers. Such values are copied and _then_ moved into the function, so the
-/// value persists after this function call.
-///
-/// This function is not magic; it is literally defined as
-///
-/// ```
-/// pub fn drop<T>(_x: T) { }
-/// ```
-///
-/// Because `_x` is moved into the function, it is automatically dropped before
-/// the function returns.
-///
-/// [drop]: ../ops/trait.Drop.html
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// let v = vec![1, 2, 3];
-///
-/// drop(v); // explicitly drop the vector
-/// ```
-///
-/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can
-/// release a [`RefCell`] borrow:
-///
-/// ```
-/// use std::cell::RefCell;
-///
-/// let x = RefCell::new(1);
-///
-/// let mut mutable_borrow = x.borrow_mut();
-/// *mutable_borrow = 1;
-///
-/// drop(mutable_borrow); // relinquish the mutable borrow on this slot
-///
-/// let borrow = x.borrow();
-/// println!("{}", *borrow);
-/// ```
-///
-/// Integers and other types implementing [`Copy`] are unaffected by `drop`.
-///
-/// ```
-/// #[derive(Copy, Clone)]
-/// struct Foo(u8);
-///
-/// let x = 1;
-/// let y = Foo(2);
-/// drop(x); // a copy of `x` is moved and dropped
-/// drop(y); // a copy of `y` is moved and dropped
-///
-/// println!("x: {}, y: {}", x, y.0); // still available
-/// ```
-///
-/// [`RefCell`]: ../../std/cell/struct.RefCell.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn drop<T>(_x: T) { }
-
-/// Interprets `src` as having type `&U`, and then reads `src` without moving
-/// the contained value.
-///
-/// This function will unsafely assume the pointer `src` is valid for
-/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
-/// the `&U`. It will also unsafely create a copy of the contained value instead of
-/// moving out of `src`.
-///
-/// It is not a compile-time error if `T` and `U` have different sizes, but it
-/// is highly encouraged to only invoke this function where `T` and `U` have the
-/// same size. This function triggers [undefined behavior][ub] if `U` is larger than
-/// `T`.
-///
-/// [ub]: ../../reference/behavior-considered-undefined.html
-/// [size_of]: fn.size_of.html
-///
-/// # Examples
-///
-/// ```
-/// use std::mem;
-///
-/// #[repr(packed)]
-/// struct Foo {
-/// bar: u8,
-/// }
-///
-/// let foo_slice = [10u8];
-///
-/// unsafe {
-/// // Copy the data from 'foo_slice' and treat it as a 'Foo'
-/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice);
-/// assert_eq!(foo_struct.bar, 10);
-///
-/// // Modify the copied data
-/// foo_struct.bar = 20;
-/// assert_eq!(foo_struct.bar, 20);
-/// }
-///
-/// // The contents of 'foo_slice' should not have changed
-/// assert_eq!(foo_slice, [10]);
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
- ptr::read_unaligned(src as *const T as *const U)
-}
-
-/// Opaque type representing the discriminant of an enum.
-///
-/// See the [`discriminant`] function in this module for more information.
-///
-/// [`discriminant`]: fn.discriminant.html
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-pub struct Discriminant<T>(u64, PhantomData<fn() -> T>);
-
-// N.B. These trait implementations cannot be derived because we don't want any bounds on T.
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> Copy for Discriminant<T> {}
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> clone::Clone for Discriminant<T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> cmp::PartialEq for Discriminant<T> {
- fn eq(&self, rhs: &Self) -> bool {
- self.0 == rhs.0
- }
-}
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> cmp::Eq for Discriminant<T> {}
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> hash::Hash for Discriminant<T> {
- fn hash<H: hash::Hasher>(&self, state: &mut H) {
- self.0.hash(state);
- }
-}
-
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-impl<T> fmt::Debug for Discriminant<T> {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt.debug_tuple("Discriminant")
- .field(&self.0)
- .finish()
- }
-}
-
-/// Returns a value uniquely identifying the enum variant in `v`.
-///
-/// If `T` is not an enum, calling this function will not result in undefined behavior, but the
-/// return value is unspecified.
-///
-/// # Stability
-///
-/// The discriminant of an enum variant may change if the enum definition changes. A discriminant
-/// of some variant will not change between compilations with the same compiler.
-///
-/// # Examples
-///
-/// This can be used to compare enums that carry data, while disregarding
-/// the actual data:
-///
-/// ```
-/// use std::mem;
-///
-/// enum Foo { A(&'static str), B(i32), C(i32) }
-///
-/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz")));
-/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2)));
-/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3)));
-/// ```
-#[stable(feature = "discriminant_value", since = "1.21.0")]
-pub fn discriminant<T>(v: &T) -> Discriminant<T> {
- unsafe {
- Discriminant(intrinsics::discriminant_value(v), PhantomData)
- }
-}
-
-/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
-///
-/// This wrapper is 0-cost.
-///
-/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
-/// As a consequence, it has *no effect* on the assumptions that the compiler makes
-/// about all values being initialized at their type. In particular, initializing
-/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
-/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
-///
-/// # Examples
-///
-/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
-/// the type:
-///
-/// ```rust
-/// use std::mem::ManuallyDrop;
-/// struct Peach;
-/// struct Banana;
-/// struct Melon;
-/// struct FruitBox {
-/// // Immediately clear there’s something non-trivial going on with these fields.
-/// peach: ManuallyDrop<Peach>,
-/// melon: Melon, // Field that’s independent of the other two.
-/// banana: ManuallyDrop<Banana>,
-/// }
-///
-/// impl Drop for FruitBox {
-/// fn drop(&mut self) {
-/// unsafe {
-/// // Explicit ordering in which field destructors are run specified in the intuitive
-/// // location – the destructor of the structure containing the fields.
-/// // Moreover, one can now reorder fields within the struct however much they want.
-/// ManuallyDrop::drop(&mut self.peach);
-/// ManuallyDrop::drop(&mut self.banana);
-/// }
-/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
-/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
-/// }
-/// }
-/// ```
-///
-/// [`mem::zeroed`]: fn.zeroed.html
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-#[stable(feature = "manually_drop", since = "1.20.0")]
-#[lang = "manually_drop"]
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[repr(transparent)]
-pub struct ManuallyDrop<T: ?Sized> {
- value: T,
-}
-
-impl<T> ManuallyDrop<T> {
- /// Wrap a value to be manually dropped.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::mem::ManuallyDrop;
- /// ManuallyDrop::new(Box::new(()));
- /// ```
- #[stable(feature = "manually_drop", since = "1.20.0")]
- #[inline(always)]
- pub const fn new(value: T) -> ManuallyDrop<T> {
- ManuallyDrop { value }
- }
-
- /// Extracts the value from the `ManuallyDrop` container.
- ///
- /// This allows the value to be dropped again.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::mem::ManuallyDrop;
- /// let x = ManuallyDrop::new(Box::new(()));
- /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
- /// ```
- #[stable(feature = "manually_drop", since = "1.20.0")]
- #[inline(always)]
- pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
- slot.value
- }
-
- /// Takes the contained value out.
- ///
- /// This method is primarily intended for moving out values in drop.
- /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
- /// you can use this method to take the value and use it however desired.
- /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
- ///
- /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
- ///
- /// # Safety
- ///
- /// This function semantically moves out the contained value without preventing further usage.
- /// It is up to the user of this method to ensure that this container is not used again.
- ///
- /// [`ManuallyDrop::drop`]: #method.drop
- /// [`ManuallyDrop::into_inner`]: #method.into_inner
- #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
- #[unstable(feature = "manually_drop_take", issue = "55422")]
- #[inline]
- pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
- ManuallyDrop::into_inner(ptr::read(slot))
- }
-}
-
-impl<T: ?Sized> ManuallyDrop<T> {
- /// Manually drops the contained value.
- ///
- /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
- ///
- /// # Safety
- ///
- /// This function runs the destructor of the contained value and thus the wrapped value
- /// now represents uninitialized data. It is up to the user of this method to ensure the
- /// uninitialized data is not actually used.
- ///
- /// [`ManuallyDrop::into_inner`]: #method.into_inner
- #[stable(feature = "manually_drop", since = "1.20.0")]
- #[inline]
- pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
- ptr::drop_in_place(&mut slot.value)
- }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> Deref for ManuallyDrop<T> {
- type Target = T;
- #[inline(always)]
- fn deref(&self) -> &T {
- &self.value
- }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut T {
- &mut self.value
- }
-}
-
-/// A wrapper type to construct uninitialized instances of `T`.
-///
-/// # Initialization invariant
-///
-/// The compiler, in general, assumes that variables are properly initialized
-/// at their respective type. For example, a variable of reference type must
-/// be aligned and non-NULL. This is an invariant that must *always* be upheld,
-/// even in unsafe code. As a consequence, zero-initializing a variable of reference
-/// type causes instantaneous [undefined behavior][ub], no matter whether that reference
-/// ever gets used to access memory:
-///
-/// ```rust,no_run
-/// use std::mem::{self, MaybeUninit};
-///
-/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
-/// // The equivalent code with `MaybeUninit<&i32>`:
-/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
-/// ```
-///
-/// This is exploited by the compiler for various optimizations, such as eliding
-/// run-time checks and optimizing `enum` layout.
-///
-/// Similarly, entirely uninitialized memory may have any content, while a `bool` must
-/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
-///
-/// ```rust,no_run
-/// use std::mem::{self, MaybeUninit};
-///
-/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
-/// // The equivalent code with `MaybeUninit<bool>`:
-/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
-/// ```
-///
-/// Moreover, uninitialized memory is special in that the compiler knows that
-/// it does not have a fixed value. This makes it undefined behavior to have
-/// uninitialized data in a variable even if that variable has an integer type,
-/// which otherwise can hold any *fixed* bit pattern:
-///
-/// ```rust,no_run
-/// use std::mem::{self, MaybeUninit};
-///
-/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
-/// // The equivalent code with `MaybeUninit<i32>`:
-/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
-/// ```
-/// (Notice that the rules around uninitialized integers are not finalized yet, but
-/// until they are, it is advisable to avoid them.)
-///
-/// On top of that, remember that most types have additional invariants beyond merely
-/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
-/// is considered initialized because the only requirement the compiler knows about it
-/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
-/// *immediate* undefined behavior, but will cause undefined behavior with most
-/// safe operations (including dropping it).
-///
-/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
-///
-/// # Examples
-///
-/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
-/// It is a signal to the compiler indicating that the data here might *not*
-/// be initialized:
-///
-/// ```rust
-/// use std::mem::MaybeUninit;
-///
-/// // Create an explicitly uninitialized reference. The compiler knows that data inside
-/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
-/// let mut x = MaybeUninit::<&i32>::uninit();
-/// // Set it to a valid value.
-/// unsafe { x.as_mut_ptr().write(&0); }
-/// // Extract the initialized data -- this is only allowed *after* properly
-/// // initializing `x`!
-/// let x = unsafe { x.assume_init() };
-/// ```
-///
-/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
-///
-/// ## out-pointers
-///
-/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data
-/// from a function, pass it a pointer to some (uninitialized) memory to put the
-/// result into. This can be useful when it is important for the caller to control
-/// how the memory the result is stored in gets allocated, and you want to avoid
-/// unnecessary moves.
-///
-/// ```
-/// use std::mem::MaybeUninit;
-///
-/// unsafe fn make_vec(out: *mut Vec<i32>) {
-/// // `write` does not drop the old contents, which is important.
-/// out.write(vec![1, 2, 3]);
-/// }
-///
-/// let mut v = MaybeUninit::uninit();
-/// unsafe { make_vec(v.as_mut_ptr()); }
-/// // Now we know `v` is initialized! This also makes sure the vector gets
-/// // properly dropped.
-/// let v = unsafe { v.assume_init() };
-/// assert_eq!(&v, &[1, 2, 3]);
-/// ```
-///
-/// ## Initializing an array element-by-element
-///
-/// `MaybeUninit<T>` can be used to initialize a large array element-by-element:
-///
-/// ```
-/// use std::mem::{self, MaybeUninit};
-/// use std::ptr;
-///
-/// let data = {
-/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
-/// // safe because the type we are claiming to have initialized here is a
-/// // bunch of `MaybeUninit`s, which do not require initialization.
-/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
-/// MaybeUninit::uninit().assume_init()
-/// };
-///
-/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
-/// // we have a memory leak, but there is no memory safety issue.
-/// for elem in &mut data[..] {
-/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
-/// }
-///
-/// // Everything is initialized. Transmute the array to the
-/// // initialized type.
-/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
-/// };
-///
-/// assert_eq!(&data[0], &[42]);
-/// ```
-///
-/// You can also work with partially initialized arrays, which could
-/// be found in low-level datastructures.
-///
-/// ```
-/// use std::mem::MaybeUninit;
-/// use std::ptr;
-///
-/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
-/// // safe because the type we are claiming to have initialized here is a
-/// // bunch of `MaybeUninit`s, which do not require initialization.
-/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
-/// // Count the number of elements we have assigned.
-/// let mut data_len: usize = 0;
-///
-/// for elem in &mut data[0..500] {
-/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); }
-/// data_len += 1;
-/// }
-///
-/// // For each item in the array, drop if we allocated it.
-/// for elem in &mut data[0..data_len] {
-/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
-/// }
-/// ```
-///
-/// ## Initializing a struct field-by-field
-///
-/// There is currently no supported way to create a raw pointer or reference
-/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
-/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
-/// to its fields.
-///
-/// [ub]: ../../reference/behavior-considered-undefined.html
-///
-/// # Layout
-///
-/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
-///
-/// ```rust
-/// use std::mem::{MaybeUninit, size_of, align_of};
-/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>());
-/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>());
-/// ```
-///
-/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same
-/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as
-/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit
-/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling
-/// optimizations, potentially resulting in a larger size:
-///
-/// ```rust
-/// # use std::mem::{MaybeUninit, size_of};
-/// assert_eq!(size_of::<Option<bool>>(), 1);
-/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
-/// ```
-#[allow(missing_debug_implementations)]
-#[stable(feature = "maybe_uninit", since = "1.36.0")]
-#[derive(Copy)]
-pub union MaybeUninit<T> {
- uninit: (),
- value: ManuallyDrop<T>,
-}
-
-#[stable(feature = "maybe_uninit", since = "1.36.0")]
-impl<T: Copy> Clone for MaybeUninit<T> {
- #[inline(always)]
- fn clone(&self) -> Self {
- // Not calling `T::clone()`, we cannot know if we are initialized enough for that.
- *self
- }
-}
-
-impl<T> MaybeUninit<T> {
- /// Creates a new `MaybeUninit<T>` initialized with the given value.
- /// It is safe to call [`assume_init`] on the return value of this function.
- ///
- /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
- /// It is your responsibility to make sure `T` gets dropped if it got initialized.
- ///
- /// [`assume_init`]: #method.assume_init
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline(always)]
- pub const fn new(val: T) -> MaybeUninit<T> {
- MaybeUninit { value: ManuallyDrop::new(val) }
- }
-
- /// Creates a new `MaybeUninit<T>` in an uninitialized state.
- ///
- /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
- /// It is your responsibility to make sure `T` gets dropped if it got initialized.
- ///
- /// See the [type-level documentation][type] for some examples.
- ///
- /// [type]: union.MaybeUninit.html
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline(always)]
- pub const fn uninit() -> MaybeUninit<T> {
- MaybeUninit { uninit: () }
- }
-
- /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
- /// filled with `0` bytes. It depends on `T` whether that already makes for
- /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
- /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
- /// be null.
- ///
- /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
- /// It is your responsibility to make sure `T` gets dropped if it got initialized.
- ///
- /// # Example
- ///
- /// Correct usage of this function: initializing a struct with zero, where all
- /// fields of the struct can hold the bit-pattern 0 as a valid value.
- ///
- /// ```rust
- /// use std::mem::MaybeUninit;
- ///
- /// let x = MaybeUninit::<(u8, bool)>::zeroed();
- /// let x = unsafe { x.assume_init() };
- /// assert_eq!(x, (0, false));
- /// ```
- ///
- /// *Incorrect* usage of this function: initializing a struct with zero, where some fields
- /// cannot hold 0 as a valid value.
- ///
- /// ```rust,no_run
- /// use std::mem::MaybeUninit;
- ///
- /// enum NotZero { One = 1, Two = 2 };
- ///
- /// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
- /// let x = unsafe { x.assume_init() };
- /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
- /// // This is undefined behavior.
- /// ```
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline]
- pub fn zeroed() -> MaybeUninit<T> {
- let mut u = MaybeUninit::<T>::uninit();
- unsafe {
- u.as_mut_ptr().write_bytes(0u8, 1);
- }
- u
- }
-
- /// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
- /// without dropping it, so be careful not to use this twice unless you want to
- /// skip running the destructor. For your convenience, this also returns a mutable
- /// reference to the (now safely initialized) contents of `self`.
- #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
- #[inline(always)]
- pub fn write(&mut self, val: T) -> &mut T {
- unsafe {
- self.value = ManuallyDrop::new(val);
- self.get_mut()
- }
- }
-
- /// Gets a pointer to the contained value. Reading from this pointer or turning it
- /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
- /// Writing to memory that this pointer (non-transitively) points to is undefined behavior
- /// (except inside an `UnsafeCell<T>`).
- ///
- /// # Examples
- ///
- /// Correct usage of this method:
- ///
- /// ```rust
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
- /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
- /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
- /// let x_vec = unsafe { &*x.as_ptr() };
- /// assert_eq!(x_vec.len(), 3);
- /// ```
- ///
- /// *Incorrect* usage of this method:
- ///
- /// ```rust,no_run
- /// use std::mem::MaybeUninit;
- ///
- /// let x = MaybeUninit::<Vec<u32>>::uninit();
- /// let x_vec = unsafe { &*x.as_ptr() };
- /// // We have created a reference to an uninitialized vector! This is undefined behavior.
- /// ```
- ///
- /// (Notice that the rules around references to uninitialized data are not finalized yet, but
- /// until they are, it is advisable to avoid them.)
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline(always)]
- pub fn as_ptr(&self) -> *const T {
- unsafe { &*self.value as *const T }
- }
-
- /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
- /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
- ///
- /// # Examples
- ///
- /// Correct usage of this method:
- ///
- /// ```rust
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
- /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
- /// // Create a reference into the `MaybeUninit<Vec<u32>>`.
- /// // This is okay because we initialized it.
- /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
- /// x_vec.push(3);
- /// assert_eq!(x_vec.len(), 4);
- /// ```
- ///
- /// *Incorrect* usage of this method:
- ///
- /// ```rust,no_run
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
- /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
- /// // We have created a reference to an uninitialized vector! This is undefined behavior.
- /// ```
- ///
- /// (Notice that the rules around references to uninitialized data are not finalized yet, but
- /// until they are, it is advisable to avoid them.)
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline(always)]
- pub fn as_mut_ptr(&mut self) -> *mut T {
- unsafe { &mut *self.value as *mut T }
- }
-
- /// Extracts the value from the `MaybeUninit<T>` container. This is a great way
- /// to ensure that the data will get dropped, because the resulting `T` is
- /// subject to the usual drop handling.
- ///
- /// # Safety
- ///
- /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
- /// state. Calling this when the content is not yet fully initialized causes immediate undefined
- /// behavior. The [type-level documentation][inv] contains more information about
- /// this initialization invariant.
- ///
- /// [inv]: #initialization-invariant
- ///
- /// # Examples
- ///
- /// Correct usage of this method:
- ///
- /// ```rust
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<bool>::uninit();
- /// unsafe { x.as_mut_ptr().write(true); }
- /// let x_init = unsafe { x.assume_init() };
- /// assert_eq!(x_init, true);
- /// ```
- ///
- /// *Incorrect* usage of this method:
- ///
- /// ```rust,no_run
- /// use std::mem::MaybeUninit;
- ///
- /// let x = MaybeUninit::<Vec<u32>>::uninit();
- /// let x_init = unsafe { x.assume_init() };
- /// // `x` had not been initialized yet, so this last line caused undefined behavior.
- /// ```
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[inline(always)]
- pub unsafe fn assume_init(self) -> T {
- intrinsics::panic_if_uninhabited::<T>();
- ManuallyDrop::into_inner(self.value)
- }
-
- /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
- /// to the usual drop handling.
- ///
- /// Whenever possible, it is preferrable to use [`assume_init`] instead, which
- /// prevents duplicating the content of the `MaybeUninit<T>`.
- ///
- /// # Safety
- ///
- /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
- /// state. Calling this when the content is not yet fully initialized causes undefined
- /// behavior. The [type-level documentation][inv] contains more information about
- /// this initialization invariant.
- ///
- /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
- /// multiple copies of the data (by calling `read` multiple times, or first
- /// calling `read` and then [`assume_init`]), it is your responsibility
- /// to ensure that that data may indeed be duplicated.
- ///
- /// [inv]: #initialization-invariant
- /// [`assume_init`]: #method.assume_init
- ///
- /// # Examples
- ///
- /// Correct usage of this method:
- ///
- /// ```rust
- /// #![feature(maybe_uninit_extra)]
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<u32>::uninit();
- /// x.write(13);
- /// let x1 = unsafe { x.read() };
- /// // `u32` is `Copy`, so we may read multiple times.
- /// let x2 = unsafe { x.read() };
- /// assert_eq!(x1, x2);
- ///
- /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
- /// x.write(None);
- /// let x1 = unsafe { x.read() };
- /// // Duplicating a `None` value is okay, so we may read multiple times.
- /// let x2 = unsafe { x.read() };
- /// assert_eq!(x1, x2);
- /// ```
- ///
- /// *Incorrect* usage of this method:
- ///
- /// ```rust,no_run
- /// #![feature(maybe_uninit_extra)]
- /// use std::mem::MaybeUninit;
- ///
- /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
- /// x.write(Some(vec![0,1,2]));
- /// let x1 = unsafe { x.read() };
- /// let x2 = unsafe { x.read() };
- /// // We now created two copies of the same vector, leading to a double-free when
- /// // they both get dropped!
- /// ```
- #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
- #[inline(always)]
- pub unsafe fn read(&self) -> T {
- intrinsics::panic_if_uninhabited::<T>();
- self.as_ptr().read()
- }
-
- /// Gets a reference to the contained value.
- ///
- /// # Safety
- ///
- /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
- /// state. Calling this when the content is not yet fully initialized causes undefined
- /// behavior.
- #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
- #[inline(always)]
- pub unsafe fn get_ref(&self) -> &T {
- &*self.value
- }
-
- /// Gets a mutable reference to the contained value.
- ///
- /// # Safety
- ///
- /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
- /// state. Calling this when the content is not yet fully initialized causes undefined
- /// behavior.
- // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
- // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
- // a final decision about the rules before stabilization.
- #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
- #[inline(always)]
- pub unsafe fn get_mut(&mut self) -> &mut T {
- &mut *self.value
- }
-
- /// Gets a pointer to the first element of the array.
- #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
- #[inline(always)]
- pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
- this as *const [MaybeUninit<T>] as *const T
- }
-
- /// Gets a mutable pointer to the first element of the array.
- #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
- #[inline(always)]
- pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
- this as *mut [MaybeUninit<T>] as *mut T
- }
-}
--- /dev/null
+use crate::ptr;
+use crate::ops::{Deref, DerefMut};
+
+/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
+///
+/// This wrapper is 0-cost.
+///
+/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
+/// As a consequence, it has *no effect* on the assumptions that the compiler makes
+/// about all values being initialized at their type. In particular, initializing
+/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
+///
+/// # Examples
+///
+/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
+/// the type:
+///
+/// ```rust
+/// use std::mem::ManuallyDrop;
+/// struct Peach;
+/// struct Banana;
+/// struct Melon;
+/// struct FruitBox {
+/// // Immediately clear there’s something non-trivial going on with these fields.
+/// peach: ManuallyDrop<Peach>,
+/// melon: Melon, // Field that’s independent of the other two.
+/// banana: ManuallyDrop<Banana>,
+/// }
+///
+/// impl Drop for FruitBox {
+/// fn drop(&mut self) {
+/// unsafe {
+/// // Explicit ordering in which field destructors are run specified in the intuitive
+/// // location – the destructor of the structure containing the fields.
+/// // Moreover, one can now reorder fields within the struct however much they want.
+/// ManuallyDrop::drop(&mut self.peach);
+/// ManuallyDrop::drop(&mut self.banana);
+/// }
+/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
+/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
+/// }
+/// }
+/// ```
+///
+/// [`mem::zeroed`]: fn.zeroed.html
+/// [`MaybeUninit<T>`]: union.MaybeUninit.html
+#[stable(feature = "manually_drop", since = "1.20.0")]
+#[lang = "manually_drop"]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(transparent)]
+pub struct ManuallyDrop<T: ?Sized> {
+ value: T,
+}
+
+impl<T> ManuallyDrop<T> {
+ /// Wrap a value to be manually dropped.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::mem::ManuallyDrop;
+ /// ManuallyDrop::new(Box::new(()));
+ /// ```
+ #[stable(feature = "manually_drop", since = "1.20.0")]
+ #[inline(always)]
+ pub const fn new(value: T) -> ManuallyDrop<T> {
+ ManuallyDrop { value }
+ }
+
+ /// Extracts the value from the `ManuallyDrop` container.
+ ///
+ /// This allows the value to be dropped again.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::mem::ManuallyDrop;
+ /// let x = ManuallyDrop::new(Box::new(()));
+ /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
+ /// ```
+ #[stable(feature = "manually_drop", since = "1.20.0")]
+ #[inline(always)]
+ pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
+ slot.value
+ }
+
+ /// Takes the contained value out.
+ ///
+ /// This method is primarily intended for moving out values in drop.
+ /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
+ /// you can use this method to take the value and use it however desired.
+ /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
+ ///
+ /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
+ ///
+ /// # Safety
+ ///
+ /// This function semantically moves out the contained value without preventing further usage.
+ /// It is up to the user of this method to ensure that this container is not used again.
+ ///
+ /// [`ManuallyDrop::drop`]: #method.drop
+ /// [`ManuallyDrop::into_inner`]: #method.into_inner
+ #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
+ #[unstable(feature = "manually_drop_take", issue = "55422")]
+ #[inline]
+ pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
+ ManuallyDrop::into_inner(ptr::read(slot))
+ }
+}
+
+impl<T: ?Sized> ManuallyDrop<T> {
+ /// Manually drops the contained value.
+ ///
+ /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
+ ///
+ /// # Safety
+ ///
+ /// This function runs the destructor of the contained value and thus the wrapped value
+ /// now represents uninitialized data. It is up to the user of this method to ensure the
+ /// uninitialized data is not actually used.
+ ///
+ /// [`ManuallyDrop::into_inner`]: #method.into_inner
+ #[stable(feature = "manually_drop", since = "1.20.0")]
+ #[inline]
+ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
+ ptr::drop_in_place(&mut slot.value)
+ }
+}
+
+#[stable(feature = "manually_drop", since = "1.20.0")]
+impl<T: ?Sized> Deref for ManuallyDrop<T> {
+ type Target = T;
+ #[inline(always)]
+ fn deref(&self) -> &T {
+ &self.value
+ }
+}
+
+#[stable(feature = "manually_drop", since = "1.20.0")]
+impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
+ #[inline(always)]
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.value
+ }
+}
--- /dev/null
+use crate::intrinsics;
+use crate::mem::ManuallyDrop;
+
+/// A wrapper type to construct uninitialized instances of `T`.
+///
+/// # Initialization invariant
+///
+/// The compiler, in general, assumes that variables are properly initialized
+/// at their respective type. For example, a variable of reference type must
+/// be aligned and non-NULL. This is an invariant that must *always* be upheld,
+/// even in unsafe code. As a consequence, zero-initializing a variable of reference
+/// type causes instantaneous [undefined behavior][ub], no matter whether that reference
+/// ever gets used to access memory:
+///
+/// ```rust,no_run
+/// use std::mem::{self, MaybeUninit};
+///
+/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
+/// // The equivalent code with `MaybeUninit<&i32>`:
+/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
+/// ```
+///
+/// This is exploited by the compiler for various optimizations, such as eliding
+/// run-time checks and optimizing `enum` layout.
+///
+/// Similarly, entirely uninitialized memory may have any content, while a `bool` must
+/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
+///
+/// ```rust,no_run
+/// use std::mem::{self, MaybeUninit};
+///
+/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
+/// // The equivalent code with `MaybeUninit<bool>`:
+/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// ```
+///
+/// Moreover, uninitialized memory is special in that the compiler knows that
+/// it does not have a fixed value. This makes it undefined behavior to have
+/// uninitialized data in a variable even if that variable has an integer type,
+/// which otherwise can hold any *fixed* bit pattern:
+///
+/// ```rust,no_run
+/// use std::mem::{self, MaybeUninit};
+///
+/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
+/// // The equivalent code with `MaybeUninit<i32>`:
+/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
+/// ```
+/// (Notice that the rules around uninitialized integers are not finalized yet, but
+/// until they are, it is advisable to avoid them.)
+///
+/// On top of that, remember that most types have additional invariants beyond merely
+/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
+/// is considered initialized because the only requirement the compiler knows about it
+/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
+/// *immediate* undefined behavior, but will cause undefined behavior with most
+/// safe operations (including dropping it).
+///
+/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
+///
+/// # Examples
+///
+/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
+/// It is a signal to the compiler indicating that the data here might *not*
+/// be initialized:
+///
+/// ```rust
+/// use std::mem::MaybeUninit;
+///
+/// // Create an explicitly uninitialized reference. The compiler knows that data inside
+/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
+/// let mut x = MaybeUninit::<&i32>::uninit();
+/// // Set it to a valid value.
+/// unsafe { x.as_mut_ptr().write(&0); }
+/// // Extract the initialized data -- this is only allowed *after* properly
+/// // initializing `x`!
+/// let x = unsafe { x.assume_init() };
+/// ```
+///
+/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
+///
+/// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without
+/// any of the run-time tracking and without any of the safety checks.
+///
+/// ## out-pointers
+///
+/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data
+/// from a function, pass it a pointer to some (uninitialized) memory to put the
+/// result into. This can be useful when it is important for the caller to control
+/// how the memory the result is stored in gets allocated, and you want to avoid
+/// unnecessary moves.
+///
+/// ```
+/// use std::mem::MaybeUninit;
+///
+/// unsafe fn make_vec(out: *mut Vec<i32>) {
+/// // `write` does not drop the old contents, which is important.
+/// out.write(vec![1, 2, 3]);
+/// }
+///
+/// let mut v = MaybeUninit::uninit();
+/// unsafe { make_vec(v.as_mut_ptr()); }
+/// // Now we know `v` is initialized! This also makes sure the vector gets
+/// // properly dropped.
+/// let v = unsafe { v.assume_init() };
+/// assert_eq!(&v, &[1, 2, 3]);
+/// ```
+///
+/// ## Initializing an array element-by-element
+///
+/// `MaybeUninit<T>` can be used to initialize a large array element-by-element:
+///
+/// ```
+/// use std::mem::{self, MaybeUninit};
+/// use std::ptr;
+///
+/// let data = {
+/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
+/// // safe because the type we are claiming to have initialized here is a
+/// // bunch of `MaybeUninit`s, which do not require initialization.
+/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
+/// MaybeUninit::uninit().assume_init()
+/// };
+///
+/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
+/// // we have a memory leak, but there is no memory safety issue.
+/// for elem in &mut data[..] {
+/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
+/// }
+///
+/// // Everything is initialized. Transmute the array to the
+/// // initialized type.
+/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
+/// };
+///
+/// assert_eq!(&data[0], &[42]);
+/// ```
+///
+/// You can also work with partially initialized arrays, which could
+/// be found in low-level datastructures.
+///
+/// ```
+/// use std::mem::MaybeUninit;
+/// use std::ptr;
+///
+/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
+/// // safe because the type we are claiming to have initialized here is a
+/// // bunch of `MaybeUninit`s, which do not require initialization.
+/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
+/// // Count the number of elements we have assigned.
+/// let mut data_len: usize = 0;
+///
+/// for elem in &mut data[0..500] {
+/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); }
+/// data_len += 1;
+/// }
+///
+/// // For each item in the array, drop if we allocated it.
+/// for elem in &mut data[0..data_len] {
+/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
+/// }
+/// ```
+///
+/// ## Initializing a struct field-by-field
+///
+/// There is currently no supported way to create a raw pointer or reference
+/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
+/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
+/// to its fields.
+///
+/// [ub]: ../../reference/behavior-considered-undefined.html
+///
+/// # Layout
+///
+/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
+///
+/// ```rust
+/// use std::mem::{MaybeUninit, size_of, align_of};
+/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>());
+/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>());
+/// ```
+///
+/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same
+/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as
+/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit
+/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling
+/// optimizations, potentially resulting in a larger size:
+///
+/// ```rust
+/// # use std::mem::{MaybeUninit, size_of};
+/// assert_eq!(size_of::<Option<bool>>(), 1);
+/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
+/// ```
+#[allow(missing_debug_implementations)]
+#[stable(feature = "maybe_uninit", since = "1.36.0")]
+#[derive(Copy)]
+pub union MaybeUninit<T> {
+ uninit: (),
+ value: ManuallyDrop<T>,
+}
+
+#[stable(feature = "maybe_uninit", since = "1.36.0")]
+impl<T: Copy> Clone for MaybeUninit<T> {
+ #[inline(always)]
+ fn clone(&self) -> Self {
+ // Not calling `T::clone()`, we cannot know if we are initialized enough for that.
+ *self
+ }
+}
+
+impl<T> MaybeUninit<T> {
+ /// Creates a new `MaybeUninit<T>` initialized with the given value.
+ /// It is safe to call [`assume_init`] on the return value of this function.
+ ///
+ /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
+ /// It is your responsibility to make sure `T` gets dropped if it got initialized.
+ ///
+ /// [`assume_init`]: #method.assume_init
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline(always)]
+ pub const fn new(val: T) -> MaybeUninit<T> {
+ MaybeUninit { value: ManuallyDrop::new(val) }
+ }
+
+ /// Creates a new `MaybeUninit<T>` in an uninitialized state.
+ ///
+ /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
+ /// It is your responsibility to make sure `T` gets dropped if it got initialized.
+ ///
+ /// See the [type-level documentation][type] for some examples.
+ ///
+ /// [type]: union.MaybeUninit.html
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline(always)]
+ pub const fn uninit() -> MaybeUninit<T> {
+ MaybeUninit { uninit: () }
+ }
+
+ /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
+ /// filled with `0` bytes. It depends on `T` whether that already makes for
+ /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
+ /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
+ /// be null.
+ ///
+ /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
+ /// It is your responsibility to make sure `T` gets dropped if it got initialized.
+ ///
+ /// # Example
+ ///
+ /// Correct usage of this function: initializing a struct with zero, where all
+ /// fields of the struct can hold the bit-pattern 0 as a valid value.
+ ///
+ /// ```rust
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let x = MaybeUninit::<(u8, bool)>::zeroed();
+ /// let x = unsafe { x.assume_init() };
+ /// assert_eq!(x, (0, false));
+ /// ```
+ ///
+ /// *Incorrect* usage of this function: initializing a struct with zero, where some fields
+ /// cannot hold 0 as a valid value.
+ ///
+ /// ```rust,no_run
+ /// use std::mem::MaybeUninit;
+ ///
+ /// enum NotZero { One = 1, Two = 2 };
+ ///
+ /// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
+ /// let x = unsafe { x.assume_init() };
+ /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
+ /// // This is undefined behavior.
+ /// ```
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline]
+ pub fn zeroed() -> MaybeUninit<T> {
+ let mut u = MaybeUninit::<T>::uninit();
+ unsafe {
+ u.as_mut_ptr().write_bytes(0u8, 1);
+ }
+ u
+ }
+
+ /// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
+ /// without dropping it, so be careful not to use this twice unless you want to
+ /// skip running the destructor. For your convenience, this also returns a mutable
+ /// reference to the (now safely initialized) contents of `self`.
+ #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
+ #[inline(always)]
+ pub fn write(&mut self, val: T) -> &mut T {
+ unsafe {
+ self.value = ManuallyDrop::new(val);
+ self.get_mut()
+ }
+ }
+
+ /// Gets a pointer to the contained value. Reading from this pointer or turning it
+ /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
+ /// Writing to memory that this pointer (non-transitively) points to is undefined behavior
+ /// (except inside an `UnsafeCell<T>`).
+ ///
+ /// # Examples
+ ///
+ /// Correct usage of this method:
+ ///
+ /// ```rust
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
+ /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
+ /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
+ /// let x_vec = unsafe { &*x.as_ptr() };
+ /// assert_eq!(x_vec.len(), 3);
+ /// ```
+ ///
+ /// *Incorrect* usage of this method:
+ ///
+ /// ```rust,no_run
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let x = MaybeUninit::<Vec<u32>>::uninit();
+ /// let x_vec = unsafe { &*x.as_ptr() };
+ /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+ /// ```
+ ///
+ /// (Notice that the rules around references to uninitialized data are not finalized yet, but
+ /// until they are, it is advisable to avoid them.)
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline(always)]
+ pub fn as_ptr(&self) -> *const T {
+ unsafe { &*self.value as *const T }
+ }
+
+ /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
+ /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
+ ///
+ /// # Examples
+ ///
+ /// Correct usage of this method:
+ ///
+ /// ```rust
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
+ /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
+ /// // Create a reference into the `MaybeUninit<Vec<u32>>`.
+ /// // This is okay because we initialized it.
+ /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
+ /// x_vec.push(3);
+ /// assert_eq!(x_vec.len(), 4);
+ /// ```
+ ///
+ /// *Incorrect* usage of this method:
+ ///
+ /// ```rust,no_run
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
+ /// let x_vec = unsafe { &mut *x.as_mut_ptr() };
+ /// // We have created a reference to an uninitialized vector! This is undefined behavior.
+ /// ```
+ ///
+ /// (Notice that the rules around references to uninitialized data are not finalized yet, but
+ /// until they are, it is advisable to avoid them.)
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline(always)]
+ pub fn as_mut_ptr(&mut self) -> *mut T {
+ unsafe { &mut *self.value as *mut T }
+ }
+
+ /// Extracts the value from the `MaybeUninit<T>` container. This is a great way
+ /// to ensure that the data will get dropped, because the resulting `T` is
+ /// subject to the usual drop handling.
+ ///
+ /// # Safety
+ ///
+ /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
+ /// state. Calling this when the content is not yet fully initialized causes immediate undefined
+ /// behavior. The [type-level documentation][inv] contains more information about
+ /// this initialization invariant.
+ ///
+ /// [inv]: #initialization-invariant
+ ///
+ /// # Examples
+ ///
+ /// Correct usage of this method:
+ ///
+ /// ```rust
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<bool>::uninit();
+ /// unsafe { x.as_mut_ptr().write(true); }
+ /// let x_init = unsafe { x.assume_init() };
+ /// assert_eq!(x_init, true);
+ /// ```
+ ///
+ /// *Incorrect* usage of this method:
+ ///
+ /// ```rust,no_run
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let x = MaybeUninit::<Vec<u32>>::uninit();
+ /// let x_init = unsafe { x.assume_init() };
+ /// // `x` had not been initialized yet, so this last line caused undefined behavior.
+ /// ```
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ #[inline(always)]
+ pub unsafe fn assume_init(self) -> T {
+ intrinsics::panic_if_uninhabited::<T>();
+ ManuallyDrop::into_inner(self.value)
+ }
+
+ /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
+ /// to the usual drop handling.
+ ///
+ /// Whenever possible, it is preferrable to use [`assume_init`] instead, which
+ /// prevents duplicating the content of the `MaybeUninit<T>`.
+ ///
+ /// # Safety
+ ///
+ /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
+ /// state. Calling this when the content is not yet fully initialized causes undefined
+ /// behavior. The [type-level documentation][inv] contains more information about
+ /// this initialization invariant.
+ ///
+ /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
+ /// multiple copies of the data (by calling `read` multiple times, or first
+ /// calling `read` and then [`assume_init`]), it is your responsibility
+ /// to ensure that that data may indeed be duplicated.
+ ///
+ /// [inv]: #initialization-invariant
+ /// [`assume_init`]: #method.assume_init
+ ///
+ /// # Examples
+ ///
+ /// Correct usage of this method:
+ ///
+ /// ```rust
+ /// #![feature(maybe_uninit_extra)]
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<u32>::uninit();
+ /// x.write(13);
+ /// let x1 = unsafe { x.read() };
+ /// // `u32` is `Copy`, so we may read multiple times.
+ /// let x2 = unsafe { x.read() };
+ /// assert_eq!(x1, x2);
+ ///
+ /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
+ /// x.write(None);
+ /// let x1 = unsafe { x.read() };
+ /// // Duplicating a `None` value is okay, so we may read multiple times.
+ /// let x2 = unsafe { x.read() };
+ /// assert_eq!(x1, x2);
+ /// ```
+ ///
+ /// *Incorrect* usage of this method:
+ ///
+ /// ```rust,no_run
+ /// #![feature(maybe_uninit_extra)]
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
+ /// x.write(Some(vec![0,1,2]));
+ /// let x1 = unsafe { x.read() };
+ /// let x2 = unsafe { x.read() };
+ /// // We now created two copies of the same vector, leading to a double-free when
+ /// // they both get dropped!
+ /// ```
+ #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
+ #[inline(always)]
+ pub unsafe fn read(&self) -> T {
+ intrinsics::panic_if_uninhabited::<T>();
+ self.as_ptr().read()
+ }
+
+ /// Gets a reference to the contained value.
+ ///
+ /// # Safety
+ ///
+ /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
+ /// state. Calling this when the content is not yet fully initialized causes undefined
+ /// behavior.
+ #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
+ #[inline(always)]
+ pub unsafe fn get_ref(&self) -> &T {
+ &*self.value
+ }
+
+ /// Gets a mutable reference to the contained value.
+ ///
+ /// # Safety
+ ///
+ /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
+ /// state. Calling this when the content is not yet fully initialized causes undefined
+ /// behavior.
+ // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
+ // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
+ // a final decision about the rules before stabilization.
+ #[unstable(feature = "maybe_uninit_ref", issue = "53491")]
+ #[inline(always)]
+ pub unsafe fn get_mut(&mut self) -> &mut T {
+ &mut *self.value
+ }
+
+ /// Gets a pointer to the first element of the array.
+ #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
+ #[inline(always)]
+ pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
+ this as *const [MaybeUninit<T>] as *const T
+ }
+
+ /// Gets a mutable pointer to the first element of the array.
+ #[unstable(feature = "maybe_uninit_slice", issue = "53491")]
+ #[inline(always)]
+ pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
+ this as *mut [MaybeUninit<T>] as *mut T
+ }
+}
--- /dev/null
+//! Basic functions for dealing with memory.
+//!
+//! This module contains functions for querying the size and alignment of
+//! types, initializing and manipulating memory.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use crate::clone;
+use crate::cmp;
+use crate::fmt;
+use crate::hash;
+use crate::intrinsics;
+use crate::marker::{Copy, PhantomData, Sized};
+use crate::ptr;
+
+mod manually_drop;
+#[stable(feature = "manually_drop", since = "1.20.0")]
+pub use manually_drop::ManuallyDrop;
+
+mod maybe_uninit;
+#[stable(feature = "maybe_uninit", since = "1.36.0")]
+pub use maybe_uninit::MaybeUninit;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
+pub use crate::intrinsics::transmute;
+
+/// Takes ownership and "forgets" about the value **without running its destructor**.
+///
+/// Any resources the value manages, such as heap memory or a file handle, will linger
+/// forever in an unreachable state. However, it does not guarantee that pointers
+/// to this memory will remain valid.
+///
+/// * If you want to leak memory, see [`Box::leak`][leak].
+/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
+/// * If you want to dispose of a value properly, running its destructor, see
+/// [`mem::drop`][drop].
+///
+/// # Safety
+///
+/// `forget` is not marked as `unsafe`, because Rust's safety guarantees
+/// do not include a guarantee that destructors will always run. For example,
+/// a program can create a reference cycle using [`Rc`][rc], or call
+/// [`process::exit`][exit] to exit without running destructors. Thus, allowing
+/// `mem::forget` from safe code does not fundamentally change Rust's safety
+/// guarantees.
+///
+/// That said, leaking resources such as memory or I/O objects is usually undesirable,
+/// so `forget` is only recommended for specialized use cases like those shown below.
+///
+/// Because forgetting a value is allowed, any `unsafe` code you write must
+/// allow for this possibility. You cannot return a value and expect that the
+/// caller will necessarily run the value's destructor.
+///
+/// [rc]: ../../std/rc/struct.Rc.html
+/// [exit]: ../../std/process/fn.exit.html
+///
+/// # Examples
+///
+/// Leak an I/O object, never closing the file:
+///
+/// ```no_run
+/// use std::mem;
+/// use std::fs::File;
+///
+/// let file = File::open("foo.txt").unwrap();
+/// mem::forget(file);
+/// ```
+///
+/// The practical use cases for `forget` are rather specialized and mainly come
+/// up in unsafe or FFI code.
+///
+/// [drop]: fn.drop.html
+/// [uninit]: fn.uninitialized.html
+/// [clone]: ../clone/trait.Clone.html
+/// [swap]: fn.swap.html
+/// [box]: ../../std/boxed/struct.Box.html
+/// [leak]: ../../std/boxed/struct.Box.html#method.leak
+/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
+/// [ub]: ../../reference/behavior-considered-undefined.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn forget<T>(t: T) {
+ ManuallyDrop::new(t);
+}
+
+/// Like [`forget`], but also accepts unsized values.
+///
+/// This function is just a shim intended to be removed when the `unsized_locals` feature gets
+/// stabilized.
+///
+/// [`forget`]: fn.forget.html
+#[inline]
+#[unstable(feature = "forget_unsized", issue = "0")]
+pub fn forget_unsized<T: ?Sized>(t: T) {
+ unsafe { intrinsics::forget(t) }
+}
+
+/// Returns the size of a type in bytes.
+///
+/// More specifically, this is the offset in bytes between successive elements
+/// in an array with that item type including alignment padding. Thus, for any
+/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`.
+///
+/// In general, the size of a type is not stable across compilations, but
+/// specific types such as primitives are.
+///
+/// The following table gives the size for primitives.
+///
+/// Type | size_of::\<Type>()
+/// ---- | ---------------
+/// () | 0
+/// bool | 1
+/// u8 | 1
+/// u16 | 2
+/// u32 | 4
+/// u64 | 8
+/// u128 | 16
+/// i8 | 1
+/// i16 | 2
+/// i32 | 4
+/// i64 | 8
+/// i128 | 16
+/// f32 | 4
+/// f64 | 8
+/// char | 4
+///
+/// Furthermore, `usize` and `isize` have the same size.
+///
+/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have
+/// the same size. If `T` is Sized, all of those types have the same size as `usize`.
+///
+/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
+/// have the same size. Likewise for `*const T` and `*mut T`.
+///
+/// # Size of `#[repr(C)]` items
+///
+/// The `C` representation for items has a defined layout. With this layout,
+/// the size of items is also stable as long as all fields have a stable size.
+///
+/// ## Size of Structs
+///
+/// For `structs`, the size is determined by the following algorithm.
+///
+/// For each field in the struct ordered by declaration order:
+///
+/// 1. Add the size of the field.
+/// 2. Round up the current size to the nearest multiple of the next field's [alignment].
+///
+/// Finally, round the size of the struct to the nearest multiple of its [alignment].
+/// The alignment of the struct is usually the largest alignment of all its
+/// fields; this can be changed with the use of `repr(align(N))`.
+///
+/// Unlike `C`, zero sized structs are not rounded up to one byte in size.
+///
+/// ## Size of Enums
+///
+/// Enums that carry no data other than the discriminant have the same size as C enums
+/// on the platform they are compiled for.
+///
+/// ## Size of Unions
+///
+/// The size of a union is the size of its largest field.
+///
+/// Unlike `C`, zero sized unions are not rounded up to one byte in size.
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// // Some primitives
+/// assert_eq!(4, mem::size_of::<i32>());
+/// assert_eq!(8, mem::size_of::<f64>());
+/// assert_eq!(0, mem::size_of::<()>());
+///
+/// // Some arrays
+/// assert_eq!(8, mem::size_of::<[i32; 2]>());
+/// assert_eq!(12, mem::size_of::<[i32; 3]>());
+/// assert_eq!(0, mem::size_of::<[i32; 0]>());
+///
+///
+/// // Pointer size equality
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>());
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>());
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
+/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
+/// ```
+///
+/// Using `#[repr(C)]`.
+///
+/// ```
+/// use std::mem;
+///
+/// #[repr(C)]
+/// struct FieldStruct {
+/// first: u8,
+/// second: u16,
+/// third: u8
+/// }
+///
+/// // The size of the first field is 1, so add 1 to the size. Size is 1.
+/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
+/// // The size of the second field is 2, so add 2 to the size. Size is 4.
+/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
+/// // The size of the third field is 1, so add 1 to the size. Size is 5.
+/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its
+/// // fields is 2), so add 1 to the size for padding. Size is 6.
+/// assert_eq!(6, mem::size_of::<FieldStruct>());
+///
+/// #[repr(C)]
+/// struct TupleStruct(u8, u16, u8);
+///
+/// // Tuple structs follow the same rules.
+/// assert_eq!(6, mem::size_of::<TupleStruct>());
+///
+/// // Note that reordering the fields can lower the size. We can remove both padding bytes
+/// // by putting `third` before `second`.
+/// #[repr(C)]
+/// struct FieldStructOptimized {
+/// first: u8,
+/// third: u8,
+/// second: u16
+/// }
+///
+/// assert_eq!(4, mem::size_of::<FieldStructOptimized>());
+///
+/// // Union size is the size of the largest field.
+/// #[repr(C)]
+/// union ExampleUnion {
+/// smaller: u8,
+/// larger: u16
+/// }
+///
+/// assert_eq!(2, mem::size_of::<ExampleUnion>());
+/// ```
+///
+/// [alignment]: ./fn.align_of.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+pub const fn size_of<T>() -> usize {
+ intrinsics::size_of::<T>()
+}
+
+/// Returns the size of the pointed-to value in bytes.
+///
+/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no
+/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object],
+/// then `size_of_val` can be used to get the dynamically-known size.
+///
+/// [slice]: ../../std/primitive.slice.html
+/// [trait object]: ../../book/ch17-02-trait-objects.html
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// assert_eq!(4, mem::size_of_val(&5i32));
+///
+/// let x: [u8; 13] = [0; 13];
+/// let y: &[u8] = &x;
+/// assert_eq!(13, mem::size_of_val(y));
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
+ unsafe { intrinsics::size_of_val(val) }
+}
+
+/// Returns the [ABI]-required minimum alignment of a type.
+///
+/// Every reference to a value of the type `T` must be a multiple of this number.
+///
+/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
+///
+/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
+///
+/// # Examples
+///
+/// ```
+/// # #![allow(deprecated)]
+/// use std::mem;
+///
+/// assert_eq!(4, mem::min_align_of::<i32>());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")]
+pub fn min_align_of<T>() -> usize {
+ intrinsics::min_align_of::<T>()
+}
+
+/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
+///
+/// Every reference to a value of the type `T` must be a multiple of this number.
+///
+/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
+///
+/// # Examples
+///
+/// ```
+/// # #![allow(deprecated)]
+/// use std::mem;
+///
+/// assert_eq!(4, mem::min_align_of_val(&5i32));
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
+pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
+ unsafe { intrinsics::min_align_of_val(val) }
+}
+
+/// Returns the [ABI]-required minimum alignment of a type.
+///
+/// Every reference to a value of the type `T` must be a multiple of this number.
+///
+/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
+///
+/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// assert_eq!(4, mem::align_of::<i32>());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+pub const fn align_of<T>() -> usize {
+ intrinsics::min_align_of::<T>()
+}
+
+/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
+///
+/// Every reference to a value of the type `T` must be a multiple of this number.
+///
+/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// assert_eq!(4, mem::align_of_val(&5i32));
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
+ unsafe { intrinsics::min_align_of_val(val) }
+}
+
+/// Returns `true` if dropping values of type `T` matters.
+///
+/// This is purely an optimization hint, and may be implemented conservatively:
+/// it may return `true` for types that don't actually need to be dropped.
+/// As such always returning `true` would be a valid implementation of
+/// this function. However if this function actually returns `false`, then you
+/// can be certain dropping `T` has no side effect.
+///
+/// Low level implementations of things like collections, which need to manually
+/// drop their data, should use this function to avoid unnecessarily
+/// trying to drop all their contents when they are destroyed. This might not
+/// make a difference in release builds (where a loop that has no side-effects
+/// is easily detected and eliminated), but is often a big win for debug builds.
+///
+/// Note that `ptr::drop_in_place` already performs this check, so if your workload
+/// can be reduced to some small number of drop_in_place calls, using this is
+/// unnecessary. In particular note that you can drop_in_place a slice, and that
+/// will do a single needs_drop check for all the values.
+///
+/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
+/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
+/// values one at a time and should use this API.
+///
+///
+/// # Examples
+///
+/// Here's an example of how a collection might make use of needs_drop:
+///
+/// ```
+/// use std::{mem, ptr};
+///
+/// pub struct MyCollection<T> {
+/// # data: [T; 1],
+/// /* ... */
+/// }
+/// # impl<T> MyCollection<T> {
+/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data }
+/// # fn free_buffer(&mut self) {}
+/// # }
+///
+/// impl<T> Drop for MyCollection<T> {
+/// fn drop(&mut self) {
+/// unsafe {
+/// // drop the data
+/// if mem::needs_drop::<T>() {
+/// for x in self.iter_mut() {
+/// ptr::drop_in_place(x);
+/// }
+/// }
+/// self.free_buffer();
+/// }
+/// }
+/// }
+/// ```
+#[inline]
+#[stable(feature = "needs_drop", since = "1.21.0")]
+pub const fn needs_drop<T>() -> bool {
+ intrinsics::needs_drop::<T>()
+}
+
+/// Creates a value whose bytes are all zero.
+///
+/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
+/// It is useful for FFI sometimes, but should generally be avoided.
+///
+/// There is no guarantee that an all-zero byte-pattern represents a valid value of
+/// some type `T`. For example, the all-zero byte-pattern is not a valid value
+/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
+/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
+/// that there always is a valid value in a variable it considers initialized.
+///
+/// [zeroed]: union.MaybeUninit.html#method.zeroed
+/// [ub]: ../../reference/behavior-considered-undefined.html
+/// [inv]: union.MaybeUninit.html#initialization-invariant
+///
+/// # Examples
+///
+/// Correct usage of this function: initializing an integer with zero.
+///
+/// ```
+/// use std::mem;
+///
+/// let x: i32 = unsafe { mem::zeroed() };
+/// assert_eq!(0, x);
+/// ```
+///
+/// *Incorrect* usage of this function: initializing a reference with zero.
+///
+/// ```no_run
+/// use std::mem;
+///
+/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn zeroed<T>() -> T {
+ intrinsics::panic_if_uninhabited::<T>();
+ intrinsics::init()
+}
+
+/// Bypasses Rust's normal memory-initialization checks by pretending to
+/// produce a value of type `T`, while doing nothing at all.
+///
+/// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead.
+///
+/// The reason for deprecation is that the function basically cannot be used
+/// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
+/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
+/// undefined behavior for returning a `bool` that is not definitely either `true`
+/// or `false`. Worse, truly uninitialized memory like what gets returned here
+/// is special in that the compiler knows that it does not have a fixed value.
+/// This makes it undefined behavior to have uninitialized data in a variable even
+/// if that variable has an integer type.
+/// (Notice that the rules around uninitialized integers are not finalized yet, but
+/// until they are, it is advisable to avoid them.)
+///
+/// [`MaybeUninit<T>`]: union.MaybeUninit.html
+/// [inv]: union.MaybeUninit.html#initialization-invariant
+#[inline]
+#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn uninitialized<T>() -> T {
+ intrinsics::panic_if_uninhabited::<T>();
+ intrinsics::uninit()
+}
+
+/// Swaps the values at two mutable locations, without deinitializing either one.
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// let mut x = 5;
+/// let mut y = 42;
+///
+/// mem::swap(&mut x, &mut y);
+///
+/// assert_eq!(42, x);
+/// assert_eq!(5, y);
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn swap<T>(x: &mut T, y: &mut T) {
+ unsafe {
+ ptr::swap_nonoverlapping_one(x, y);
+ }
+}
+
+/// Moves `src` into the referenced `dest`, returning the previous `dest` value.
+///
+/// Neither value is dropped.
+///
+/// # Examples
+///
+/// A simple example:
+///
+/// ```
+/// use std::mem;
+///
+/// let mut v: Vec<i32> = vec![1, 2];
+///
+/// let old_v = mem::replace(&mut v, vec![3, 4, 5]);
+/// assert_eq!(vec![1, 2], old_v);
+/// assert_eq!(vec![3, 4, 5], v);
+/// ```
+///
+/// `replace` allows consumption of a struct field by replacing it with another value.
+/// Without `replace` you can run into issues like these:
+///
+/// ```compile_fail,E0507
+/// struct Buffer<T> { buf: Vec<T> }
+///
+/// impl<T> Buffer<T> {
+/// fn get_and_reset(&mut self) -> Vec<T> {
+/// // error: cannot move out of dereference of `&mut`-pointer
+/// let buf = self.buf;
+/// self.buf = Vec::new();
+/// buf
+/// }
+/// }
+/// ```
+///
+/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
+/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
+/// `self`, allowing it to be returned:
+///
+/// ```
+/// # #![allow(dead_code)]
+/// use std::mem;
+///
+/// # struct Buffer<T> { buf: Vec<T> }
+/// impl<T> Buffer<T> {
+/// fn get_and_reset(&mut self) -> Vec<T> {
+/// mem::replace(&mut self.buf, Vec::new())
+/// }
+/// }
+/// ```
+///
+/// [`Clone`]: ../../std/clone/trait.Clone.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+ swap(dest, &mut src);
+ src
+}
+
+/// Disposes of a value.
+///
+/// This does call the argument's implementation of [`Drop`][drop].
+///
+/// This effectively does nothing for types which implement `Copy`, e.g.
+/// integers. Such values are copied and _then_ moved into the function, so the
+/// value persists after this function call.
+///
+/// This function is not magic; it is literally defined as
+///
+/// ```
+/// pub fn drop<T>(_x: T) { }
+/// ```
+///
+/// Because `_x` is moved into the function, it is automatically dropped before
+/// the function returns.
+///
+/// [drop]: ../ops/trait.Drop.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let v = vec![1, 2, 3];
+///
+/// drop(v); // explicitly drop the vector
+/// ```
+///
+/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can
+/// release a [`RefCell`] borrow:
+///
+/// ```
+/// use std::cell::RefCell;
+///
+/// let x = RefCell::new(1);
+///
+/// let mut mutable_borrow = x.borrow_mut();
+/// *mutable_borrow = 1;
+///
+/// drop(mutable_borrow); // relinquish the mutable borrow on this slot
+///
+/// let borrow = x.borrow();
+/// println!("{}", *borrow);
+/// ```
+///
+/// Integers and other types implementing [`Copy`] are unaffected by `drop`.
+///
+/// ```
+/// #[derive(Copy, Clone)]
+/// struct Foo(u8);
+///
+/// let x = 1;
+/// let y = Foo(2);
+/// drop(x); // a copy of `x` is moved and dropped
+/// drop(y); // a copy of `y` is moved and dropped
+///
+/// println!("x: {}, y: {}", x, y.0); // still available
+/// ```
+///
+/// [`RefCell`]: ../../std/cell/struct.RefCell.html
+/// [`Copy`]: ../../std/marker/trait.Copy.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn drop<T>(_x: T) { }
+
+/// Interprets `src` as having type `&U`, and then reads `src` without moving
+/// the contained value.
+///
+/// This function will unsafely assume the pointer `src` is valid for
+/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
+/// the `&U`. It will also unsafely create a copy of the contained value instead of
+/// moving out of `src`.
+///
+/// It is not a compile-time error if `T` and `U` have different sizes, but it
+/// is highly encouraged to only invoke this function where `T` and `U` have the
+/// same size. This function triggers [undefined behavior][ub] if `U` is larger than
+/// `T`.
+///
+/// [ub]: ../../reference/behavior-considered-undefined.html
+/// [size_of]: fn.size_of.html
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+///
+/// #[repr(packed)]
+/// struct Foo {
+/// bar: u8,
+/// }
+///
+/// let foo_slice = [10u8];
+///
+/// unsafe {
+/// // Copy the data from 'foo_slice' and treat it as a 'Foo'
+/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice);
+/// assert_eq!(foo_struct.bar, 10);
+///
+/// // Modify the copied data
+/// foo_struct.bar = 20;
+/// assert_eq!(foo_struct.bar, 20);
+/// }
+///
+/// // The contents of 'foo_slice' should not have changed
+/// assert_eq!(foo_slice, [10]);
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+ ptr::read_unaligned(src as *const T as *const U)
+}
+
+/// Opaque type representing the discriminant of an enum.
+///
+/// See the [`discriminant`] function in this module for more information.
+///
+/// [`discriminant`]: fn.discriminant.html
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+pub struct Discriminant<T>(u64, PhantomData<fn() -> T>);
+
+// N.B. These trait implementations cannot be derived because we don't want any bounds on T.
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> Copy for Discriminant<T> {}
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> clone::Clone for Discriminant<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> cmp::PartialEq for Discriminant<T> {
+ fn eq(&self, rhs: &Self) -> bool {
+ self.0 == rhs.0
+ }
+}
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> cmp::Eq for Discriminant<T> {}
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> hash::Hash for Discriminant<T> {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+}
+
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+impl<T> fmt::Debug for Discriminant<T> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt.debug_tuple("Discriminant")
+ .field(&self.0)
+ .finish()
+ }
+}
+
+/// Returns a value uniquely identifying the enum variant in `v`.
+///
+/// If `T` is not an enum, calling this function will not result in undefined behavior, but the
+/// return value is unspecified.
+///
+/// # Stability
+///
+/// The discriminant of an enum variant may change if the enum definition changes. A discriminant
+/// of some variant will not change between compilations with the same compiler.
+///
+/// # Examples
+///
+/// This can be used to compare enums that carry data, while disregarding
+/// the actual data:
+///
+/// ```
+/// use std::mem;
+///
+/// enum Foo { A(&'static str), B(i32), C(i32) }
+///
+/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz")));
+/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2)));
+/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3)));
+/// ```
+#[stable(feature = "discriminant_value", since = "1.21.0")]
+pub fn discriminant<T>(v: &T) -> Discriminant<T> {
+ unsafe {
+ Discriminant(intrinsics::discriminant_value(v), PhantomData)
+ }
+}
+++ /dev/null
-// ignore-tidy-filelength
-
-//! Manually manage memory through raw pointers.
-//!
-//! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
-//!
-//! # Safety
-//!
-//! Many functions in this module take raw pointers as arguments and read from
-//! or write to them. For this to be safe, these pointers must be *valid*.
-//! Whether a pointer is valid depends on the operation it is used for
-//! (read or write), and the extent of the memory that is accessed (i.e.,
-//! how many bytes are read/written). Most functions use `*mut T` and `*const T`
-//! to access only a single value, in which case the documentation omits the size
-//! and implicitly assumes it to be `size_of::<T>()` bytes.
-//!
-//! The precise rules for validity are not determined yet. The guarantees that are
-//! provided at this point are very minimal:
-//!
-//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
-//! * All pointers (except for the null pointer) are valid for all operations of
-//! [size zero][zst].
-//! * All accesses performed by functions in this module are *non-atomic* in the sense
-//! of [atomic operations] used to synchronize between threads. This means it is
-//! undefined behavior to perform two concurrent accesses to the same location from different
-//! threads unless both accesses only read from memory. Notice that this explicitly
-//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
-//! be used for inter-thread synchronization.
-//! * The result of casting a reference to a pointer is valid for as long as the
-//! underlying object is live and no reference (just raw pointers) is used to
-//! access the same memory.
-//!
-//! These axioms, along with careful use of [`offset`] for pointer arithmetic,
-//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees
-//! will be provided eventually, as the [aliasing] rules are being determined. For more
-//! information, see the [book] as well as the section in the reference devoted
-//! to [undefined behavior][ub].
-//!
-//! ## Alignment
-//!
-//! Valid raw pointers as defined above are not necessarily properly aligned (where
-//! "proper" alignment is defined by the pointee type, i.e., `*const T` must be
-//! aligned to `mem::align_of::<T>()`). However, most functions require their
-//! arguments to be properly aligned, and will explicitly state
-//! this requirement in their documentation. Notable exceptions to this are
-//! [`read_unaligned`] and [`write_unaligned`].
-//!
-//! When a function requires proper alignment, it does so even if the access
-//! has size 0, i.e., even if memory is not actually touched. Consider using
-//! [`NonNull::dangling`] in such cases.
-//!
-//! [aliasing]: ../../nomicon/aliasing.html
-//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
-//! [ub]: ../../reference/behavior-considered-undefined.html
-//! [null]: ./fn.null.html
-//! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts
-//! [atomic operations]: ../../std/sync/atomic/index.html
-//! [`copy`]: ../../std/ptr/fn.copy.html
-//! [`offset`]: ../../std/primitive.pointer.html#method.offset
-//! [`read_unaligned`]: ./fn.read_unaligned.html
-//! [`write_unaligned`]: ./fn.write_unaligned.html
-//! [`read_volatile`]: ./fn.read_volatile.html
-//! [`write_volatile`]: ./fn.write_volatile.html
-//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use crate::convert::From;
-use crate::intrinsics;
-use crate::ops::{CoerceUnsized, DispatchFromDyn};
-use crate::fmt;
-use crate::hash;
-use crate::marker::{PhantomData, Unsize};
-use crate::mem::{self, MaybeUninit};
-
-use crate::cmp::Ordering::{self, Less, Equal, Greater};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::intrinsics::copy_nonoverlapping;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::intrinsics::copy;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::intrinsics::write_bytes;
-
-/// Executes the destructor (if any) of the pointed-to value.
-///
-/// This is semantically equivalent to calling [`ptr::read`] and discarding
-/// the result, but has the following advantages:
-///
-/// * It is *required* to use `drop_in_place` to drop unsized types like
-/// trait objects, because they can't be read out onto the stack and
-/// dropped normally.
-///
-/// * It is friendlier to the optimizer to do this over [`ptr::read`] when
-/// dropping manually allocated memory (e.g., when writing Box/Rc/Vec),
-/// as the compiler doesn't need to prove that it's sound to elide the
-/// copy.
-///
-/// [`ptr::read`]: ../ptr/fn.read.html
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `to_drop` must be [valid] for reads.
-///
-/// * `to_drop` must be properly aligned. See the example below for how to drop
-/// an unaligned pointer.
-///
-/// Additionally, if `T` is not [`Copy`], using the pointed-to value after
-/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
-/// foo` counts as a use because it will cause the value to be dropped
-/// again. [`write`] can be used to overwrite data without causing it to be
-/// dropped.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`write`]: ../ptr/fn.write.html
-///
-/// # Examples
-///
-/// Manually remove the last item from a vector:
-///
-/// ```
-/// use std::ptr;
-/// use std::rc::Rc;
-///
-/// let last = Rc::new(1);
-/// let weak = Rc::downgrade(&last);
-///
-/// let mut v = vec![Rc::new(0), last];
-///
-/// unsafe {
-/// // Get a raw pointer to the last element in `v`.
-/// let ptr = &mut v[1] as *mut _;
-/// // Shorten `v` to prevent the last item from being dropped. We do that first,
-/// // to prevent issues if the `drop_in_place` below panics.
-/// v.set_len(1);
-/// // Without a call `drop_in_place`, the last item would never be dropped,
-/// // and the memory it manages would be leaked.
-/// ptr::drop_in_place(ptr);
-/// }
-///
-/// assert_eq!(v, &[0.into()]);
-///
-/// // Ensure that the last item was dropped.
-/// assert!(weak.upgrade().is_none());
-/// ```
-///
-/// Unaligned values cannot be dropped in place, they must be copied to an aligned
-/// location first:
-/// ```
-/// use std::ptr;
-/// use std::mem::{self, MaybeUninit};
-///
-/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
-/// let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
-/// ptr::copy(to_drop, copy.as_mut_ptr(), 1);
-/// drop(copy.assume_init());
-/// }
-///
-/// #[repr(packed, C)]
-/// struct Packed {
-/// _padding: u8,
-/// unaligned: Vec<i32>,
-/// }
-///
-/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
-/// unsafe {
-/// drop_after_copy(&mut p.unaligned as *mut _);
-/// mem::forget(p);
-/// }
-/// ```
-///
-/// Notice that the compiler performs this copy automatically when dropping packed structs,
-/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
-/// manually.
-#[stable(feature = "drop_in_place", since = "1.8.0")]
-#[inline(always)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
- real_drop_in_place(&mut *to_drop)
-}
-
-// The real `drop_in_place` -- the one that gets called implicitly when variables go
-// out of scope -- should have a safe reference and not a raw pointer as argument
-// type. When we drop a local variable, we access it with a pointer that behaves
-// like a safe reference; transmuting that to a raw pointer does not mean we can
-// actually access it with raw pointers.
-#[lang = "drop_in_place"]
-#[allow(unconditional_recursion)]
-unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
- // Code here does not matter - this is replaced by the
- // real drop glue by the compiler.
- real_drop_in_place(to_drop)
-}
-
-/// Creates a null raw pointer.
-///
-/// # Examples
-///
-/// ```
-/// use std::ptr;
-///
-/// let p: *const i32 = ptr::null();
-/// assert!(p.is_null());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_promotable]
-pub const fn null<T>() -> *const T { 0 as *const T }
-
-/// Creates a null mutable raw pointer.
-///
-/// # Examples
-///
-/// ```
-/// use std::ptr;
-///
-/// let p: *mut i32 = ptr::null_mut();
-/// assert!(p.is_null());
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_promotable]
-pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
-
-/// Swaps the values at two mutable locations of the same type, without
-/// deinitializing either.
-///
-/// But for the following two exceptions, this function is semantically
-/// equivalent to [`mem::swap`]:
-///
-/// * It operates on raw pointers instead of references. When references are
-/// available, [`mem::swap`] should be preferred.
-///
-/// * The two pointed-to values may overlap. If the values do overlap, then the
-/// overlapping region of memory from `x` will be used. This is demonstrated
-/// in the second example below.
-///
-/// [`mem::swap`]: ../mem/fn.swap.html
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * Both `x` and `y` must be [valid] for reads and writes.
-///
-/// * Both `x` and `y` must be properly aligned.
-///
-/// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-///
-/// # Examples
-///
-/// Swapping two non-overlapping regions:
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut array = [0, 1, 2, 3];
-///
-/// let x = array[0..].as_mut_ptr() as *mut [u32; 2]; // this is `array[0..2]`
-/// let y = array[2..].as_mut_ptr() as *mut [u32; 2]; // this is `array[2..4]`
-///
-/// unsafe {
-/// ptr::swap(x, y);
-/// assert_eq!([2, 3, 0, 1], array);
-/// }
-/// ```
-///
-/// Swapping two overlapping regions:
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut array = [0, 1, 2, 3];
-///
-/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]`
-/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]`
-///
-/// unsafe {
-/// ptr::swap(x, y);
-/// // The indices `1..3` of the slice overlap between `x` and `y`.
-/// // Reasonable results would be for to them be `[2, 3]`, so that indices `0..3` are
-/// // `[1, 2, 3]` (matching `y` before the `swap`); or for them to be `[0, 1]`
-/// // so that indices `1..4` are `[0, 1, 2]` (matching `x` before the `swap`).
-/// // This implementation is defined to make the latter choice.
-/// assert_eq!([1, 0, 1, 2], array);
-/// }
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
- // Give ourselves some scratch space to work with.
- // We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
- let mut tmp = MaybeUninit::<T>::uninit();
-
- // Perform the swap
- copy_nonoverlapping(x, tmp.as_mut_ptr(), 1);
- copy(y, x, 1); // `x` and `y` may overlap
- copy_nonoverlapping(tmp.as_ptr(), y, 1);
-}
-
-/// Swaps `count * size_of::<T>()` bytes between the two regions of memory
-/// beginning at `x` and `y`. The two regions must *not* overlap.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * Both `x` and `y` must be [valid] for reads and writes of `count *
-/// size_of::<T>()` bytes.
-///
-/// * Both `x` and `y` must be properly aligned.
-///
-/// * The region of memory beginning at `x` with a size of `count *
-/// size_of::<T>()` bytes must *not* overlap with the region of memory
-/// beginning at `y` with the same size.
-///
-/// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
-/// the pointers must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut x = [1, 2, 3, 4];
-/// let mut y = [7, 8, 9];
-///
-/// unsafe {
-/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2);
-/// }
-///
-/// assert_eq!(x, [7, 8, 3, 4]);
-/// assert_eq!(y, [1, 2, 9]);
-/// ```
-#[inline]
-#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
-pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
- let x = x as *mut u8;
- let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
- swap_nonoverlapping_bytes(x, y, len)
-}
-
-#[inline]
-pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
- // For types smaller than the block optimization below,
- // just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
- let z = read(x);
- copy_nonoverlapping(y, x, 1);
- write(y, z);
- } else {
- swap_nonoverlapping(x, y, 1);
- }
-}
-
-#[inline]
-unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
- // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
- // that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
- // Haswell E processors. LLVM is more able to optimize if we give a struct a
- // #[repr(simd)], even if we don't actually use this struct directly.
- //
- // FIXME repr(simd) broken on emscripten and redox
- #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
- struct Block(u64, u64, u64, u64);
- struct UnalignedBlock(u64, u64, u64, u64);
-
- let block_size = mem::size_of::<Block>();
-
- // Loop through x & y, copying them `Block` at a time
- // The optimizer should unroll the loop fully for most types
- // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
- let mut i = 0;
- while i + block_size <= len {
- // Create some uninitialized memory as scratch space
- // Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t = mem::MaybeUninit::<Block>::uninit();
- let t = t.as_mut_ptr() as *mut u8;
- let x = x.add(i);
- let y = y.add(i);
-
- // Swap a block of bytes of x & y, using t as a temporary buffer
- // This should be optimized into efficient SIMD operations where available
- copy_nonoverlapping(x, t, block_size);
- copy_nonoverlapping(y, x, block_size);
- copy_nonoverlapping(t, y, block_size);
- i += block_size;
- }
-
- if i < len {
- // Swap any remaining bytes
- let mut t = mem::MaybeUninit::<UnalignedBlock>::uninit();
- let rem = len - i;
-
- let t = t.as_mut_ptr() as *mut u8;
- let x = x.add(i);
- let y = y.add(i);
-
- copy_nonoverlapping(x, t, rem);
- copy_nonoverlapping(y, x, rem);
- copy_nonoverlapping(t, y, rem);
- }
-}
-
-/// Moves `src` into the pointed `dst`, returning the previous `dst` value.
-///
-/// Neither value is dropped.
-///
-/// This function is semantically equivalent to [`mem::replace`] except that it
-/// operates on raw pointers instead of references. When references are
-/// available, [`mem::replace`] should be preferred.
-///
-/// [`mem::replace`]: ../mem/fn.replace.html
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `dst` must be [valid] for writes.
-///
-/// * `dst` must be properly aligned.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-///
-/// # Examples
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut rust = vec!['b', 'u', 's', 't'];
-///
-/// // `mem::replace` would have the same effect without requiring the unsafe
-/// // block.
-/// let b = unsafe {
-/// ptr::replace(&mut rust[0], 'r')
-/// };
-///
-/// assert_eq!(b, 'b');
-/// assert_eq!(rust, &['r', 'u', 's', 't']);
-/// ```
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
- mem::swap(&mut *dst, &mut src); // cannot overlap
- src
-}
-
-/// Reads the value from `src` without moving it. This leaves the
-/// memory in `src` unchanged.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `src` must be [valid] for reads.
-///
-/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the
-/// case.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// let x = 12;
-/// let y = &x as *const i32;
-///
-/// unsafe {
-/// assert_eq!(std::ptr::read(y), 12);
-/// }
-/// ```
-///
-/// Manually implement [`mem::swap`]:
-///
-/// ```
-/// use std::ptr;
-///
-/// fn swap<T>(a: &mut T, b: &mut T) {
-/// unsafe {
-/// // Create a bitwise copy of the value at `a` in `tmp`.
-/// let tmp = ptr::read(a);
-///
-/// // Exiting at this point (either by explicitly returning or by
-/// // calling a function which panics) would cause the value in `tmp` to
-/// // be dropped while the same value is still referenced by `a`. This
-/// // could trigger undefined behavior if `T` is not `Copy`.
-///
-/// // Create a bitwise copy of the value at `b` in `a`.
-/// // This is safe because mutable references cannot alias.
-/// ptr::copy_nonoverlapping(b, a, 1);
-///
-/// // As above, exiting here could trigger undefined behavior because
-/// // the same value is referenced by `a` and `b`.
-///
-/// // Move `tmp` into `b`.
-/// ptr::write(b, tmp);
-///
-/// // `tmp` has been moved (`write` takes ownership of its second argument),
-/// // so nothing is dropped implicitly here.
-/// }
-/// }
-///
-/// let mut foo = "foo".to_owned();
-/// let mut bar = "bar".to_owned();
-///
-/// swap(&mut foo, &mut bar);
-///
-/// assert_eq!(foo, "bar");
-/// assert_eq!(bar, "foo");
-/// ```
-///
-/// ## Ownership of the Returned Value
-///
-/// `read` creates a bitwise copy of `T`, regardless of whether `T` is [`Copy`].
-/// If `T` is not [`Copy`], using both the returned value and the value at
-/// `*src` can violate memory safety. Note that assigning to `*src` counts as a
-/// use because it will attempt to drop the value at `*src`.
-///
-/// [`write`] can be used to overwrite data without causing it to be dropped.
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut s = String::from("foo");
-/// unsafe {
-/// // `s2` now points to the same underlying memory as `s`.
-/// let mut s2: String = ptr::read(&s);
-///
-/// assert_eq!(s2, "foo");
-///
-/// // Assigning to `s2` causes its original value to be dropped. Beyond
-/// // this point, `s` must no longer be used, as the underlying memory has
-/// // been freed.
-/// s2 = String::default();
-/// assert_eq!(s2, "");
-///
-/// // Assigning to `s` would cause the old value to be dropped again,
-/// // resulting in undefined behavior.
-/// // s = String::from("bar"); // ERROR
-///
-/// // `ptr::write` can be used to overwrite a value without dropping it.
-/// ptr::write(&mut s, String::from("bar"));
-/// }
-///
-/// assert_eq!(s, "bar");
-/// ```
-///
-/// [`mem::swap`]: ../mem/fn.swap.html
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read_unaligned`]: ./fn.read_unaligned.html
-/// [`write`]: ./fn.write.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp = MaybeUninit::<T>::uninit();
- copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- tmp.assume_init()
-}
-
-/// Reads the value from `src` without moving it. This leaves the
-/// memory in `src` unchanged.
-///
-/// Unlike [`read`], `read_unaligned` works with unaligned pointers.
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `src` must be [valid] for reads.
-///
-/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
-/// value and the value at `*src` can [violate memory safety][read-ownership].
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL.
-///
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ./fn.read.html
-/// [`write_unaligned`]: ./fn.write_unaligned.html
-/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
-/// [valid]: ../ptr/index.html#safety
-///
-/// # Examples
-///
-/// Access members of a packed struct by reference:
-///
-/// ```
-/// use std::ptr;
-///
-/// #[repr(packed, C)]
-/// struct Packed {
-/// _padding: u8,
-/// unaligned: u32,
-/// }
-///
-/// let x = Packed {
-/// _padding: 0x00,
-/// unaligned: 0x01020304,
-/// };
-///
-/// let v = unsafe {
-/// // Take the address of a 32-bit integer which is not aligned.
-/// // This must be done as a raw pointer; unaligned references are invalid.
-/// let unaligned = &x.unaligned as *const u32;
-///
-/// // Dereferencing normally will emit an aligned load instruction,
-/// // causing undefined behavior.
-/// // let v = *unaligned; // ERROR
-///
-/// // Instead, use `read_unaligned` to read improperly aligned values.
-/// let v = ptr::read_unaligned(unaligned);
-///
-/// v
-/// };
-///
-/// // Accessing unaligned values directly is safe.
-/// assert!(x.unaligned == v);
-/// ```
-#[inline]
-#[stable(feature = "ptr_unaligned", since = "1.17.0")]
-pub unsafe fn read_unaligned<T>(src: *const T) -> T {
- let mut tmp = MaybeUninit::<T>::uninit();
- copy_nonoverlapping(src as *const u8,
- tmp.as_mut_ptr() as *mut u8,
- mem::size_of::<T>());
- tmp.assume_init()
-}
-
-/// Overwrites a memory location with the given value without reading or
-/// dropping the old value.
-///
-/// `write` does not drop the contents of `dst`. This is safe, but it could leak
-/// allocations or resources, so care should be taken not to overwrite an object
-/// that should be dropped.
-///
-/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-/// location pointed to by `dst`.
-///
-/// This is appropriate for initializing uninitialized memory, or overwriting
-/// memory that has previously been [`read`] from.
-///
-/// [`read`]: ./fn.read.html
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `dst` must be [valid] for writes.
-///
-/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
-/// case.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-/// [`write_unaligned`]: ./fn.write_unaligned.html
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// let mut x = 0;
-/// let y = &mut x as *mut i32;
-/// let z = 12;
-///
-/// unsafe {
-/// std::ptr::write(y, z);
-/// assert_eq!(std::ptr::read(y), 12);
-/// }
-/// ```
-///
-/// Manually implement [`mem::swap`]:
-///
-/// ```
-/// use std::ptr;
-///
-/// fn swap<T>(a: &mut T, b: &mut T) {
-/// unsafe {
-/// // Create a bitwise copy of the value at `a` in `tmp`.
-/// let tmp = ptr::read(a);
-///
-/// // Exiting at this point (either by explicitly returning or by
-/// // calling a function which panics) would cause the value in `tmp` to
-/// // be dropped while the same value is still referenced by `a`. This
-/// // could trigger undefined behavior if `T` is not `Copy`.
-///
-/// // Create a bitwise copy of the value at `b` in `a`.
-/// // This is safe because mutable references cannot alias.
-/// ptr::copy_nonoverlapping(b, a, 1);
-///
-/// // As above, exiting here could trigger undefined behavior because
-/// // the same value is referenced by `a` and `b`.
-///
-/// // Move `tmp` into `b`.
-/// ptr::write(b, tmp);
-///
-/// // `tmp` has been moved (`write` takes ownership of its second argument),
-/// // so nothing is dropped implicitly here.
-/// }
-/// }
-///
-/// let mut foo = "foo".to_owned();
-/// let mut bar = "bar".to_owned();
-///
-/// swap(&mut foo, &mut bar);
-///
-/// assert_eq!(foo, "bar");
-/// assert_eq!(bar, "foo");
-/// ```
-///
-/// [`mem::swap`]: ../mem/fn.swap.html
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
-}
-
-/// Overwrites a memory location with the given value without reading or
-/// dropping the old value.
-///
-/// Unlike [`write`], the pointer may be unaligned.
-///
-/// `write_unaligned` does not drop the contents of `dst`. This is safe, but it
-/// could leak allocations or resources, so care should be taken not to overwrite
-/// an object that should be dropped.
-///
-/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-/// location pointed to by `dst`.
-///
-/// This is appropriate for initializing uninitialized memory, or overwriting
-/// memory that has previously been read with [`read_unaligned`].
-///
-/// [`write`]: ./fn.write.html
-/// [`read_unaligned`]: ./fn.read_unaligned.html
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `dst` must be [valid] for writes.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL.
-///
-/// [valid]: ../ptr/index.html#safety
-///
-/// # Examples
-///
-/// Access fields in a packed struct:
-///
-/// ```
-/// use std::{mem, ptr};
-///
-/// #[repr(packed, C)]
-/// #[derive(Default)]
-/// struct Packed {
-/// _padding: u8,
-/// unaligned: u32,
-/// }
-///
-/// let v = 0x01020304;
-/// let mut x: Packed = unsafe { mem::zeroed() };
-///
-/// unsafe {
-/// // Take a reference to a 32-bit integer which is not aligned.
-/// let unaligned = &mut x.unaligned as *mut u32;
-///
-/// // Dereferencing normally will emit an aligned store instruction,
-/// // causing undefined behavior because the pointer is not aligned.
-/// // *unaligned = v; // ERROR
-///
-/// // Instead, use `write_unaligned` to write improperly aligned values.
-/// ptr::write_unaligned(unaligned, v);
-/// }
-///
-/// // Accessing unaligned values directly is safe.
-/// assert!(x.unaligned == v);
-/// ```
-#[inline]
-#[stable(feature = "ptr_unaligned", since = "1.17.0")]
-pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
- copy_nonoverlapping(&src as *const T as *const u8,
- dst as *mut u8,
- mem::size_of::<T>());
- mem::forget(src);
-}
-
-/// Performs a volatile read of the value from `src` without moving it. This
-/// leaves the memory in `src` unchanged.
-///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
-///
-/// [`write_volatile`]: ./fn.write_volatile.html
-///
-/// # Notes
-///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
-///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
-/// and may be ignored.
-///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `src` must be [valid] for reads.
-///
-/// * `src` must be properly aligned.
-///
-/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
-/// value and the value at `*src` can [violate memory safety][read-ownership].
-/// However, storing non-[`Copy`] types in volatile memory is almost certainly
-/// incorrect.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-/// [`Copy`]: ../marker/trait.Copy.html
-/// [`read`]: ./fn.read.html
-/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
-///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `read_volatile` and any write operation to the same location
-/// is undefined behavior.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// let x = 12;
-/// let y = &x as *const i32;
-///
-/// unsafe {
-/// assert_eq!(std::ptr::read_volatile(y), 12);
-/// }
-/// ```
-#[inline]
-#[stable(feature = "volatile", since = "1.9.0")]
-pub unsafe fn read_volatile<T>(src: *const T) -> T {
- intrinsics::volatile_load(src)
-}
-
-/// Performs a volatile write of a memory location with the given value without
-/// reading or dropping the old value.
-///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
-///
-/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
-/// could leak allocations or resources, so care should be taken not to overwrite
-/// an object that should be dropped.
-///
-/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-/// location pointed to by `dst`.
-///
-/// [`read_volatile`]: ./fn.read_volatile.html
-///
-/// # Notes
-///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
-///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops
-/// and may be ignored.
-///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `dst` must be [valid] for writes.
-///
-/// * `dst` must be properly aligned.
-///
-/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
-///
-/// [valid]: ../ptr/index.html#safety
-///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `write_volatile` and any other operation (reading or writing)
-/// on the same location is undefined behavior.
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// let mut x = 0;
-/// let y = &mut x as *mut i32;
-/// let z = 12;
-///
-/// unsafe {
-/// std::ptr::write_volatile(y, z);
-/// assert_eq!(std::ptr::read_volatile(y), 12);
-/// }
-/// ```
-#[inline]
-#[stable(feature = "volatile", since = "1.9.0")]
-pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
- intrinsics::volatile_store(dst, src);
-}
-
-#[lang = "const_ptr"]
-impl<T: ?Sized> *const T {
- /// Returns `true` if the pointer is null.
- ///
- /// Note that unsized types have many possible null pointers, as only the
- /// raw data pointer is considered, not their length, vtable, etc.
- /// Therefore, two pointers that are null may still not compare equal to
- /// each other.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "Follow the rabbit";
- /// let ptr: *const u8 = s.as_ptr();
- /// assert!(!ptr.is_null());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub fn is_null(self) -> bool {
- // Compare via a cast to a thin pointer, so fat pointers are only
- // considering their "data" part for null-ness.
- (self as *const u8) == null()
- }
-
- /// Cast to a pointer to a different type
- #[unstable(feature = "ptr_cast", issue = "60602")]
- #[inline]
- pub const fn cast<U>(self) -> *const U {
- self as _
- }
-
- /// Returns `None` if the pointer is null, or else returns a reference to
- /// the value wrapped in `Some`.
- ///
- /// # Safety
- ///
- /// While this method and its mutable counterpart are useful for
- /// null-safety, it is important to note that this is still an unsafe
- /// operation because the returned value could be pointing to invalid
- /// memory.
- ///
- /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
- /// not necessarily reflect the actual lifetime of the data.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let ptr: *const u8 = &10u8 as *const u8;
- ///
- /// unsafe {
- /// if let Some(val_back) = ptr.as_ref() {
- /// println!("We got back the value: {}!", val_back);
- /// }
- /// }
- /// ```
- ///
- /// # Null-unchecked version
- ///
- /// If you are sure the pointer can never be null and are looking for some kind of
- /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
- /// dereference the pointer directly.
- ///
- /// ```
- /// let ptr: *const u8 = &10u8 as *const u8;
- ///
- /// unsafe {
- /// let val_back = &*ptr;
- /// println!("We got back the value: {}!", val_back);
- /// }
- /// ```
- #[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[inline]
- pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
- if self.is_null() {
- None
- } else {
- Some(&*self)
- }
- }
-
- /// Calculates the offset from a pointer.
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "123";
- /// let ptr: *const u8 = s.as_ptr();
- ///
- /// unsafe {
- /// println!("{}", *ptr.offset(1) as char);
- /// println!("{}", *ptr.offset(2) as char);
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
- intrinsics::offset(self, count)
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- /// In particular, the resulting pointer may *not* be used to access a
- /// different allocated object than the one `self` points to. In other
- /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
- /// *not* the same as `y`, and dereferencing it is undefined behavior
- /// unless `x` and `y` point into the same allocated object.
- ///
- /// Always use `.offset(count)` instead when possible, because `offset`
- /// allows the compiler to optimize better. If you need to cross object
- /// boundaries, cast the pointer to an integer and do the arithmetic there.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements
- /// let data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *const u8 = data.as_ptr();
- /// let step = 2;
- /// let end_rounded_up = ptr.wrapping_offset(6);
- ///
- /// // This loop prints "1, 3, 5, "
- /// while ptr != end_rounded_up {
- /// unsafe {
- /// print!("{}, ", *ptr);
- /// }
- /// ptr = ptr.wrapping_offset(step);
- /// }
- /// ```
- #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
- #[inline]
- pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
- unsafe {
- intrinsics::arith_offset(self, count)
- }
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// This function is the inverse of [`offset`].
- ///
- /// [`offset`]: #method.offset
- /// [`wrapping_offset_from`]: #method.wrapping_offset_from
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and other pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The distance between the pointers, in bytes, must be an exact multiple
- /// of the size of `T`.
- ///
- /// * The distance being in bounds cannot rely on "wrapping around" the address space.
- ///
- /// The compiler and standard library generally try to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using [`wrapping_offset_from`] instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Panics
- ///
- /// This function panics if `T` is a Zero-Sized Type ("ZST").
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(ptr_offset_from)]
- ///
- /// let a = [0; 5];
- /// let ptr1: *const i32 = &a[1];
- /// let ptr2: *const i32 = &a[3];
- /// unsafe {
- /// assert_eq!(ptr2.offset_from(ptr1), 2);
- /// assert_eq!(ptr1.offset_from(ptr2), -2);
- /// assert_eq!(ptr1.offset(2), ptr2);
- /// assert_eq!(ptr2.offset(-2), ptr1);
- /// }
- /// ```
- #[unstable(feature = "ptr_offset_from", issue = "41079")]
- #[inline]
- pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
- let pointee_size = mem::size_of::<T>();
- assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
-
- // This is the same sequence that Clang emits for pointer subtraction.
- // It can be neither `nsw` nor `nuw` because the input is treated as
- // unsigned but then the output is treated as signed, so neither works.
- let d = isize::wrapping_sub(self as _, origin as _);
- intrinsics::exact_div(d, pointee_size as _)
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// If the address different between the two pointers is not a multiple of
- /// `mem::size_of::<T>()` then the result of the division is rounded towards
- /// zero.
- ///
- /// Though this method is safe for any two pointers, note that its result
- /// will be mostly useless if the two pointers aren't into the same allocated
- /// object, for example if they point to two different local variables.
- ///
- /// # Panics
- ///
- /// This function panics if `T` is a zero-sized type.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(ptr_wrapping_offset_from)]
- ///
- /// let a = [0; 5];
- /// let ptr1: *const i32 = &a[1];
- /// let ptr2: *const i32 = &a[3];
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
- /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
- /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
- ///
- /// let ptr1: *const i32 = 3 as _;
- /// let ptr2: *const i32 = 13 as _;
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// ```
- #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
- #[inline]
- pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
- let pointee_size = mem::size_of::<T>();
- assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
-
- let d = isize::wrapping_sub(self as _, origin as _);
- d.wrapping_div(pointee_size as _)
- }
-
- /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum must fit in a `usize`.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "123";
- /// let ptr: *const u8 = s.as_ptr();
- ///
- /// unsafe {
- /// println!("{}", *ptr.add(1) as char);
- /// println!("{}", *ptr.add(2) as char);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn add(self, count: usize) -> Self
- where T: Sized,
- {
- self.offset(count as isize)
- }
-
- /// Calculates the offset from a pointer (convenience for
- /// `.offset((count as isize).wrapping_neg())`).
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset cannot exceed `isize::MAX` **bytes**.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum must fit in a usize.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "123";
- ///
- /// unsafe {
- /// let end: *const u8 = s.as_ptr().add(3);
- /// println!("{}", *end.sub(1) as char);
- /// println!("{}", *end.sub(2) as char);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn sub(self, count: usize) -> Self
- where T: Sized,
- {
- self.offset((count as isize).wrapping_neg())
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset(count as isize)`)
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.add(count)` instead when possible, because `add`
- /// allows the compiler to optimize better.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements
- /// let data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *const u8 = data.as_ptr();
- /// let step = 2;
- /// let end_rounded_up = ptr.wrapping_add(6);
- ///
- /// // This loop prints "1, 3, 5, "
- /// while ptr != end_rounded_up {
- /// unsafe {
- /// print!("{}, ", *ptr);
- /// }
- /// ptr = ptr.wrapping_add(step);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub fn wrapping_add(self, count: usize) -> Self
- where T: Sized,
- {
- self.wrapping_offset(count as isize)
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.sub(count)` instead when possible, because `sub`
- /// allows the compiler to optimize better.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements (backwards)
- /// let data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *const u8 = data.as_ptr();
- /// let start_rounded_down = ptr.wrapping_sub(2);
- /// ptr = ptr.wrapping_add(4);
- /// let step = 2;
- /// // This loop prints "5, 3, 1, "
- /// while ptr != start_rounded_down {
- /// unsafe {
- /// print!("{}, ", *ptr);
- /// }
- /// ptr = ptr.wrapping_sub(step);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub fn wrapping_sub(self, count: usize) -> Self
- where T: Sized,
- {
- self.wrapping_offset((count as isize).wrapping_neg())
- }
-
- /// Reads the value from `self` without moving it. This leaves the
- /// memory in `self` unchanged.
- ///
- /// See [`ptr::read`] for safety concerns and examples.
- ///
- /// [`ptr::read`]: ./ptr/fn.read.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read(self) -> T
- where T: Sized,
- {
- read(self)
- }
-
- /// Performs a volatile read of the value from `self` without moving it. This
- /// leaves the memory in `self` unchanged.
- ///
- /// Volatile operations are intended to act on I/O memory, and are guaranteed
- /// to not be elided or reordered by the compiler across other volatile
- /// operations.
- ///
- /// See [`ptr::read_volatile`] for safety concerns and examples.
- ///
- /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read_volatile(self) -> T
- where T: Sized,
- {
- read_volatile(self)
- }
-
- /// Reads the value from `self` without moving it. This leaves the
- /// memory in `self` unchanged.
- ///
- /// Unlike `read`, the pointer may be unaligned.
- ///
- /// See [`ptr::read_unaligned`] for safety concerns and examples.
- ///
- /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read_unaligned(self) -> T
- where T: Sized,
- {
- read_unaligned(self)
- }
-
- /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
- /// and destination may overlap.
- ///
- /// NOTE: this has the *same* argument order as [`ptr::copy`].
- ///
- /// See [`ptr::copy`] for safety concerns and examples.
- ///
- /// [`ptr::copy`]: ./ptr/fn.copy.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_to(self, dest: *mut T, count: usize)
- where T: Sized,
- {
- copy(self, dest, count)
- }
-
- /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
- /// and destination may *not* overlap.
- ///
- /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
- ///
- /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
- ///
- /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
- where T: Sized,
- {
- copy_nonoverlapping(self, dest, count)
- }
-
- /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
- /// `align`.
- ///
- /// If it is not possible to align the pointer, the implementation returns
- /// `usize::max_value()`.
- ///
- /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
- /// used with the `offset` or `offset_to` methods.
- ///
- /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
- /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
- /// the returned offset is correct in all terms other than alignment.
- ///
- /// # Panics
- ///
- /// The function panics if `align` is not a power-of-two.
- ///
- /// # Examples
- ///
- /// Accessing adjacent `u8` as `u16`
- ///
- /// ```
- /// # fn foo(n: usize) {
- /// # use std::mem::align_of;
- /// # unsafe {
- /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
- /// let ptr = &x[n] as *const u8;
- /// let offset = ptr.align_offset(align_of::<u16>());
- /// if offset < x.len() - n - 1 {
- /// let u16_ptr = ptr.add(offset) as *const u16;
- /// assert_ne!(*u16_ptr, 500);
- /// } else {
- /// // while the pointer can be aligned via `offset`, it would point
- /// // outside the allocation
- /// }
- /// # } }
- /// ```
- #[stable(feature = "align_offset", since = "1.36.0")]
- pub fn align_offset(self, align: usize) -> usize where T: Sized {
- if !align.is_power_of_two() {
- panic!("align_offset: align is not a power-of-two");
- }
- unsafe {
- align_offset(self, align)
- }
- }
-}
-
-
-#[lang = "mut_ptr"]
-impl<T: ?Sized> *mut T {
- /// Returns `true` if the pointer is null.
- ///
- /// Note that unsized types have many possible null pointers, as only the
- /// raw data pointer is considered, not their length, vtable, etc.
- /// Therefore, two pointers that are null may still not compare equal to
- /// each other.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let mut s = [1, 2, 3];
- /// let ptr: *mut u32 = s.as_mut_ptr();
- /// assert!(!ptr.is_null());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub fn is_null(self) -> bool {
- // Compare via a cast to a thin pointer, so fat pointers are only
- // considering their "data" part for null-ness.
- (self as *mut u8) == null_mut()
- }
-
- /// Cast to a pointer to a different type
- #[unstable(feature = "ptr_cast", issue = "60602")]
- #[inline]
- pub const fn cast<U>(self) -> *mut U {
- self as _
- }
-
- /// Returns `None` if the pointer is null, or else returns a reference to
- /// the value wrapped in `Some`.
- ///
- /// # Safety
- ///
- /// While this method and its mutable counterpart are useful for
- /// null-safety, it is important to note that this is still an unsafe
- /// operation because the returned value could be pointing to invalid
- /// memory.
- ///
- /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
- /// not necessarily reflect the actual lifetime of the data.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
- ///
- /// unsafe {
- /// if let Some(val_back) = ptr.as_ref() {
- /// println!("We got back the value: {}!", val_back);
- /// }
- /// }
- /// ```
- ///
- /// # Null-unchecked version
- ///
- /// If you are sure the pointer can never be null and are looking for some kind of
- /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
- /// dereference the pointer directly.
- ///
- /// ```
- /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
- ///
- /// unsafe {
- /// let val_back = &*ptr;
- /// println!("We got back the value: {}!", val_back);
- /// }
- /// ```
- #[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[inline]
- pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
- if self.is_null() {
- None
- } else {
- Some(&*self)
- }
- }
-
- /// Calculates the offset from a pointer.
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let mut s = [1, 2, 3];
- /// let ptr: *mut u32 = s.as_mut_ptr();
- ///
- /// unsafe {
- /// println!("{}", *ptr.offset(1));
- /// println!("{}", *ptr.offset(2));
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
- intrinsics::offset(self, count) as *mut T
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- /// In particular, the resulting pointer may *not* be used to access a
- /// different allocated object than the one `self` points to. In other
- /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
- /// *not* the same as `y`, and dereferencing it is undefined behavior
- /// unless `x` and `y` point into the same allocated object.
- ///
- /// Always use `.offset(count)` instead when possible, because `offset`
- /// allows the compiler to optimize better. If you need to cross object
- /// boundaries, cast the pointer to an integer and do the arithmetic there.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements
- /// let mut data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *mut u8 = data.as_mut_ptr();
- /// let step = 2;
- /// let end_rounded_up = ptr.wrapping_offset(6);
- ///
- /// while ptr != end_rounded_up {
- /// unsafe {
- /// *ptr = 0;
- /// }
- /// ptr = ptr.wrapping_offset(step);
- /// }
- /// assert_eq!(&data, &[0, 2, 0, 4, 0]);
- /// ```
- #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
- #[inline]
- pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
- unsafe {
- intrinsics::arith_offset(self, count) as *mut T
- }
- }
-
- /// Returns `None` if the pointer is null, or else returns a mutable
- /// reference to the value wrapped in `Some`.
- ///
- /// # Safety
- ///
- /// As with `as_ref`, this is unsafe because it cannot verify the validity
- /// of the returned pointer, nor can it ensure that the lifetime `'a`
- /// returned is indeed a valid lifetime for the contained data.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let mut s = [1, 2, 3];
- /// let ptr: *mut u32 = s.as_mut_ptr();
- /// let first_value = unsafe { ptr.as_mut().unwrap() };
- /// *first_value = 4;
- /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
- /// ```
- #[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[inline]
- pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
- if self.is_null() {
- None
- } else {
- Some(&mut *self)
- }
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// This function is the inverse of [`offset`].
- ///
- /// [`offset`]: #method.offset-1
- /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and other pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The distance between the pointers, in bytes, must be an exact multiple
- /// of the size of `T`.
- ///
- /// * The distance being in bounds cannot rely on "wrapping around" the address space.
- ///
- /// The compiler and standard library generally try to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using [`wrapping_offset_from`] instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Panics
- ///
- /// This function panics if `T` is a Zero-Sized Type ("ZST").
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(ptr_offset_from)]
- ///
- /// let mut a = [0; 5];
- /// let ptr1: *mut i32 = &mut a[1];
- /// let ptr2: *mut i32 = &mut a[3];
- /// unsafe {
- /// assert_eq!(ptr2.offset_from(ptr1), 2);
- /// assert_eq!(ptr1.offset_from(ptr2), -2);
- /// assert_eq!(ptr1.offset(2), ptr2);
- /// assert_eq!(ptr2.offset(-2), ptr1);
- /// }
- /// ```
- #[unstable(feature = "ptr_offset_from", issue = "41079")]
- #[inline]
- pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
- (self as *const T).offset_from(origin)
- }
-
- /// Calculates the distance between two pointers. The returned value is in
- /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
- ///
- /// If the address different between the two pointers is not a multiple of
- /// `mem::size_of::<T>()` then the result of the division is rounded towards
- /// zero.
- ///
- /// Though this method is safe for any two pointers, note that its result
- /// will be mostly useless if the two pointers aren't into the same allocated
- /// object, for example if they point to two different local variables.
- ///
- /// # Panics
- ///
- /// This function panics if `T` is a zero-sized type.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(ptr_wrapping_offset_from)]
- ///
- /// let mut a = [0; 5];
- /// let ptr1: *mut i32 = &mut a[1];
- /// let ptr2: *mut i32 = &mut a[3];
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
- /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
- /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
- ///
- /// let ptr1: *mut i32 = 3 as _;
- /// let ptr2: *mut i32 = 13 as _;
- /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
- /// ```
- #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
- #[inline]
- pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
- (self as *const T).wrapping_offset_from(origin)
- }
-
- /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset, **in bytes**, cannot overflow an `isize`.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum must fit in a `usize`.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "123";
- /// let ptr: *const u8 = s.as_ptr();
- ///
- /// unsafe {
- /// println!("{}", *ptr.add(1) as char);
- /// println!("{}", *ptr.add(2) as char);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn add(self, count: usize) -> Self
- where T: Sized,
- {
- self.offset(count as isize)
- }
-
- /// Calculates the offset from a pointer (convenience for
- /// `.offset((count as isize).wrapping_neg())`).
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// If any of the following conditions are violated, the result is Undefined
- /// Behavior:
- ///
- /// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object.
- ///
- /// * The computed offset cannot exceed `isize::MAX` **bytes**.
- ///
- /// * The offset being in bounds cannot rely on "wrapping around" the address
- /// space. That is, the infinite-precision sum must fit in a usize.
- ///
- /// The compiler and standard library generally tries to ensure allocations
- /// never reach a size where an offset is a concern. For instance, `Vec`
- /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
- /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
- ///
- /// Most platforms fundamentally can't even construct such an allocation.
- /// For instance, no known 64-bit platform can ever serve a request
- /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
- /// However, some 32-bit and 16-bit platforms may successfully serve a request for
- /// more than `isize::MAX` bytes with things like Physical Address
- /// Extension. As such, memory acquired directly from allocators or memory
- /// mapped files *may* be too large to handle with this function.
- ///
- /// Consider using `wrapping_offset` instead if these constraints are
- /// difficult to satisfy. The only advantage of this method is that it
- /// enables more aggressive compiler optimizations.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// let s: &str = "123";
- ///
- /// unsafe {
- /// let end: *const u8 = s.as_ptr().add(3);
- /// println!("{}", *end.sub(1) as char);
- /// println!("{}", *end.sub(2) as char);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn sub(self, count: usize) -> Self
- where T: Sized,
- {
- self.offset((count as isize).wrapping_neg())
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset(count as isize)`)
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.add(count)` instead when possible, because `add`
- /// allows the compiler to optimize better.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements
- /// let data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *const u8 = data.as_ptr();
- /// let step = 2;
- /// let end_rounded_up = ptr.wrapping_add(6);
- ///
- /// // This loop prints "1, 3, 5, "
- /// while ptr != end_rounded_up {
- /// unsafe {
- /// print!("{}, ", *ptr);
- /// }
- /// ptr = ptr.wrapping_add(step);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub fn wrapping_add(self, count: usize) -> Self
- where T: Sized,
- {
- self.wrapping_offset(count as isize)
- }
-
- /// Calculates the offset from a pointer using wrapping arithmetic.
- /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
- ///
- /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
- /// offset of `3 * size_of::<T>()` bytes.
- ///
- /// # Safety
- ///
- /// The resulting pointer does not need to be in bounds, but it is
- /// potentially hazardous to dereference (which requires `unsafe`).
- ///
- /// Always use `.sub(count)` instead when possible, because `sub`
- /// allows the compiler to optimize better.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// // Iterate using a raw pointer in increments of two elements (backwards)
- /// let data = [1u8, 2, 3, 4, 5];
- /// let mut ptr: *const u8 = data.as_ptr();
- /// let start_rounded_down = ptr.wrapping_sub(2);
- /// ptr = ptr.wrapping_add(4);
- /// let step = 2;
- /// // This loop prints "5, 3, 1, "
- /// while ptr != start_rounded_down {
- /// unsafe {
- /// print!("{}, ", *ptr);
- /// }
- /// ptr = ptr.wrapping_sub(step);
- /// }
- /// ```
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub fn wrapping_sub(self, count: usize) -> Self
- where T: Sized,
- {
- self.wrapping_offset((count as isize).wrapping_neg())
- }
-
- /// Reads the value from `self` without moving it. This leaves the
- /// memory in `self` unchanged.
- ///
- /// See [`ptr::read`] for safety concerns and examples.
- ///
- /// [`ptr::read`]: ./ptr/fn.read.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read(self) -> T
- where T: Sized,
- {
- read(self)
- }
-
- /// Performs a volatile read of the value from `self` without moving it. This
- /// leaves the memory in `self` unchanged.
- ///
- /// Volatile operations are intended to act on I/O memory, and are guaranteed
- /// to not be elided or reordered by the compiler across other volatile
- /// operations.
- ///
- /// See [`ptr::read_volatile`] for safety concerns and examples.
- ///
- /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read_volatile(self) -> T
- where T: Sized,
- {
- read_volatile(self)
- }
-
- /// Reads the value from `self` without moving it. This leaves the
- /// memory in `self` unchanged.
- ///
- /// Unlike `read`, the pointer may be unaligned.
- ///
- /// See [`ptr::read_unaligned`] for safety concerns and examples.
- ///
- /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn read_unaligned(self) -> T
- where T: Sized,
- {
- read_unaligned(self)
- }
-
- /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
- /// and destination may overlap.
- ///
- /// NOTE: this has the *same* argument order as [`ptr::copy`].
- ///
- /// See [`ptr::copy`] for safety concerns and examples.
- ///
- /// [`ptr::copy`]: ./ptr/fn.copy.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_to(self, dest: *mut T, count: usize)
- where T: Sized,
- {
- copy(self, dest, count)
- }
-
- /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
- /// and destination may *not* overlap.
- ///
- /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
- ///
- /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
- ///
- /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
- where T: Sized,
- {
- copy_nonoverlapping(self, dest, count)
- }
-
- /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
- /// and destination may overlap.
- ///
- /// NOTE: this has the *opposite* argument order of [`ptr::copy`].
- ///
- /// See [`ptr::copy`] for safety concerns and examples.
- ///
- /// [`ptr::copy`]: ./ptr/fn.copy.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_from(self, src: *const T, count: usize)
- where T: Sized,
- {
- copy(src, self, count)
- }
-
- /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
- /// and destination may *not* overlap.
- ///
- /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`].
- ///
- /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
- ///
- /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
- where T: Sized,
- {
- copy_nonoverlapping(src, self, count)
- }
-
- /// Executes the destructor (if any) of the pointed-to value.
- ///
- /// See [`ptr::drop_in_place`] for safety concerns and examples.
- ///
- /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn drop_in_place(self) {
- drop_in_place(self)
- }
-
- /// Overwrites a memory location with the given value without reading or
- /// dropping the old value.
- ///
- /// See [`ptr::write`] for safety concerns and examples.
- ///
- /// [`ptr::write`]: ./ptr/fn.write.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn write(self, val: T)
- where T: Sized,
- {
- write(self, val)
- }
-
- /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
- /// bytes of memory starting at `self` to `val`.
- ///
- /// See [`ptr::write_bytes`] for safety concerns and examples.
- ///
- /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn write_bytes(self, val: u8, count: usize)
- where T: Sized,
- {
- write_bytes(self, val, count)
- }
-
- /// Performs a volatile write of a memory location with the given value without
- /// reading or dropping the old value.
- ///
- /// Volatile operations are intended to act on I/O memory, and are guaranteed
- /// to not be elided or reordered by the compiler across other volatile
- /// operations.
- ///
- /// See [`ptr::write_volatile`] for safety concerns and examples.
- ///
- /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn write_volatile(self, val: T)
- where T: Sized,
- {
- write_volatile(self, val)
- }
-
- /// Overwrites a memory location with the given value without reading or
- /// dropping the old value.
- ///
- /// Unlike `write`, the pointer may be unaligned.
- ///
- /// See [`ptr::write_unaligned`] for safety concerns and examples.
- ///
- /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn write_unaligned(self, val: T)
- where T: Sized,
- {
- write_unaligned(self, val)
- }
-
- /// Replaces the value at `self` with `src`, returning the old
- /// value, without dropping either.
- ///
- /// See [`ptr::replace`] for safety concerns and examples.
- ///
- /// [`ptr::replace`]: ./ptr/fn.replace.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn replace(self, src: T) -> T
- where T: Sized,
- {
- replace(self, src)
- }
-
- /// Swaps the values at two mutable locations of the same type, without
- /// deinitializing either. They may overlap, unlike `mem::swap` which is
- /// otherwise equivalent.
- ///
- /// See [`ptr::swap`] for safety concerns and examples.
- ///
- /// [`ptr::swap`]: ./ptr/fn.swap.html
- #[stable(feature = "pointer_methods", since = "1.26.0")]
- #[inline]
- pub unsafe fn swap(self, with: *mut T)
- where T: Sized,
- {
- swap(self, with)
- }
-
- /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
- /// `align`.
- ///
- /// If it is not possible to align the pointer, the implementation returns
- /// `usize::max_value()`.
- ///
- /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
- /// used with the `offset` or `offset_to` methods.
- ///
- /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
- /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
- /// the returned offset is correct in all terms other than alignment.
- ///
- /// # Panics
- ///
- /// The function panics if `align` is not a power-of-two.
- ///
- /// # Examples
- ///
- /// Accessing adjacent `u8` as `u16`
- ///
- /// ```
- /// # fn foo(n: usize) {
- /// # use std::mem::align_of;
- /// # unsafe {
- /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
- /// let ptr = &x[n] as *const u8;
- /// let offset = ptr.align_offset(align_of::<u16>());
- /// if offset < x.len() - n - 1 {
- /// let u16_ptr = ptr.add(offset) as *const u16;
- /// assert_ne!(*u16_ptr, 500);
- /// } else {
- /// // while the pointer can be aligned via `offset`, it would point
- /// // outside the allocation
- /// }
- /// # } }
- /// ```
- #[stable(feature = "align_offset", since = "1.36.0")]
- pub fn align_offset(self, align: usize) -> usize where T: Sized {
- if !align.is_power_of_two() {
- panic!("align_offset: align is not a power-of-two");
- }
- unsafe {
- align_offset(self, align)
- }
- }
-}
-
-/// Align pointer `p`.
-///
-/// Calculate offset (in terms of elements of `stride` stride) that has to be applied
-/// to pointer `p` so that pointer `p` would get aligned to `a`.
-///
-/// Note: This implementation has been carefully tailored to not panic. It is UB for this to panic.
-/// The only real change that can be made here is change of `INV_TABLE_MOD_16` and associated
-/// constants.
-///
-/// If we ever decide to make it possible to call the intrinsic with `a` that is not a
-/// power-of-two, it will probably be more prudent to just change to a naive implementation rather
-/// than trying to adapt this to accommodate that change.
-///
-/// Any questions go to @nagisa.
-#[lang="align_offset"]
-pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
- /// Calculate multiplicative modular inverse of `x` modulo `m`.
- ///
- /// This implementation is tailored for align_offset and has following preconditions:
- ///
- /// * `m` is a power-of-two;
- /// * `x < m`; (if `x ≥ m`, pass in `x % m` instead)
- ///
- /// Implementation of this function shall not panic. Ever.
- #[inline]
- fn mod_inv(x: usize, m: usize) -> usize {
- /// Multiplicative modular inverse table modulo 2⁴ = 16.
- ///
- /// Note, that this table does not contain values where inverse does not exist (i.e., for
- /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.)
- const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
- /// Modulo for which the `INV_TABLE_MOD_16` is intended.
- const INV_TABLE_MOD: usize = 16;
- /// INV_TABLE_MOD²
- const INV_TABLE_MOD_SQUARED: usize = INV_TABLE_MOD * INV_TABLE_MOD;
-
- let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize;
- if m <= INV_TABLE_MOD {
- table_inverse & (m - 1)
- } else {
- // We iterate "up" using the following formula:
- //
- // $$ xy ≡ 1 (mod 2ⁿ) → xy (2 - xy) ≡ 1 (mod 2²ⁿ) $$
- //
- // until 2²ⁿ ≥ m. Then we can reduce to our desired `m` by taking the result `mod m`.
- let mut inverse = table_inverse;
- let mut going_mod = INV_TABLE_MOD_SQUARED;
- loop {
- // y = y * (2 - xy) mod n
- //
- // Note, that we use wrapping operations here intentionally – the original formula
- // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod
- // usize::max_value()` instead, because we take the result `mod n` at the end
- // anyway.
- inverse = inverse.wrapping_mul(
- 2usize.wrapping_sub(x.wrapping_mul(inverse))
- ) & (going_mod - 1);
- if going_mod > m {
- return inverse & (m - 1);
- }
- going_mod = going_mod.wrapping_mul(going_mod);
- }
- }
- }
-
- let stride = mem::size_of::<T>();
- let a_minus_one = a.wrapping_sub(1);
- let pmoda = p as usize & a_minus_one;
-
- if pmoda == 0 {
- // Already aligned. Yay!
- return 0;
- }
-
- if stride <= 1 {
- return if stride == 0 {
- // If the pointer is not aligned, and the element is zero-sized, then no amount of
- // elements will ever align the pointer.
- !0
- } else {
- a.wrapping_sub(pmoda)
- };
- }
-
- let smoda = stride & a_minus_one;
- // a is power-of-two so cannot be 0. stride = 0 is handled above.
- let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a));
- let gcd = 1usize << gcdpow;
-
- if p as usize & (gcd - 1) == 0 {
- // This branch solves for the following linear congruence equation:
- //
- // $$ p + so ≡ 0 mod a $$
- //
- // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the
- // requested alignment.
- //
- // g = gcd(a, s)
- // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a)
- //
- // The first term is “the relative alignment of p to a”, the second term is “how does
- // incrementing p by s bytes change the relative alignment of p”. Division by `g` is
- // necessary to make this equation well formed if $a$ and $s$ are not co-prime.
- //
- // Furthermore, the result produced by this solution is not “minimal”, so it is necessary
- // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$.
- let j = a.wrapping_sub(pmoda) >> gcdpow;
- let k = smoda >> gcdpow;
- return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow);
- }
-
- // Cannot be aligned at all.
- usize::max_value()
-}
-
-
-
-// Equality for pointers
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *const T {
- #[inline]
- fn eq(&self, other: &*const T) -> bool { *self == *other }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *const T {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *mut T {
- #[inline]
- fn eq(&self, other: &*mut T) -> bool { *self == *other }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *mut T {}
-
-/// Compares raw pointers for equality.
-///
-/// This is the same as using the `==` operator, but less generic:
-/// the arguments have to be `*const T` raw pointers,
-/// not anything that implements `PartialEq`.
-///
-/// This can be used to compare `&T` references (which coerce to `*const T` implicitly)
-/// by their address rather than comparing the values they point to
-/// (which is what the `PartialEq for &T` implementation does).
-///
-/// # Examples
-///
-/// ```
-/// use std::ptr;
-///
-/// let five = 5;
-/// let other_five = 5;
-/// let five_ref = &five;
-/// let same_five_ref = &five;
-/// let other_five_ref = &other_five;
-///
-/// assert!(five_ref == same_five_ref);
-/// assert!(ptr::eq(five_ref, same_five_ref));
-///
-/// assert!(five_ref == other_five_ref);
-/// assert!(!ptr::eq(five_ref, other_five_ref));
-/// ```
-///
-/// Slices are also compared by their length (fat pointers):
-///
-/// ```
-/// let a = [1, 2, 3];
-/// assert!(std::ptr::eq(&a[..3], &a[..3]));
-/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
-/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
-/// ```
-///
-/// Traits are also compared by their implementation:
-///
-/// ```
-/// #[repr(transparent)]
-/// struct Wrapper { member: i32 }
-///
-/// trait Trait {}
-/// impl Trait for Wrapper {}
-/// impl Trait for i32 {}
-///
-/// fn main() {
-/// let wrapper = Wrapper { member: 10 };
-///
-/// // Pointers have equal addresses.
-/// assert!(std::ptr::eq(
-/// &wrapper as *const Wrapper as *const u8,
-/// &wrapper.member as *const i32 as *const u8
-/// ));
-///
-/// // Objects have equal addresses, but `Trait` has different implementations.
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait,
-/// &wrapper.member as &dyn Trait,
-/// ));
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait,
-/// &wrapper.member as &dyn Trait as *const dyn Trait,
-/// ));
-///
-/// // Converting the reference to a `*const u8` compares by address.
-/// assert!(std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
-/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
-/// ));
-/// }
-/// ```
-#[stable(feature = "ptr_eq", since = "1.17.0")]
-#[inline]
-pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
- a == b
-}
-
-/// Hash a raw pointer.
-///
-/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly)
-/// by its address rather than the value it points to
-/// (which is what the `Hash for &T` implementation does).
-///
-/// # Examples
-///
-/// ```
-/// use std::collections::hash_map::DefaultHasher;
-/// use std::hash::{Hash, Hasher};
-/// use std::ptr;
-///
-/// let five = 5;
-/// let five_ref = &five;
-///
-/// let mut hasher = DefaultHasher::new();
-/// ptr::hash(five_ref, &mut hasher);
-/// let actual = hasher.finish();
-///
-/// let mut hasher = DefaultHasher::new();
-/// (five_ref as *const i32).hash(&mut hasher);
-/// let expected = hasher.finish();
-///
-/// assert_eq!(actual, expected);
-/// ```
-#[stable(feature = "ptr_hash", since = "1.35.0")]
-pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
- use crate::hash::Hash;
- hashee.hash(into);
-}
-
-// Impls for function pointers
-macro_rules! fnptr_impls_safety_abi {
- ($FnTy: ty, $($Arg: ident),*) => {
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> PartialEq for $FnTy {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- *self as usize == *other as usize
- }
- }
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> Eq for $FnTy {}
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> PartialOrd for $FnTy {
- #[inline]
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- (*self as usize).partial_cmp(&(*other as usize))
- }
- }
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> Ord for $FnTy {
- #[inline]
- fn cmp(&self, other: &Self) -> Ordering {
- (*self as usize).cmp(&(*other as usize))
- }
- }
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> hash::Hash for $FnTy {
- fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
- state.write_usize(*self as usize)
- }
- }
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&(*self as *const ()), f)
- }
- }
-
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
- impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&(*self as *const ()), f)
- }
- }
- }
-}
-
-macro_rules! fnptr_impls_args {
- ($($Arg: ident),+) => {
- fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* }
- fnptr_impls_safety_abi! { extern "C" fn($($Arg),*) -> Ret, $($Arg),* }
- fnptr_impls_safety_abi! { extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* }
- fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* }
- fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),*) -> Ret, $($Arg),* }
- fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* }
- };
- () => {
- // No variadic functions with 0 parameters
- fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
- fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
- fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
- fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
- };
-}
-
-fnptr_impls_args! { }
-fnptr_impls_args! { A }
-fnptr_impls_args! { A, B }
-fnptr_impls_args! { A, B, C }
-fnptr_impls_args! { A, B, C, D }
-fnptr_impls_args! { A, B, C, D, E }
-fnptr_impls_args! { A, B, C, D, E, F }
-fnptr_impls_args! { A, B, C, D, E, F, G }
-fnptr_impls_args! { A, B, C, D, E, F, G, H }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
-
-// Comparison for pointers
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Ord for *const T {
- #[inline]
- fn cmp(&self, other: &*const T) -> Ordering {
- if self < other {
- Less
- } else if self == other {
- Equal
- } else {
- Greater
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialOrd for *const T {
- #[inline]
- fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-
- #[inline]
- fn lt(&self, other: &*const T) -> bool { *self < *other }
-
- #[inline]
- fn le(&self, other: &*const T) -> bool { *self <= *other }
-
- #[inline]
- fn gt(&self, other: &*const T) -> bool { *self > *other }
-
- #[inline]
- fn ge(&self, other: &*const T) -> bool { *self >= *other }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Ord for *mut T {
- #[inline]
- fn cmp(&self, other: &*mut T) -> Ordering {
- if self < other {
- Less
- } else if self == other {
- Equal
- } else {
- Greater
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialOrd for *mut T {
- #[inline]
- fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-
- #[inline]
- fn lt(&self, other: &*mut T) -> bool { *self < *other }
-
- #[inline]
- fn le(&self, other: &*mut T) -> bool { *self <= *other }
-
- #[inline]
- fn gt(&self, other: &*mut T) -> bool { *self > *other }
-
- #[inline]
- fn ge(&self, other: &*mut T) -> bool { *self >= *other }
-}
-
-/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
-/// of this wrapper owns the referent. Useful for building abstractions like
-/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
-///
-/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
-/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
-/// the kind of strong aliasing guarantees an instance of `T` can expect:
-/// the referent of the pointer should not be modified without a unique path to
-/// its owning Unique.
-///
-/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
-/// consider using `NonNull`, which has weaker semantics.
-///
-/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
-/// is never dereferenced. This is so that enums may use this forbidden value
-/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
-/// However the pointer may still dangle if it isn't dereferenced.
-///
-/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
-/// for any type which upholds Unique's aliasing requirements.
-#[unstable(feature = "ptr_internals", issue = "0",
- reason = "use NonNull instead and consider PhantomData<T> \
- (if you also use #[may_dangle]), Send, and/or Sync")]
-#[doc(hidden)]
-#[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(1)]
-pub struct Unique<T: ?Sized> {
- pointer: *const T,
- // NOTE: this marker has no consequences for variance, but is necessary
- // for dropck to understand that we logically own a `T`.
- //
- // For details, see:
- // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
- _marker: PhantomData<T>,
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> fmt::Debug for Unique<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&self.as_ptr(), f)
- }
-}
-
-/// `Unique` pointers are `Send` if `T` is `Send` because the data they
-/// reference is unaliased. Note that this aliasing invariant is
-/// unenforced by the type system; the abstraction using the
-/// `Unique` must enforce it.
-#[unstable(feature = "ptr_internals", issue = "0")]
-unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
-
-/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
-/// reference is unaliased. Note that this aliasing invariant is
-/// unenforced by the type system; the abstraction using the
-/// `Unique` must enforce it.
-#[unstable(feature = "ptr_internals", issue = "0")]
-unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: Sized> Unique<T> {
- /// Creates a new `Unique` that is dangling, but well-aligned.
- ///
- /// This is useful for initializing types which lazily allocate, like
- /// `Vec::new` does.
- ///
- /// Note that the pointer value may potentially represent a valid pointer to
- /// a `T`, which means this must not be used as a "not yet initialized"
- /// sentinel value. Types that lazily allocate must track initialization by
- /// some other means.
- // FIXME: rename to dangling() to match NonNull?
- pub const fn empty() -> Self {
- unsafe {
- Unique::new_unchecked(mem::align_of::<T>() as *mut T)
- }
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> Unique<T> {
- /// Creates a new `Unique`.
- ///
- /// # Safety
- ///
- /// `ptr` must be non-null.
- pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
- Unique { pointer: ptr as _, _marker: PhantomData }
- }
-
- /// Creates a new `Unique` if `ptr` is non-null.
- pub fn new(ptr: *mut T) -> Option<Self> {
- if !ptr.is_null() {
- Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
- } else {
- None
- }
- }
-
- /// Acquires the underlying `*mut` pointer.
- pub const fn as_ptr(self) -> *mut T {
- self.pointer as *mut T
- }
-
- /// Dereferences the content.
- ///
- /// The resulting lifetime is bound to self so this behaves "as if"
- /// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
- pub unsafe fn as_ref(&self) -> &T {
- &*self.as_ptr()
- }
-
- /// Mutably dereferences the content.
- ///
- /// The resulting lifetime is bound to self so this behaves "as if"
- /// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
- pub unsafe fn as_mut(&mut self) -> &mut T {
- &mut *self.as_ptr()
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> Clone for Unique<T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> Copy for Unique<T> { }
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> fmt::Pointer for Unique<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&self.as_ptr(), f)
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> From<&mut T> for Unique<T> {
- fn from(reference: &mut T) -> Self {
- unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> From<&T> for Unique<T> {
- fn from(reference: &T) -> Self {
- unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
- fn from(p: NonNull<T>) -> Self {
- unsafe { Unique { pointer: p.pointer, _marker: PhantomData } }
- }
-}
-
-/// `*mut T` but non-zero and covariant.
-///
-/// This is often the correct thing to use when building data structures using
-/// raw pointers, but is ultimately more dangerous to use because of its additional
-/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
-///
-/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
-/// is never dereferenced. This is so that enums may use this forbidden value
-/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
-/// However the pointer may still dangle if it isn't dereferenced.
-///
-/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
-/// for your use case, you should include some [`PhantomData`] in your type to
-/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
-/// Usually this won't be necessary; covariance is correct for most safe abstractions,
-/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
-/// provide a public API that follows the normal shared XOR mutable rules of Rust.
-///
-/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
-/// not change the fact that mutating through a (pointer derived from a) shared
-/// reference is undefined behavior unless the mutation happens inside an
-/// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared
-/// reference. When using this `From` instance without an `UnsafeCell<T>`,
-/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
-/// is never used for mutation.
-///
-/// [`PhantomData`]: ../marker/struct.PhantomData.html
-/// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
-#[stable(feature = "nonnull", since = "1.25.0")]
-#[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(1)]
-#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
-pub struct NonNull<T: ?Sized> {
- pointer: *const T,
-}
-
-/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
-// N.B., this impl is unnecessary, but should provide better error messages.
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> !Send for NonNull<T> { }
-
-/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
-// N.B., this impl is unnecessary, but should provide better error messages.
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> !Sync for NonNull<T> { }
-
-impl<T: Sized> NonNull<T> {
- /// Creates a new `NonNull` that is dangling, but well-aligned.
- ///
- /// This is useful for initializing types which lazily allocate, like
- /// `Vec::new` does.
- ///
- /// Note that the pointer value may potentially represent a valid pointer to
- /// a `T`, which means this must not be used as a "not yet initialized"
- /// sentinel value. Types that lazily allocate must track initialization by
- /// some other means.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub const fn dangling() -> Self {
- unsafe {
- let ptr = mem::align_of::<T>() as *mut T;
- NonNull::new_unchecked(ptr)
- }
- }
-}
-
-impl<T: ?Sized> NonNull<T> {
- /// Creates a new `NonNull`.
- ///
- /// # Safety
- ///
- /// `ptr` must be non-null.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
- NonNull { pointer: ptr as _ }
- }
-
- /// Creates a new `NonNull` if `ptr` is non-null.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub fn new(ptr: *mut T) -> Option<Self> {
- if !ptr.is_null() {
- Some(unsafe { Self::new_unchecked(ptr) })
- } else {
- None
- }
- }
-
- /// Acquires the underlying `*mut` pointer.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub const fn as_ptr(self) -> *mut T {
- self.pointer as *mut T
- }
-
- /// Dereferences the content.
- ///
- /// The resulting lifetime is bound to self so this behaves "as if"
- /// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub unsafe fn as_ref(&self) -> &T {
- &*self.as_ptr()
- }
-
- /// Mutably dereferences the content.
- ///
- /// The resulting lifetime is bound to self so this behaves "as if"
- /// it were actually an instance of T that is getting borrowed. If a longer
- /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
- #[stable(feature = "nonnull", since = "1.25.0")]
- #[inline]
- pub unsafe fn as_mut(&mut self) -> &mut T {
- &mut *self.as_ptr()
- }
-
- /// Cast to a pointer of another type
- #[stable(feature = "nonnull_cast", since = "1.27.0")]
- #[inline]
- pub const fn cast<U>(self) -> NonNull<U> {
- unsafe {
- NonNull::new_unchecked(self.as_ptr() as *mut U)
- }
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Clone for NonNull<T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Copy for NonNull<T> { }
-
-#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
-
-#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> fmt::Debug for NonNull<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&self.as_ptr(), f)
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> fmt::Pointer for NonNull<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Pointer::fmt(&self.as_ptr(), f)
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Eq for NonNull<T> {}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> PartialEq for NonNull<T> {
- #[inline]
- fn eq(&self, other: &Self) -> bool {
- self.as_ptr() == other.as_ptr()
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Ord for NonNull<T> {
- #[inline]
- fn cmp(&self, other: &Self) -> Ordering {
- self.as_ptr().cmp(&other.as_ptr())
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> PartialOrd for NonNull<T> {
- #[inline]
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- self.as_ptr().partial_cmp(&other.as_ptr())
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> hash::Hash for NonNull<T> {
- #[inline]
- fn hash<H: hash::Hasher>(&self, state: &mut H) {
- self.as_ptr().hash(state)
- }
-}
-
-#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
- #[inline]
- fn from(unique: Unique<T>) -> Self {
- unsafe { NonNull { pointer: unique.pointer } }
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> From<&mut T> for NonNull<T> {
- #[inline]
- fn from(reference: &mut T) -> Self {
- unsafe { NonNull { pointer: reference as *mut T } }
- }
-}
-
-#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> From<&T> for NonNull<T> {
- #[inline]
- fn from(reference: &T) -> Self {
- unsafe { NonNull { pointer: reference as *const T } }
- }
-}
--- /dev/null
+//! Manually manage memory through raw pointers.
+//!
+//! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
+//!
+//! # Safety
+//!
+//! Many functions in this module take raw pointers as arguments and read from
+//! or write to them. For this to be safe, these pointers must be *valid*.
+//! Whether a pointer is valid depends on the operation it is used for
+//! (read or write), and the extent of the memory that is accessed (i.e.,
+//! how many bytes are read/written). Most functions use `*mut T` and `*const T`
+//! to access only a single value, in which case the documentation omits the size
+//! and implicitly assumes it to be `size_of::<T>()` bytes.
+//!
+//! The precise rules for validity are not determined yet. The guarantees that are
+//! provided at this point are very minimal:
+//!
+//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
+//! * All pointers (except for the null pointer) are valid for all operations of
+//! [size zero][zst].
+//! * All accesses performed by functions in this module are *non-atomic* in the sense
+//! of [atomic operations] used to synchronize between threads. This means it is
+//! undefined behavior to perform two concurrent accesses to the same location from different
+//! threads unless both accesses only read from memory. Notice that this explicitly
+//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
+//! be used for inter-thread synchronization.
+//! * The result of casting a reference to a pointer is valid for as long as the
+//! underlying object is live and no reference (just raw pointers) is used to
+//! access the same memory.
+//!
+//! These axioms, along with careful use of [`offset`] for pointer arithmetic,
+//! are enough to correctly implement many useful things in unsafe code. Stronger guarantees
+//! will be provided eventually, as the [aliasing] rules are being determined. For more
+//! information, see the [book] as well as the section in the reference devoted
+//! to [undefined behavior][ub].
+//!
+//! ## Alignment
+//!
+//! Valid raw pointers as defined above are not necessarily properly aligned (where
+//! "proper" alignment is defined by the pointee type, i.e., `*const T` must be
+//! aligned to `mem::align_of::<T>()`). However, most functions require their
+//! arguments to be properly aligned, and will explicitly state
+//! this requirement in their documentation. Notable exceptions to this are
+//! [`read_unaligned`] and [`write_unaligned`].
+//!
+//! When a function requires proper alignment, it does so even if the access
+//! has size 0, i.e., even if memory is not actually touched. Consider using
+//! [`NonNull::dangling`] in such cases.
+//!
+//! [aliasing]: ../../nomicon/aliasing.html
+//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
+//! [ub]: ../../reference/behavior-considered-undefined.html
+//! [null]: ./fn.null.html
+//! [zst]: ../../nomicon/exotic-sizes.html#zero-sized-types-zsts
+//! [atomic operations]: ../../std/sync/atomic/index.html
+//! [`copy`]: ../../std/ptr/fn.copy.html
+//! [`offset`]: ../../std/primitive.pointer.html#method.offset
+//! [`read_unaligned`]: ./fn.read_unaligned.html
+//! [`write_unaligned`]: ./fn.write_unaligned.html
+//! [`read_volatile`]: ./fn.read_volatile.html
+//! [`write_volatile`]: ./fn.write_volatile.html
+//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use crate::intrinsics;
+use crate::fmt;
+use crate::hash;
+use crate::mem::{self, MaybeUninit};
+use crate::cmp::Ordering::{self, Less, Equal, Greater};
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::intrinsics::copy_nonoverlapping;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::intrinsics::copy;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::intrinsics::write_bytes;
+
+mod non_null;
+#[stable(feature = "nonnull", since = "1.25.0")]
+pub use non_null::NonNull;
+
+mod unique;
+#[unstable(feature = "ptr_internals", issue = "0")]
+pub use unique::Unique;
+
+/// Executes the destructor (if any) of the pointed-to value.
+///
+/// This is semantically equivalent to calling [`ptr::read`] and discarding
+/// the result, but has the following advantages:
+///
+/// * It is *required* to use `drop_in_place` to drop unsized types like
+/// trait objects, because they can't be read out onto the stack and
+/// dropped normally.
+///
+/// * It is friendlier to the optimizer to do this over [`ptr::read`] when
+/// dropping manually allocated memory (e.g., when writing Box/Rc/Vec),
+/// as the compiler doesn't need to prove that it's sound to elide the
+/// copy.
+///
+/// [`ptr::read`]: ../ptr/fn.read.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `to_drop` must be [valid] for reads.
+///
+/// * `to_drop` must be properly aligned. See the example below for how to drop
+/// an unaligned pointer.
+///
+/// Additionally, if `T` is not [`Copy`], using the pointed-to value after
+/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
+/// foo` counts as a use because it will cause the value to be dropped
+/// again. [`write`] can be used to overwrite data without causing it to be
+/// dropped.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`write`]: ../ptr/fn.write.html
+///
+/// # Examples
+///
+/// Manually remove the last item from a vector:
+///
+/// ```
+/// use std::ptr;
+/// use std::rc::Rc;
+///
+/// let last = Rc::new(1);
+/// let weak = Rc::downgrade(&last);
+///
+/// let mut v = vec![Rc::new(0), last];
+///
+/// unsafe {
+/// // Get a raw pointer to the last element in `v`.
+/// let ptr = &mut v[1] as *mut _;
+/// // Shorten `v` to prevent the last item from being dropped. We do that first,
+/// // to prevent issues if the `drop_in_place` below panics.
+/// v.set_len(1);
+/// // Without a call `drop_in_place`, the last item would never be dropped,
+/// // and the memory it manages would be leaked.
+/// ptr::drop_in_place(ptr);
+/// }
+///
+/// assert_eq!(v, &[0.into()]);
+///
+/// // Ensure that the last item was dropped.
+/// assert!(weak.upgrade().is_none());
+/// ```
+///
+/// Unaligned values cannot be dropped in place, they must be copied to an aligned
+/// location first:
+/// ```
+/// use std::ptr;
+/// use std::mem::{self, MaybeUninit};
+///
+/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
+/// let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
+/// ptr::copy(to_drop, copy.as_mut_ptr(), 1);
+/// drop(copy.assume_init());
+/// }
+///
+/// #[repr(packed, C)]
+/// struct Packed {
+/// _padding: u8,
+/// unaligned: Vec<i32>,
+/// }
+///
+/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
+/// unsafe {
+/// drop_after_copy(&mut p.unaligned as *mut _);
+/// mem::forget(p);
+/// }
+/// ```
+///
+/// Notice that the compiler performs this copy automatically when dropping packed structs,
+/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
+/// manually.
+#[stable(feature = "drop_in_place", since = "1.8.0")]
+#[inline(always)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+ real_drop_in_place(&mut *to_drop)
+}
+
+// The real `drop_in_place` -- the one that gets called implicitly when variables go
+// out of scope -- should have a safe reference and not a raw pointer as argument
+// type. When we drop a local variable, we access it with a pointer that behaves
+// like a safe reference; transmuting that to a raw pointer does not mean we can
+// actually access it with raw pointers.
+#[lang = "drop_in_place"]
+#[allow(unconditional_recursion)]
+unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
+ // Code here does not matter - this is replaced by the
+ // real drop glue by the compiler.
+ real_drop_in_place(to_drop)
+}
+
+/// Creates a null raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *const i32 = ptr::null();
+/// assert!(p.is_null());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+pub const fn null<T>() -> *const T { 0 as *const T }
+
+/// Creates a null mutable raw pointer.
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let p: *mut i32 = ptr::null_mut();
+/// assert!(p.is_null());
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_promotable]
+pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
+
+/// Swaps the values at two mutable locations of the same type, without
+/// deinitializing either.
+///
+/// But for the following two exceptions, this function is semantically
+/// equivalent to [`mem::swap`]:
+///
+/// * It operates on raw pointers instead of references. When references are
+/// available, [`mem::swap`] should be preferred.
+///
+/// * The two pointed-to values may overlap. If the values do overlap, then the
+/// overlapping region of memory from `x` will be used. This is demonstrated
+/// in the second example below.
+///
+/// [`mem::swap`]: ../mem/fn.swap.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * Both `x` and `y` must be [valid] for reads and writes.
+///
+/// * Both `x` and `y` must be properly aligned.
+///
+/// Note that even if `T` has size `0`, the pointers must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// # Examples
+///
+/// Swapping two non-overlapping regions:
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut array = [0, 1, 2, 3];
+///
+/// let x = array[0..].as_mut_ptr() as *mut [u32; 2]; // this is `array[0..2]`
+/// let y = array[2..].as_mut_ptr() as *mut [u32; 2]; // this is `array[2..4]`
+///
+/// unsafe {
+/// ptr::swap(x, y);
+/// assert_eq!([2, 3, 0, 1], array);
+/// }
+/// ```
+///
+/// Swapping two overlapping regions:
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut array = [0, 1, 2, 3];
+///
+/// let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]`
+/// let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]`
+///
+/// unsafe {
+/// ptr::swap(x, y);
+/// // The indices `1..3` of the slice overlap between `x` and `y`.
+/// // Reasonable results would be for to them be `[2, 3]`, so that indices `0..3` are
+/// // `[1, 2, 3]` (matching `y` before the `swap`); or for them to be `[0, 1]`
+/// // so that indices `1..4` are `[0, 1, 2]` (matching `x` before the `swap`).
+/// // This implementation is defined to make the latter choice.
+/// assert_eq!([1, 0, 1, 2], array);
+/// }
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
+ // Give ourselves some scratch space to work with.
+ // We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
+ let mut tmp = MaybeUninit::<T>::uninit();
+
+ // Perform the swap
+ copy_nonoverlapping(x, tmp.as_mut_ptr(), 1);
+ copy(y, x, 1); // `x` and `y` may overlap
+ copy_nonoverlapping(tmp.as_ptr(), y, 1);
+}
+
+/// Swaps `count * size_of::<T>()` bytes between the two regions of memory
+/// beginning at `x` and `y`. The two regions must *not* overlap.
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * Both `x` and `y` must be [valid] for reads and writes of `count *
+/// size_of::<T>()` bytes.
+///
+/// * Both `x` and `y` must be properly aligned.
+///
+/// * The region of memory beginning at `x` with a size of `count *
+/// size_of::<T>()` bytes must *not* overlap with the region of memory
+/// beginning at `y` with the same size.
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
+/// the pointers must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut x = [1, 2, 3, 4];
+/// let mut y = [7, 8, 9];
+///
+/// unsafe {
+/// ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2);
+/// }
+///
+/// assert_eq!(x, [7, 8, 3, 4]);
+/// assert_eq!(y, [1, 2, 9]);
+/// ```
+#[inline]
+#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
+pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ let x = x as *mut u8;
+ let y = y as *mut u8;
+ let len = mem::size_of::<T>() * count;
+ swap_nonoverlapping_bytes(x, y, len)
+}
+
+#[inline]
+pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+ // For types smaller than the block optimization below,
+ // just swap directly to avoid pessimizing codegen.
+ if mem::size_of::<T>() < 32 {
+ let z = read(x);
+ copy_nonoverlapping(y, x, 1);
+ write(y, z);
+ } else {
+ swap_nonoverlapping(x, y, 1);
+ }
+}
+
+#[inline]
+unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+ // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
+ // that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
+ // Haswell E processors. LLVM is more able to optimize if we give a struct a
+ // #[repr(simd)], even if we don't actually use this struct directly.
+ //
+ // FIXME repr(simd) broken on emscripten and redox
+ #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
+ struct Block(u64, u64, u64, u64);
+ struct UnalignedBlock(u64, u64, u64, u64);
+
+ let block_size = mem::size_of::<Block>();
+
+ // Loop through x & y, copying them `Block` at a time
+ // The optimizer should unroll the loop fully for most types
+ // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+ let mut i = 0;
+ while i + block_size <= len {
+ // Create some uninitialized memory as scratch space
+ // Declaring `t` here avoids aligning the stack when this loop is unused
+ let mut t = mem::MaybeUninit::<Block>::uninit();
+ let t = t.as_mut_ptr() as *mut u8;
+ let x = x.add(i);
+ let y = y.add(i);
+
+ // Swap a block of bytes of x & y, using t as a temporary buffer
+ // This should be optimized into efficient SIMD operations where available
+ copy_nonoverlapping(x, t, block_size);
+ copy_nonoverlapping(y, x, block_size);
+ copy_nonoverlapping(t, y, block_size);
+ i += block_size;
+ }
+
+ if i < len {
+ // Swap any remaining bytes
+ let mut t = mem::MaybeUninit::<UnalignedBlock>::uninit();
+ let rem = len - i;
+
+ let t = t.as_mut_ptr() as *mut u8;
+ let x = x.add(i);
+ let y = y.add(i);
+
+ copy_nonoverlapping(x, t, rem);
+ copy_nonoverlapping(y, x, rem);
+ copy_nonoverlapping(t, y, rem);
+ }
+}
+
+/// Moves `src` into the pointed `dst`, returning the previous `dst` value.
+///
+/// Neither value is dropped.
+///
+/// This function is semantically equivalent to [`mem::replace`] except that it
+/// operates on raw pointers instead of references. When references are
+/// available, [`mem::replace`] should be preferred.
+///
+/// [`mem::replace`]: ../mem/fn.replace.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// * `dst` must be properly aligned.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut rust = vec!['b', 'u', 's', 't'];
+///
+/// // `mem::replace` would have the same effect without requiring the unsafe
+/// // block.
+/// let b = unsafe {
+/// ptr::replace(&mut rust[0], 'r')
+/// };
+///
+/// assert_eq!(b, 'b');
+/// assert_eq!(rust, &['r', 'u', 's', 't']);
+/// ```
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
+ mem::swap(&mut *dst, &mut src); // cannot overlap
+ src
+}
+
+/// Reads the value from `src` without moving it. This leaves the
+/// memory in `src` unchanged.
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the
+/// case.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let x = 12;
+/// let y = &x as *const i32;
+///
+/// unsafe {
+/// assert_eq!(std::ptr::read(y), 12);
+/// }
+/// ```
+///
+/// Manually implement [`mem::swap`]:
+///
+/// ```
+/// use std::ptr;
+///
+/// fn swap<T>(a: &mut T, b: &mut T) {
+/// unsafe {
+/// // Create a bitwise copy of the value at `a` in `tmp`.
+/// let tmp = ptr::read(a);
+///
+/// // Exiting at this point (either by explicitly returning or by
+/// // calling a function which panics) would cause the value in `tmp` to
+/// // be dropped while the same value is still referenced by `a`. This
+/// // could trigger undefined behavior if `T` is not `Copy`.
+///
+/// // Create a bitwise copy of the value at `b` in `a`.
+/// // This is safe because mutable references cannot alias.
+/// ptr::copy_nonoverlapping(b, a, 1);
+///
+/// // As above, exiting here could trigger undefined behavior because
+/// // the same value is referenced by `a` and `b`.
+///
+/// // Move `tmp` into `b`.
+/// ptr::write(b, tmp);
+///
+/// // `tmp` has been moved (`write` takes ownership of its second argument),
+/// // so nothing is dropped implicitly here.
+/// }
+/// }
+///
+/// let mut foo = "foo".to_owned();
+/// let mut bar = "bar".to_owned();
+///
+/// swap(&mut foo, &mut bar);
+///
+/// assert_eq!(foo, "bar");
+/// assert_eq!(bar, "foo");
+/// ```
+///
+/// ## Ownership of the Returned Value
+///
+/// `read` creates a bitwise copy of `T`, regardless of whether `T` is [`Copy`].
+/// If `T` is not [`Copy`], using both the returned value and the value at
+/// `*src` can violate memory safety. Note that assigning to `*src` counts as a
+/// use because it will attempt to drop the value at `*src`.
+///
+/// [`write`] can be used to overwrite data without causing it to be dropped.
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut s = String::from("foo");
+/// unsafe {
+/// // `s2` now points to the same underlying memory as `s`.
+/// let mut s2: String = ptr::read(&s);
+///
+/// assert_eq!(s2, "foo");
+///
+/// // Assigning to `s2` causes its original value to be dropped. Beyond
+/// // this point, `s` must no longer be used, as the underlying memory has
+/// // been freed.
+/// s2 = String::default();
+/// assert_eq!(s2, "");
+///
+/// // Assigning to `s` would cause the old value to be dropped again,
+/// // resulting in undefined behavior.
+/// // s = String::from("bar"); // ERROR
+///
+/// // `ptr::write` can be used to overwrite a value without dropping it.
+/// ptr::write(&mut s, String::from("bar"));
+/// }
+///
+/// assert_eq!(s, "bar");
+/// ```
+///
+/// [`mem::swap`]: ../mem/fn.swap.html
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read_unaligned`]: ./fn.read_unaligned.html
+/// [`write`]: ./fn.write.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn read<T>(src: *const T) -> T {
+ let mut tmp = MaybeUninit::<T>::uninit();
+ copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+ tmp.assume_init()
+}
+
+/// Reads the value from `src` without moving it. This leaves the
+/// memory in `src` unchanged.
+///
+/// Unlike [`read`], `read_unaligned` works with unaligned pointers.
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
+/// value and the value at `*src` can [violate memory safety][read-ownership].
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL.
+///
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read`]: ./fn.read.html
+/// [`write_unaligned`]: ./fn.write_unaligned.html
+/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
+/// [valid]: ../ptr/index.html#safety
+///
+/// # Examples
+///
+/// Access members of a packed struct by reference:
+///
+/// ```
+/// use std::ptr;
+///
+/// #[repr(packed, C)]
+/// struct Packed {
+/// _padding: u8,
+/// unaligned: u32,
+/// }
+///
+/// let x = Packed {
+/// _padding: 0x00,
+/// unaligned: 0x01020304,
+/// };
+///
+/// let v = unsafe {
+/// // Take the address of a 32-bit integer which is not aligned.
+/// // This must be done as a raw pointer; unaligned references are invalid.
+/// let unaligned = &x.unaligned as *const u32;
+///
+/// // Dereferencing normally will emit an aligned load instruction,
+/// // causing undefined behavior.
+/// // let v = *unaligned; // ERROR
+///
+/// // Instead, use `read_unaligned` to read improperly aligned values.
+/// let v = ptr::read_unaligned(unaligned);
+///
+/// v
+/// };
+///
+/// // Accessing unaligned values directly is safe.
+/// assert!(x.unaligned == v);
+/// ```
+#[inline]
+#[stable(feature = "ptr_unaligned", since = "1.17.0")]
+pub unsafe fn read_unaligned<T>(src: *const T) -> T {
+ let mut tmp = MaybeUninit::<T>::uninit();
+ copy_nonoverlapping(src as *const u8,
+ tmp.as_mut_ptr() as *mut u8,
+ mem::size_of::<T>());
+ tmp.assume_init()
+}
+
+/// Overwrites a memory location with the given value without reading or
+/// dropping the old value.
+///
+/// `write` does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care should be taken not to overwrite an object
+/// that should be dropped.
+///
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
+///
+/// This is appropriate for initializing uninitialized memory, or overwriting
+/// memory that has previously been [`read`] from.
+///
+/// [`read`]: ./fn.read.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
+/// case.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`write_unaligned`]: ./fn.write_unaligned.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let mut x = 0;
+/// let y = &mut x as *mut i32;
+/// let z = 12;
+///
+/// unsafe {
+/// std::ptr::write(y, z);
+/// assert_eq!(std::ptr::read(y), 12);
+/// }
+/// ```
+///
+/// Manually implement [`mem::swap`]:
+///
+/// ```
+/// use std::ptr;
+///
+/// fn swap<T>(a: &mut T, b: &mut T) {
+/// unsafe {
+/// // Create a bitwise copy of the value at `a` in `tmp`.
+/// let tmp = ptr::read(a);
+///
+/// // Exiting at this point (either by explicitly returning or by
+/// // calling a function which panics) would cause the value in `tmp` to
+/// // be dropped while the same value is still referenced by `a`. This
+/// // could trigger undefined behavior if `T` is not `Copy`.
+///
+/// // Create a bitwise copy of the value at `b` in `a`.
+/// // This is safe because mutable references cannot alias.
+/// ptr::copy_nonoverlapping(b, a, 1);
+///
+/// // As above, exiting here could trigger undefined behavior because
+/// // the same value is referenced by `a` and `b`.
+///
+/// // Move `tmp` into `b`.
+/// ptr::write(b, tmp);
+///
+/// // `tmp` has been moved (`write` takes ownership of its second argument),
+/// // so nothing is dropped implicitly here.
+/// }
+/// }
+///
+/// let mut foo = "foo".to_owned();
+/// let mut bar = "bar".to_owned();
+///
+/// swap(&mut foo, &mut bar);
+///
+/// assert_eq!(foo, "bar");
+/// assert_eq!(bar, "foo");
+/// ```
+///
+/// [`mem::swap`]: ../mem/fn.swap.html
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub unsafe fn write<T>(dst: *mut T, src: T) {
+ intrinsics::move_val_init(&mut *dst, src)
+}
+
+/// Overwrites a memory location with the given value without reading or
+/// dropping the old value.
+///
+/// Unlike [`write`], the pointer may be unaligned.
+///
+/// `write_unaligned` does not drop the contents of `dst`. This is safe, but it
+/// could leak allocations or resources, so care should be taken not to overwrite
+/// an object that should be dropped.
+///
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
+///
+/// This is appropriate for initializing uninitialized memory, or overwriting
+/// memory that has previously been read with [`read_unaligned`].
+///
+/// [`write`]: ./fn.write.html
+/// [`read_unaligned`]: ./fn.read_unaligned.html
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// # Examples
+///
+/// Access fields in a packed struct:
+///
+/// ```
+/// use std::{mem, ptr};
+///
+/// #[repr(packed, C)]
+/// #[derive(Default)]
+/// struct Packed {
+/// _padding: u8,
+/// unaligned: u32,
+/// }
+///
+/// let v = 0x01020304;
+/// let mut x: Packed = unsafe { mem::zeroed() };
+///
+/// unsafe {
+/// // Take a reference to a 32-bit integer which is not aligned.
+/// let unaligned = &mut x.unaligned as *mut u32;
+///
+/// // Dereferencing normally will emit an aligned store instruction,
+/// // causing undefined behavior because the pointer is not aligned.
+/// // *unaligned = v; // ERROR
+///
+/// // Instead, use `write_unaligned` to write improperly aligned values.
+/// ptr::write_unaligned(unaligned, v);
+/// }
+///
+/// // Accessing unaligned values directly is safe.
+/// assert!(x.unaligned == v);
+/// ```
+#[inline]
+#[stable(feature = "ptr_unaligned", since = "1.17.0")]
+pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
+ copy_nonoverlapping(&src as *const T as *const u8,
+ dst as *mut u8,
+ mem::size_of::<T>());
+ mem::forget(src);
+}
+
+/// Performs a volatile read of the value from `src` without moving it. This
+/// leaves the memory in `src` unchanged.
+///
+/// Volatile operations are intended to act on I/O memory, and are guaranteed
+/// to not be elided or reordered by the compiler across other volatile
+/// operations.
+///
+/// [`write_volatile`]: ./fn.write_volatile.html
+///
+/// # Notes
+///
+/// Rust does not currently have a rigorously and formally defined memory model,
+/// so the precise semantics of what "volatile" means here is subject to change
+/// over time. That being said, the semantics will almost always end up pretty
+/// similar to [C11's definition of volatile][c11].
+///
+/// The compiler shouldn't change the relative order or number of volatile
+/// memory operations. However, volatile memory operations on zero-sized types
+/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
+/// and may be ignored.
+///
+/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads.
+///
+/// * `src` must be properly aligned.
+///
+/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
+/// value and the value at `*src` can [violate memory safety][read-ownership].
+/// However, storing non-[`Copy`] types in volatile memory is almost certainly
+/// incorrect.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+/// [`Copy`]: ../marker/trait.Copy.html
+/// [`read`]: ./fn.read.html
+/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
+///
+/// Just like in C, whether an operation is volatile has no bearing whatsoever
+/// on questions involving concurrent access from multiple threads. Volatile
+/// accesses behave exactly like non-atomic accesses in that regard. In particular,
+/// a race between a `read_volatile` and any write operation to the same location
+/// is undefined behavior.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let x = 12;
+/// let y = &x as *const i32;
+///
+/// unsafe {
+/// assert_eq!(std::ptr::read_volatile(y), 12);
+/// }
+/// ```
+#[inline]
+#[stable(feature = "volatile", since = "1.9.0")]
+pub unsafe fn read_volatile<T>(src: *const T) -> T {
+ intrinsics::volatile_load(src)
+}
+
+/// Performs a volatile write of a memory location with the given value without
+/// reading or dropping the old value.
+///
+/// Volatile operations are intended to act on I/O memory, and are guaranteed
+/// to not be elided or reordered by the compiler across other volatile
+/// operations.
+///
+/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
+/// could leak allocations or resources, so care should be taken not to overwrite
+/// an object that should be dropped.
+///
+/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+/// location pointed to by `dst`.
+///
+/// [`read_volatile`]: ./fn.read_volatile.html
+///
+/// # Notes
+///
+/// Rust does not currently have a rigorously and formally defined memory model,
+/// so the precise semantics of what "volatile" means here is subject to change
+/// over time. That being said, the semantics will almost always end up pretty
+/// similar to [C11's definition of volatile][c11].
+///
+/// The compiler shouldn't change the relative order or number of volatile
+/// memory operations. However, volatile memory operations on zero-sized types
+/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops
+/// and may be ignored.
+///
+/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes.
+///
+/// * `dst` must be properly aligned.
+///
+/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned.
+///
+/// [valid]: ../ptr/index.html#safety
+///
+/// Just like in C, whether an operation is volatile has no bearing whatsoever
+/// on questions involving concurrent access from multiple threads. Volatile
+/// accesses behave exactly like non-atomic accesses in that regard. In particular,
+/// a race between a `write_volatile` and any other operation (reading or writing)
+/// on the same location is undefined behavior.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let mut x = 0;
+/// let y = &mut x as *mut i32;
+/// let z = 12;
+///
+/// unsafe {
+/// std::ptr::write_volatile(y, z);
+/// assert_eq!(std::ptr::read_volatile(y), 12);
+/// }
+/// ```
+#[inline]
+#[stable(feature = "volatile", since = "1.9.0")]
+pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
+ intrinsics::volatile_store(dst, src);
+}
+
+#[lang = "const_ptr"]
+impl<T: ?Sized> *const T {
+ /// Returns `true` if the pointer is null.
+ ///
+ /// Note that unsized types have many possible null pointers, as only the
+ /// raw data pointer is considered, not their length, vtable, etc.
+ /// Therefore, two pointers that are null may still not compare equal to
+ /// each other.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "Follow the rabbit";
+ /// let ptr: *const u8 = s.as_ptr();
+ /// assert!(!ptr.is_null());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub fn is_null(self) -> bool {
+ // Compare via a cast to a thin pointer, so fat pointers are only
+ // considering their "data" part for null-ness.
+ (self as *const u8) == null()
+ }
+
+ /// Cast to a pointer to a different type
+ #[unstable(feature = "ptr_cast", issue = "60602")]
+ #[inline]
+ pub const fn cast<U>(self) -> *const U {
+ self as _
+ }
+
+ /// Returns `None` if the pointer is null, or else returns a reference to
+ /// the value wrapped in `Some`.
+ ///
+ /// # Safety
+ ///
+ /// While this method and its mutable counterpart are useful for
+ /// null-safety, it is important to note that this is still an unsafe
+ /// operation because the returned value could be pointing to invalid
+ /// memory.
+ ///
+ /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
+ /// not necessarily reflect the actual lifetime of the data.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let ptr: *const u8 = &10u8 as *const u8;
+ ///
+ /// unsafe {
+ /// if let Some(val_back) = ptr.as_ref() {
+ /// println!("We got back the value: {}!", val_back);
+ /// }
+ /// }
+ /// ```
+ ///
+ /// # Null-unchecked version
+ ///
+ /// If you are sure the pointer can never be null and are looking for some kind of
+ /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
+ /// dereference the pointer directly.
+ ///
+ /// ```
+ /// let ptr: *const u8 = &10u8 as *const u8;
+ ///
+ /// unsafe {
+ /// let val_back = &*ptr;
+ /// println!("We got back the value: {}!", val_back);
+ /// }
+ /// ```
+ #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+ #[inline]
+ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+ if self.is_null() {
+ None
+ } else {
+ Some(&*self)
+ }
+ }
+
+ /// Calculates the offset from a pointer.
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "123";
+ /// let ptr: *const u8 = s.as_ptr();
+ ///
+ /// unsafe {
+ /// println!("{}", *ptr.offset(1) as char);
+ /// println!("{}", *ptr.offset(2) as char);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
+ intrinsics::offset(self, count)
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ /// In particular, the resulting pointer may *not* be used to access a
+ /// different allocated object than the one `self` points to. In other
+ /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+ /// *not* the same as `y`, and dereferencing it is undefined behavior
+ /// unless `x` and `y` point into the same allocated object.
+ ///
+ /// Always use `.offset(count)` instead when possible, because `offset`
+ /// allows the compiler to optimize better. If you need to cross object
+ /// boundaries, cast the pointer to an integer and do the arithmetic there.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements
+ /// let data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *const u8 = data.as_ptr();
+ /// let step = 2;
+ /// let end_rounded_up = ptr.wrapping_offset(6);
+ ///
+ /// // This loop prints "1, 3, 5, "
+ /// while ptr != end_rounded_up {
+ /// unsafe {
+ /// print!("{}, ", *ptr);
+ /// }
+ /// ptr = ptr.wrapping_offset(step);
+ /// }
+ /// ```
+ #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
+ #[inline]
+ pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized {
+ unsafe {
+ intrinsics::arith_offset(self, count)
+ }
+ }
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// This function is the inverse of [`offset`].
+ ///
+ /// [`offset`]: #method.offset
+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and other pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The distance between the pointers, in bytes, must be an exact multiple
+ /// of the size of `T`.
+ ///
+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
+ ///
+ /// The compiler and standard library generally try to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(ptr_offset_from)]
+ ///
+ /// let a = [0; 5];
+ /// let ptr1: *const i32 = &a[1];
+ /// let ptr2: *const i32 = &a[3];
+ /// unsafe {
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
+ /// assert_eq!(ptr1.offset(2), ptr2);
+ /// assert_eq!(ptr2.offset(-2), ptr1);
+ /// }
+ /// ```
+ #[unstable(feature = "ptr_offset_from", issue = "41079")]
+ #[inline]
+ pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+ let pointee_size = mem::size_of::<T>();
+ assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+
+ // This is the same sequence that Clang emits for pointer subtraction.
+ // It can be neither `nsw` nor `nuw` because the input is treated as
+ // unsigned but then the output is treated as signed, so neither works.
+ let d = isize::wrapping_sub(self as _, origin as _);
+ intrinsics::exact_div(d, pointee_size as _)
+ }
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// If the address different between the two pointers is not a multiple of
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
+ /// zero.
+ ///
+ /// Though this method is safe for any two pointers, note that its result
+ /// will be mostly useless if the two pointers aren't into the same allocated
+ /// object, for example if they point to two different local variables.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(ptr_wrapping_offset_from)]
+ ///
+ /// let a = [0; 5];
+ /// let ptr1: *const i32 = &a[1];
+ /// let ptr2: *const i32 = &a[3];
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
+ ///
+ /// let ptr1: *const i32 = 3 as _;
+ /// let ptr2: *const i32 = 13 as _;
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// ```
+ #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
+ #[inline]
+ pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
+ let pointee_size = mem::size_of::<T>();
+ assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+
+ let d = isize::wrapping_sub(self as _, origin as _);
+ d.wrapping_div(pointee_size as _)
+ }
+
+ /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum must fit in a `usize`.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "123";
+ /// let ptr: *const u8 = s.as_ptr();
+ ///
+ /// unsafe {
+ /// println!("{}", *ptr.add(1) as char);
+ /// println!("{}", *ptr.add(2) as char);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn add(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.offset(count as isize)
+ }
+
+ /// Calculates the offset from a pointer (convenience for
+ /// `.offset((count as isize).wrapping_neg())`).
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum must fit in a usize.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "123";
+ ///
+ /// unsafe {
+ /// let end: *const u8 = s.as_ptr().add(3);
+ /// println!("{}", *end.sub(1) as char);
+ /// println!("{}", *end.sub(2) as char);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn sub(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.offset((count as isize).wrapping_neg())
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ /// (convenience for `.wrapping_offset(count as isize)`)
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ ///
+ /// Always use `.add(count)` instead when possible, because `add`
+ /// allows the compiler to optimize better.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements
+ /// let data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *const u8 = data.as_ptr();
+ /// let step = 2;
+ /// let end_rounded_up = ptr.wrapping_add(6);
+ ///
+ /// // This loop prints "1, 3, 5, "
+ /// while ptr != end_rounded_up {
+ /// unsafe {
+ /// print!("{}, ", *ptr);
+ /// }
+ /// ptr = ptr.wrapping_add(step);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub fn wrapping_add(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.wrapping_offset(count as isize)
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ ///
+ /// Always use `.sub(count)` instead when possible, because `sub`
+ /// allows the compiler to optimize better.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements (backwards)
+ /// let data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *const u8 = data.as_ptr();
+ /// let start_rounded_down = ptr.wrapping_sub(2);
+ /// ptr = ptr.wrapping_add(4);
+ /// let step = 2;
+ /// // This loop prints "5, 3, 1, "
+ /// while ptr != start_rounded_down {
+ /// unsafe {
+ /// print!("{}, ", *ptr);
+ /// }
+ /// ptr = ptr.wrapping_sub(step);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub fn wrapping_sub(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.wrapping_offset((count as isize).wrapping_neg())
+ }
+
+ /// Reads the value from `self` without moving it. This leaves the
+ /// memory in `self` unchanged.
+ ///
+ /// See [`ptr::read`] for safety concerns and examples.
+ ///
+ /// [`ptr::read`]: ./ptr/fn.read.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read(self) -> T
+ where T: Sized,
+ {
+ read(self)
+ }
+
+ /// Performs a volatile read of the value from `self` without moving it. This
+ /// leaves the memory in `self` unchanged.
+ ///
+ /// Volatile operations are intended to act on I/O memory, and are guaranteed
+ /// to not be elided or reordered by the compiler across other volatile
+ /// operations.
+ ///
+ /// See [`ptr::read_volatile`] for safety concerns and examples.
+ ///
+ /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read_volatile(self) -> T
+ where T: Sized,
+ {
+ read_volatile(self)
+ }
+
+ /// Reads the value from `self` without moving it. This leaves the
+ /// memory in `self` unchanged.
+ ///
+ /// Unlike `read`, the pointer may be unaligned.
+ ///
+ /// See [`ptr::read_unaligned`] for safety concerns and examples.
+ ///
+ /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read_unaligned(self) -> T
+ where T: Sized,
+ {
+ read_unaligned(self)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+ /// and destination may overlap.
+ ///
+ /// NOTE: this has the *same* argument order as [`ptr::copy`].
+ ///
+ /// See [`ptr::copy`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy`]: ./ptr/fn.copy.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+ where T: Sized,
+ {
+ copy(self, dest, count)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+ /// and destination may *not* overlap.
+ ///
+ /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
+ ///
+ /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+ where T: Sized,
+ {
+ copy_nonoverlapping(self, dest, count)
+ }
+
+ /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
+ /// `align`.
+ ///
+ /// If it is not possible to align the pointer, the implementation returns
+ /// `usize::max_value()`.
+ ///
+ /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
+ /// used with the `offset` or `offset_to` methods.
+ ///
+ /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
+ /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
+ /// the returned offset is correct in all terms other than alignment.
+ ///
+ /// # Panics
+ ///
+ /// The function panics if `align` is not a power-of-two.
+ ///
+ /// # Examples
+ ///
+ /// Accessing adjacent `u8` as `u16`
+ ///
+ /// ```
+ /// # fn foo(n: usize) {
+ /// # use std::mem::align_of;
+ /// # unsafe {
+ /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+ /// let ptr = &x[n] as *const u8;
+ /// let offset = ptr.align_offset(align_of::<u16>());
+ /// if offset < x.len() - n - 1 {
+ /// let u16_ptr = ptr.add(offset) as *const u16;
+ /// assert_ne!(*u16_ptr, 500);
+ /// } else {
+ /// // while the pointer can be aligned via `offset`, it would point
+ /// // outside the allocation
+ /// }
+ /// # } }
+ /// ```
+ #[stable(feature = "align_offset", since = "1.36.0")]
+ pub fn align_offset(self, align: usize) -> usize where T: Sized {
+ if !align.is_power_of_two() {
+ panic!("align_offset: align is not a power-of-two");
+ }
+ unsafe {
+ align_offset(self, align)
+ }
+ }
+}
+
+
+#[lang = "mut_ptr"]
+impl<T: ?Sized> *mut T {
+ /// Returns `true` if the pointer is null.
+ ///
+ /// Note that unsized types have many possible null pointers, as only the
+ /// raw data pointer is considered, not their length, vtable, etc.
+ /// Therefore, two pointers that are null may still not compare equal to
+ /// each other.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let mut s = [1, 2, 3];
+ /// let ptr: *mut u32 = s.as_mut_ptr();
+ /// assert!(!ptr.is_null());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub fn is_null(self) -> bool {
+ // Compare via a cast to a thin pointer, so fat pointers are only
+ // considering their "data" part for null-ness.
+ (self as *mut u8) == null_mut()
+ }
+
+ /// Cast to a pointer to a different type
+ #[unstable(feature = "ptr_cast", issue = "60602")]
+ #[inline]
+ pub const fn cast<U>(self) -> *mut U {
+ self as _
+ }
+
+ /// Returns `None` if the pointer is null, or else returns a reference to
+ /// the value wrapped in `Some`.
+ ///
+ /// # Safety
+ ///
+ /// While this method and its mutable counterpart are useful for
+ /// null-safety, it is important to note that this is still an unsafe
+ /// operation because the returned value could be pointing to invalid
+ /// memory.
+ ///
+ /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
+ /// not necessarily reflect the actual lifetime of the data.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+ ///
+ /// unsafe {
+ /// if let Some(val_back) = ptr.as_ref() {
+ /// println!("We got back the value: {}!", val_back);
+ /// }
+ /// }
+ /// ```
+ ///
+ /// # Null-unchecked version
+ ///
+ /// If you are sure the pointer can never be null and are looking for some kind of
+ /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
+ /// dereference the pointer directly.
+ ///
+ /// ```
+ /// let ptr: *mut u8 = &mut 10u8 as *mut u8;
+ ///
+ /// unsafe {
+ /// let val_back = &*ptr;
+ /// println!("We got back the value: {}!", val_back);
+ /// }
+ /// ```
+ #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+ #[inline]
+ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+ if self.is_null() {
+ None
+ } else {
+ Some(&*self)
+ }
+ }
+
+ /// Calculates the offset from a pointer.
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let mut s = [1, 2, 3];
+ /// let ptr: *mut u32 = s.as_mut_ptr();
+ ///
+ /// unsafe {
+ /// println!("{}", *ptr.offset(1));
+ /// println!("{}", *ptr.offset(2));
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
+ intrinsics::offset(self, count) as *mut T
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ /// In particular, the resulting pointer may *not* be used to access a
+ /// different allocated object than the one `self` points to. In other
+ /// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
+ /// *not* the same as `y`, and dereferencing it is undefined behavior
+ /// unless `x` and `y` point into the same allocated object.
+ ///
+ /// Always use `.offset(count)` instead when possible, because `offset`
+ /// allows the compiler to optimize better. If you need to cross object
+ /// boundaries, cast the pointer to an integer and do the arithmetic there.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements
+ /// let mut data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *mut u8 = data.as_mut_ptr();
+ /// let step = 2;
+ /// let end_rounded_up = ptr.wrapping_offset(6);
+ ///
+ /// while ptr != end_rounded_up {
+ /// unsafe {
+ /// *ptr = 0;
+ /// }
+ /// ptr = ptr.wrapping_offset(step);
+ /// }
+ /// assert_eq!(&data, &[0, 2, 0, 4, 0]);
+ /// ```
+ #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
+ #[inline]
+ pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized {
+ unsafe {
+ intrinsics::arith_offset(self, count) as *mut T
+ }
+ }
+
+ /// Returns `None` if the pointer is null, or else returns a mutable
+ /// reference to the value wrapped in `Some`.
+ ///
+ /// # Safety
+ ///
+ /// As with `as_ref`, this is unsafe because it cannot verify the validity
+ /// of the returned pointer, nor can it ensure that the lifetime `'a`
+ /// returned is indeed a valid lifetime for the contained data.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let mut s = [1, 2, 3];
+ /// let ptr: *mut u32 = s.as_mut_ptr();
+ /// let first_value = unsafe { ptr.as_mut().unwrap() };
+ /// *first_value = 4;
+ /// println!("{:?}", s); // It'll print: "[4, 2, 3]".
+ /// ```
+ #[stable(feature = "ptr_as_ref", since = "1.9.0")]
+ #[inline]
+ pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
+ if self.is_null() {
+ None
+ } else {
+ Some(&mut *self)
+ }
+ }
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// This function is the inverse of [`offset`].
+ ///
+ /// [`offset`]: #method.offset-1
+ /// [`wrapping_offset_from`]: #method.wrapping_offset_from-1
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and other pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The distance between the pointers, in bytes, must be an exact multiple
+ /// of the size of `T`.
+ ///
+ /// * The distance being in bounds cannot rely on "wrapping around" the address space.
+ ///
+ /// The compiler and standard library generally try to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `ptr_into_vec.offset_from(vec.as_ptr())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using [`wrapping_offset_from`] instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if `T` is a Zero-Sized Type ("ZST").
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(ptr_offset_from)]
+ ///
+ /// let mut a = [0; 5];
+ /// let ptr1: *mut i32 = &mut a[1];
+ /// let ptr2: *mut i32 = &mut a[3];
+ /// unsafe {
+ /// assert_eq!(ptr2.offset_from(ptr1), 2);
+ /// assert_eq!(ptr1.offset_from(ptr2), -2);
+ /// assert_eq!(ptr1.offset(2), ptr2);
+ /// assert_eq!(ptr2.offset(-2), ptr1);
+ /// }
+ /// ```
+ #[unstable(feature = "ptr_offset_from", issue = "41079")]
+ #[inline]
+ pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized {
+ (self as *const T).offset_from(origin)
+ }
+
+ /// Calculates the distance between two pointers. The returned value is in
+ /// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
+ ///
+ /// If the address different between the two pointers is not a multiple of
+ /// `mem::size_of::<T>()` then the result of the division is rounded towards
+ /// zero.
+ ///
+ /// Though this method is safe for any two pointers, note that its result
+ /// will be mostly useless if the two pointers aren't into the same allocated
+ /// object, for example if they point to two different local variables.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if `T` is a zero-sized type.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(ptr_wrapping_offset_from)]
+ ///
+ /// let mut a = [0; 5];
+ /// let ptr1: *mut i32 = &mut a[1];
+ /// let ptr2: *mut i32 = &mut a[3];
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// assert_eq!(ptr1.wrapping_offset_from(ptr2), -2);
+ /// assert_eq!(ptr1.wrapping_offset(2), ptr2);
+ /// assert_eq!(ptr2.wrapping_offset(-2), ptr1);
+ ///
+ /// let ptr1: *mut i32 = 3 as _;
+ /// let ptr2: *mut i32 = 13 as _;
+ /// assert_eq!(ptr2.wrapping_offset_from(ptr1), 2);
+ /// ```
+ #[unstable(feature = "ptr_wrapping_offset_from", issue = "41079")]
+ #[inline]
+ pub fn wrapping_offset_from(self, origin: *const T) -> isize where T: Sized {
+ (self as *const T).wrapping_offset_from(origin)
+ }
+
+ /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum must fit in a `usize`.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "123";
+ /// let ptr: *const u8 = s.as_ptr();
+ ///
+ /// unsafe {
+ /// println!("{}", *ptr.add(1) as char);
+ /// println!("{}", *ptr.add(2) as char);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn add(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.offset(count as isize)
+ }
+
+ /// Calculates the offset from a pointer (convenience for
+ /// `.offset((count as isize).wrapping_neg())`).
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// If any of the following conditions are violated, the result is Undefined
+ /// Behavior:
+ ///
+ /// * Both the starting and resulting pointer must be either in bounds or one
+ /// byte past the end of the same allocated object.
+ ///
+ /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+ ///
+ /// * The offset being in bounds cannot rely on "wrapping around" the address
+ /// space. That is, the infinite-precision sum must fit in a usize.
+ ///
+ /// The compiler and standard library generally tries to ensure allocations
+ /// never reach a size where an offset is a concern. For instance, `Vec`
+ /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+ /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+ ///
+ /// Most platforms fundamentally can't even construct such an allocation.
+ /// For instance, no known 64-bit platform can ever serve a request
+ /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
+ /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+ /// more than `isize::MAX` bytes with things like Physical Address
+ /// Extension. As such, memory acquired directly from allocators or memory
+ /// mapped files *may* be too large to handle with this function.
+ ///
+ /// Consider using `wrapping_offset` instead if these constraints are
+ /// difficult to satisfy. The only advantage of this method is that it
+ /// enables more aggressive compiler optimizations.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// let s: &str = "123";
+ ///
+ /// unsafe {
+ /// let end: *const u8 = s.as_ptr().add(3);
+ /// println!("{}", *end.sub(1) as char);
+ /// println!("{}", *end.sub(2) as char);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn sub(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.offset((count as isize).wrapping_neg())
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ /// (convenience for `.wrapping_offset(count as isize)`)
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ ///
+ /// Always use `.add(count)` instead when possible, because `add`
+ /// allows the compiler to optimize better.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements
+ /// let data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *const u8 = data.as_ptr();
+ /// let step = 2;
+ /// let end_rounded_up = ptr.wrapping_add(6);
+ ///
+ /// // This loop prints "1, 3, 5, "
+ /// while ptr != end_rounded_up {
+ /// unsafe {
+ /// print!("{}, ", *ptr);
+ /// }
+ /// ptr = ptr.wrapping_add(step);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub fn wrapping_add(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.wrapping_offset(count as isize)
+ }
+
+ /// Calculates the offset from a pointer using wrapping arithmetic.
+ /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+ ///
+ /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
+ /// offset of `3 * size_of::<T>()` bytes.
+ ///
+ /// # Safety
+ ///
+ /// The resulting pointer does not need to be in bounds, but it is
+ /// potentially hazardous to dereference (which requires `unsafe`).
+ ///
+ /// Always use `.sub(count)` instead when possible, because `sub`
+ /// allows the compiler to optimize better.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// // Iterate using a raw pointer in increments of two elements (backwards)
+ /// let data = [1u8, 2, 3, 4, 5];
+ /// let mut ptr: *const u8 = data.as_ptr();
+ /// let start_rounded_down = ptr.wrapping_sub(2);
+ /// ptr = ptr.wrapping_add(4);
+ /// let step = 2;
+ /// // This loop prints "5, 3, 1, "
+ /// while ptr != start_rounded_down {
+ /// unsafe {
+ /// print!("{}, ", *ptr);
+ /// }
+ /// ptr = ptr.wrapping_sub(step);
+ /// }
+ /// ```
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub fn wrapping_sub(self, count: usize) -> Self
+ where T: Sized,
+ {
+ self.wrapping_offset((count as isize).wrapping_neg())
+ }
+
+ /// Reads the value from `self` without moving it. This leaves the
+ /// memory in `self` unchanged.
+ ///
+ /// See [`ptr::read`] for safety concerns and examples.
+ ///
+ /// [`ptr::read`]: ./ptr/fn.read.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read(self) -> T
+ where T: Sized,
+ {
+ read(self)
+ }
+
+ /// Performs a volatile read of the value from `self` without moving it. This
+ /// leaves the memory in `self` unchanged.
+ ///
+ /// Volatile operations are intended to act on I/O memory, and are guaranteed
+ /// to not be elided or reordered by the compiler across other volatile
+ /// operations.
+ ///
+ /// See [`ptr::read_volatile`] for safety concerns and examples.
+ ///
+ /// [`ptr::read_volatile`]: ./ptr/fn.read_volatile.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read_volatile(self) -> T
+ where T: Sized,
+ {
+ read_volatile(self)
+ }
+
+ /// Reads the value from `self` without moving it. This leaves the
+ /// memory in `self` unchanged.
+ ///
+ /// Unlike `read`, the pointer may be unaligned.
+ ///
+ /// See [`ptr::read_unaligned`] for safety concerns and examples.
+ ///
+ /// [`ptr::read_unaligned`]: ./ptr/fn.read_unaligned.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn read_unaligned(self) -> T
+ where T: Sized,
+ {
+ read_unaligned(self)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+ /// and destination may overlap.
+ ///
+ /// NOTE: this has the *same* argument order as [`ptr::copy`].
+ ///
+ /// See [`ptr::copy`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy`]: ./ptr/fn.copy.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+ where T: Sized,
+ {
+ copy(self, dest, count)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+ /// and destination may *not* overlap.
+ ///
+ /// NOTE: this has the *same* argument order as [`ptr::copy_nonoverlapping`].
+ ///
+ /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+ where T: Sized,
+ {
+ copy_nonoverlapping(self, dest, count)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+ /// and destination may overlap.
+ ///
+ /// NOTE: this has the *opposite* argument order of [`ptr::copy`].
+ ///
+ /// See [`ptr::copy`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy`]: ./ptr/fn.copy.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_from(self, src: *const T, count: usize)
+ where T: Sized,
+ {
+ copy(src, self, count)
+ }
+
+ /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+ /// and destination may *not* overlap.
+ ///
+ /// NOTE: this has the *opposite* argument order of [`ptr::copy_nonoverlapping`].
+ ///
+ /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples.
+ ///
+ /// [`ptr::copy_nonoverlapping`]: ./ptr/fn.copy_nonoverlapping.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
+ where T: Sized,
+ {
+ copy_nonoverlapping(src, self, count)
+ }
+
+ /// Executes the destructor (if any) of the pointed-to value.
+ ///
+ /// See [`ptr::drop_in_place`] for safety concerns and examples.
+ ///
+ /// [`ptr::drop_in_place`]: ./ptr/fn.drop_in_place.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn drop_in_place(self) {
+ drop_in_place(self)
+ }
+
+ /// Overwrites a memory location with the given value without reading or
+ /// dropping the old value.
+ ///
+ /// See [`ptr::write`] for safety concerns and examples.
+ ///
+ /// [`ptr::write`]: ./ptr/fn.write.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn write(self, val: T)
+ where T: Sized,
+ {
+ write(self, val)
+ }
+
+ /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
+ /// bytes of memory starting at `self` to `val`.
+ ///
+ /// See [`ptr::write_bytes`] for safety concerns and examples.
+ ///
+ /// [`ptr::write_bytes`]: ./ptr/fn.write_bytes.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn write_bytes(self, val: u8, count: usize)
+ where T: Sized,
+ {
+ write_bytes(self, val, count)
+ }
+
+ /// Performs a volatile write of a memory location with the given value without
+ /// reading or dropping the old value.
+ ///
+ /// Volatile operations are intended to act on I/O memory, and are guaranteed
+ /// to not be elided or reordered by the compiler across other volatile
+ /// operations.
+ ///
+ /// See [`ptr::write_volatile`] for safety concerns and examples.
+ ///
+ /// [`ptr::write_volatile`]: ./ptr/fn.write_volatile.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn write_volatile(self, val: T)
+ where T: Sized,
+ {
+ write_volatile(self, val)
+ }
+
+ /// Overwrites a memory location with the given value without reading or
+ /// dropping the old value.
+ ///
+ /// Unlike `write`, the pointer may be unaligned.
+ ///
+ /// See [`ptr::write_unaligned`] for safety concerns and examples.
+ ///
+ /// [`ptr::write_unaligned`]: ./ptr/fn.write_unaligned.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn write_unaligned(self, val: T)
+ where T: Sized,
+ {
+ write_unaligned(self, val)
+ }
+
+ /// Replaces the value at `self` with `src`, returning the old
+ /// value, without dropping either.
+ ///
+ /// See [`ptr::replace`] for safety concerns and examples.
+ ///
+ /// [`ptr::replace`]: ./ptr/fn.replace.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn replace(self, src: T) -> T
+ where T: Sized,
+ {
+ replace(self, src)
+ }
+
+ /// Swaps the values at two mutable locations of the same type, without
+ /// deinitializing either. They may overlap, unlike `mem::swap` which is
+ /// otherwise equivalent.
+ ///
+ /// See [`ptr::swap`] for safety concerns and examples.
+ ///
+ /// [`ptr::swap`]: ./ptr/fn.swap.html
+ #[stable(feature = "pointer_methods", since = "1.26.0")]
+ #[inline]
+ pub unsafe fn swap(self, with: *mut T)
+ where T: Sized,
+ {
+ swap(self, with)
+ }
+
+ /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
+ /// `align`.
+ ///
+ /// If it is not possible to align the pointer, the implementation returns
+ /// `usize::max_value()`.
+ ///
+ /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
+ /// used with the `offset` or `offset_to` methods.
+ ///
+ /// There are no guarantees whatsover that offsetting the pointer will not overflow or go
+ /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
+ /// the returned offset is correct in all terms other than alignment.
+ ///
+ /// # Panics
+ ///
+ /// The function panics if `align` is not a power-of-two.
+ ///
+ /// # Examples
+ ///
+ /// Accessing adjacent `u8` as `u16`
+ ///
+ /// ```
+ /// # fn foo(n: usize) {
+ /// # use std::mem::align_of;
+ /// # unsafe {
+ /// let x = [5u8, 6u8, 7u8, 8u8, 9u8];
+ /// let ptr = &x[n] as *const u8;
+ /// let offset = ptr.align_offset(align_of::<u16>());
+ /// if offset < x.len() - n - 1 {
+ /// let u16_ptr = ptr.add(offset) as *const u16;
+ /// assert_ne!(*u16_ptr, 500);
+ /// } else {
+ /// // while the pointer can be aligned via `offset`, it would point
+ /// // outside the allocation
+ /// }
+ /// # } }
+ /// ```
+ #[stable(feature = "align_offset", since = "1.36.0")]
+ pub fn align_offset(self, align: usize) -> usize where T: Sized {
+ if !align.is_power_of_two() {
+ panic!("align_offset: align is not a power-of-two");
+ }
+ unsafe {
+ align_offset(self, align)
+ }
+ }
+}
+
+/// Align pointer `p`.
+///
+/// Calculate offset (in terms of elements of `stride` stride) that has to be applied
+/// to pointer `p` so that pointer `p` would get aligned to `a`.
+///
+/// Note: This implementation has been carefully tailored to not panic. It is UB for this to panic.
+/// The only real change that can be made here is change of `INV_TABLE_MOD_16` and associated
+/// constants.
+///
+/// If we ever decide to make it possible to call the intrinsic with `a` that is not a
+/// power-of-two, it will probably be more prudent to just change to a naive implementation rather
+/// than trying to adapt this to accommodate that change.
+///
+/// Any questions go to @nagisa.
+#[lang="align_offset"]
+pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
+ /// Calculate multiplicative modular inverse of `x` modulo `m`.
+ ///
+ /// This implementation is tailored for align_offset and has following preconditions:
+ ///
+ /// * `m` is a power-of-two;
+ /// * `x < m`; (if `x ≥ m`, pass in `x % m` instead)
+ ///
+ /// Implementation of this function shall not panic. Ever.
+ #[inline]
+ fn mod_inv(x: usize, m: usize) -> usize {
+ /// Multiplicative modular inverse table modulo 2⁴ = 16.
+ ///
+ /// Note, that this table does not contain values where inverse does not exist (i.e., for
+ /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.)
+ const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15];
+ /// Modulo for which the `INV_TABLE_MOD_16` is intended.
+ const INV_TABLE_MOD: usize = 16;
+ /// INV_TABLE_MOD²
+ const INV_TABLE_MOD_SQUARED: usize = INV_TABLE_MOD * INV_TABLE_MOD;
+
+ let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize;
+ if m <= INV_TABLE_MOD {
+ table_inverse & (m - 1)
+ } else {
+ // We iterate "up" using the following formula:
+ //
+ // $$ xy ≡ 1 (mod 2ⁿ) → xy (2 - xy) ≡ 1 (mod 2²ⁿ) $$
+ //
+ // until 2²ⁿ ≥ m. Then we can reduce to our desired `m` by taking the result `mod m`.
+ let mut inverse = table_inverse;
+ let mut going_mod = INV_TABLE_MOD_SQUARED;
+ loop {
+ // y = y * (2 - xy) mod n
+ //
+ // Note, that we use wrapping operations here intentionally – the original formula
+ // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod
+ // usize::max_value()` instead, because we take the result `mod n` at the end
+ // anyway.
+ inverse = inverse.wrapping_mul(
+ 2usize.wrapping_sub(x.wrapping_mul(inverse))
+ ) & (going_mod - 1);
+ if going_mod > m {
+ return inverse & (m - 1);
+ }
+ going_mod = going_mod.wrapping_mul(going_mod);
+ }
+ }
+ }
+
+ let stride = mem::size_of::<T>();
+ let a_minus_one = a.wrapping_sub(1);
+ let pmoda = p as usize & a_minus_one;
+
+ if pmoda == 0 {
+ // Already aligned. Yay!
+ return 0;
+ }
+
+ if stride <= 1 {
+ return if stride == 0 {
+ // If the pointer is not aligned, and the element is zero-sized, then no amount of
+ // elements will ever align the pointer.
+ !0
+ } else {
+ a.wrapping_sub(pmoda)
+ };
+ }
+
+ let smoda = stride & a_minus_one;
+ // a is power-of-two so cannot be 0. stride = 0 is handled above.
+ let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a));
+ let gcd = 1usize << gcdpow;
+
+ if p as usize & (gcd - 1) == 0 {
+ // This branch solves for the following linear congruence equation:
+ //
+ // $$ p + so ≡ 0 mod a $$
+ //
+ // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the
+ // requested alignment.
+ //
+ // g = gcd(a, s)
+ // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a)
+ //
+ // The first term is “the relative alignment of p to a”, the second term is “how does
+ // incrementing p by s bytes change the relative alignment of p”. Division by `g` is
+ // necessary to make this equation well formed if $a$ and $s$ are not co-prime.
+ //
+ // Furthermore, the result produced by this solution is not “minimal”, so it is necessary
+ // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$.
+ let j = a.wrapping_sub(pmoda) >> gcdpow;
+ let k = smoda >> gcdpow;
+ return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow);
+ }
+
+ // Cannot be aligned at all.
+ usize::max_value()
+}
+
+
+
+// Equality for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *const T {
+ #[inline]
+ fn eq(&self, other: &*const T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *const T {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *mut T {
+ #[inline]
+ fn eq(&self, other: &*mut T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *mut T {}
+
+/// Compares raw pointers for equality.
+///
+/// This is the same as using the `==` operator, but less generic:
+/// the arguments have to be `*const T` raw pointers,
+/// not anything that implements `PartialEq`.
+///
+/// This can be used to compare `&T` references (which coerce to `*const T` implicitly)
+/// by their address rather than comparing the values they point to
+/// (which is what the `PartialEq for &T` implementation does).
+///
+/// # Examples
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(ptr::eq(five_ref, same_five_ref));
+///
+/// assert!(five_ref == other_five_ref);
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
+/// Slices are also compared by their length (fat pointers):
+///
+/// ```
+/// let a = [1, 2, 3];
+/// assert!(std::ptr::eq(&a[..3], &a[..3]));
+/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
+/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
+/// ```
+///
+/// Traits are also compared by their implementation:
+///
+/// ```
+/// #[repr(transparent)]
+/// struct Wrapper { member: i32 }
+///
+/// trait Trait {}
+/// impl Trait for Wrapper {}
+/// impl Trait for i32 {}
+///
+/// fn main() {
+/// let wrapper = Wrapper { member: 10 };
+///
+/// // Pointers have equal addresses.
+/// assert!(std::ptr::eq(
+/// &wrapper as *const Wrapper as *const u8,
+/// &wrapper.member as *const i32 as *const u8
+/// ));
+///
+/// // Objects have equal addresses, but `Trait` has different implementations.
+/// assert!(!std::ptr::eq(
+/// &wrapper as &dyn Trait,
+/// &wrapper.member as &dyn Trait,
+/// ));
+/// assert!(!std::ptr::eq(
+/// &wrapper as &dyn Trait as *const dyn Trait,
+/// &wrapper.member as &dyn Trait as *const dyn Trait,
+/// ));
+///
+/// // Converting the reference to a `*const u8` compares by address.
+/// assert!(std::ptr::eq(
+/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
+/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
+/// ));
+/// }
+/// ```
+#[stable(feature = "ptr_eq", since = "1.17.0")]
+#[inline]
+pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
+ a == b
+}
+
+/// Hash a raw pointer.
+///
+/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly)
+/// by its address rather than the value it points to
+/// (which is what the `Hash for &T` implementation does).
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::DefaultHasher;
+/// use std::hash::{Hash, Hasher};
+/// use std::ptr;
+///
+/// let five = 5;
+/// let five_ref = &five;
+///
+/// let mut hasher = DefaultHasher::new();
+/// ptr::hash(five_ref, &mut hasher);
+/// let actual = hasher.finish();
+///
+/// let mut hasher = DefaultHasher::new();
+/// (five_ref as *const i32).hash(&mut hasher);
+/// let expected = hasher.finish();
+///
+/// assert_eq!(actual, expected);
+/// ```
+#[stable(feature = "ptr_hash", since = "1.35.0")]
+pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
+ use crate::hash::Hash;
+ hashee.hash(into);
+}
+
+// Impls for function pointers
+macro_rules! fnptr_impls_safety_abi {
+ ($FnTy: ty, $($Arg: ident),*) => {
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> PartialEq for $FnTy {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ *self as usize == *other as usize
+ }
+ }
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> Eq for $FnTy {}
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> PartialOrd for $FnTy {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ (*self as usize).partial_cmp(&(*other as usize))
+ }
+ }
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> Ord for $FnTy {
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ (*self as usize).cmp(&(*other as usize))
+ }
+ }
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> hash::Hash for $FnTy {
+ fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
+ state.write_usize(*self as usize)
+ }
+ }
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&(*self as *const ()), f)
+ }
+ }
+
+ #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&(*self as *const ()), f)
+ }
+ }
+ }
+}
+
+macro_rules! fnptr_impls_args {
+ ($($Arg: ident),+) => {
+ fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* }
+ fnptr_impls_safety_abi! { extern "C" fn($($Arg),*) -> Ret, $($Arg),* }
+ fnptr_impls_safety_abi! { extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* }
+ fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),*) -> Ret, $($Arg),* }
+ fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),*) -> Ret, $($Arg),* }
+ fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),* , ...) -> Ret, $($Arg),* }
+ };
+ () => {
+ // No variadic functions with 0 parameters
+ fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
+ fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
+ fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
+ fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
+ };
+}
+
+fnptr_impls_args! { }
+fnptr_impls_args! { A }
+fnptr_impls_args! { A, B }
+fnptr_impls_args! { A, B, C }
+fnptr_impls_args! { A, B, C, D }
+fnptr_impls_args! { A, B, C, D, E }
+fnptr_impls_args! { A, B, C, D, E, F }
+fnptr_impls_args! { A, B, C, D, E, F, G }
+fnptr_impls_args! { A, B, C, D, E, F, G, H }
+fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
+fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
+fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
+fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
+
+// Comparison for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Ord for *const T {
+ #[inline]
+ fn cmp(&self, other: &*const T) -> Ordering {
+ if self < other {
+ Less
+ } else if self == other {
+ Equal
+ } else {
+ Greater
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialOrd for *const T {
+ #[inline]
+ fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+
+ #[inline]
+ fn lt(&self, other: &*const T) -> bool { *self < *other }
+
+ #[inline]
+ fn le(&self, other: &*const T) -> bool { *self <= *other }
+
+ #[inline]
+ fn gt(&self, other: &*const T) -> bool { *self > *other }
+
+ #[inline]
+ fn ge(&self, other: &*const T) -> bool { *self >= *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Ord for *mut T {
+ #[inline]
+ fn cmp(&self, other: &*mut T) -> Ordering {
+ if self < other {
+ Less
+ } else if self == other {
+ Equal
+ } else {
+ Greater
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialOrd for *mut T {
+ #[inline]
+ fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+
+ #[inline]
+ fn lt(&self, other: &*mut T) -> bool { *self < *other }
+
+ #[inline]
+ fn le(&self, other: &*mut T) -> bool { *self <= *other }
+
+ #[inline]
+ fn gt(&self, other: &*mut T) -> bool { *self > *other }
+
+ #[inline]
+ fn ge(&self, other: &*mut T) -> bool { *self >= *other }
+}
--- /dev/null
+use crate::convert::From;
+use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::fmt;
+use crate::hash;
+use crate::marker::Unsize;
+use crate::mem;
+use crate::ptr::Unique;
+use crate::cmp::Ordering;
+
+/// `*mut T` but non-zero and covariant.
+///
+/// This is often the correct thing to use when building data structures using
+/// raw pointers, but is ultimately more dangerous to use because of its additional
+/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
+///
+/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
+/// is never dereferenced. This is so that enums may use this forbidden value
+/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
+/// However the pointer may still dangle if it isn't dereferenced.
+///
+/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
+/// for your use case, you should include some [`PhantomData`] in your type to
+/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
+/// Usually this won't be necessary; covariance is correct for most safe abstractions,
+/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
+/// provide a public API that follows the normal shared XOR mutable rules of Rust.
+///
+/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
+/// not change the fact that mutating through a (pointer derived from a) shared
+/// reference is undefined behavior unless the mutation happens inside an
+/// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared
+/// reference. When using this `From` instance without an `UnsafeCell<T>`,
+/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
+/// is never used for mutation.
+///
+/// [`PhantomData`]: ../marker/struct.PhantomData.html
+/// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
+#[stable(feature = "nonnull", since = "1.25.0")]
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
+pub struct NonNull<T: ?Sized> {
+ pointer: *const T,
+}
+
+/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
+// N.B., this impl is unnecessary, but should provide better error messages.
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> !Send for NonNull<T> { }
+
+/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
+// N.B., this impl is unnecessary, but should provide better error messages.
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> !Sync for NonNull<T> { }
+
+impl<T: Sized> NonNull<T> {
+ /// Creates a new `NonNull` that is dangling, but well-aligned.
+ ///
+ /// This is useful for initializing types which lazily allocate, like
+ /// `Vec::new` does.
+ ///
+ /// Note that the pointer value may potentially represent a valid pointer to
+ /// a `T`, which means this must not be used as a "not yet initialized"
+ /// sentinel value. Types that lazily allocate must track initialization by
+ /// some other means.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub const fn dangling() -> Self {
+ unsafe {
+ let ptr = mem::align_of::<T>() as *mut T;
+ NonNull::new_unchecked(ptr)
+ }
+ }
+}
+
+impl<T: ?Sized> NonNull<T> {
+ /// Creates a new `NonNull`.
+ ///
+ /// # Safety
+ ///
+ /// `ptr` must be non-null.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
+ NonNull { pointer: ptr as _ }
+ }
+
+ /// Creates a new `NonNull` if `ptr` is non-null.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub fn new(ptr: *mut T) -> Option<Self> {
+ if !ptr.is_null() {
+ Some(unsafe { Self::new_unchecked(ptr) })
+ } else {
+ None
+ }
+ }
+
+ /// Acquires the underlying `*mut` pointer.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub const fn as_ptr(self) -> *mut T {
+ self.pointer as *mut T
+ }
+
+ /// Dereferences the content.
+ ///
+ /// The resulting lifetime is bound to self so this behaves "as if"
+ /// it were actually an instance of T that is getting borrowed. If a longer
+ /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T {
+ &*self.as_ptr()
+ }
+
+ /// Mutably dereferences the content.
+ ///
+ /// The resulting lifetime is bound to self so this behaves "as if"
+ /// it were actually an instance of T that is getting borrowed. If a longer
+ /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+ #[stable(feature = "nonnull", since = "1.25.0")]
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T {
+ &mut *self.as_ptr()
+ }
+
+ /// Cast to a pointer of another type
+ #[stable(feature = "nonnull_cast", since = "1.27.0")]
+ #[inline]
+ pub const fn cast<U>(self) -> NonNull<U> {
+ unsafe {
+ NonNull::new_unchecked(self.as_ptr() as *mut U)
+ }
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> Clone for NonNull<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> Copy for NonNull<T> { }
+
+#[unstable(feature = "coerce_unsized", issue = "27732")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
+
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> fmt::Debug for NonNull<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> fmt::Pointer for NonNull<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> Eq for NonNull<T> {}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> PartialEq for NonNull<T> {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.as_ptr() == other.as_ptr()
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> Ord for NonNull<T> {
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.as_ptr().cmp(&other.as_ptr())
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> PartialOrd for NonNull<T> {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.as_ptr().partial_cmp(&other.as_ptr())
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> hash::Hash for NonNull<T> {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.as_ptr().hash(state)
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
+ #[inline]
+ fn from(unique: Unique<T>) -> Self {
+ unsafe { NonNull::new_unchecked(unique.as_ptr()) }
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> From<&mut T> for NonNull<T> {
+ #[inline]
+ fn from(reference: &mut T) -> Self {
+ unsafe { NonNull { pointer: reference as *mut T } }
+ }
+}
+
+#[stable(feature = "nonnull", since = "1.25.0")]
+impl<T: ?Sized> From<&T> for NonNull<T> {
+ #[inline]
+ fn from(reference: &T) -> Self {
+ unsafe { NonNull { pointer: reference as *const T } }
+ }
+}
--- /dev/null
+use crate::convert::From;
+use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::fmt;
+use crate::marker::{PhantomData, Unsize};
+use crate::mem;
+use crate::ptr::NonNull;
+
+/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
+/// of this wrapper owns the referent. Useful for building abstractions like
+/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
+///
+/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
+/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
+/// the kind of strong aliasing guarantees an instance of `T` can expect:
+/// the referent of the pointer should not be modified without a unique path to
+/// its owning Unique.
+///
+/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
+/// consider using `NonNull`, which has weaker semantics.
+///
+/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
+/// is never dereferenced. This is so that enums may use this forbidden value
+/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
+/// However the pointer may still dangle if it isn't dereferenced.
+///
+/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
+/// for any type which upholds Unique's aliasing requirements.
+#[unstable(feature = "ptr_internals", issue = "0",
+ reason = "use NonNull instead and consider PhantomData<T> \
+ (if you also use #[may_dangle]), Send, and/or Sync")]
+#[doc(hidden)]
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+pub struct Unique<T: ?Sized> {
+ pointer: *const T,
+ // NOTE: this marker has no consequences for variance, but is necessary
+ // for dropck to understand that we logically own a `T`.
+ //
+ // For details, see:
+ // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
+ _marker: PhantomData<T>,
+}
+
+/// `Unique` pointers are `Send` if `T` is `Send` because the data they
+/// reference is unaliased. Note that this aliasing invariant is
+/// unenforced by the type system; the abstraction using the
+/// `Unique` must enforce it.
+#[unstable(feature = "ptr_internals", issue = "0")]
+unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
+
+/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
+/// reference is unaliased. Note that this aliasing invariant is
+/// unenforced by the type system; the abstraction using the
+/// `Unique` must enforce it.
+#[unstable(feature = "ptr_internals", issue = "0")]
+unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: Sized> Unique<T> {
+ /// Creates a new `Unique` that is dangling, but well-aligned.
+ ///
+ /// This is useful for initializing types which lazily allocate, like
+ /// `Vec::new` does.
+ ///
+ /// Note that the pointer value may potentially represent a valid pointer to
+ /// a `T`, which means this must not be used as a "not yet initialized"
+ /// sentinel value. Types that lazily allocate must track initialization by
+ /// some other means.
+ // FIXME: rename to dangling() to match NonNull?
+ #[inline]
+ pub const fn empty() -> Self {
+ unsafe {
+ Unique::new_unchecked(mem::align_of::<T>() as *mut T)
+ }
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> Unique<T> {
+ /// Creates a new `Unique`.
+ ///
+ /// # Safety
+ ///
+ /// `ptr` must be non-null.
+ #[inline]
+ pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
+ Unique { pointer: ptr as _, _marker: PhantomData }
+ }
+
+ /// Creates a new `Unique` if `ptr` is non-null.
+ #[inline]
+ pub fn new(ptr: *mut T) -> Option<Self> {
+ if !ptr.is_null() {
+ Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
+ } else {
+ None
+ }
+ }
+
+ /// Acquires the underlying `*mut` pointer.
+ #[inline]
+ pub const fn as_ptr(self) -> *mut T {
+ self.pointer as *mut T
+ }
+
+ /// Dereferences the content.
+ ///
+ /// The resulting lifetime is bound to self so this behaves "as if"
+ /// it were actually an instance of T that is getting borrowed. If a longer
+ /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+ #[inline]
+ pub unsafe fn as_ref(&self) -> &T {
+ &*self.as_ptr()
+ }
+
+ /// Mutably dereferences the content.
+ ///
+ /// The resulting lifetime is bound to self so this behaves "as if"
+ /// it were actually an instance of T that is getting borrowed. If a longer
+ /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut T {
+ &mut *self.as_ptr()
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> Clone for Unique<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> Copy for Unique<T> { }
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> fmt::Debug for Unique<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> fmt::Pointer for Unique<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Pointer::fmt(&self.as_ptr(), f)
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> From<&mut T> for Unique<T> {
+ #[inline]
+ fn from(reference: &mut T) -> Self {
+ unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> From<&T> for Unique<T> {
+ #[inline]
+ fn from(reference: &T) -> Self {
+ unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
+ #[inline]
+ fn from(p: NonNull<T>) -> Self {
+ unsafe { Unique::new_unchecked(p.as_ptr()) }
+ }
+}
Some(snd)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &[];
+ None
+ } else {
+ let start = (len - 1 - n) * self.chunk_size;
+ let end = match start.checked_add(self.chunk_size) {
+ Some(res) => cmp::min(res, self.v.len()),
+ None => self.v.len(),
+ };
+ let nth_back = &self.v[start..end];
+ self.v = &self.v[..start];
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
Some(fst)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &[];
+ None
+ } else {
+ // can't underflow because `n < len`
+ let offset_from_end = (len - 1 - n) * self.chunk_size;
+ let end = self.v.len() - offset_from_end;
+ let start = end.saturating_sub(self.chunk_size);
+ let nth_back = &self.v[start..end];
+ self.v = &self.v[end..];
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "rchunks", since = "1.31.0")]
Some(head)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &mut [];
+ None
+ } else {
+ // can't underflow because `n < len`
+ let offset_from_end = (len - 1 - n) * self.chunk_size;
+ let end = self.v.len() - offset_from_end;
+ let start = end.saturating_sub(self.chunk_size);
+ let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
+ let (_, nth_back) = tmp.split_at_mut(start);
+ self.v = tail;
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "rchunks", since = "1.31.0")]
Some(fst)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &[];
+ None
+ } else {
+ // now that we know that `n` corresponds to a chunk,
+ // none of these operations can underflow/overflow
+ let offset = (len - n) * self.chunk_size;
+ let start = self.v.len() - offset;
+ let end = start + self.chunk_size;
+ let nth_back = &self.v[start..end];
+ self.v = &self.v[end..];
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "rchunks", since = "1.31.0")]
Some(head)
}
}
+
+ #[inline]
+ fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+ let len = self.len();
+ if n >= len {
+ self.v = &mut [];
+ None
+ } else {
+ // now that we know that `n` corresponds to a chunk,
+ // none of these operations can underflow/overflow
+ let offset = (len - n) * self.chunk_size;
+ let start = self.v.len() - offset;
+ let end = start + self.chunk_size;
+ let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
+ let (_, nth_back) = tmp.split_at_mut(start);
+ self.v = tail;
+ Some(nth_back)
+ }
+ }
}
#[stable(feature = "rchunks", since = "1.31.0")]
assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
}
+#[test]
+fn test_iterator_sum_option() {
+ let v: &[Option<i32>] = &[Some(1), Some(2), Some(3), Some(4)];
+ assert_eq!(v.iter().cloned().sum::<Option<i32>>(), Some(10));
+ let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
+ assert_eq!(v.iter().cloned().sum::<Option<i32>>(), None);
+}
+
#[test]
fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
}
}
+#[test]
+fn test_iterator_product_option() {
+ let v: &[Option<i32>] = &[Some(1), Some(2), Some(3), Some(4)];
+ assert_eq!(v.iter().cloned().product::<Option<i32>>(), Some(24));
+ let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
+ assert_eq!(v.iter().cloned().product::<Option<i32>>(), None);
+}
+
#[test]
fn test_iterator_max() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_chunks_nth_back() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.chunks(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next().unwrap(), &[0, 1]);
+ assert_eq!(c.next(), None);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.chunks(3);
+ assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]);
+ assert_eq!(c2.next(), None);
+ assert_eq!(c2.next_back(), None);
+
+ let v3: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c3 = v3.chunks(10);
+ assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]);
+ assert_eq!(c3.next(), None);
+
+ let v4: &[i32] = &[0, 1, 2];
+ let mut c4 = v4.chunks(10);
+ assert_eq!(c4.nth_back(1_000_000_000usize), None);
+}
+
#[test]
fn test_chunks_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_rchunks_nth_back() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.rchunks(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next_back().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4];
+ let mut c2 = v2.rchunks(3);
+ assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]);
+ assert_eq!(c2.next_back(), None);
+}
+
#[test]
fn test_rchunks_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_rchunks_mut_nth_back() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let mut c = v.rchunks_mut(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next_back().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
+ let mut c2 = v2.rchunks_mut(3);
+ assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]);
+ assert_eq!(c2.next_back(), None);
+}
+
#[test]
fn test_rchunks_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_rchunks_exact_nth_back() {
+ let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+ let mut c = v.rchunks_exact(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next_back().unwrap(), &[4, 5]);
+
+ let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.rchunks_exact(3);
+ assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]);
+ assert_eq!(c2.next(), None);
+}
+
#[test]
fn test_rchunks_exact_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
assert_eq!(c2.next(), None);
}
+#[test]
+fn test_rchunks_exact_mut_nth_back() {
+ let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+ let mut c = v.rchunks_exact_mut(2);
+ assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+ assert_eq!(c.next_back().unwrap(), &[4, 5]);
+
+ let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
+ let mut c2 = v2.rchunks_exact_mut(3);
+ assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]);
+ assert_eq!(c2.next(), None);
+}
+
#[test]
fn test_rchunks_exact_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
GenericArg::Const(c) => c.value.hir_id,
}
}
+
+ pub fn is_const(&self) -> bool {
+ match self {
+ GenericArg::Const(_) => true,
+ _ => false,
+ }
+ }
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
for sp in prior_arms {
err.span_label(*sp, format!(
"this is found to be of type `{}`",
- self.resolve_type_vars_if_possible(&last_ty),
+ self.resolve_vars_if_possible(&last_ty),
));
}
} else if let Some(sp) = prior_arms.last() {
&self,
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
- let exp_found = self.resolve_type_vars_if_possible(exp_found);
+ let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
&self,
exp_found: &ty::error::ExpectedFound<T>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
- let exp_found = self.resolve_type_vars_if_possible(exp_found);
+ let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
});
match ty_opt {
Some(ty) => {
- let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+ let ty = self.infcx.resolve_vars_if_possible(&ty);
ty.walk().any(|inner_ty| {
inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
span: Span,
ty: Ty<'tcx>
) -> DiagnosticBuilder<'gcx> {
- let ty = self.resolve_type_vars_if_possible(&ty);
+ let ty = self.resolve_vars_if_possible(&ty);
let name = self.extract_type_name(&ty, None);
let mut err_span = span;
span: Span,
ty: Ty<'tcx>
) -> DiagnosticBuilder<'gcx> {
- let ty = self.resolve_type_vars_if_possible(&ty);
+ let ty = self.resolve_vars_if_possible(&ty);
let name = self.extract_type_name(&ty, None);
let mut err = struct_span_err!(self.tcx.sess,
_ => (),
}
- let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
+ let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id,
substs: expected_substs,
});
- let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef {
+ let actual_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
def_id: trait_def_id,
substs: actual_substs,
});
let (mut fudger, value) = self.probe(|snapshot| {
match f() {
Ok(value) => {
- let value = self.resolve_type_vars_if_possible(&value);
+ let value = self.resolve_vars_if_possible(&value);
// At this point, `value` could in principle refer
// to inference variables that have been created during
/// Process the region constraints and report any errors that
/// result. After this, no more unification operations should be
/// done -- or the compiler will panic -- but it is legal to use
- /// `resolve_type_vars_if_possible` as well as `fully_resolve`.
+ /// `resolve_vars_if_possible` as well as `fully_resolve`.
pub fn resolve_regions_and_report_errors(
&self,
region_context: DefId,
}
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
- self.resolve_type_vars_if_possible(&t).to_string()
+ self.resolve_vars_if_possible(&t).to_string()
}
pub fn tys_to_string(&self, ts: &[Ty<'tcx>]) -> String {
}
pub fn trait_ref_to_string(&self, t: &ty::TraitRef<'tcx>) -> String {
- self.resolve_type_vars_if_possible(t).to_string()
+ self.resolve_vars_if_possible(t).to_string()
}
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the
self.type_variables.borrow_mut().root_var(var)
}
- /// Where possible, replaces type/int/float variables in
+ /// Where possible, replaces type/const variables in
/// `value` with their final value. Note that region variables
- /// are unaffected. If a type variable has not been unified, it
+ /// are unaffected. If a type/const variable has not been unified, it
/// is left as is. This is an idempotent operation that does
/// not affect inference state in any way and so you can do it
/// at will.
- pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
+ pub fn resolve_vars_if_possible<T>(&self, value: &T) -> T
where
T: TypeFoldable<'tcx>,
{
if !value.needs_infer() {
return value.clone(); // avoid duplicated subst-folding
}
- let mut r = resolve::OpportunisticTypeResolver::new(self);
+ let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
}
/// process of visiting `T`, this will resolve (where possible)
/// type variables in `T`, but it never constructs the final,
/// resolved type, so it's more efficient than
- /// `resolve_type_vars_if_possible()`.
+ /// `resolve_vars_if_possible()`.
pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
where
T: TypeFoldable<'tcx>,
where
M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
{
- let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
+ let actual_ty = self.resolve_vars_if_possible(&actual_ty);
debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
// Don't report an error if actual type is `Error`.
ty: Ty<'tcx>,
span: Span,
) -> bool {
- let ty = self.resolve_type_vars_if_possible(&ty);
+ let ty = self.resolve_vars_if_possible(&ty);
// Even if the type may have no inference variables, during
// type-checking closure types are in local tables only.
let tcx = self.tcx;
- let concrete_ty = self.resolve_type_vars_if_possible(&opaque_defn.concrete_ty);
+ let concrete_ty = self.resolve_vars_if_possible(&opaque_defn.concrete_ty);
debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
debug!("add_implied_bounds()");
for &ty in fn_sig_tys {
- let ty = infcx.resolve_type_vars_if_possible(&ty);
+ let ty = infcx.resolve_vars_if_possible(&ty);
debug!("add_implied_bounds: ty = {}", ty);
let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
self.add_outlives_bounds(Some(infcx), implied_bounds)
sup_type, sub_region, origin
);
- let sup_type = self.resolve_type_vars_if_possible(&sup_type);
+ let sup_type = self.resolve_vars_if_possible(&sup_type);
if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
let outlives = &mut TypeOutlives::new(
implicit_region_bound,
param_env,
);
- let ty = self.resolve_type_vars_if_possible(&ty);
+ let ty = self.resolve_vars_if_possible(&ty);
outlives.type_must_outlive(origin, ty, region);
}
}
use super::{InferCtxt, FixupError, FixupResult, Span, type_variable::TypeVariableOrigin};
use crate::mir::interpret::ConstValue;
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable, InferConst};
+use crate::ty::{self, Ty, Const, TyCtxt, TypeFoldable, InferConst, TypeFlags};
use crate::ty::fold::{TypeFolder, TypeVisitor};
///////////////////////////////////////////////////////////////////////////
-// OPPORTUNISTIC TYPE RESOLVER
+// OPPORTUNISTIC VAR RESOLVER
-/// The opportunistic type resolver can be used at any time. It simply replaces
-/// type variables that have been unified with the things they have
+/// The opportunistic resolver can be used at any time. It simply replaces
+/// type/const variables that have been unified with the things they have
/// been unified with (similar to `shallow_resolve`, but deep). This is
/// useful for printing messages etc but also required at various
/// points for correctness.
-pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+pub struct OpportunisticVarResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
}
-impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> OpportunisticVarResolver<'a, 'gcx, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
- OpportunisticTypeResolver { infcx }
+ OpportunisticVarResolver { infcx }
}
}
-impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticVarResolver<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.infcx.tcx
}
if !t.has_infer_types() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
- let t0 = self.infcx.shallow_resolve(t);
- t0.super_fold_with(self)
+ let t = self.infcx.shallow_resolve(t);
+ t.super_fold_with(self)
+ }
+ }
+
+ fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
+ if !ct.has_type_flags(TypeFlags::HAS_CT_INFER) {
+ ct // micro-optimize -- if there is nothing in this const that this fold affects...
+ } else {
+ let ct = self.infcx.shallow_resolve(ct);
+ ct.super_fold_with(self)
}
}
}
declare_lint! {
pub BARE_TRAIT_OBJECTS,
- Allow,
+ Warn,
"suggest using `dyn Trait` for trait objects"
}
.unwrap_or(true)
}
- fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
+ fn resolve_vars_if_possible<T>(&self, value: &T) -> T
where T: TypeFoldable<'tcx>
{
- self.infcx.map(|infcx| infcx.resolve_type_vars_if_possible(value))
+ self.infcx.map(|infcx| infcx.resolve_vars_if_possible(value))
.unwrap_or_else(|| value.clone())
}
-> McResult<Ty<'tcx>> {
match ty {
Some(ty) => {
- let ty = self.resolve_type_vars_if_possible(&ty);
+ let ty = self.resolve_vars_if_possible(&ty);
if ty.references_error() || ty.is_ty_var() {
debug!("resolve_type_vars_or_error: error from {:?}", ty);
Err(())
where F: FnOnce() -> McResult<cmt_<'tcx>>
{
debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
- let target = self.resolve_type_vars_if_possible(&adjustment.target);
+ let target = self.resolve_vars_if_possible(&adjustment.target);
match adjustment.kind {
adjustment::Adjust::Deref(overloaded) => {
// Equivalent to *expr or something similar.
impl<T: PartialEq> Set1<T> {
pub fn insert(&mut self, value: T) {
- if let Set1::Empty = *self {
- *self = Set1::One(value);
- return;
- }
- if let Set1::One(ref old) = *self {
- if *old == value {
- return;
- }
- }
- *self = Set1::Many;
+ *self = match self {
+ Set1::Empty => Set1::One(value),
+ Set1::One(old) if *old == value => return,
+ _ => Set1::Many,
+ };
}
}
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult};
use crate::ich::StableHashingContext;
-use crate::mir::{Mir, BasicBlock};
+use crate::mir::{Body, BasicBlock};
use crate::rustc_serialize as serialize;
pub fn predecessors(
&self,
- mir: &Mir<'_>
+ mir: &Body<'_>
) -> MappedReadGuard<'_, IndexVec<BasicBlock, Vec<BasicBlock>>> {
if self.predecessors.borrow().is_none() {
*self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
}
}
-fn calculate_predecessors(mir: &Mir<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
+fn calculate_predecessors(mir: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
for (bb, data) in mir.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
use super::{
Pointer, EvalResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar,
- truncate,
};
use crate::ty::layout::{Size, Align};
ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
};
- let bytes = match val {
- Scalar::Ptr(val) => {
- assert_eq!(type_size, cx.data_layout().pointer_size);
- val.offset.bytes() as u128
- }
-
- Scalar::Bits { bits, size } => {
- assert_eq!(size as u64, type_size.bytes());
- debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
- "Unexpected value of size {} when writing to memory", size);
- bits
- },
+ let bytes = match val.to_bits_or_ptr(type_size, cx) {
+ Err(val) => val.offset.bytes() as u128,
+ Ok(data) => data,
};
let endian = cx.data_layout().endian;
/// For a promoted global, the `Instance` of the function they belong to.
pub instance: ty::Instance<'tcx>,
- /// The index for promoted globals within their function's `Mir`.
+ /// The index for promoted globals within their function's `mir::Body`.
pub promoted: Option<mir::Promoted>,
}
/// illegal and will likely ICE.
/// This function exists to allow const eval to detect the difference between evaluation-
/// local dangling pointers and allocations in constants/statics.
+ #[inline]
pub fn get(&self, id: AllocId) -> Option<AllocKind<'tcx>> {
self.id_to_kind.get(&id).cloned()
}
// Methods to access integers in the target endianness
////////////////////////////////////////////////////////////////////////////////
+#[inline]
pub fn write_target_uint(
endianness: layout::Endian,
mut target: &mut [u8],
}
}
+#[inline]
pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
match endianness {
layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
// Methods to facilitate working with signed integers stored in a u128
////////////////////////////////////////////////////////////////////////////////
+/// Truncate `value` to `size` bits and then sign-extend it to 128 bits
+/// (i.e., if it is negative, fill with 1's on the left).
+#[inline]
pub fn sign_extend(value: u128, size: Size) -> u128 {
let size = size.bits();
+ if size == 0 {
+ // Truncated until nothing is left.
+ return 0;
+ }
// sign extend
let shift = 128 - size;
// shift the unsigned value to the left
(((value << shift) as i128) >> shift) as u128
}
+/// Truncate `value` to `size` bits.
+#[inline]
pub fn truncate(value: u128, size: Size) -> u128 {
let size = size.bits();
+ if size == 0 {
+ // Truncated until nothing is left.
+ return 0;
+ }
let shift = 128 - size;
// truncate (shift left to drop out leftover values, shift right to fill with zeroes)
(value << shift) >> shift
self.data_layout().pointer_size
}
- //// Trunace the given value to the pointer size; also return whether there was an overflow
+ /// Helper function: truncate given value-"overflowed flag" pair to pointer size and
+ /// update "overflowed flag" if there was an overflow.
+ /// This should be called by all the other methods before returning!
#[inline]
- fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
+ fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
+ let val = val as u128;
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
- ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
- }
-
- #[inline]
- fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
- let (res, over) = self.overflowing_offset(val, i);
- if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+ ((val % max_ptr_plus_1) as u64, over || val >= max_ptr_plus_1)
}
#[inline]
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
- let (res, over1) = val.overflowing_add(i);
- let (res, over2) = self.truncate_to_ptr(u128::from(res));
- (res, over1 || over2)
- }
-
- #[inline]
- fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
- let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
- if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+ let res = val.overflowing_add(i);
+ self.truncate_to_ptr(res)
}
// Overflow checking only works properly on the range from -u64 to +u64.
fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
// FIXME: is it possible to over/underflow here?
if i < 0 {
- // trickery to ensure that i64::min_value() works fine
- // this formula only works for true negative values, it panics for zero!
+ // Trickery to ensure that i64::min_value() works fine: compute n = -i.
+ // This formula only works for true negative values, it overflows for zero!
let n = u64::max_value() - (i as u64) + 1;
- val.overflowing_sub(n)
+ let res = val.overflowing_sub(n);
+ self.truncate_to_ptr(res)
} else {
self.overflowing_offset(val, i as u64)
}
}
+
+ #[inline]
+ fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
+ let (res, over) = self.overflowing_offset(val, i);
+ if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+ }
+
+ #[inline]
+ fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
+ let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
+ if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+ }
}
impl<T: layout::HasDataLayout> PointerArithmetic for T {}
RustcEncodable, RustcDecodable, Hash, HashStable)]
pub enum Scalar<Tag=(), Id=AllocId> {
/// The raw bytes of a simple value.
- Bits {
- /// The first `size` bytes are the value.
+ Raw {
+ /// The first `size` bytes of `data` are the value.
/// Do not try to read less or more bytes than that. The remaining bytes must be 0.
+ data: u128,
size: u8,
- bits: u128,
},
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
match self {
Scalar::Ptr(ptr) =>
write!(f, "{:?}", ptr),
- &Scalar::Bits { bits, size } => {
+ &Scalar::Raw { data, size } => {
+ Scalar::check_data(data, size);
if size == 0 {
- assert_eq!(bits, 0, "ZST value must be 0");
write!(f, "<ZST>")
} else {
- assert_eq!(truncate(bits, Size::from_bytes(size as u64)), bits,
- "Scalar value {:#x} exceeds size of {} bytes", bits, size);
// Format as hex number wide enough to fit any value of the given `size`.
- // So bits=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
- write!(f, "0x{:>0width$x}", bits, width=(size*2) as usize)
+ // So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
+ write!(f, "0x{:>0width$x}", data, width=(size*2) as usize)
}
}
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scalar::Ptr(_) => write!(f, "a pointer"),
- Scalar::Bits { bits, .. } => write!(f, "{}", bits),
+ Scalar::Raw { data, .. } => write!(f, "{}", data),
}
}
}
impl<'tcx> Scalar<()> {
+ #[inline(always)]
+ fn check_data(data: u128, size: u8) {
+ debug_assert_eq!(truncate(data, Size::from_bytes(size as u64)), data,
+ "Scalar value {:#x} exceeds size of {} bytes", data, size);
+ }
+
#[inline]
pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
- Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+ Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
}
pub fn erase_tag(self) -> Scalar {
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
- Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
+ Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
}
#[inline]
pub fn ptr_null(cx: &impl HasDataLayout) -> Self {
- Scalar::Bits {
- bits: 0,
+ Scalar::Raw {
+ data: 0,
size: cx.data_layout().pointer_size.bytes() as u8,
}
}
#[inline]
pub fn zst() -> Self {
- Scalar::Bits { bits: 0, size: 0 }
+ Scalar::Raw { data: 0, size: 0 }
}
#[inline]
pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
- Ok(Scalar::Bits {
- bits: dl.offset(bits as u64, i.bytes())? as u128,
+ Ok(Scalar::Raw {
+ data: dl.offset(data as u64, i.bytes())? as u128,
size,
})
}
pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
let dl = cx.data_layout();
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
- Scalar::Bits {
- bits: dl.overflowing_offset(bits as u64, i.bytes()).0 as u128,
+ Scalar::Raw {
+ data: dl.overflowing_offset(data as u64, i.bytes()).0 as u128,
size,
}
}
pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size().bytes());
- Ok(Scalar::Bits {
- bits: dl.signed_offset(bits as u64, i)? as u128,
+ Ok(Scalar::Raw {
+ data: dl.signed_offset(data as u64, i)? as u128,
size,
})
}
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
let dl = cx.data_layout();
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, dl.pointer_size.bytes());
- Scalar::Bits {
- bits: dl.overflowing_signed_offset(bits as u64, i128::from(i)).0 as u128,
+ Scalar::Raw {
+ data: dl.overflowing_signed_offset(data as u64, i128::from(i)).0 as u128,
size,
}
}
}
}
- /// Returns this pointers offset from the allocation base, or from NULL (for
+ /// Returns this pointer's offset from the allocation base, or from NULL (for
/// integer pointers).
#[inline]
pub fn get_ptr_offset(self, cx: &impl HasDataLayout) -> Size {
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, cx.pointer_size().bytes());
- Size::from_bytes(bits as u64)
+ Size::from_bytes(data as u64)
}
Scalar::Ptr(ptr) => ptr.offset,
}
#[inline]
pub fn is_null_ptr(self, cx: &impl HasDataLayout) -> bool {
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
- bits == 0
+ data == 0
},
Scalar::Ptr(_) => false,
}
#[inline]
pub fn from_bool(b: bool) -> Self {
- Scalar::Bits { bits: b as u128, size: 1 }
+ Scalar::Raw { data: b as u128, size: 1 }
}
#[inline]
pub fn from_char(c: char) -> Self {
- Scalar::Bits { bits: c as u128, size: 4 }
+ Scalar::Raw { data: c as u128, size: 4 }
}
#[inline]
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
let i = i.into();
- debug_assert_eq!(truncate(i, size), i,
- "Unsigned value {} does not fit in {} bits", i, size.bits());
- Scalar::Bits { bits: i, size: size.bytes() as u8 }
+ assert_eq!(
+ truncate(i, size), i,
+ "Unsigned value {:#x} does not fit in {} bits", i, size.bits()
+ );
+ Scalar::Raw { data: i, size: size.bytes() as u8 }
}
#[inline]
let i = i.into();
// `into` performed sign extension, we have to truncate
let truncated = truncate(i as u128, size);
- debug_assert_eq!(sign_extend(truncated, size) as i128, i,
- "Signed value {} does not fit in {} bits", i, size.bits());
- Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
+ assert_eq!(
+ sign_extend(truncated, size) as i128, i,
+ "Signed value {:#x} does not fit in {} bits", i, size.bits()
+ );
+ Scalar::Raw { data: truncated, size: size.bytes() as u8 }
}
#[inline]
pub fn from_f32(f: f32) -> Self {
- Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
+ Scalar::Raw { data: f.to_bits() as u128, size: 4 }
}
#[inline]
pub fn from_f64(f: f64) -> Self {
- Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
+ Scalar::Raw { data: f.to_bits() as u128, size: 8 }
+ }
+
+ #[inline]
+ pub fn to_bits_or_ptr(
+ self,
+ target_size: Size,
+ cx: &impl HasDataLayout,
+ ) -> Result<u128, Pointer<Tag>> {
+ match self {
+ Scalar::Raw { data, size } => {
+ assert_eq!(target_size.bytes(), size as u64);
+ assert_ne!(size, 0, "you should never look at the bits of a ZST");
+ Scalar::check_data(data, size);
+ Ok(data)
+ }
+ Scalar::Ptr(ptr) => {
+ assert_eq!(target_size, cx.data_layout().pointer_size);
+ Err(ptr)
+ }
+ }
}
#[inline]
pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
match self {
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(target_size.bytes(), size as u64);
- assert_ne!(size, 0, "to_bits cannot be used with zsts");
- Ok(bits)
+ assert_ne!(size, 0, "you should never look at the bits of a ZST");
+ Scalar::check_data(data, size);
+ Ok(data)
}
Scalar::Ptr(_) => err!(ReadPointerAsBytes),
}
#[inline]
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
match self {
- Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
- Scalar::Bits { .. } => err!(ReadBytesAsPointer),
+ Scalar::Raw { data: 0, .. } => err!(InvalidNullPointerUsage),
+ Scalar::Raw { .. } => err!(ReadBytesAsPointer),
Scalar::Ptr(p) => Ok(p),
}
}
#[inline]
pub fn is_bits(self) -> bool {
match self {
- Scalar::Bits { .. } => true,
+ Scalar::Raw { .. } => true,
_ => false,
}
}
pub fn to_bool(self) -> EvalResult<'tcx, bool> {
match self {
- Scalar::Bits { bits: 0, size: 1 } => Ok(false),
- Scalar::Bits { bits: 1, size: 1 } => Ok(true),
+ Scalar::Raw { data: 0, size: 1 } => Ok(false),
+ Scalar::Raw { data: 1, size: 1 } => Ok(true),
_ => err!(InvalidBool),
}
}
pub fn to_u8(self) -> EvalResult<'static, u8> {
let sz = Size::from_bits(8);
let b = self.to_bits(sz)?;
- assert_eq!(b as u8 as u128, b);
Ok(b as u8)
}
pub fn to_u32(self) -> EvalResult<'static, u32> {
let sz = Size::from_bits(32);
let b = self.to_bits(sz)?;
- assert_eq!(b as u32 as u128, b);
Ok(b as u32)
}
pub fn to_u64(self) -> EvalResult<'static, u64> {
let sz = Size::from_bits(64);
let b = self.to_bits(sz)?;
- assert_eq!(b as u64 as u128, b);
Ok(b as u64)
}
pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'static, u64> {
let b = self.to_bits(cx.data_layout().pointer_size)?;
- assert_eq!(b as u64 as u128, b);
Ok(b as u64)
}
let sz = Size::from_bits(8);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
- assert_eq!(b as i8 as i128, b);
Ok(b as i8)
}
let sz = Size::from_bits(32);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
- assert_eq!(b as i32 as i128, b);
Ok(b as i32)
}
let sz = Size::from_bits(64);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
- assert_eq!(b as i64 as i128, b);
Ok(b as i64)
}
pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'static, i64> {
- let b = self.to_bits(cx.data_layout().pointer_size)?;
- let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
- assert_eq!(b as i64 as i128, b);
+ let sz = cx.data_layout().pointer_size;
+ let b = self.to_bits(sz)?;
+ let b = sign_extend(b, sz) as i128;
Ok(b as i64)
}
}
}
-impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
+impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx> {
&self.local_decls
}
/// Lowered representation of a single function.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct Mir<'tcx> {
+pub struct Body<'tcx> {
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
/// that indexes into this vector.
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
pub source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
/// Rvalues promoted from this function, such as borrows of constants.
- /// Each of them is the Mir of a constant with the fn's type parameters
+ /// Each of them is the Body of a constant with the fn's type parameters
/// in scope, but a separate set of locals.
- pub promoted: IndexVec<Promoted, Mir<'tcx>>,
+ pub promoted: IndexVec<Promoted, Body<'tcx>>,
/// Yields type of the function, if it is a generator.
pub yield_ty: Option<Ty<'tcx>>,
/// Generator drop glue
- pub generator_drop: Option<Box<Mir<'tcx>>>,
+ pub generator_drop: Option<Box<Body<'tcx>>>,
/// The layout of a generator. Produced by the state transformation.
pub generator_layout: Option<GeneratorLayout<'tcx>>,
cache: cache::Cache,
}
-impl<'tcx> Mir<'tcx> {
+impl<'tcx> Body<'tcx> {
pub fn new(
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
source_scopes: IndexVec<SourceScope, SourceScopeData>,
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
- promoted: IndexVec<Promoted, Mir<'tcx>>,
+ promoted: IndexVec<Promoted, Body<'tcx>>,
yield_ty: Option<Ty<'tcx>>,
local_decls: LocalDecls<'tcx>,
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
local_decls.len()
);
- Mir {
+ Body {
phase: MirPhase::Build,
basic_blocks,
source_scopes,
ExplicitUnsafe(hir::HirId),
}
-impl_stable_hash_for!(struct Mir<'tcx> {
+impl_stable_hash_for!(struct Body<'tcx> {
phase,
basic_blocks,
source_scopes,
cache
});
-impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
+impl<'tcx> Index<BasicBlock> for Body<'tcx> {
type Output = BasicBlockData<'tcx>;
#[inline]
}
}
-impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
+impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
#[inline]
fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks_mut()[index]
}
}
-/// Classifies locals into categories. See `Mir::local_kind`.
+/// Classifies locals into categories. See `Body::local_kind`.
#[derive(PartialEq, Eq, Debug, HashStable)]
pub enum LocalKind {
/// User-declared variable binding
.map(|&u| {
tcx.mk_const(ty::Const {
val: ConstValue::Scalar(
- Scalar::Bits {
- bits: u,
- size: size.bytes() as u8,
- }.into(),
+ Scalar::from_uint(u, size).into(),
),
ty: switch_ty,
}).to_string().into()
/// a single deref of a local.
//
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
- pub fn local(&self) -> Option<Local> {
+ pub fn local_or_deref_local(&self) -> Option<Local> {
match self {
Place::Base(PlaceBase::Local(local)) |
Place::Projection(box Projection {
}
}
-impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
+impl<'tcx> graph::DirectedGraph for Body<'tcx> {
type Node = BasicBlock;
}
-impl<'tcx> graph::WithNumNodes for Mir<'tcx> {
+impl<'tcx> graph::WithNumNodes for Body<'tcx> {
fn num_nodes(&self) -> usize {
self.basic_blocks.len()
}
}
-impl<'tcx> graph::WithStartNode for Mir<'tcx> {
+impl<'tcx> graph::WithStartNode for Body<'tcx> {
fn start_node(&self) -> Self::Node {
START_BLOCK
}
}
-impl<'tcx> graph::WithPredecessors for Mir<'tcx> {
+impl<'tcx> graph::WithPredecessors for Body<'tcx> {
fn predecessors<'graph>(
&'graph self,
node: Self::Node,
}
}
-impl<'tcx> graph::WithSuccessors for Mir<'tcx> {
+impl<'tcx> graph::WithSuccessors for Body<'tcx> {
fn successors<'graph>(
&'graph self,
node: Self::Node,
}
}
-impl<'a, 'b> graph::GraphPredecessors<'b> for Mir<'a> {
+impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> {
type Item = BasicBlock;
type Iter = IntoIter<BasicBlock>;
}
-impl<'a, 'b> graph::GraphSuccessors<'b> for Mir<'a> {
+impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
type Item = BasicBlock;
type Iter = iter::Cloned<Successors<'b>>;
}
}
/// Returns `true` if `other` is earlier in the control flow graph than `self`.
- pub fn is_predecessor_of<'tcx>(&self, other: Location, mir: &Mir<'tcx>) -> bool {
+ pub fn is_predecessor_of<'tcx>(&self, other: Location, mir: &Body<'tcx>) -> bool {
// If we are in the same block as the other location and are an earlier statement
// then we are a predecessor of `other`.
if self.block == other.block && self.statement_index < other.statement_index {
}
BraceStructTypeFoldableImpl! {
- impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
+ impl<'tcx> TypeFoldable<'tcx> for Body<'tcx> {
phase,
basic_blocks,
source_scopes,
}
}
-#[derive(Clone, Default)]
-pub struct Stats {
- pub n_glues_created: usize,
- pub n_null_glues: usize,
- pub n_real_glues: usize,
- pub n_fns: usize,
- pub n_inlines: usize,
- pub n_closures: usize,
- pub n_llvm_insns: usize,
- pub llvm_insns: FxHashMap<String, usize>,
- // (ident, llvm-instructions)
- pub fn_stats: Vec<(String, usize)>,
-}
-
-impl_stable_hash_for!(struct self::Stats {
- n_glues_created,
- n_null_glues,
- n_real_glues,
- n_fns,
- n_inlines,
- n_closures,
- n_llvm_insns,
- llvm_insns,
- fn_stats
-});
-
-impl Stats {
- pub fn extend(&mut self, stats: Stats) {
- self.n_glues_created += stats.n_glues_created;
- self.n_null_glues += stats.n_null_glues;
- self.n_real_glues += stats.n_real_glues;
- self.n_fns += stats.n_fns;
- self.n_inlines += stats.n_inlines;
- self.n_closures += stats.n_closures;
- self.n_llvm_insns += stats.n_llvm_insns;
-
- for (k, v) in stats.llvm_insns {
- *self.llvm_insns.entry(k).or_insert(0) += v;
- }
- self.fn_stats.extend(stats.fn_stats);
- }
-}
-
pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
cache: FxHashMap<CrateNum, String>,
/// A preorder traversal of this graph is either `A B D C` or `A C D B`
#[derive(Clone)]
pub struct Preorder<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
visited: BitSet<BasicBlock>,
worklist: Vec<BasicBlock>,
root_is_start_block: bool,
}
impl<'a, 'tcx> Preorder<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
+ pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
let worklist = vec![root];
Preorder {
}
}
-pub fn preorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> Preorder<'a, 'tcx> {
+pub fn preorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> Preorder<'a, 'tcx> {
Preorder::new(mir, START_BLOCK)
}
///
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
pub struct Postorder<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
visited: BitSet<BasicBlock>,
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
root_is_start_block: bool,
}
impl<'a, 'tcx> Postorder<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
+ pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
let mut po = Postorder {
mir,
visited: BitSet::new_empty(mir.basic_blocks().len()),
}
}
-pub fn postorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> Postorder<'a, 'tcx> {
+pub fn postorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
Postorder::new(mir, START_BLOCK)
}
/// to re-use the traversal
#[derive(Clone)]
pub struct ReversePostorder<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
blocks: Vec<BasicBlock>,
idx: usize
}
impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
+ pub fn new(mir: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
let blocks : Vec<_> = Postorder::new(mir, root).map(|(bb, _)| bb).collect();
let len = blocks.len();
}
-pub fn reverse_postorder<'a, 'tcx>(mir: &'a Mir<'tcx>) -> ReversePostorder<'a, 'tcx> {
+pub fn reverse_postorder<'a, 'tcx>(mir: &'a Body<'tcx>) -> ReversePostorder<'a, 'tcx> {
ReversePostorder::new(mir, START_BLOCK)
}
// Override these, and call `self.super_xxx` to revert back to the
// default behavior.
- fn visit_mir(&mut self, mir: & $($mutability)? Mir<'tcx>) {
- self.super_mir(mir);
+ fn visit_body(&mut self, mir: & $($mutability)? Body<'tcx>) {
+ self.super_body(mir);
}
fn visit_basic_block_data(&mut self,
// The `super_xxx` methods comprise the default behavior and are
// not meant to be overridden.
- fn super_mir(&mut self,
- mir: & $($mutability)? Mir<'tcx>) {
+ fn super_body(&mut self,
+ mir: & $($mutability)? Body<'tcx>) {
if let Some(yield_ty) = &$($mutability)? mir.yield_ty {
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
span: mir.span,
}
// for best performance, we want to use an iterator rather
- // than a for-loop, to avoid calling Mir::invalidate for
+ // than a for-loop, to avoid calling `mir::Body::invalidate` for
// each basic block.
macro_rules! basic_blocks {
(mut) => (mir.basic_blocks_mut().iter_enumerated_mut());
// Convenience methods
- fn visit_location(&mut self, mir: & $($mutability)? Mir<'tcx>, location: Location) {
+ fn visit_location(&mut self, mir: & $($mutability)? Body<'tcx>, location: Location) {
let basic_block = & $($mutability)? mir[location.block];
if basic_block.statements.len() == location.statement_index {
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
desc { "getting a list of all mir_keys" }
}
- /// Maps DefId's that have an associated Mir to the result
+ /// Maps DefId's that have an associated `mir::Body` to the result
/// of the MIR qualify_consts pass. The actual meaning of
/// the value isn't known except to the pass itself.
query mir_const_qualif(key: DefId) -> (u8, &'tcx BitSet<mir::Local>) {
/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
- query mir_built(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {}
+ query mir_built(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {}
/// Fetch the MIR for a given `DefId` up till the point where it is
/// ready for const evaluation.
///
/// See the README for the `mir` module for details.
- query mir_const(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+ query mir_const(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
no_hash
}
- query mir_validated(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+ query mir_validated(_: DefId) -> &'tcx Steal<mir::Body<'tcx>> {
no_hash
}
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
- query optimized_mir(key: DefId) -> &'tcx mir::Mir<'tcx> {
+ query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
cache { key.is_local() }
load_cached(tcx, id) {
- let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
+ let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
mir.map(|x| tcx.alloc_mir(x))
}
/// in the case of closures, this will be redirected to the enclosing function.
query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
- query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Mir<'tcx> {
+ query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
no_force
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
}
}
#[derive(Clone, PartialEq, Hash)]
-pub enum PgoGenerate {
+pub enum SwitchWithOptPath {
Enabled(Option<PathBuf>),
Disabled,
}
-impl PgoGenerate {
+impl SwitchWithOptPath {
pub fn enabled(&self) -> bool {
match *self {
- PgoGenerate::Enabled(_) => true,
- PgoGenerate::Disabled => false,
+ SwitchWithOptPath::Enabled(_) => true,
+ SwitchWithOptPath::Disabled => false,
}
}
}
pub const parse_linker_plugin_lto: Option<&str> =
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
or the path to the linker plugin");
- pub const parse_pgo_generate: Option<&str> =
+ pub const parse_switch_with_opt_path: Option<&str> =
Some("an optional path to the profiling data output directory");
pub const parse_merge_functions: Option<&str> =
Some("one of: `disabled`, `trampolines`, or `aliases`");
#[allow(dead_code)]
mod $mod_set {
- use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
+ use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath};
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use std::path::PathBuf;
use std::str::FromStr;
true
}
- fn parse_pgo_generate(slot: &mut PgoGenerate, v: Option<&str>) -> bool {
+ fn parse_switch_with_opt_path(slot: &mut SwitchWithOptPath, v: Option<&str>) -> bool {
*slot = match v {
- None => PgoGenerate::Enabled(None),
- Some(path) => PgoGenerate::Enabled(Some(PathBuf::from(path))),
+ None => SwitchWithOptPath::Enabled(None),
+ Some(path) => SwitchWithOptPath::Enabled(Some(PathBuf::from(path))),
};
true
}
"measure time of each rustc pass"),
time: bool = (false, parse_bool, [UNTRACKED],
"measure time of rustc processes"),
- count_llvm_insns: bool = (false, parse_bool,
- [UNTRACKED_WITH_WARNING(true,
- "The output generated by `-Z count_llvm_insns` might not be reliable \
- when used with incremental compilation")],
- "count where LLVM instrs originate"),
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z time-llvm-passes` will only reflect timings of \
re-codegened modules when used with incremental compilation" )],
"measure time of each LLVM pass"),
input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input"),
- codegen_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
- "The output of `-Z codegen-stats` might not be accurate when incremental \
- compilation is enabled")],
- "gather codegen statistics"),
asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior)"),
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
- pgo_gen: PgoGenerate = (PgoGenerate::Disabled, parse_pgo_generate, [TRACKED],
+ pgo_gen: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+ parse_switch_with_opt_path, [TRACKED],
"Generate PGO profile data, to a given file, or to the default location if it's empty."),
pgo_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"Use PGO profile data from the given profile file."),
"don't interleave execution of lints; allows benchmarking individual lints"),
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
"inject the given attribute in the crate"),
- self_profile: bool = (false, parse_bool, [UNTRACKED],
+ self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+ parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"),
self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
"specifies which kinds of events get recorded by the self profiler"),
use std::path::PathBuf;
use std::collections::hash_map::DefaultHasher;
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
- Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
+ Passes, Sanitizer, LtoCli, LinkerPluginLto, SwitchWithOptPath};
use syntax::feature_gate::UnstableFeatures;
use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
use syntax::edition::Edition;
impl_dep_tracking_hash_via_hash!(TargetTriple);
impl_dep_tracking_hash_via_hash!(Edition);
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
- impl_dep_tracking_hash_via_hash!(PgoGenerate);
+ impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
build_session_options_and_crate_config,
to_crate_config
};
- use crate::session::config::{LtoCli, LinkerPluginLto, PgoGenerate, ExternEntry};
+ use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
use crate::session::build_session;
use crate::session::search_paths::SearchPath;
use std::collections::{BTreeMap, BTreeSet};
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
- opts.debugging_opts.pgo_gen = PgoGenerate::Enabled(None);
+ opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None);
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
- opts.debugging_opts.count_llvm_insns = true;
- assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.input_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
- opts.debugging_opts.codegen_stats = true;
- assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true;
use crate::lint::builtin::BuiltinLintDiagnostics;
use crate::middle::allocator::AllocatorKind;
use crate::middle::dependency_format;
-use crate::session::config::OutputType;
+use crate::session::config::{OutputType, SwitchWithOptPath};
use crate::session::search_paths::{PathKind, SearchPath};
use crate::util::nodemap::{FxHashMap, FxHashSet};
use crate::util::common::{duration_to_secs_str, ErrorReported};
pub fn instrument_mcount(&self) -> bool {
self.opts.debugging_opts.instrument_mcount
}
- pub fn count_llvm_insns(&self) -> bool {
- self.opts.debugging_opts.count_llvm_insns
- }
pub fn time_llvm_passes(&self) -> bool {
self.opts.debugging_opts.time_llvm_passes
}
- pub fn codegen_stats(&self) -> bool {
- self.opts.debugging_opts.codegen_stats
- }
pub fn meta_stats(&self) -> bool {
self.opts.debugging_opts.meta_stats
}
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
) -> Session {
let self_profiler =
- if sopts.debugging_opts.self_profile {
- let profiler = SelfProfiler::new(&sopts.debugging_opts.self_profile_events);
+ if let SwitchWithOptPath::Enabled(ref d) = sopts.debugging_opts.self_profile {
+ let directory = if let Some(ref directory) = d {
+ directory
+ } else {
+ std::path::Path::new(".")
+ };
+
+ let profiler = SelfProfiler::new(
+ directory,
+ sopts.crate_name.as_ref().map(|s| &s[..]),
+ &sopts.debugging_opts.self_profile_events
+ );
match profiler {
Ok(profiler) => {
crate::ty::query::QueryName::register_with_profiler(&profiler);
path.display()));
}
}
+
+ // PGO does not work reliably with panic=unwind on Windows. Let's make it
+ // an error to combine the two for now. It always runs into an assertions
+ // if LLVM is built with assertions, but without assertions it sometimes
+ // does not crash and will probably generate a corrupted binary.
+ if sess.opts.debugging_opts.pgo_gen.enabled() &&
+ sess.target.target.options.is_like_msvc &&
+ sess.panic_strategy() == PanicStrategy::Unwind {
+ sess.err("Profile-guided optimization does not yet work in conjunction \
+ with `-Cpanic=unwind` on Windows when targeting MSVC. \
+ See https://github.com/rust-lang/rust/issues/61002 for details.");
+ }
}
/// Hash value constructed out of all the `-C metadata` arguments passed to the
continue;
}
- // Call infcx.resolve_type_vars_if_possible to see if we can
+ // Call infcx.resolve_vars_if_possible to see if we can
// get rid of any inference variables.
- let obligation = infcx.resolve_type_vars_if_possible(
+ let obligation = infcx.resolve_vars_if_possible(
&Obligation::new(dummy_cause.clone(), new_env, pred)
);
let result = select.select(&obligation);
fresh_preds.insert(self.clean_pred(select.infcx(), predicate));
// Resolve any inference variables that we can, to help selection succeed
- predicate = select.infcx().resolve_type_vars_if_possible(&predicate);
+ predicate = select.infcx().resolve_vars_if_possible(&predicate);
// We only add a predicate as a user-displayable bound if
// it involves a generic parameter, and doesn't contain
obligation: PredicateObligation<'tcx>
) -> InEnvironment<'tcx, PredicateObligation<'tcx>> {
assert!(!infcx.is_in_snapshot());
- let obligation = infcx.resolve_type_vars_if_possible(&obligation);
+ let obligation = infcx.resolve_vars_if_possible(&obligation);
let environment = match obligation.param_env.def_id {
Some(def_id) => infcx.tcx.environment(def_id),
bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
}
- let result = self.resolve_type_vars_if_possible(result);
+ let result = self.resolve_vars_if_possible(result);
let result = self.tcx.erase_regions(&result);
self.tcx.lift_to_global(&result).unwrap_or_else(||
- bug!("Uninferred types/regions in `{:?}`", result)
+ bug!("Uninferred types/regions/consts in `{:?}`", result)
)
}
}
a_impl_header.predicates
.iter()
.chain(&b_impl_header.predicates)
- .map(|p| infcx.resolve_type_vars_if_possible(p))
+ .map(|p| infcx.resolve_vars_if_possible(p))
.map(|p| Obligation { cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
return None
}
- let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
+ let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header);
let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
error: &MismatchedProjectionTypes<'tcx>)
{
let predicate =
- self.resolve_type_vars_if_possible(&obligation.predicate);
+ self.resolve_vars_if_possible(&obligation.predicate);
if predicate.references_error() {
return
where T: fmt::Display + TypeFoldable<'tcx>
{
let predicate =
- self.resolve_type_vars_if_possible(&obligation.predicate);
+ self.resolve_vars_if_possible(&obligation.predicate);
let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
"overflow evaluating the requirement `{}`",
predicate);
/// we do not suggest increasing the overflow limit, which is not
/// going to help).
pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
- let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned());
+ let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
assert!(cycle.len() > 0);
debug!("report_overflow_error_cycle: cycle={:?}", cycle);
fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> {
match code {
&ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
- let parent_trait_ref = self.resolve_type_vars_if_possible(
+ let parent_trait_ref = self.resolve_vars_if_possible(
&data.parent_trait_ref);
match self.get_parent_trait_ref(&data.parent_code) {
Some(t) => Some(t),
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
let trait_predicate =
- self.resolve_type_vars_if_possible(trait_predicate);
+ self.resolve_vars_if_possible(trait_predicate);
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
return;
}
ty::Predicate::RegionOutlives(ref predicate) => {
- let predicate = self.resolve_type_vars_if_possible(predicate);
+ let predicate = self.resolve_vars_if_possible(predicate);
let err = self.region_outlives_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
- self.resolve_type_vars_if_possible(&obligation.predicate);
+ self.resolve_vars_if_possible(&obligation.predicate);
struct_span_err!(self.tcx.sess, span, E0280,
"the requirement `{}` is not satisfied",
predicate)
}
OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
- let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref);
- let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
+ let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+ let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
if expected_trait_ref.self_ty().references_error() {
return;
// ambiguous impls. The latter *ought* to be a
// coherence violation, so we don't report it here.
- let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
+ let predicate = self.resolve_vars_if_possible(&obligation.predicate);
let span = obligation.cause.span;
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
err.note("shared static variables must have a type that implements `Sync`");
}
ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
- let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
+ let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
let ty = parent_trait_ref.skip_binder().self_ty();
err.note(&format!("required because it appears within the type `{}`", ty));
obligated_types.push(ty);
}
}
ObligationCauseCode::ImplDerivedObligation(ref data) => {
- let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
+ let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
err.note(
&format!("required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref,
obligated_types: &mut Vec<&ty::TyS<'tcx>>,
cause_code: &ObligationCauseCode<'tcx>) -> bool {
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
- let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
+ let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
return true;
{
// this helps to reduce duplicate errors, as well as making
// debug output much nicer to read and so on.
- let obligation = infcx.resolve_type_vars_if_possible(&obligation);
+ let obligation = infcx.resolve_vars_if_possible(&obligation);
debug!("register_predicate_obligation(obligation={:?})", obligation);
}) {
debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
self.selcx.infcx()
- .resolve_type_vars_if_possible(&pending_obligation.obligation),
+ .resolve_vars_if_possible(&pending_obligation.obligation),
pending_obligation.stalled_on);
return ProcessResult::Unchanged;
}
if obligation.predicate.has_infer_types() {
obligation.predicate =
- self.selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate);
+ self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
}
debug!("process_obligation: obligation = {:?}", obligation);
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
debug!("process_predicate: pending obligation {:?} now stalled on {:?}",
- self.selcx.infcx().resolve_type_vars_if_possible(obligation),
+ self.selcx.infcx().resolve_vars_if_possible(obligation),
pending_obligation.stalled_on);
ProcessResult::Unchanged
{
t.skip_binder() // ok b/c this check doesn't care about regions
.input_types()
- .map(|t| selcx.infcx().resolve_type_vars_if_possible(&t))
+ .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
.filter(|t| t.has_infer_types())
.flat_map(|t| t.walk())
.filter(|t| match t.sty { ty::Infer(_) => true, _ => false })
debug!("fully_normalize: select_all_or_error start");
fulfill_cx.select_all_or_error(infcx)?;
debug!("fully_normalize: select_all_or_error complete");
- let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
+ let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
debug!("fully_normalize: resolved_value={:?}", resolved_value);
Ok(resolved_value)
}
}
fn fold<T:TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
- let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
+ let value = self.selcx.infcx().resolve_vars_if_possible(value);
if !value.has_projections() {
value
{
let infcx = selcx.infcx();
- let projection_ty = infcx.resolve_type_vars_if_possible(&projection_ty);
+ let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
let cache_key = ProjectionCacheKey { ty: projection_ty };
debug!("opt_normalize_projection_type(\
// from a specific call to `opt_normalize_projection_type` - if
// there's no precise match, the original cache entry is "stranded"
// anyway.
- ty: infcx.resolve_type_vars_if_possible(&predicate.projection_ty)
+ ty: infcx.resolve_vars_if_possible(&predicate.projection_ty)
})
}
}
&orig_values,
result)
{
- let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+ let ty = self.infcx.resolve_vars_if_possible(&ty);
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
return InferOk {
value: kinds,
region_obligations
.iter()
.map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
- .map(|(ty, r)| (infcx.resolve_type_vars_if_possible(&ty), r)),
+ .map(|(ty, r)| (infcx.resolve_vars_if_possible(&ty), r)),
®ion_constraint_data,
);
let obligation = &stack.obligation;
let predicate = self.infcx()
- .resolve_type_vars_if_possible(&obligation.predicate);
+ .resolve_vars_if_possible(&obligation.predicate);
// OK to skip binder because of the nature of the
// trait-ref-is-knowable check, which does not care about
cause: obligation.cause.clone(),
recursion_depth: obligation.recursion_depth,
predicate: self.infcx()
- .resolve_type_vars_if_possible(&obligation.predicate),
+ .resolve_vars_if_possible(&obligation.predicate),
};
if obligation.predicate.skip_binder().self_ty().is_ty_var() {
snapshot: &CombinedSnapshot<'_, 'tcx>,
) -> bool {
let poly_trait_predicate = self.infcx()
- .resolve_type_vars_if_possible(&obligation.predicate);
+ .resolve_vars_if_possible(&obligation.predicate);
let (placeholder_trait_predicate, placeholder_map) = self.infcx()
.replace_bound_vars_with_placeholders(&poly_trait_predicate);
debug!(
// Now resolve the *substitution* we built for the target earlier, replacing
// the inference variables inside with whatever we got from fulfillment.
- Ok(infcx.resolve_type_vars_if_possible(&target_substs))
+ Ok(infcx.resolve_vars_if_possible(&target_substs))
}
}
})
use crate::middle::lang_items;
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
-use crate::mir::{self, Mir, interpret, ProjectionKind};
+use crate::mir::{self, Body, interpret, ProjectionKind};
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
generics: TypedArena<ty::Generics>,
trait_def: TypedArena<ty::TraitDef>,
adt_def: TypedArena<ty::AdtDef>,
- steal_mir: TypedArena<Steal<Mir<'tcx>>>,
- mir: TypedArena<Mir<'tcx>>,
+ steal_mir: TypedArena<Steal<Body<'tcx>>>,
+ mir: TypedArena<Body<'tcx>>,
tables: TypedArena<ty::TypeckTables<'tcx>>,
/// miri allocations
const_allocs: TypedArena<interpret::Allocation>,
CommonConsts {
err: mk_const(ty::Const {
- val: ConstValue::Scalar(Scalar::Bits { bits: 0, size: 0 }),
+ val: ConstValue::Scalar(Scalar::zst()),
ty: types.err,
}),
}
self.global_arenas.generics.alloc(generics)
}
- pub fn alloc_steal_mir(self, mir: Mir<'gcx>) -> &'gcx Steal<Mir<'gcx>> {
+ pub fn alloc_steal_mir(self, mir: Body<'gcx>) -> &'gcx Steal<Body<'gcx>> {
self.global_arenas.steal_mir.alloc(Steal::new(mir))
}
- pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx Mir<'gcx> {
+ pub fn alloc_mir(self, mir: Body<'gcx>) -> &'gcx Body<'gcx> {
self.global_arenas.mir.alloc(mir)
}
}
};
+ macro_rules! pluralise {
+ ($x:expr) => {
+ if $x != 1 { "s" } else { "" }
+ };
+ }
+
match *self {
CyclicTy(_) => write!(f, "cyclic type of infinite size"),
Mismatch => write!(f, "types differ"),
values.found)
}
Mutability => write!(f, "types differ in mutability"),
- FixedArraySize(values) => {
- write!(f, "expected an array with a fixed size of {} elements, \
- found one with {} elements",
+ TupleSize(values) => {
+ write!(f, "expected a tuple with {} element{}, \
+ found one with {} element{}",
values.expected,
- values.found)
+ pluralise!(values.expected),
+ values.found,
+ pluralise!(values.found))
}
- TupleSize(values) => {
- write!(f, "expected a tuple with {} elements, \
- found one with {} elements",
+ FixedArraySize(values) => {
+ write!(f, "expected an array with a fixed size of {} element{}, \
+ found one with {} element{}",
values.expected,
- values.found)
+ pluralise!(values.expected),
+ values.found,
+ pluralise!(values.found))
}
ArgCount => {
write!(f, "incorrect number of function parameters")
tcx.def_path_str(values.found))
}),
ProjectionBoundsLength(ref values) => {
- write!(f, "expected {} associated type bindings, found {}",
+ write!(f, "expected {} associated type binding{}, found {}",
values.expected,
+ pluralise!(values.expected),
values.found)
},
ExistentialMismatch(ref values) => {
&format!("trait `{}`", values.found))
}
ConstMismatch(ref values) => {
- write!(f, "expected `{:?}`, found `{:?}`", values.expected, values.found)
+ write!(f, "expected `{}`, found `{}`", values.expected, values.found)
}
}
}
use crate::infer::canonical::Canonical;
use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
-use crate::mir::Mir;
+use crate::mir::Body;
use crate::mir::interpret::{GlobalId, ErrorHandled};
use crate::mir::GeneratorLayout;
use crate::session::CrateDisambiguator;
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
pub fn instance_mir(self, instance: ty::InstanceDef<'gcx>)
- -> &'gcx Mir<'gcx>
+ -> &'gcx Body<'gcx>
{
match instance {
ty::InstanceDef::Item(did) => {
p!(write("{}", name));
return Ok(self);
}
- if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = ct.val {
+ if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
match ct.ty.sty {
ty::Bool => {
- p!(write("{}", if bits == 0 { "false" } else { "true" }));
+ p!(write("{}", if data == 0 { "false" } else { "true" }));
return Ok(self);
},
ty::Float(ast::FloatTy::F32) => {
- p!(write("{}f32", Single::from_bits(bits)));
+ p!(write("{}f32", Single::from_bits(data)));
return Ok(self);
},
ty::Float(ast::FloatTy::F64) => {
- p!(write("{}f64", Double::from_bits(bits)));
+ p!(write("{}f64", Double::from_bits(data)));
return Ok(self);
},
ty::Uint(ui) => {
- p!(write("{}{}", bits, ui));
+ p!(write("{}{}", data, ui));
return Ok(self);
},
ty::Int(i) =>{
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
- p!(write("{}{}", sign_extend(bits, size) as i128, i));
+ p!(write("{}{}", sign_extend(data, size) as i128, i));
return Ok(self);
},
ty::Char => {
- p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap()));
+ p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
return Ok(self);
}
_ => {},
use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::{GlobalId, ConstValue, Scalar};
-use crate::util::common::ErrorReported;
-use syntax_pos::DUMMY_SP;
+use crate::mir::interpret::{ConstValue, Scalar, GlobalId};
use std::rc::Rc;
use std::iter;
use rustc_target::spec::abi;
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
{
let t = relation.relate(&a_t, &b_t)?;
- let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
- match x.val {
- // FIXME(const_generics): this doesn't work right now,
- // because it tries to relate an `Infer` to a `Param`.
- ConstValue::Unevaluated(def_id, substs) => {
- // FIXME(eddyb) get the right param_env.
- let param_env = ty::ParamEnv::empty();
- if let Some(substs) = tcx.lift_to_global(&substs) {
- let instance = ty::Instance::resolve(
- tcx.global_tcx(),
- param_env,
- def_id,
- substs,
- );
- if let Some(instance) = instance {
- let cid = GlobalId {
- instance,
- promoted: None,
- };
- if let Some(s) = tcx.const_eval(param_env.and(cid))
- .ok()
- .map(|c| c.unwrap_usize(tcx)) {
- return Ok(s)
- }
- }
+ match relation.relate(&sz_a, &sz_b) {
+ Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))),
+ Err(err) => {
+ // Check whether the lengths are both concrete/known values,
+ // but are unequal, for better diagnostics.
+ match (sz_a.assert_usize(tcx), sz_b.assert_usize(tcx)) {
+ (Some(sz_a_val), Some(sz_b_val)) => {
+ Err(TypeError::FixedArraySize(
+ expected_found(relation, &sz_a_val, &sz_b_val)
+ ))
}
- tcx.sess.delay_span_bug(tcx.def_span(def_id),
- "array length could not be evaluated");
- Err(ErrorReported)
+ _ => return Err(err),
}
- _ => x.assert_usize(tcx).ok_or_else(|| {
- tcx.sess.delay_span_bug(DUMMY_SP,
- "array length could not be evaluated");
- ErrorReported
- })
- }
- };
- match (to_u64(*sz_a), to_u64(*sz_b)) {
- (Ok(sz_a_u64), Ok(sz_b_u64)) => {
- if sz_a_u64 == sz_b_u64 {
- Ok(tcx.mk_ty(ty::Array(t, sz_a)))
- } else {
- Err(TypeError::FixedArraySize(
- expected_found(relation, &sz_a_u64, &sz_b_u64)))
- }
- }
- // We reported an error or will ICE, so we can return Error.
- (Err(ErrorReported), _) | (_, Err(ErrorReported)) => {
- Ok(tcx.types.err)
}
}
}
{
let tcx = relation.tcx();
+ let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
+ if let ConstValue::Unevaluated(def_id, substs) = x.val {
+ // FIXME(eddyb) get the right param_env.
+ let param_env = ty::ParamEnv::empty();
+ if let Some(substs) = tcx.lift_to_global(&substs) {
+ let instance = ty::Instance::resolve(
+ tcx.global_tcx(),
+ param_env,
+ def_id,
+ substs,
+ );
+ if let Some(instance) = instance {
+ let cid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ if let Ok(ct) = tcx.const_eval(param_env.and(cid)) {
+ return ct.val;
+ }
+ }
+ }
+ }
+ x.val
+ };
+
// Currently, the values that can be unified are those that
// implement both `PartialEq` and `Eq`, corresponding to
// `structural_match` types.
// FIXME(const_generics): check for `structural_match` synthetic attribute.
- match (a.val, b.val) {
+ match (eagerly_eval(a), eagerly_eval(b)) {
(ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
// The caller should handle these cases!
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
(ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
Ok(a)
}
- (ConstValue::Scalar(Scalar::Bits { .. }), _) if a == b => {
- Ok(a)
+ (a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _)
+ if a.ty == b.ty && a_val == b_val =>
+ {
+ Ok(tcx.mk_const(ty::Const {
+ val: a_val,
+ ty: a.ty,
+ }))
}
(ConstValue::ByRef(..), _) => {
bug!(
}))
}
- _ => {
- Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
- }
+ _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
}
}
/// optimization, but that'd be expensive. And yet we don't just want
/// to mutate it in place, because that would spoil the idea that
/// queries are these pure functions that produce an immutable value
-/// (since if you did the query twice, you could observe the
-/// mutations). So instead we have the query produce a `&'tcx
-/// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
+/// (since if you did the query twice, you could observe the mutations).
+/// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>`
+/// (to be very specific). Now we can read from this
/// as much as we want (using `borrow()`), but you can also
/// `steal()`. Once you steal, any further attempt to read will panic.
/// Therefore, we know that -- assuming no ICE -- nobody is observing
use crate::hir;
use crate::hir::def_id::DefId;
use crate::infer::canonical::Canonical;
-use crate::mir::interpret::{ConstValue, truncate};
+use crate::mir::interpret::ConstValue;
use crate::middle::region;
use polonius_engine::Atom;
use rustc_data_structures::indexed_vec::Idx;
let size = tcx.layout_of(ty).unwrap_or_else(|e| {
panic!("could not compute layout for {:?}: {:?}", ty, e)
}).size;
- let truncated = truncate(bits, size);
- assert_eq!(truncated, bits, "from_bits called with untruncated value");
- Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value)
+ Self::from_scalar(tcx, Scalar::from_uint(bits, size), ty.value)
}
#[inline]
pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
- Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty)
+ Self::from_scalar(tcx, Scalar::zst(), ty)
}
#[inline]
use std::borrow::Cow;
use std::error::Error;
+use std::fs;
use std::mem::{self, Discriminant};
+use std::path::Path;
use std::process;
use std::thread::ThreadId;
use std::u32;
}
impl SelfProfiler {
- pub fn new(event_filters: &Option<Vec<String>>) -> Result<SelfProfiler, Box<dyn Error>> {
- let filename = format!("pid-{}.rustc_profile", process::id());
- let path = std::path::Path::new(&filename);
- let profiler = Profiler::new(path)?;
+ pub fn new(
+ output_directory: &Path,
+ crate_name: Option<&str>,
+ event_filters: &Option<Vec<String>>
+ ) -> Result<SelfProfiler, Box<dyn Error>> {
+ fs::create_dir_all(output_directory)?;
+
+ let crate_name = crate_name.unwrap_or("unknown-crate");
+ let filename = format!("{}-{}.rustc_profile", crate_name, process::id());
+ let path = output_directory.join(&filename);
+ let profiler = Profiler::new(&path)?;
let query_event_kind = profiler.alloc_string("Query");
let generic_activity_event_kind = profiler.alloc_string("GenericActivity");
use rustc::hir::def_id::LOCAL_CRATE;
use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
use rustc_codegen_ssa::traits::*;
-use rustc::session::config::{self, OutputType, Passes, Lto, PgoGenerate};
+use rustc::session::config::{self, OutputType, Passes, Lto, SwitchWithOptPath};
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, CompiledModule};
let inline_threshold = config.inline_threshold;
let pgo_gen_path = match config.pgo_gen {
- PgoGenerate::Enabled(ref opt_dir_path) => {
+ SwitchWithOptPath::Enabled(ref opt_dir_path) => {
let path = if let Some(dir_path) = opt_dir_path {
dir_path.join("default_%m.profraw")
} else {
Some(CString::new(format!("{}", path.display())).unwrap())
}
- PgoGenerate::Disabled => {
+ SwitchWithOptPath::Disabled => {
None
}
};
use crate::context::CodegenCx;
use crate::monomorphize::partitioning::CodegenUnitExt;
use rustc::dep_graph;
-use rustc::mir::mono::{Linkage, Visibility, Stats};
+use rustc::mir::mono::{Linkage, Visibility};
use rustc::middle::cstore::{EncodedMetadata};
use rustc::ty::TyCtxt;
use rustc::middle::exported_symbols;
}
}
-pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- cgu_name: InternedString)
- -> Stats {
+pub fn compile_codegen_unit(tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) {
let start_time = Instant::now();
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
- let ((stats, module), _) = tcx.dep_graph.with_task(dep_node,
- tcx,
- cgu_name,
- module_codegen,
- dep_graph::hash_result);
+ let (module, _) = tcx.dep_graph.with_task(
+ dep_node,
+ tcx,
+ cgu_name,
+ module_codegen,
+ dep_graph::hash_result,
+ );
let time_to_codegen = start_time.elapsed();
// We assume that the cost to run LLVM on a CGU is proportional to
time_to_codegen.subsec_nanos() as u64;
submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost);
- return stats;
fn module_codegen<'ll, 'tcx>(
tcx: TyCtxt<'ll, 'tcx, 'tcx>,
- cgu_name: InternedString)
- -> (Stats, ModuleCodegen<ModuleLlvm>)
- {
+ cgu_name: InternedString,
+ ) -> ModuleCodegen<ModuleLlvm> {
let cgu = tcx.codegen_unit(cgu_name);
// Instantiate monomorphizations without filling out definitions yet...
let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
- let stats = {
+ {
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
let mono_items = cx.codegen_unit
.items_in_deterministic_order(cx.tcx);
if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize();
}
+ }
- cx.consume_stats().into_inner()
- };
-
- (stats, ModuleCodegen {
+ ModuleCodegen {
name: cgu_name.to_string(),
module_llvm: llvm_module,
kind: ModuleKind::Regular,
- })
+ }
}
}
}
fn ret_void(&mut self) {
- self.count_insn("retvoid");
unsafe {
llvm::LLVMBuildRetVoid(self.llbuilder);
}
}
fn ret(&mut self, v: &'ll Value) {
- self.count_insn("ret");
unsafe {
llvm::LLVMBuildRet(self.llbuilder, v);
}
}
fn br(&mut self, dest: &'ll BasicBlock) {
- self.count_insn("br");
unsafe {
llvm::LLVMBuildBr(self.llbuilder, dest);
}
then_llbb: &'ll BasicBlock,
else_llbb: &'ll BasicBlock,
) {
- self.count_insn("condbr");
unsafe {
llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
}
catch: &'ll BasicBlock,
funclet: Option<&Funclet<'ll>>,
) -> &'ll Value {
- self.count_insn("invoke");
debug!("Invoke {:?} with args ({:?})",
llfn,
}
fn unreachable(&mut self) {
- self.count_insn("unreachable");
unsafe {
llvm::LLVMBuildUnreachable(self.llbuilder);
}
/* Arithmetic */
fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("add");
unsafe {
llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
}
}
fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fadd");
unsafe {
llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
}
}
fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fadd");
unsafe {
let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("sub");
unsafe {
llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
}
}
fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fsub");
unsafe {
llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
}
}
fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fsub");
unsafe {
let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("mul");
unsafe {
llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
}
}
fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fmul");
unsafe {
llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
}
}
fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fmul");
unsafe {
let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("udiv");
unsafe {
llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
}
}
fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("exactudiv");
unsafe {
llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
}
}
fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("sdiv");
unsafe {
llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
}
}
fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("exactsdiv");
unsafe {
llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
}
}
fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fdiv");
unsafe {
llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
}
}
fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fdiv");
unsafe {
let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("urem");
unsafe {
llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
}
}
fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("srem");
unsafe {
llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
}
}
fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("frem");
unsafe {
llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
}
}
fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("frem");
unsafe {
let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("shl");
unsafe {
llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
}
}
fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("lshr");
unsafe {
llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
}
}
fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("ashr");
unsafe {
llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
}
}
fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("and");
unsafe {
llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
}
}
fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("or");
unsafe {
llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
}
}
fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("xor");
unsafe {
llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
}
}
fn neg(&mut self, v: &'ll Value) -> &'ll Value {
- self.count_insn("neg");
unsafe {
llvm::LLVMBuildNeg(self.llbuilder, v, noname())
}
}
fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
- self.count_insn("fneg");
unsafe {
llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
}
}
fn not(&mut self, v: &'ll Value) -> &'ll Value {
- self.count_insn("not");
unsafe {
llvm::LLVMBuildNot(self.llbuilder, v, noname())
}
}
fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
- self.count_insn("alloca");
unsafe {
let alloca = if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
len: &'ll Value,
name: &str,
align: Align) -> &'ll Value {
- self.count_insn("alloca");
unsafe {
let alloca = if name.is_empty() {
llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
}
fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
- self.count_insn("load");
unsafe {
let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
}
fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
- self.count_insn("load.volatile");
unsafe {
- let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
- llvm::LLVMSetVolatile(insn, llvm::True);
- insn
+ let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+ llvm::LLVMSetVolatile(load, llvm::True);
+ load
}
}
order: rustc_codegen_ssa::common::AtomicOrdering,
size: Size,
) -> &'ll Value {
- self.count_insn("load.atomic");
unsafe {
let load = llvm::LLVMRustBuildAtomicLoad(
self.llbuilder,
flags: MemFlags,
) -> &'ll Value {
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
- self.count_insn("store");
let ptr = self.check_store(val, ptr);
unsafe {
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value,
order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
debug!("Store {:?} -> {:?}", val, ptr);
- self.count_insn("store.atomic");
let ptr = self.check_store(val, ptr);
unsafe {
let store = llvm::LLVMRustBuildAtomicStore(
}
fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
- self.count_insn("gep");
unsafe {
llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
indices.len() as c_uint, noname())
}
fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
- self.count_insn("inboundsgep");
unsafe {
llvm::LLVMBuildInBoundsGEP(
self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
}
fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
- self.count_insn("structgep");
assert_eq!(idx as c_uint as u64, idx);
unsafe {
llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
/* Casts */
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("trunc");
unsafe {
llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
}
}
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("sext");
unsafe {
llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
}
}
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("fptoui");
unsafe {
llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
}
}
fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("fptosi");
unsafe {
llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
}
}
fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("uitofp");
unsafe {
llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
}
}
fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("sitofp");
unsafe {
llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
}
}
fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("fptrunc");
unsafe {
llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
}
}
fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("fpext");
unsafe {
llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
}
}
fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("ptrtoint");
unsafe {
llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
}
}
fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("inttoptr");
unsafe {
llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
}
}
fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("bitcast");
unsafe {
llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
}
fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
- self.count_insn("intcast");
unsafe {
llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
}
}
fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("pointercast");
unsafe {
llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
}
/* Comparisons */
fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("icmp");
let op = llvm::IntPredicate::from_generic(op);
unsafe {
llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
}
fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("fcmp");
unsafe {
llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
}
then_val: &'ll Value,
else_val: &'ll Value,
) -> &'ll Value {
- self.count_insn("select");
unsafe {
llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
}
#[allow(dead_code)]
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
- self.count_insn("vaarg");
unsafe {
llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
}
}
fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
- self.count_insn("extractelement");
unsafe {
llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
}
}
fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
- self.count_insn("extractvalue");
assert_eq!(idx as c_uint as u64, idx);
unsafe {
llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value,
idx: u64) -> &'ll Value {
- self.count_insn("insertvalue");
assert_eq!(idx as c_uint as u64, idx);
unsafe {
llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value,
num_clauses: usize) -> &'ll Value {
- self.count_insn("landingpad");
unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
num_clauses as c_uint, noname())
}
fn set_cleanup(&mut self, landing_pad: &'ll Value) {
- self.count_insn("setcleanup");
unsafe {
llvm::LLVMSetCleanup(landing_pad, llvm::True);
}
}
fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
- self.count_insn("resume");
unsafe {
llvm::LLVMBuildResume(self.llbuilder, exn)
}
fn cleanup_pad(&mut self,
parent: Option<&'ll Value>,
args: &[&'ll Value]) -> Funclet<'ll> {
- self.count_insn("cleanuppad");
let name = const_cstr!("cleanuppad");
let ret = unsafe {
llvm::LLVMRustBuildCleanupPad(self.llbuilder,
&mut self, funclet: &Funclet<'ll>,
unwind: Option<&'ll BasicBlock>,
) -> &'ll Value {
- self.count_insn("cleanupret");
let ret = unsafe {
llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
};
fn catch_pad(&mut self,
parent: &'ll Value,
args: &[&'ll Value]) -> Funclet<'ll> {
- self.count_insn("catchpad");
let name = const_cstr!("catchpad");
let ret = unsafe {
llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
unwind: Option<&'ll BasicBlock>,
num_handlers: usize,
) -> &'ll Value {
- self.count_insn("catchswitch");
let name = const_cstr!("catchswitch");
let ret = unsafe {
llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
) -> &'ll Value {
- self.count_insn("call");
debug!("Call {:?} with args ({:?})",
llfn,
}
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
- self.count_insn("zext");
unsafe {
llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
}
}
}
- fn count_insn(&self, category: &str) {
- if self.sess().codegen_stats() {
- self.stats.borrow_mut().n_llvm_insns += 1;
- }
- if self.sess().count_llvm_insns() {
- *self.stats
- .borrow_mut()
- .llvm_insns
- .entry(category.to_string())
- .or_insert(0) += 1;
- }
- }
-
fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
unsafe {
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
}
pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("minnum");
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
}
pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- self.count_insn("maxnum");
unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
}
elt: &'ll Value,
idx: &'ll Value,
) -> &'ll Value {
- self.count_insn("insertelement");
unsafe {
llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
}
v2: &'ll Value,
mask: &'ll Value,
) -> &'ll Value {
- self.count_insn("shufflevector");
unsafe {
llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
}
}
pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fadd_fast");
unsafe {
// FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732
}
}
pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fmul_fast");
unsafe {
// FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732
}
}
pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.add");
unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
}
pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.mul");
unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
}
pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.and");
unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
}
pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.or");
unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
}
pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.xor");
unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
}
pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fmin");
unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
}
pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fmax");
unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
}
pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fmin_fast");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
}
pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
- self.count_insn("vector.reduce.fmax_fast");
unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
}
}
pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
- self.count_insn("vector.reduce.min");
unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
}
pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
- self.count_insn("vector.reduce.max");
unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
}
}
pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
- self.count_insn("catchret");
let ret = unsafe {
llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
};
}
pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
- self.count_insn("vaarg");
unsafe {
llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
}
}
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
- self.count_insn("addincoming");
assert_eq!(vals.len(), bbs.len());
let phi = unsafe {
llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
}
fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
- self.count_insn("addincoming");
unsafe {
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
}
) -> &'ll Value {
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
match cv {
- Scalar::Bits { size: 0, .. } => {
+ Scalar::Raw { size: 0, .. } => {
assert_eq!(0, layout.value.size(self).bytes());
self.const_undef(self.type_ix(0))
},
- Scalar::Bits { bits, size } => {
+ Scalar::Raw { data, size } => {
assert_eq!(size as u64, layout.value.size(self).bytes());
- let llval = self.const_uint_big(self.type_ix(bitsize), bits);
+ let llval = self.const_uint_big(self.type_ix(bitsize), data);
if layout.value == layout::Pointer {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
} else {
attrs: &CodegenFnAttrs,
ty: Ty<'tcx>,
sym: LocalInternedString,
- span: Option<Span>
+ span: Span
) -> &'ll Value {
let llty = cx.layout_of(ty).llvm_type(cx);
if let Some(linkage) = attrs.linkage {
let llty2 = if let ty::RawPtr(ref mt) = ty.sty {
cx.layout_of(mt.ty).llvm_type(cx)
} else {
- if let Some(span) = span {
- cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`")
- } else {
- bug!("must have type `*const T` or `*mut T`")
- }
+ cx.sess().span_fatal(
+ span, "must have type `*const T` or `*mut T` due to `#[linkage]` attribute")
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&sym);
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(||{
- if let Some(span) = span {
- cx.sess().span_fatal(
- span,
- &format!("symbol `{}` is already defined", &sym)
- )
- } else {
- bug!("symbol `{}` is already defined", &sym)
- }
+ cx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym))
});
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);
ref attrs, span, node: hir::ForeignItemKind::Static(..), ..
}) => {
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
- (check_and_apply_linkage(&self, &fn_attrs, ty, sym, Some(span)), attrs)
+ (check_and_apply_linkage(&self, &fn_attrs, ty, sym, span), attrs)
}
item => bug!("get_static: expected static, found {:?}", item)
debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
let attrs = self.tcx.codegen_fn_attrs(def_id);
- let g = check_and_apply_linkage(&self, &attrs, ty, sym, None);
+ let span = self.tcx.def_span(def_id);
+ let g = check_and_apply_linkage(&self, &attrs, ty, sym, span);
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
use rustc_data_structures::base_n;
use rustc_data_structures::small_c_str::SmallCStr;
-use rustc::mir::mono::Stats;
use rustc::session::config::{self, DebugInfo};
use rustc::session::Session;
use rustc::ty::layout::{
pub llmod: &'ll llvm::Module,
pub llcx: &'ll llvm::Context,
- pub stats: RefCell<Stats>,
pub codegen_unit: Arc<CodegenUnit<'tcx>>,
/// Cache instances of monomorphic and polymorphic items
tls_model,
llmod,
llcx,
- stats: RefCell::new(Stats::default()),
codegen_unit,
instances: Default::default(),
vtables: Default::default(),
self.check_overflow
}
- fn stats(&self) -> &RefCell<Stats> {
- &self.stats
- }
-
- fn consume_stats(self) -> RefCell<Stats> {
- self.stats
- }
-
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>> {
&self.codegen_unit
}
use crate::llvm;
use crate::llvm::debuginfo::{DIScope, DISubprogram};
use crate::common::CodegenCx;
-use rustc::mir::{Mir, SourceScope};
+use rustc::mir::{Body, SourceScope};
use libc::c_uint;
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes(
cx: &CodegenCx<'ll, '_>,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
debug_context: &FunctionDebugContext<&'ll DISubprogram>,
) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
let null_scope = MirDebugScope {
}
fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
has_variables: &BitSet<SourceScope>,
debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
scope: SourceScope,
instance: Instance<'tcx>,
sig: ty::FnSig<'tcx>,
llfn: &'ll Value,
- mir: &mir::Mir<'_>,
+ mir: &mir::Body<'_>,
) -> FunctionDebugContext<&'ll DISubprogram> {
if self.sess().opts.debuginfo == DebugInfo::None {
return FunctionDebugContext::DebugInfoDisabled;
fn create_mir_scopes(
&self,
- mir: &mir::Mir<'_>,
+ mir: &mir::Body<'_>,
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
create_scope_map::create_mir_scopes(self, mir, debug_context)
use errors::{FatalError, Handler};
use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::InternedString;
-use rustc::mir::mono::Stats;
pub use llvm_util::target_features;
use std::any::Any;
use std::sync::{mpsc, Arc};
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString,
- ) -> Stats {
- base::compile_codegen_unit(tcx, cgu_name)
+ ) {
+ base::compile_codegen_unit(tcx, cgu_name);
}
fn target_machine_factory(
&self,
use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker;
use rustc::middle::cstore::EncodedMetadata;
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto,
- Sanitizer, PgoGenerate};
+ Sanitizer, SwitchWithOptPath};
use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
/// Some(level) to optimize binary size, or None to not affect program size.
pub opt_size: Option<config::OptLevel>,
- pub pgo_gen: PgoGenerate,
+ pub pgo_gen: SwitchWithOptPath,
pub pgo_use: Option<PathBuf>,
// Flags indicating which outputs to produce.
opt_level: None,
opt_size: None,
- pgo_gen: PgoGenerate::Disabled,
+ pgo_gen: SwitchWithOptPath::Disabled,
pgo_use: None,
emit_no_opt_bc: false,
use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::lang_items::StartFnLangItem;
use rustc::middle::weak_lang_items;
-use rustc::mir::mono::{Stats, CodegenUnitNameBuilder};
+use rustc::mir::mono::CodegenUnitNameBuilder;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
use rustc::ty::query::Providers;
use rustc::util::common::{time, print_time_passes_entry};
use rustc::session::config::{self, EntryFnType, Lto};
use rustc::session::Session;
-use rustc_mir::monomorphize::item::DefPathBasedNames;
use rustc_mir::monomorphize::Instance;
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
use rustc::util::nodemap::FxHashMap;
use crate::mir::operand::OperandValue;
-use std::marker::PhantomData;
-
-pub struct StatRecorder<'a, 'tcx, Cx: 'a + CodegenMethods<'tcx>> {
- cx: &'a Cx,
- name: Option<String>,
- istart: usize,
- _marker: PhantomData<&'tcx ()>,
-}
-
-impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> StatRecorder<'a, 'tcx, Cx> {
- pub fn new(cx: &'a Cx, name: String) -> Self {
- let istart = cx.stats().borrow().n_llvm_insns;
- StatRecorder {
- cx,
- name: Some(name),
- istart,
- _marker: PhantomData,
- }
- }
-}
-
-impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> {
- fn drop(&mut self) {
- if self.cx.sess().codegen_stats() {
- let mut stats = self.cx.stats().borrow_mut();
- let iend = stats.n_llvm_insns;
- stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
- stats.n_fns += 1;
- // Reset LLVM insn count to avoid compound costs.
- stats.n_llvm_insns = self.istart;
- }
- }
-}
-
pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
signed: bool)
-> IntPredicate {
cx: &'a Bx::CodegenCx,
instance: Instance<'tcx>,
) {
- let _s = if cx.sess().codegen_stats() {
- let mut instance_name = String::new();
- DefPathBasedNames::new(cx.tcx(), true, true)
- .push_def_path(instance.def_id(), &mut instance_name);
- Some(StatRecorder::new(cx, instance_name))
- } else {
- None
- };
-
// this is an info! to allow collecting monomorphization statistics
// and to allow finding the last function before LLVM aborts from
// release builds.
let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(||
bug!("Instance `{:?}` not already declared", instance));
- cx.stats().borrow_mut().n_closures += 1;
-
let mir = cx.tcx().instance_mir(instance.def);
mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig);
}
};
let mut total_codegen_time = Duration::new(0, 0);
- let mut all_stats = Stats::default();
for cgu in codegen_units.into_iter() {
ongoing_codegen.wait_for_signal_to_codegen_item();
CguReuse::No => {
tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name())));
let start_time = Instant::now();
- let stats = backend.compile_codegen_unit(tcx, *cgu.name());
- all_stats.extend(stats);
+ backend.compile_codegen_unit(tcx, *cgu.name());
total_codegen_time += start_time.elapsed();
tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name())));
false
symbol_names_test::report_symbol_names(tcx);
- if tcx.sess.codegen_stats() {
- println!("--- codegen stats ---");
- println!("n_glues_created: {}", all_stats.n_glues_created);
- println!("n_null_glues: {}", all_stats.n_null_glues);
- println!("n_real_glues: {}", all_stats.n_real_glues);
-
- println!("n_fns: {}", all_stats.n_fns);
- println!("n_inlines: {}", all_stats.n_inlines);
- println!("n_closures: {}", all_stats.n_closures);
- println!("fn stats:");
- all_stats.fn_stats.sort_by_key(|&(_, insns)| insns);
- for &(ref name, insns) in all_stats.fn_stats.iter() {
- println!("{} insns, {}", insns, *name);
- }
- }
-
- if tcx.sess.count_llvm_insns() {
- for (k, v) in all_stats.llvm_insns.iter() {
- println!("{:7} {}", *v, *k);
- }
- }
-
ongoing_codegen.check_for_errors(tcx.sess);
assert_and_save_dep_graph(tcx);
let mir = fx.mir;
let mut analyzer = LocalAnalyzer::new(fx);
- analyzer.visit_mir(mir);
+ analyzer.visit_body(mir);
for (index, ty) in mir.local_decls.iter().map(|l| l.ty).enumerate() {
let ty = fx.monomorphize(&ty);
}
}
-pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
+pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Body<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
- mir: &mir::Mir<'tcx>) {
+ mir: &mir::Body<'tcx>) {
for (bb, data) in mir.basic_blocks().iter_enumerated() {
match data.terminator().kind {
TerminatorKind::Goto { .. } |
}
fn propagate<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
- mir: &mir::Mir<'tcx>) {
+ mir: &mir::Body<'tcx>) {
let mut funclet_succs = IndexVec::from_elem(None, mir.basic_blocks());
let mut set_successor = |funclet: mir::BasicBlock, succ| {
use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
-use rustc::mir::{self, Mir};
+use rustc::mir::{self, Body};
use rustc::session::config::DebugInfo;
use rustc_mir::monomorphize::Instance;
use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> {
instance: Instance<'tcx>,
- mir: &'a mir::Mir<'tcx>,
+ mir: &'a mir::Body<'tcx>,
debug_context: FunctionDebugContext<Bx::DIScope>,
pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
llfn: Bx::Value,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
instance: Instance<'tcx>,
sig: ty::FnSig<'tcx>,
) {
}
fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
bx: &mut Bx,
cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>)
let cx = self.cx;
let tcx = self.cx.tcx();
- if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
- match self.locals[index] {
- LocalRef::Place(place) => {
- return place;
- }
- LocalRef::UnsizedPlace(place) => {
- return bx.load_operand(place).deref(cx);
- }
- LocalRef::Operand(..) => {
- bug!("using operand local {:?} as place", place);
+ let result = match *place {
+ mir::Place::Base(mir::PlaceBase::Local(index)) => {
+ match self.locals[index] {
+ LocalRef::Place(place) => {
+ return place;
+ }
+ LocalRef::UnsizedPlace(place) => {
+ return bx.load_operand(place).deref(cx);
+ }
+ LocalRef::Operand(..) => {
+ bug!("using operand local {:?} as place", place);
+ }
}
}
- }
-
- let result = match *place {
- mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
mir::Place::Base(
mir::PlaceBase::Static(
box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
use super::CodegenObject;
use rustc::middle::allocator::AllocatorKind;
use rustc::middle::cstore::EncodedMetadata;
-use rustc::mir::mono::Stats;
use rustc::session::{Session, config};
use rustc::ty::TyCtxt;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString,
- ) -> Stats;
+ );
// If find_features is true this won't access `sess.crate_types` by assuming
// that `is_pie_binary` is false. When we discover LLVM target features
// `sess.crate_types` is uninitialized so we cannot access it.
instance: Instance<'tcx>,
sig: ty::FnSig<'tcx>,
llfn: Self::Value,
- mir: &mir::Mir<'_>,
+ mir: &mir::Body<'_>,
) -> FunctionDebugContext<Self::DIScope>;
fn create_mir_scopes(
&self,
- mir: &mir::Mir<'_>,
+ mir: &mir::Body<'_>,
debug_context: &mut FunctionDebugContext<Self::DIScope>,
) -> IndexVec<mir::SourceScope, MirDebugScope<Self::DIScope>>;
fn extend_scope_to_file(
use super::BackendTypes;
-use rustc::mir::mono::Stats;
use rustc::session::Session;
use rustc::ty::{self, Instance, Ty};
use rustc::util::nodemap::FxHashMap;
fn eh_personality(&self) -> Self::Value;
fn eh_unwind_resume(&self) -> Self::Value;
fn sess(&self) -> &Session;
- fn stats(&self) -> &RefCell<Stats>;
- fn consume_stats(self) -> RefCell<Stats>;
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
fn set_frame_pointer_elimination(&self, llfn: Self::Value);
ct: &'tcx ty::Const<'tcx>,
) -> Result<Self::Const, Self::Error> {
// only print integers
- if let ConstValue::Scalar(Scalar::Bits { .. }) = ct.val {
+ if let ConstValue::Scalar(Scalar::Raw { .. }) = ct.val {
if ct.ty.is_integral() {
return self.pretty_print_const(ct);
}
// for ':' and '-'
'-' | ':' => self.path.temp_buf.push('.'),
+ // Avoid segmentation fault on some platforms, see #60925.
+ 'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$6d$"),
+
// These are legal symbols
'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c),
fn add_usize(&self, u: usize) -> Option<Self> {
Idx::index(*self).checked_add(u).map(Self::new)
}
+
+ #[inline]
+ fn sub_usize(&self, u: usize) -> Option<Self> {
+ Idx::index(*self).checked_sub(u).map(Self::new)
+ }
}
impl From<$type> for u32 {
}
}
+/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
pub struct EmitterWriter {
dst: Destination,
sm: Option<Lrc<SourceMapperDyn>>,
ui_testing: bool,
}
-struct FileWithAnnotatedLines {
+#[derive(Debug)]
+pub struct FileWithAnnotatedLines {
file: Lrc<SourceFile>,
lines: Vec<Line>,
multiline_depth: usize,
}
}
- fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
- fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
- file: Lrc<SourceFile>,
- line_index: usize,
- ann: Annotation) {
-
- for slot in file_vec.iter_mut() {
- // Look through each of our files for the one we're adding to
- if slot.file.name == file.name {
- // See if we already have a line for it
- for line_slot in &mut slot.lines {
- if line_slot.line_index == line_index {
- line_slot.annotations.push(ann);
- return;
- }
- }
- // We don't have a line yet, create one
- slot.lines.push(Line {
- line_index,
- annotations: vec![ann],
- });
- slot.lines.sort();
- return;
- }
- }
- // This is the first time we're seeing the file
- file_vec.push(FileWithAnnotatedLines {
- file,
- lines: vec![Line {
- line_index,
- annotations: vec![ann],
- }],
- multiline_depth: 0,
- });
- }
-
- let mut output = vec![];
- let mut multiline_annotations = vec![];
-
- if let Some(ref sm) = self.sm {
- for span_label in msp.span_labels() {
- if span_label.span.is_dummy() {
- continue;
- }
-
- let lo = sm.lookup_char_pos(span_label.span.lo());
- let mut hi = sm.lookup_char_pos(span_label.span.hi());
-
- // Watch out for "empty spans". If we get a span like 6..6, we
- // want to just display a `^` at 6, so convert that to
- // 6..7. This is degenerate input, but it's best to degrade
- // gracefully -- and the parser likes to supply a span like
- // that for EOF, in particular.
-
- if lo.col_display == hi.col_display && lo.line == hi.line {
- hi.col_display += 1;
- }
-
- let ann_type = if lo.line != hi.line {
- let ml = MultilineAnnotation {
- depth: 1,
- line_start: lo.line,
- line_end: hi.line,
- start_col: lo.col_display,
- end_col: hi.col_display,
- is_primary: span_label.is_primary,
- label: span_label.label.clone(),
- overlaps_exactly: false,
- };
- multiline_annotations.push((lo.file.clone(), ml.clone()));
- AnnotationType::Multiline(ml)
- } else {
- AnnotationType::Singleline
- };
- let ann = Annotation {
- start_col: lo.col_display,
- end_col: hi.col_display,
- is_primary: span_label.is_primary,
- label: span_label.label.clone(),
- annotation_type: ann_type,
- };
-
- if !ann.is_multiline() {
- add_annotation_to_file(&mut output, lo.file, lo.line, ann);
- }
- }
- }
-
- // Find overlapping multiline annotations, put them at different depths
- multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end));
- for item in multiline_annotations.clone() {
- let ann = item.1;
- for item in multiline_annotations.iter_mut() {
- let ref mut a = item.1;
- // Move all other multiline annotations overlapping with this one
- // one level to the right.
- if !(ann.same_span(a)) &&
- num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
- {
- a.increase_depth();
- } else if ann.same_span(a) && &ann != a {
- a.overlaps_exactly = true;
- } else {
- break;
- }
- }
- }
-
- let mut max_depth = 0; // max overlapping multiline spans
- for (file, ann) in multiline_annotations {
- if ann.depth > max_depth {
- max_depth = ann.depth;
- }
- let mut end_ann = ann.as_end();
- if !ann.overlaps_exactly {
- // avoid output like
- //
- // | foo(
- // | _____^
- // | |_____|
- // | || bar,
- // | || );
- // | || ^
- // | ||______|
- // | |______foo
- // | baz
- //
- // and instead get
- //
- // | foo(
- // | _____^
- // | | bar,
- // | | );
- // | | ^
- // | | |
- // | |______foo
- // | baz
- add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
- // 4 is the minimum vertical length of a multiline span when presented: two lines
- // of code and two lines of underline. This is not true for the special case where
- // the beginning doesn't have an underline, but the current logic seems to be
- // working correctly.
- let middle = min(ann.line_start + 4, ann.line_end);
- for line in ann.line_start + 1..middle {
- // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
- add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
- }
- if middle < ann.line_end - 1 {
- for line in ann.line_end - 1..ann.line_end {
- add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
- }
- }
- } else {
- end_ann.annotation_type = AnnotationType::Singleline;
- }
- add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
- }
- for file_vec in output.iter_mut() {
- file_vec.multiline_depth = max_depth;
- }
- output
- }
-
fn render_source_line(&self,
buffer: &mut StyledBuffer,
file: Lrc<SourceFile>,
}
}
- // Preprocess all the annotations so that they are grouped by file and by line number
- // This helps us quickly iterate over the whole message (including secondary file spans)
- let mut annotated_files = self.preprocess_annotations(msp);
+ let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.sm);
// Make sure our primary file comes first
let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) =
}
}
+impl FileWithAnnotatedLines {
+ /// Preprocess all the annotations so that they are grouped by file and by line number
+ /// This helps us quickly iterate over the whole message (including secondary file spans)
+ pub fn collect_annotations(
+ msp: &MultiSpan,
+ source_map: &Option<Lrc<SourceMapperDyn>>
+ ) -> Vec<FileWithAnnotatedLines> {
+ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
+ file: Lrc<SourceFile>,
+ line_index: usize,
+ ann: Annotation) {
+
+ for slot in file_vec.iter_mut() {
+ // Look through each of our files for the one we're adding to
+ if slot.file.name == file.name {
+ // See if we already have a line for it
+ for line_slot in &mut slot.lines {
+ if line_slot.line_index == line_index {
+ line_slot.annotations.push(ann);
+ return;
+ }
+ }
+ // We don't have a line yet, create one
+ slot.lines.push(Line {
+ line_index,
+ annotations: vec![ann],
+ });
+ slot.lines.sort();
+ return;
+ }
+ }
+ // This is the first time we're seeing the file
+ file_vec.push(FileWithAnnotatedLines {
+ file,
+ lines: vec![Line {
+ line_index,
+ annotations: vec![ann],
+ }],
+ multiline_depth: 0,
+ });
+ }
+
+ let mut output = vec![];
+ let mut multiline_annotations = vec![];
+
+ if let Some(ref sm) = source_map {
+ for span_label in msp.span_labels() {
+ if span_label.span.is_dummy() {
+ continue;
+ }
+
+ let lo = sm.lookup_char_pos(span_label.span.lo());
+ let mut hi = sm.lookup_char_pos(span_label.span.hi());
+
+ // Watch out for "empty spans". If we get a span like 6..6, we
+ // want to just display a `^` at 6, so convert that to
+ // 6..7. This is degenerate input, but it's best to degrade
+ // gracefully -- and the parser likes to supply a span like
+ // that for EOF, in particular.
+
+ if lo.col_display == hi.col_display && lo.line == hi.line {
+ hi.col_display += 1;
+ }
+
+ let ann_type = if lo.line != hi.line {
+ let ml = MultilineAnnotation {
+ depth: 1,
+ line_start: lo.line,
+ line_end: hi.line,
+ start_col: lo.col_display,
+ end_col: hi.col_display,
+ is_primary: span_label.is_primary,
+ label: span_label.label.clone(),
+ overlaps_exactly: false,
+ };
+ multiline_annotations.push((lo.file.clone(), ml.clone()));
+ AnnotationType::Multiline(ml)
+ } else {
+ AnnotationType::Singleline
+ };
+ let ann = Annotation {
+ start_col: lo.col_display,
+ end_col: hi.col_display,
+ is_primary: span_label.is_primary,
+ label: span_label.label.clone(),
+ annotation_type: ann_type,
+ };
+
+ if !ann.is_multiline() {
+ add_annotation_to_file(&mut output, lo.file, lo.line, ann);
+ }
+ }
+ }
+
+ // Find overlapping multiline annotations, put them at different depths
+ multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end));
+ for item in multiline_annotations.clone() {
+ let ann = item.1;
+ for item in multiline_annotations.iter_mut() {
+ let ref mut a = item.1;
+ // Move all other multiline annotations overlapping with this one
+ // one level to the right.
+ if !(ann.same_span(a)) &&
+ num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
+ {
+ a.increase_depth();
+ } else if ann.same_span(a) && &ann != a {
+ a.overlaps_exactly = true;
+ } else {
+ break;
+ }
+ }
+ }
+
+ let mut max_depth = 0; // max overlapping multiline spans
+ for (file, ann) in multiline_annotations {
+ if ann.depth > max_depth {
+ max_depth = ann.depth;
+ }
+ let mut end_ann = ann.as_end();
+ if !ann.overlaps_exactly {
+ // avoid output like
+ //
+ // | foo(
+ // | _____^
+ // | |_____|
+ // | || bar,
+ // | || );
+ // | || ^
+ // | ||______|
+ // | |______foo
+ // | baz
+ //
+ // and instead get
+ //
+ // | foo(
+ // | _____^
+ // | | bar,
+ // | | );
+ // | | ^
+ // | | |
+ // | |______foo
+ // | baz
+ add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
+ // 4 is the minimum vertical length of a multiline span when presented: two lines
+ // of code and two lines of underline. This is not true for the special case where
+ // the beginning doesn't have an underline, but the current logic seems to be
+ // working correctly.
+ let middle = min(ann.line_start + 4, ann.line_end);
+ for line in ann.line_start + 1..middle {
+ // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
+ add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
+ }
+ if middle < ann.line_end - 1 {
+ for line in ann.line_end - 1..ann.line_end {
+ add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
+ }
+ }
+ } else {
+ end_ann.annotation_type = AnnotationType::Singleline;
+ }
+ add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
+ }
+ for file_vec in output.iter_mut() {
+ file_vec.multiline_depth = max_depth;
+ }
+ output
+ }
+}
+
fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
buffer.puts(line, col, "| ", Style::LineNumber);
}
proc-macro = true
[dependencies]
-synstructure = "0.10.1"
+synstructure = "0.10.2"
syn = { version = "0.15.22", features = ["full"] }
proc-macro2 = "0.4.24"
quote = "0.6.10"
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::codec::TyDecoder;
-use rustc::mir::Mir;
+use rustc::mir::Body;
use rustc::util::captures::Captures;
use std::io;
pub fn maybe_get_optimized_mir(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: DefIndex)
- -> Option<Mir<'tcx>> {
+ -> Option<Body<'tcx>> {
match self.is_proc_macro(id) {
true => None,
false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))),
self.lazy_seq(param_names.iter().map(|ident| ident.name))
}
- fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
+ fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Body<'tcx>>> {
debug!("EntryBuilder::encode_mir({:?})", def_id);
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
let mir = self.tcx.optimized_mir(def_id);
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
- pub mir: Option<Lazy<mir::Mir<'tcx>>>,
+ pub mir: Option<Lazy<mir::Body<'tcx>>>,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
use crate::dataflow::move_paths::MoveData;
use rustc::mir::traversal;
use rustc::mir::visit::{PlaceContext, Visitor, NonUseContext, MutatingUseContext};
-use rustc::mir::{self, Location, Mir, Local};
+use rustc::mir::{self, Location, Body, Local};
use rustc::ty::{RegionVid, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::IndexVec;
impl LocalsStateAtExit {
fn build(
locals_are_invalidated_at_exit: bool,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>
) -> Self {
struct HasStorageDead(BitSet<Local>);
LocalsStateAtExit::AllAreInvalidated
} else {
let mut has_storage_dead = HasStorageDead(BitSet::new_empty(mir.local_decls.len()));
- has_storage_dead.visit_mir(mir);
+ has_storage_dead.visit_body(mir);
let mut has_storage_dead_or_moved = has_storage_dead.0;
for move_out in &move_data.moves {
if let Some(index) = move_data.base_local(move_out.path) {
impl<'tcx> BorrowSet<'tcx> {
pub fn build(
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
locals_are_invalidated_at_exit: bool,
move_data: &MoveData<'tcx>
) -> Self {
struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
location_map: FxHashMap<Location, BorrowIndex>,
activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
) -> (String, String, String, String) {
// Define a small closure that we can use to check if the type of a place
// is a union.
- let is_union = |place: &Place<'tcx>| -> bool {
- place.ty(self.mir, self.infcx.tcx).ty
- .ty_adt_def()
- .map(|adt| adt.is_union())
- .unwrap_or(false)
+ let union_ty = |place: &Place<'tcx>| -> Option<Ty<'tcx>> {
+ let ty = place.ty(self.mir, self.infcx.tcx).ty;
+ ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
};
+ let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned());
// Start with an empty tuple, so we can use the functions on `Option` to reduce some
// code duplication (particularly around returning an empty description in the failure
let mut current = first_borrowed_place;
while let Place::Projection(box Projection { base, elem }) = current {
match elem {
- ProjectionElem::Field(field, _) if is_union(base) => {
+ ProjectionElem::Field(field, _) if union_ty(base).is_some() => {
return Some((base, field));
},
_ => current = base,
// borrowed place and look for a access to a different field of the same union.
let mut current = second_borrowed_place;
while let Place::Projection(box Projection { base, elem }) = current {
- match elem {
- ProjectionElem::Field(field, _) if {
- is_union(base) && field != target_field && base == target_base
- } => {
- let desc_base = self.describe_place(base)
- .unwrap_or_else(|| "_".to_owned());
- let desc_first = self.describe_place(first_borrowed_place)
- .unwrap_or_else(|| "_".to_owned());
- let desc_second = self.describe_place(second_borrowed_place)
- .unwrap_or_else(|| "_".to_owned());
-
- // Also compute the name of the union type, eg. `Foo` so we
- // can add a helpful note with it.
- let ty = base.ty(self.mir, self.infcx.tcx).ty;
-
- return Some((desc_base, desc_first, desc_second, ty.to_string()));
- },
- _ => current = base,
+ if let ProjectionElem::Field(field, _) = elem {
+ if let Some(union_ty) = union_ty(base) {
+ if field != target_field && base == target_base {
+ return Some((
+ describe_place(base),
+ describe_place(first_borrowed_place),
+ describe_place(second_borrowed_place),
+ union_ty.to_string(),
+ ));
+ }
+ }
}
+
+ current = base;
}
None
})
.unwrap_or_else(|| {
// If we didn't find a field access into a union, or both places match, then
// only return the description of the first place.
- let desc_place = self.describe_place(first_borrowed_place)
- .unwrap_or_else(|| "_".to_owned());
- (desc_place, "".to_string(), "".to_string(), "".to_string())
+ (
+ describe_place(first_borrowed_place),
+ "".to_string(),
+ "".to_string(),
+ "".to_string(),
+ )
})
}
);
// Find the local from the operand.
- let assigned_from_local = match assigned_from.local() {
+ let assigned_from_local = match assigned_from.local_or_deref_local() {
Some(local) => local,
None => continue,
};
);
// Find the local from the rvalue.
- let assigned_from_local = match assigned_from.local() {
+ let assigned_from_local = match assigned_from.local_or_deref_local() {
Some(local) => local,
None => continue,
};
assigned_from,
);
- if let Some(assigned_from_local) = assigned_from.local() {
+ if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
debug!(
"annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
assigned_from_local,
diag: &mut DiagnosticBuilder<'_>,
) {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
- let mut target = place.local();
+ let mut target = place.local_or_deref_local();
for stmt in &self.mir[location.block].statements[location.statement_index..] {
debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
match from {
Operand::Copy(ref place) |
- Operand::Move(ref place) if target == place.local() =>
- target = into.local(),
+ Operand::Move(ref place) if target == place.local_or_deref_local() =>
+ target = into.local_or_deref_local(),
_ => {},
}
}
if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() {
Some(Operand::Copy(ref place)) |
- Some(Operand::Move(ref place)) if target == place.local() =>
- place.local().unwrap(),
+ Some(Operand::Move(ref place)) if target == place.local_or_deref_local() =>
+ place.local_or_deref_local().unwrap(),
_ => return,
};
-use rustc::mir::{BasicBlock, Location, Mir};
+use rustc::mir::{BasicBlock, Location, Body};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
/// Maps between a MIR Location, which identifies a particular
}
impl LocationTable {
- crate fn new(mir: &Mir<'_>) -> Self {
+ crate fn new(mir: &Body<'_>) -> Self {
let mut num_points = 0;
let statements_before_block = mir.basic_blocks()
.iter()
use rustc::middle::borrowck::SignalledError;
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{
- ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase, Static, StaticKind
+ ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, Static,
+
+ StaticKind
};
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
}
let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
- let input_mir: &Mir<'_> = &input_mir.borrow();
+ let input_mir: &Body<'_> = &input_mir.borrow();
do_mir_borrowck(&infcx, input_mir, def_id)
});
debug!("mir_borrowck done");
fn do_mir_borrowck<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
- input_mir: &Mir<'gcx>,
+ input_mir: &Body<'gcx>,
def_id: DefId,
) -> BorrowCheckResult<'gcx> {
debug!("do_mir_borrowck(def_id = {:?})", def_id);
// requires first making our own copy of the MIR. This copy will
// be modified (in place) to contain non-lexical lifetimes. It
// will have a lifetime tied to the inference context.
- let mut mir: Mir<'tcx> = input_mir.clone();
+ let mut mir: Body<'tcx> = input_mir.clone();
let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir);
let mir = &mir; // no further changes
let location_table = &LocationTable::new(mir);
pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
- mir: &'cx Mir<'tcx>,
+ mir: &'cx Body<'tcx>,
mir_def_id: DefId,
move_data: &'cx MoveData<'tcx>,
impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
type FlowState = Flows<'cx, 'gcx, 'tcx>;
- fn mir(&self) -> &'cx Mir<'tcx> {
+ fn mir(&self) -> &'cx Body<'tcx> {
self.mir
}
use rustc::hir;
use rustc::hir::Node;
-use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
+use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Body};
use rustc::mir::{
Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
};
// by trying (3.), then (2.) and finally falling back on (1.).
fn suggest_ampmut<'cx, 'gcx, 'tcx>(
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
local: Local,
local_decl: &mir::LocalDecl<'tcx>,
opt_ty_info: Option<Span>,
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, PlaceBase, Rvalue};
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Body, Place, PlaceBase, Rvalue};
use rustc::mir::{SourceInfo, Statement, Terminator};
use rustc::mir::UserTypeProjection;
use rustc::ty::fold::TypeFoldable;
liveness_constraints: &mut LivenessValues<RegionVid>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) {
let mut cg = ConstraintGeneration {
use crate::borrow_check::nll::ToRegionVid;
use crate::util::liveness::{self, DefUse};
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
crate fn find<'tcx>(
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
regioncx: &Rc<RegionInferenceContext<'tcx>>,
tcx: TyCtxt<'_, '_, 'tcx>,
region_vid: RegionVid,
}
struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
- mir: &'cx Mir<'tcx>,
+ mir: &'cx Body<'tcx>,
regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
}
struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
- mir: &'cx Mir<'tcx>,
+ mir: &'cx Body<'tcx>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
region_vid: RegionVid,
def_use_result: Option<DefUseResult>,
use crate::borrow_check::nll::ConstraintDescription;
use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
use rustc::mir::{
- CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
+ CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, PlaceBase,
Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
};
use rustc::ty::{self, TyCtxt};
pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx, 'tcx>(
&self,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
err: &mut DiagnosticBuilder<'_>,
borrow_desc: &str,
borrow_span: Option<Span>,
use crate::dataflow::indexes::BorrowIndex;
use rustc::ty::TyCtxt;
use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
+use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase, Rvalue};
use rustc::mir::{Statement, StatementKind};
use rustc::mir::TerminatorKind;
use rustc::mir::{Operand, BorrowKind};
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) {
if all_facts.is_none() {
mir,
dominators,
};
- ig.visit_mir(mir);
+ ig.visit_body(mir);
}
}
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
all_facts: &'cx mut AllFacts,
location_table: &'cx LocationTable,
- mir: &'cx Mir<'tcx>,
+ mir: &'cx Body<'tcx>,
dominators: Dominators<BasicBlock>,
borrow_set: &'cx BorrowSet<'tcx>,
}
use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
-use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
+use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Body};
use rustc::ty::{self, RegionKind, RegionVid};
use rustc_errors::Diagnostic;
use std::fmt::Debug;
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
def_id: DefId,
param_env: ty::ParamEnv<'tcx>,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
) -> UniversalRegions<'tcx> {
debug!("replace_regions_in_mir(def_id={:?})", def_id);
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
def_id: DefId,
universal_regions: UniversalRegions<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
location_table: &LocationTable,
param_env: ty::ParamEnv<'gcx>,
fn dump_mir_results<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
regioncx: &RegionInferenceContext<'_>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
) {
fn dump_annotation<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::infer::NLLRegionVariableOrigin;
-use rustc::mir::{ConstraintCategory, Location, Mir};
+use rustc::mir::{ConstraintCategory, Location, Body};
use rustc::ty::{self, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
/// path to blame.
fn best_blame_constraint(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
from_region: RegionVid,
target_test: impl Fn(RegionVid) -> bool,
) -> (ConstraintCategory, bool, Span) {
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
pub(super) fn report_error(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
/// ```
fn report_fnmut_error(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
/// ```
fn report_escaping_data_error(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
/// ```
fn report_general_error(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
crate fn free_region_constraint_info(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
infcx: &InferCtxt<'_, '_, 'tcx>,
// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
crate fn find_outlives_blame_span(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
fr1: RegionVid,
fr2: RegionVid,
) -> (ConstraintCategory, Span) {
fn retrieve_closure_constraint_info(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
constraint: &OutlivesConstraint,
) -> (ConstraintCategory, bool, Span) {
let loc = match constraint.locations {
use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
-use rustc::mir::Mir;
+use rustc::mir::Body;
use rustc::ty::subst::{SubstsRef, UnpackedKind};
use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
use rustc::ty::print::RegionHighlightMode;
crate fn give_region_a_name(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
fr: RegionVid,
fn give_name_if_anonymous_region_appears_in_arguments(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
counter: &mut usize,
fn give_name_if_we_can_match_hir_ty_from_argument(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
fn give_name_if_we_cannot_match_hir_ty(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
counter: &mut usize,
fn give_name_if_anonymous_region_appears_in_output(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
counter: &mut usize,
fn give_name_if_anonymous_region_appears_in_yield_ty(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
counter: &mut usize,
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::Upvar;
-use rustc::mir::{Local, Mir};
+use rustc::mir::{Local, Body};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use syntax::source_map::Span;
crate fn get_var_name_and_span_for_region(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
fr: RegionVid,
) -> Option<(Option<Symbol>, Span)> {
/// declared.
crate fn get_argument_name_and_span_for_region(
&self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
argument_index: usize,
) -> (Option<Symbol>, Span) {
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
use rustc::mir::{
ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, Mir,
+ ConstraintCategory, Local, Location, Body,
};
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc::util::common::{self, ErrorReported};
universal_regions: Rc<UniversalRegions<'tcx>>,
placeholder_indices: Rc<PlaceholderIndices>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
- _mir: &Mir<'tcx>,
+ _mir: &Body<'tcx>,
outlives_constraints: ConstraintSet,
closure_bounds_mapping: FxHashMap<
Location,
pub(super) fn solve<'gcx>(
&mut self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
errors_buffer: &mut Vec<Diagnostic>,
fn solve_inner<'gcx>(
&mut self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
errors_buffer: &mut Vec<Diagnostic>,
/// for each region variable until all the constraints are
/// satisfied. Note that some values may grow **too** large to be
/// feasible, but we check this later.
- fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) {
+ fn propagate_constraints(&mut self, _mir: &Body<'tcx>) {
debug!("propagate_constraints()");
debug!("propagate_constraints: constraints={:#?}", {
fn check_type_tests<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
errors_buffer: &mut Vec<Diagnostic>,
fn try_promote_type_test<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
type_test: &TypeTest<'tcx>,
propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'gcx>>,
) -> bool {
fn eval_verify_bound(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
generic_ty: Ty<'tcx>,
lower_bound: RegionVid,
verify_bound: &VerifyBound<'tcx>,
fn eval_if_eq(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
generic_ty: Ty<'tcx>,
lower_bound: RegionVid,
test_ty: Ty<'tcx>,
// Evaluate whether `sup_region: sub_region @ point`.
fn eval_outlives(
&self,
- _mir: &Mir<'tcx>,
+ _mir: &Body<'tcx>,
sup_region: RegionVid,
sub_region: RegionVid,
) -> bool {
fn check_universal_regions<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
fn check_universal_region<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
longer_fr: RegionVid,
longer_fr: RegionVid,
shorter_fr: RegionVid,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
upvars: &[Upvar],
mir_def_id: DefId,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
fn check_bound_universal_region<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
_mir_def_id: DefId,
longer_fr: RegionVid,
placeholder: ty::PlaceholderRegion,
-use rustc::mir::{BasicBlock, Location, Mir};
+use rustc::mir::{BasicBlock, Location, Body};
use rustc::ty::{self, RegionVid};
use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix};
use rustc_data_structures::fx::FxHashMap;
}
impl RegionValueElements {
- crate fn new(mir: &Mir<'_>) -> Self {
+ crate fn new(mir: &Body<'_>) -> Self {
let mut num_points = 0;
let statements_before_block: IndexVec<BasicBlock, usize> = mir.basic_blocks()
.iter()
/// Pushes all predecessors of `index` onto `stack`.
crate fn push_predecessors(
&self,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
index: PointIndex,
stack: &mut Vec<PointIndex>,
) {
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{Location, Mir};
+use rustc::mir::{Location, Body};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
/// Replaces all free regions appearing in the MIR with fresh
/// inference variables, returning the number of variables created.
-pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Mir<'tcx>) {
+pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Body<'tcx>) {
debug!("renumber_mir()");
debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
let mut visitor = NLLVisitor { infcx };
- visitor.visit_mir(mir);
+ visitor.visit_body(mir);
}
/// Replaces all regions appearing in `value` with fresh inference
}
impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
- fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
+ fn visit_body(&mut self, mir: &mut Body<'tcx>) {
for promoted in mir.promoted.iter_mut() {
- self.visit_mir(promoted);
+ self.visit_body(promoted);
}
- self.super_mir(mir);
+ self.super_body(mir);
}
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
pub(super) fn equate_inputs_and_outputs(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
universal_regions: &UniversalRegions<'tcx>,
normalized_inputs_and_output: &[Ty<'tcx>],
) {
use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::vec_linked_list as vll;
crate fn build(
live_locals: &Vec<Local>,
elements: &RegionValueElements,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
) -> Self {
let nones = IndexVec::from_elem_n(None, mir.local_decls.len());
let mut local_use_map = LocalUseMap {
elements,
locals_with_use_data,
}
- .visit_mir(mir);
+ .visit_body(mir);
local_use_map
}
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::FlowAtLocation;
use crate::dataflow::MaybeInitializedPlaces;
-use rustc::mir::{Local, Mir};
+use rustc::mir::{Local, Body};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use std::rc::Rc;
/// performed before
pub(super) fn generate<'gcx, 'tcx>(
typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
fn compute_live_locals(
tcx: TyCtxt<'_, '_, 'tcx>,
free_regions: &FxHashSet<RegionVid>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
) -> Vec<Local> {
let live_locals: Vec<Local> = mir
.local_decls
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
use rustc::infer::canonical::QueryRegionConstraint;
-use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Mir};
+use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
use rustc::traits::query::type_op::TypeOp;
/// this respects `#[may_dangle]` annotations).
pub(super) fn trace(
typeck: &mut TypeChecker<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
elements: &'me RegionValueElements,
/// MIR we are analyzing.
- mir: &'me Mir<'tcx>,
+ mir: &'me Body<'tcx>,
/// Mapping to/from the various indices used for initialization tracking.
move_data: &'me MoveData<'tcx>,
pub(crate) fn type_check<'gcx, 'tcx>(
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'gcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mir_def_id: DefId,
universal_regions: &Rc<UniversalRegions<'tcx>>,
location_table: &LocationTable,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'gcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
);
let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, mir);
- verifier.visit_mir(mir);
+ verifier.visit_body(mir);
verifier.errors_reported
};
/// is a problem.
struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
- mir: &'b Mir<'tcx>,
+ mir: &'b Body<'tcx>,
last_span: Span,
mir_def_id: DefId,
errors_reported: bool,
}
}
- fn visit_mir(&mut self, mir: &Mir<'tcx>) {
+ fn visit_body(&mut self, mir: &Body<'tcx>) {
self.sanitize_type(&"return type", mir.return_ty());
for local_decl in &mir.local_decls {
self.sanitize_type(local_decl, local_decl.ty);
if self.errors_reported {
return;
}
- self.super_mir(mir);
+ self.super_body(mir);
}
}
impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
- fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Mir<'tcx>) -> Self {
+ fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Body<'tcx>) -> Self {
TypeVerifier {
mir,
mir_def_id: cx.mir_def_id,
})
}
- fn sanitize_promoted(&mut self, promoted_mir: &'b Mir<'tcx>, location: Location) {
+ fn sanitize_promoted(&mut self, promoted_mir: &'b Body<'tcx>, location: Location) {
// Determine the constraints from the promoted MIR by running the type
// checker on the promoted MIR, then transfer the constraints back to
// the main MIR, changing the locations to the provided location.
&mut closure_bounds
);
- self.visit_mir(promoted_mir);
+ self.visit_body(promoted_mir);
if !self.errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
}
/// Gets a span representing the location.
- pub fn span(&self, mir: &Mir<'_>) -> Span {
+ pub fn span(&self, mir: &Body<'_>) -> Span {
match self {
Locations::All(span) => *span,
Locations::Single(l) => mir.source_info(*l).span,
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fn new(
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mir_def_id: DefId,
param_env: ty::ParamEnv<'gcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
debug!(
"eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
opaque_decl.concrete_ty,
- infcx.resolve_type_vars_if_possible(&opaque_decl.concrete_ty),
+ infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty),
opaque_defn_ty
);
obligations.add(infcx
self.infcx.tcx
}
- fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Location) {
+ fn check_stmt(&mut self, mir: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
debug!("check_stmt: {:?}", stmt);
let tcx = self.tcx();
match stmt.kind {
fn check_terminator(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
) {
fn check_call_dest(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
destination: &Option<(Place<'tcx>, BasicBlock)>,
fn check_call_inputs(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>,
args: &[Operand<'tcx>],
}
}
- fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
+ fn check_iscleanup(&mut self, mir: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
let is_cleanup = block_data.is_cleanup;
self.last_span = block_data.terminator().source_info.span;
match block_data.terminator().kind {
fn assert_iscleanup(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
ctxt: &dyn fmt::Debug,
bb: BasicBlock,
iscleanuppad: bool,
}
}
- fn check_local(&mut self, mir: &Mir<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
+ fn check_local(&mut self, mir: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
match mir.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => {
// return values of normal functions are required to be
}
}
- fn check_rvalue(&mut self, mir: &Mir<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+ fn check_rvalue(&mut self, mir: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
let tcx = self.tcx();
match rvalue {
fn check_aggregate_rvalue(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
rvalue: &Rvalue<'tcx>,
aggregate_kind: &AggregateKind<'tcx>,
operands: &[Operand<'tcx>],
/// - `borrowed_place`: the place `P` being borrowed
fn add_reborrow_constraint(
&mut self,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
location: Location,
borrow_region: ty::Region<'tcx>,
borrowed_place: &Place<'tcx>,
})
}
- fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+ fn typeck_mir(&mut self, mir: &Body<'tcx>) {
self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span);
use crate::borrow_check::places_conflict;
use crate::borrow_check::AccessDepth;
use crate::dataflow::indexes::BorrowIndex;
-use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
+use rustc::mir::{BasicBlock, Location, Body, Place, PlaceBase};
use rustc::mir::{ProjectionElem, BorrowKind};
use rustc::ty::TyCtxt;
use rustc_data_structures::graph::dominators::Dominators;
pub(super) fn each_borrow_involving_path<'a, 'tcx, 'gcx: 'tcx, F, I, S> (
s: &mut S,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
_location: Location,
access_place: (AccessDepth, &Place<'tcx>),
borrow_set: &BorrowSet<'tcx>,
use rustc::hir;
use rustc::mir::ProjectionElem;
-use rustc::mir::{Mir, Place, PlaceBase, Mutability, Static, StaticKind};
+use rustc::mir::{Body, Place, PlaceBase, Mutability, Static, StaticKind};
use rustc::ty::{self, TyCtxt};
use crate::borrow_check::borrow_set::LocalsStateAtExit;
fn ignore_borrow(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
locals_state_at_exit: &LocalsStateAtExit,
) -> bool;
}
fn ignore_borrow(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
locals_state_at_exit: &LocalsStateAtExit,
) -> bool {
self.iterate(|place_base, place_projection| {
use crate::borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
use rustc::mir::{
- BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, ProjectionsIter,
+ BorrowKind, Body, Place, PlaceBase, Projection, ProjectionElem, ProjectionsIter,
StaticKind
};
use rustc::ty::{self, TyCtxt};
/// dataflow).
crate fn places_conflict<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
borrow_place: &Place<'tcx>,
access_place: &Place<'tcx>,
bias: PlaceConflictBias,
/// order to make the conservative choice and preserve soundness.
pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
borrow_place: &Place<'tcx>,
borrow_kind: BorrowKind,
access_place: &Place<'tcx>,
fn place_components_conflict<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
borrow_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
borrow_kind: BorrowKind,
access_projections: (&PlaceBase<'tcx>, ProjectionsIter<'_, 'tcx>),
// between `elem1` and `elem2`.
fn place_projection_conflict<'a, 'gcx: 'tcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
pi1: &Projection<'tcx>,
pi2: &Projection<'tcx>,
bias: PlaceConflictBias,
use rustc::hir;
use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Mir, Place, PlaceBase, ProjectionElem};
+use rustc::mir::{Body, Place, PlaceBase, ProjectionElem};
pub trait IsPrefixOf<'tcx> {
fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
pub(super) struct Prefixes<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
- mir: &'cx Mir<'tcx>,
+ mir: &'cx Body<'tcx>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
kind: PrefixSet,
next: Option<&'cx Place<'tcx>>,
never_initialized_mut_locals: &mut never_initialized_mut_locals,
mbcx: self,
};
- visitor.visit_mir(visitor.mbcx.mir);
+ visitor.visit_body(visitor.mbcx.mir);
}
// Take the union of the existed `used_mut` set with those variables we've found were
}) => {
// Not projected from the implicit `self` in a closure.
debug_assert!(
- match base.local() {
+ match base.local_or_deref_local() {
Some(local) => local == Local::new(1),
None => false,
},
use super::lints;
/// Construct the MIR for a given `DefId`.
-pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
+pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<'tcx> {
let id = tcx.hir().as_local_hir_id(def_id).unwrap();
// Figure out what primary body this item has.
build::construct_const(cx, body_id, return_ty, return_ty_span)
};
- // Convert the Mir to global types.
+ // Convert the `mir::Body` to global types.
let mut globalizer = GlobalizeMir {
tcx,
span: mir.span
};
- globalizer.visit_mir(&mut mir);
+ globalizer.visit_body(&mut mir);
let mir = unsafe {
- mem::transmute::<Mir<'_>, Mir<'tcx>>(mir)
+ mem::transmute::<Body<'_>, Body<'tcx>>(mir)
};
mir_util::dump_mir(tcx, None, "mir_map", &0,
fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ctor_id: hir::HirId,
v: &'tcx hir::VariantData)
- -> Mir<'tcx>
+ -> Body<'tcx>
{
let span = tcx.hir().span_by_hir_id(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
tcx.infer_ctxt().enter(|infcx| {
let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span);
- // Convert the Mir to global types.
+ // Convert the `mir::Body` to global types.
let tcx = infcx.tcx.global_tcx();
let mut globalizer = GlobalizeMir {
tcx,
span: mir.span
};
- globalizer.visit_mir(&mut mir);
+ globalizer.visit_body(&mut mir);
let mir = unsafe {
- mem::transmute::<Mir<'_>, Mir<'tcx>>(mir)
+ mem::transmute::<Body<'_>, Body<'tcx>>(mir)
};
mir_util::dump_mir(tcx, None, "mir_map", &0,
yield_ty: Option<Ty<'gcx>>,
return_ty_span: Span,
body: &'gcx hir::Body)
- -> Mir<'tcx>
+ -> Body<'tcx>
where A: Iterator<Item=ArgInfo<'gcx>>
{
let arguments: Vec<_> = arguments.collect();
body_id: hir::BodyId,
const_ty: Ty<'tcx>,
const_ty_span: Span,
-) -> Mir<'tcx> {
+) -> Body<'tcx> {
let tcx = hir.tcx();
let owner_id = tcx.hir().body_owner(body_id);
let span = tcx.hir().span(owner_id);
fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
body_id: hir::BodyId)
- -> Mir<'tcx> {
+ -> Body<'tcx> {
let owner_id = hir.tcx().hir().body_owner(body_id);
let span = hir.tcx().hir().span(owner_id);
let ty = hir.tcx().types.err;
fn finish(self,
yield_ty: Option<Ty<'tcx>>)
- -> Mir<'tcx> {
+ -> Body<'tcx> {
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
if block.terminator.is_none() {
span_bug!(self.fn_span, "no terminator on block {:?}", index);
}
}
- Mir::new(
+ Body::new(
self.cfg.basic_blocks,
self.source_scopes,
ClearCrossCrate::Set(self.source_scope_local_data),
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cid: GlobalId<'tcx>,
- mir: &'mir mir::Mir<'tcx>,
+ mir: &'mir mir::Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
let span = tcx.def_span(cid.instance.def_id());
ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
ptr.offset.bytes(),
),
- Scalar::Bits { .. } => (
+ Scalar::Raw { .. } => (
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"", ())),
0,
),
fn eval_body_using_ecx<'mir, 'tcx>(
ecx: &mut CompileTimeEvalContext<'_, 'mir, 'tcx>,
cid: GlobalId<'tcx>,
- mir: &'mir mir::Mir<'tcx>,
+ mir: &'mir mir::Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
ret: Option<mir::BasicBlock>,
- ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
+ ) -> EvalResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
debug!("eval_fn_call: {:?}", instance);
// Only check non-glue functions
if let ty::InstanceDef::Item(def_id) = instance.def {
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
use rustc::ty::{self, TyCtxt};
use crate::util::elaborate_drops::DropFlagState;
//
// FIXME: we have to do something for moving slice patterns.
fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
place: &mir::Place<'tcx>) -> bool {
let ty = place.ty(mir, tcx).ty;
match ty.sty {
pub(crate) fn on_lookup_result_bits<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>,
lookup_result: LookupResult,
each_child: F)
pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex,
mut each_child: F)
{
fn is_terminal_path<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>,
path: MovePathIndex) -> bool
{
fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex,
each_child: &mut F)
pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
path: MovePathIndex,
mut each_child: F)
pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
mut callback: F)
where F: FnMut(MovePathIndex, DropFlagState)
pub(crate) fn drop_flag_effects_for_location<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
loc: Location,
mut callback: F)
pub(crate) fn for_location_inits<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
move_data: &MoveData<'tcx>,
loc: Location,
mut callback: F)
//! Hook into libgraphviz for rendering dataflow graphs for MIR.
use rustc::hir::def_id::DefId;
-use rustc::mir::{BasicBlock, Mir};
+use rustc::mir::{BasicBlock, Body};
use std::fs;
use std::io;
pub trait MirWithFlowState<'tcx> {
type BD: BitDenotation<'tcx>;
fn def_id(&self) -> DefId;
- fn mir(&self) -> &Mir<'tcx>;
+ fn mir(&self) -> &Body<'tcx>;
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
}
{
type BD = BD;
fn def_id(&self) -> DefId { self.def_id }
- fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
+ fn mir(&self) -> &Body<'tcx> { self.flow_state.mir() }
fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Edge { source: BasicBlock, index: usize }
-fn outgoing(mir: &Mir<'_>, bb: BasicBlock) -> Vec<Edge> {
+fn outgoing(mir: &Body<'_>, bb: BasicBlock) -> Vec<Edge> {
(0..mir[bb].terminator().successors().count())
.map(|index| Edge { source: bb, index: index}).collect()
}
n: &Node,
w: &mut W,
block: BasicBlock,
- mir: &Mir<'_>) -> io::Result<()> {
+ mir: &Body<'_>) -> io::Result<()> {
// Header rows
const HDRS: [&str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"];
const HDR_FMT: &str = "bgcolor=\"grey\"";
n: &Node,
w: &mut W,
block: BasicBlock,
- mir: &Mir<'_>)
+ mir: &Body<'_>)
-> io::Result<()> {
let i = n.index();
n: &Node,
w: &mut W,
block: BasicBlock,
- mir: &Mir<'_>)
+ mir: &Body<'_>)
-> io::Result<()> {
let i = n.index();
/// immovable generators.
#[derive(Copy, Clone)]
pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
}
impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>)
+ pub fn new(mir: &'a Body<'tcx>)
-> Self {
HaveBeenBorrowedLocals { mir }
}
- pub fn mir(&self) -> &Mir<'tcx> {
+ pub fn mir(&self) -> &Body<'tcx> {
self.mir
}
}
use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
use crate::borrow_check::place_ext::PlaceExt;
-use rustc::mir::{self, Location, Place, PlaceBase, Mir};
+use rustc::mir::{self, Location, Place, PlaceBase, Body};
use rustc::ty::TyCtxt;
use rustc::ty::RegionVid;
/// borrows in compact bitvectors.
pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
borrow_set: Rc<BorrowSet<'tcx>>,
borrows_out_of_scope_at_location: FxHashMap<Location, Vec<BorrowIndex>>,
}
fn precompute_borrows_out_of_scope<'tcx>(
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
regioncx: &Rc<RegionInferenceContext<'tcx>>,
borrows_out_of_scope_at_location: &mut FxHashMap<Location, Vec<BorrowIndex>>,
borrow_index: BorrowIndex,
impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
crate fn new(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
borrow_set: &Rc<BorrowSet<'tcx>>,
) -> Self {
//! zero-sized structure.
use rustc::ty::TyCtxt;
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
use rustc_data_structures::indexed_vec::Idx;
/// places that would require a dynamic drop-flag at that statement.
pub struct MaybeInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
/// places that would require a dynamic drop-flag at that statement.
pub struct MaybeUninitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
impl<'a, 'gcx, 'tcx> MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
/// that would require a dynamic drop-flag at that statement.
pub struct DefinitelyInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
/// ```
pub struct EverInitializedPlaces<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
impl<'a, 'gcx: 'tcx, 'tcx: 'a> EverInitializedPlaces<'a, 'gcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
#[derive(Copy, Clone)]
pub struct MaybeStorageLive<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
}
impl<'a, 'tcx: 'a> MaybeStorageLive<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>)
+ pub fn new(mir: &'a Body<'tcx>)
-> Self {
MaybeStorageLive { mir }
}
- pub fn mir(&self) -> &Mir<'tcx> {
+ pub fn mir(&self) -> &Body<'tcx> {
self.mir
}
}
sets: &mut BlockSets<'_, Local>,
loc: Location) {
match &self.mir[loc.block].terminator().kind {
- TerminatorKind::Drop { location, .. } => if let Some(l) = location.local() {
- sets.kill(l);
+ TerminatorKind::Drop { location, .. } => {
+ if let Some(l) = location.local_or_deref_local() {
+ sets.kill(l);
+ }
}
_ => (),
}
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TyCtxt};
-use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
+use rustc::mir::{self, Body, BasicBlock, BasicBlockData, Location, Statement, Terminator};
use rustc::mir::traversal;
use rustc::session::Session;
}
pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
def_id: DefId,
attributes: &[ast::Attribute],
dead_unwinds: &BitSet<BasicBlock>,
// Delegated Hooks: Provide access to the MIR and process the flow state.
- fn mir(&self) -> &'a Mir<'tcx>;
+ fn mir(&self) -> &'a Body<'tcx>;
}
pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
analysis: &T,
result: &DataflowResults<'tcx, T>,
- mir: &Mir<'tcx>)
+ mir: &Body<'tcx>)
-> BitSet<T::Idx> {
let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
let mut kill_set = on_entry.to_hybrid();
{
flow_state: DataflowState<'tcx, O>,
dead_unwinds: &'a BitSet<mir::BasicBlock>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
}
impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation<'tcx>
DataflowResults(self.flow_state)
}
- pub fn mir(&self) -> &'a Mir<'tcx> { self.mir }
+ pub fn mir(&self) -> &'a Body<'tcx> { self.mir }
}
pub struct DataflowResults<'tcx, O>(pub(crate) DataflowState<'tcx, O>) where O: BitDenotation<'tcx>;
impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation<'tcx>
{
- pub fn new(mir: &'a Mir<'tcx>,
+ pub fn new(mir: &'a Body<'tcx>,
dead_unwinds: &'a BitSet<mir::BasicBlock>,
denotation: D) -> Self where D: InitialFlow {
let bits_per_block = denotation.bits_per_block();
use super::IllegalMoveOriginKind::*;
struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
data: MoveData<'tcx>,
errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
}
impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
- fn new(mir: &'a Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
+ fn new(mir: &'a Body<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
let mut init_path_map = IndexVec::new();
}
pub(super) fn gather_moves<'a, 'gcx, 'tcx>(
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
tcx: TyCtxt<'a, 'gcx, 'tcx>
) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
let mut builder = MoveDataBuilder::new(mir, tcx);
}
impl<T> LocationMap<T> where T: Default + Clone {
- fn new(mir: &Mir<'_>) -> Self {
+ fn new(mir: &Body<'_>) -> Self {
LocationMap {
map: mir.basic_blocks().iter().map(|block| {
vec![T::default(); block.statements.len()+1]
}
impl Init {
- crate fn span<'gcx>(&self, mir: &Mir<'gcx>) -> Span {
+ crate fn span<'gcx>(&self, mir: &Body<'gcx>) -> Span {
match self.location {
InitLocation::Argument(local) => mir.local_decls[local].source_info.span,
InitLocation::Statement(location) => mir.source_info(location).span,
}
impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
- pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ pub fn gather_moves(mir: &Body<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-> Result<Self, (Self, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
builder::gather_moves(mir, tcx)
}
use syntax::ast;
-use rustc::ty::{self, Ty, TyCtxt, ParamEnv};
+use rustc::ty::{self, Ty, TyCtxt, ParamEnv, layout::Size};
use syntax_pos::symbol::Symbol;
use rustc::mir::interpret::{ConstValue, Scalar};
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
let result = truncate(n, width);
trace!("trunc result: {}", result);
- Ok(ConstValue::Scalar(Scalar::Bits {
- bits: result,
- size: width.bytes() as u8,
- }))
+ Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
};
use rustc::mir::interpret::*;
let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::Ptr(id.into()))
},
- LitKind::Byte(n) => ConstValue::Scalar(Scalar::Bits {
- bits: n as u128,
- size: 1,
- }),
+ LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))),
LitKind::Int(n, _) if neg => {
let n = n as i128;
let n = n.overflowing_neg().0;
let num = num.as_str();
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::Float;
- let (bits, size) = match fty {
+ let (data, size) = match fty {
ast::FloatTy::F32 => {
num.parse::<f32>().map_err(|_| ())?;
let mut f = num.parse::<Single>().unwrap_or_else(|e| {
}
};
- Ok(ConstValue::Scalar(Scalar::Bits { bits, size }))
+ Ok(ConstValue::Scalar(Scalar::from_uint(data, Size::from_bytes(size))))
}
/// Whether this constant/function needs overflow checks.
check_overflow: bool,
- /// See field with the same name on `Mir`.
+ /// See field with the same name on `mir::Body`.
control_flow_destroyed: Vec<(Span, String)>,
}
use rustc_apfloat::ieee::{Single, Double};
use rustc::mir::interpret::{
- Scalar, EvalResult, Pointer, PointerArithmetic, InterpError, truncate
+ Scalar, EvalResult, Pointer, PointerArithmetic, InterpError,
};
use rustc::mir::CastKind;
use rustc_apfloat::Float;
use rustc::ty::TyKind::*;
trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
- match val {
- Scalar::Ptr(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
- Scalar::Bits { bits, size } => {
- debug_assert_eq!(size as u64, src_layout.size.bytes());
- debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
- "Unexpected value of size {} before casting", size);
-
- let res = match src_layout.ty.sty {
- Float(fty) => self.cast_from_float(bits, fty, dest_layout.ty)?,
- _ => self.cast_from_int(bits, src_layout, dest_layout)?,
- };
-
- // Sanity check
- match res {
- Scalar::Ptr(_) => bug!("Fabricated a ptr value from an int...?"),
- Scalar::Bits { bits, size } => {
- debug_assert_eq!(size as u64, dest_layout.size.bytes());
- debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
- "Unexpected value of size {} after casting", size);
- }
+ match val.to_bits_or_ptr(src_layout.size, self) {
+ Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
+ Ok(data) => {
+ match src_layout.ty.sty {
+ Float(fty) => self.cast_from_float(data, fty, dest_layout.ty),
+ _ => self.cast_from_int(data, src_layout, dest_layout),
}
- // Done
- Ok(res)
}
}
}
trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty);
use rustc::ty::TyKind::*;
match dest_layout.ty.sty {
- Int(_) | Uint(_) => {
+ Int(_) | Uint(_) | RawPtr(_) => {
let v = self.truncate(v, dest_layout);
Ok(Scalar::from_uint(v, dest_layout.size))
}
Ok(Scalar::from_uint(v, Size::from_bytes(4)))
},
- // No alignment check needed for raw pointers.
- // But we have to truncate to target ptr size.
- RawPtr(_) => {
- Ok(Scalar::from_uint(
- self.truncate_to_ptr(v).0,
- self.pointer_size(),
- ))
- },
-
// Casts to bool are not permitted by rustc, no need to handle them here.
_ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
}
// Function and callsite information
////////////////////////////////////////////////////////////////////////////////
/// The MIR for the function called on this frame.
- pub mir: &'mir mir::Mir<'tcx>,
+ pub mir: &'mir mir::Body<'tcx>,
/// The def_id and substs of the current function.
pub instance: ty::Instance<'tcx>,
}
#[inline(always)]
- pub(super) fn mir(&self) -> &'mir mir::Mir<'tcx> {
+ pub(super) fn mir(&self) -> &'mir mir::Body<'tcx> {
self.frame().mir
}
pub fn load_mir(
&self,
instance: ty::InstanceDef<'tcx>,
- ) -> EvalResult<'tcx, &'tcx mir::Mir<'tcx>> {
+ ) -> EvalResult<'tcx, &'tcx mir::Body<'tcx>> {
// do not continue if typeck errors occurred (can only occur in local crate)
let did = instance.def_id();
if did.is_local()
&mut self,
instance: ty::Instance<'tcx>,
span: source_map::Span,
- mir: &'mir mir::Mir<'tcx>,
+ mir: &'mir mir::Body<'tcx>,
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
return_to_block: StackPopCleanup,
) -> EvalResult<'tcx> {
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
ret: Option<mir::BasicBlock>,
- ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
+ ) -> EvalResult<'tcx, Option<&'mir mir::Body<'tcx>>>;
/// Directly process an intrinsic without pushing a stack frame.
/// If this returns successfully, the engine will take care of jumping to the next block.
use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
use rustc::ty::layout::{Align, TargetDataLayout, Size, HasDataLayout};
-pub use rustc::mir::interpret::{truncate, write_target_uint, read_target_uint};
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use syntax::ast::Mutability;
required_align: Align
) -> EvalResult<'tcx> {
// Check non-NULL/Undef, extract offset
- let (offset, alloc_align) = match ptr {
- Scalar::Ptr(ptr) => {
+ let (offset, alloc_align) = match ptr.to_bits_or_ptr(self.pointer_size(), self) {
+ Err(ptr) => {
// check this is not NULL -- which we can ensure only if this is in-bounds
// of some (potentially dead) allocation.
let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead,
CheckInAllocMsg::NullPointerTest)?;
(ptr.offset.bytes(), align)
}
- Scalar::Bits { bits, size } => {
- assert_eq!(size as u64, self.pointer_size().bytes());
- assert!(bits < (1u128 << self.pointer_size().bits()));
+ Ok(data) => {
// check this is not NULL
- if bits == 0 {
+ if data == 0 {
return err!(InvalidNullPointerUsage);
}
// the "base address" is 0 and hence always aligned
- (bits as u64, required_align)
+ (data as u64, required_align)
}
};
// Check alignment
} => {
let variants_start = niche_variants.start().as_u32() as u128;
let variants_end = niche_variants.end().as_u32() as u128;
- match raw_discr {
- ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => {
+ let raw_discr = raw_discr.not_undef()
+ .map_err(|_| InterpError::InvalidDiscriminant(ScalarMaybeUndef::Undef))?;
+ match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
+ Err(ptr) => {
// The niche must be just 0 (which an inbounds pointer value never is)
let ptr_valid = niche_start == 0 && variants_start == variants_end &&
self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead,
CheckInAllocMsg::NullPointerTest).is_ok();
if !ptr_valid {
- return err!(InvalidDiscriminant(raw_discr.erase_tag()));
+ return err!(InvalidDiscriminant(raw_discr.erase_tag().into()));
}
(dataful_variant.as_u32() as u128, dataful_variant)
},
- ScalarMaybeUndef::Scalar(Scalar::Bits { bits: raw_discr, size }) => {
- assert_eq!(size as u64, discr_val.layout.size.bytes());
+ Ok(raw_discr) => {
let adjusted_discr = raw_discr.wrapping_sub(niche_start)
.wrapping_add(variants_start);
if variants_start <= adjusted_discr && adjusted_discr <= variants_end {
(dataful_variant.as_u32() as u128, dataful_variant)
}
},
- ScalarMaybeUndef::Undef =>
- return err!(InvalidDiscriminant(ScalarMaybeUndef::Undef)),
}
}
})
Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Ptr(_))) =>
assert_eq!(self.pointer_size(), dest.layout.size,
"Size mismatch when writing pointer"),
- Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits { size, .. })) =>
+ Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Raw { size, .. })) =>
assert_eq!(Size::from_bytes(size.into()), dest.layout.size,
"Size mismatch when writing bits"),
Immediate::Scalar(ScalarMaybeUndef::Undef) => {}, // undef can have any size
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
match self {
Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)),
- Scalar::Bits{ size, bits } => Scalar::Bits {
+ Scalar::Raw{ size, data } => Scalar::Raw {
+ data: *data,
size: *size,
- bits: *bits,
},
}
}
wrapping_range_format(&layout.valid_range, max_hi),
)
);
- let bits = match value {
- Scalar::Ptr(ptr) => {
+ let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) {
+ Err(ptr) => {
if lo == 1 && hi == max_hi {
// only NULL is not allowed.
// We can call `check_align` to check non-NULL-ness, but have to also look
);
}
}
- Scalar::Bits { bits, size } => {
- assert_eq!(size as u64, op.layout.size.bytes());
- bits
- }
+ Ok(data) =>
+ data
};
// Now compare. This is slightly subtle because this is a special "wrap-around" range.
if wrapping_range_contains(&layout.valid_range, bits) {
use rustc::hir::intravisit::FnKind;
use rustc::hir::map::blocks::FnLikeNode;
use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
-use rustc::mir::{self, Mir, TerminatorKind};
+use rustc::mir::{self, Body, TerminatorKind};
use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
use rustc::ty::subst::InternalSubsts;
pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
def_id: DefId) {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn_kind: FnKind<'_>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
def_id: DefId) {
if let FnKind::Closure(_) = fn_kind {
// closures can't recur, so they don't matter.
struct MirNeighborCollector<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a mir::Mir<'tcx>,
+ mir: &'a mir::Body<'tcx>,
output: &'a mut Vec<MonoItem<'tcx>>,
param_substs: SubstsRef<'tcx>,
}
mir: &mir,
output,
param_substs: instance.substs,
- }.visit_mir(&mir);
+ }.visit_body(&mir);
let param_env = ty::ParamEnv::reveal_all();
for i in 0..mir.promoted.len() {
use rustc_data_structures::indexed_vec::Idx;
fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: ty::InstanceDef<'tcx>)
- -> &'tcx Mir<'tcx>
+ -> &'tcx Body<'tcx>
{
debug!("make_shim({:?})", instance);
fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
ty: Option<Ty<'tcx>>)
- -> Mir<'tcx>
+ -> Body<'tcx>
{
debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
block(&mut blocks, TerminatorKind::Goto { target: return_block });
block(&mut blocks, TerminatorKind::Return);
- let mut mir = Mir::new(
+ let mut mir = Body::new(
blocks,
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
}
pub struct DropShimElaborator<'a, 'tcx: 'a> {
- pub mir: &'a Mir<'tcx>,
+ pub mir: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
type Path = ();
fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
- fn mir(&self) -> &'a Mir<'tcx> { self.mir }
+ fn mir(&self) -> &'a Body<'tcx> { self.mir }
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
self_ty: Ty<'tcx>)
- -> Mir<'tcx>
+ -> Body<'tcx>
{
debug!("build_clone_shim(def_id={:?})", def_id);
}
}
- fn into_mir(self) -> Mir<'tcx> {
- Mir::new(
+ fn into_mir(self) -> Body<'tcx> {
+ Body::new(
self.blocks,
IndexVec::from_elem_n(
SourceScopeData { span: self.span, parent_scope: None }, 1
rcvr_adjustment: Adjustment,
call_kind: CallKind,
untuple_args: Option<&[Ty<'tcx>]>)
- -> Mir<'tcx>
+ -> Body<'tcx>
{
debug!("build_call_shim(def_id={:?}, rcvr_adjustment={:?}, \
call_kind={:?}, untuple_args={:?})",
block(&mut blocks, vec![], TerminatorKind::Resume, true);
}
- let mut mir = Mir::new(
+ let mut mir = Body::new(
blocks,
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
ctor_id: hir::HirId,
fields: &[hir::StructField],
span: Span)
- -> Mir<'tcx>
+ -> Body<'tcx>
{
let tcx = infcx.tcx;
let gcx = tcx.global_tcx();
is_cleanup: false
};
- Mir::new(
+ Body::new(
IndexVec::from_elem_n(start_block, 1),
IndexVec::from_elem_n(
SourceScopeData { span: span, parent_scope: None }, 1
fn run_pass<'a, 'tcx>(&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
self.add_call_guards(mir);
}
}
impl AddCallGuards {
- pub fn add_call_guards(&self, mir: &mut Mir<'_>) {
+ pub fn add_call_guards(&self, mir: &mut Body<'_>) {
let pred_count: IndexVec<_, _> =
mir.predecessors().iter().map(|ps| ps.len()).collect();
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>)
+ mir: &mut Body<'tcx>)
{
debug!("add_moves_for_packed_drops({:?} @ {:?})", src, mir.span);
add_moves_for_packed_drops(tcx, mir, src.def_id());
pub fn add_moves_for_packed_drops<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
def_id: DefId)
{
let patch = add_moves_for_packed_drops_patch(tcx, mir, def_id);
fn add_moves_for_packed_drops_patch<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
def_id: DefId)
-> MirPatch<'tcx>
{
fn add_move_for_packed_drop<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
patch: &mut MirPatch<'tcx>,
terminator: &Terminator<'tcx>,
loc: Location,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>)
+ mir: &mut Body<'tcx>)
{
if !tcx.sess.opts.debugging_opts.mir_emit_retag {
return;
use crate::util;
pub struct UnsafetyChecker<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
const_context: bool,
min_const_fn: bool,
source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
fn new(
const_context: bool,
min_const_fn: bool,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
let mut checker = UnsafetyChecker::new(
const_context, min_const_fn,
mir, source_scope_local_data, tcx, param_env);
- checker.visit_mir(mir);
+ checker.visit_body(mir);
check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);
UnsafetyCheckResult {
//! [`FakeRead`]: rustc::mir::StatementKind::FakeRead
//! [`Nop`]: rustc::mir::StatementKind::Nop
-use rustc::mir::{BorrowKind, Rvalue, Location, Mir};
+use rustc::mir::{BorrowKind, Rvalue, Location, Body};
use rustc::mir::{Statement, StatementKind};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
fn run_pass<'a, 'tcx>(&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let mut delete = DeleteNonCodegenStatements;
- delete.visit_mir(mir);
+ delete.visit_body(mir);
}
}
use rustc::hir::def::DefKind;
use rustc::mir::{
- AggregateKind, Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
+ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local,
NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
// will be evaluated by miri and produce its errors there
if source.promoted.is_some() {
return;
// That would require an uniform one-def no-mutation analysis
// and RPO (or recursing when needing the value of a local).
let mut optimization_finder = ConstPropagator::new(mir, tcx, source);
- optimization_finder.visit_mir(mir);
+ optimization_finder.visit_body(mir);
// put back the data we stole from `mir`
std::mem::replace(
param_env: ParamEnv<'tcx>,
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
- promoted: IndexVec<Promoted, Mir<'tcx>>,
+ promoted: IndexVec<Promoted, Body<'tcx>>,
}
impl<'a, 'b, 'tcx> LayoutOf for ConstPropagator<'a, 'b, 'tcx> {
impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
fn new(
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,
) -> ConstPropagator<'a, 'mir, 'tcx> {
can_const_prop,
places: IndexVec::from_elem(None, &mir.local_decls),
source_scope_local_data,
- //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_mir()` needs it
+ //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
local_decls: mir.local_decls.clone(),
promoted,
}
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
ImmTy {
imm: Immediate::Scalar(
- Scalar::Bits {
- bits: n as u128,
- size: self.tcx.data_layout.pointer_size.bytes() as u8,
- }.into()
+ Scalar::from_uint(n, self.tcx.data_layout.pointer_size).into()
),
layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
}.into()
impl CanConstProp {
/// returns true if `local` can be propagated
- fn check(mir: &Mir<'_>) -> IndexVec<Local, bool> {
+ fn check(mir: &Body<'_>) -> IndexVec<Local, bool> {
let mut cpv = CanConstProp {
can_const_prop: IndexVec::from_elem(true, &mir.local_decls),
found_assignment: IndexVec::from_elem(false, &mir.local_decls),
trace!("local {:?} can't be propagated because it's not a temporary", local);
}
}
- cpv.visit_mir(mir);
+ cpv.visit_body(mir);
cpv.can_const_prop
}
}
.eval_operand(len, source_info)
.expect("len must be const");
let len = match self.ecx.read_scalar(len) {
- Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
- bits, ..
- })) => bits,
+ Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
+ data, ..
+ })) => data,
other => bug!("const len not primitive: {:?}", other),
};
let index = self
.eval_operand(index, source_info)
.expect("index must be const");
let index = match self.ecx.read_scalar(index) {
- Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
- bits, ..
- })) => bits,
+ Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
+ data, ..
+ })) => data,
other => bug!("const index not primitive: {:?}", other),
};
format!(
//! future.
use rustc::mir::{
- Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
+ Constant, Local, LocalKind, Location, Place, PlaceBase, Body, Operand, Rvalue, StatementKind
};
use rustc::mir::visit::MutVisitor;
use rustc::ty::TyCtxt;
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
// We only run when the MIR optimization level is > 1.
// This avoids a slow pass, and messing up debug info.
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
}
fn eliminate_self_assignments(
- mir: &mut Mir<'_>,
+ mir: &mut Body<'_>,
def_use_analysis: &DefUseAnalysis,
) -> bool {
let mut changed = false;
}
impl<'tcx> Action<'tcx> {
- fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
+ fn local_copy(mir: &Body<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
-> Option<Action<'tcx>> {
// The source must be a local.
let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
}
fn perform(self,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
def_use_analysis: &DefUseAnalysis,
dest_local: Local,
location: Location)
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut();
let local_decls = &*local_decls;
for bb in basic_blocks {
use std::fs::File;
use std::io;
-use rustc::mir::Mir;
+use rustc::mir::Body;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::ty::TyCtxt;
use crate::transform::{MirPass, MirSource};
fn run_pass<'a, 'tcx>(&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource<'tcx>,
- _mir: &mut Mir<'tcx>)
+ _mir: &mut Body<'tcx>)
{
}
}
pass_num: &dyn fmt::Display,
pass_name: &str,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
is_after: bool) {
if mir_util::dump_enabled(tcx, pass_name, source) {
mir_util::dump_mir(tcx,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>)
+ mir: &mut Body<'tcx>)
{
debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
/// that can't drop anything.
fn find_dead_unwinds<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
def_id: hir::def_id::DefId,
env: &MoveDataParamEnv<'tcx, 'tcx>)
-> BitSet<BasicBlock>
impl InitializationData {
fn apply_location<'a,'tcx>(&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
env: &MoveDataParamEnv<'tcx, 'tcx>,
loc: Location)
{
&mut self.ctxt.patch
}
- fn mir(&self) -> &'a Mir<'tcx> {
+ fn mir(&self) -> &'a Body<'tcx> {
self.ctxt.mir
}
struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
env: &'a MoveDataParamEnv<'tcx, 'tcx>,
flow_inits: DataflowResults<'tcx, MaybeInitializedPlaces<'a, 'tcx, 'tcx>>,
flow_uninits: DataflowResults<'tcx, MaybeUninitializedPlaces<'a, 'tcx, 'tcx>>,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
- EraseRegionsVisitor::new(tcx).visit_mir(mir);
+ mir: &mut Body<'tcx>) {
+ EraseRegionsVisitor::new(tcx).visit_body(mir);
}
}
}
// Create a statement which reads the discriminant into a temporary
- fn get_discr(&self, mir: &mut Mir<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
+ fn get_discr(&self, mir: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) {
let temp_decl = LocalDecl::new_internal(self.tcx.types.isize, mir.span);
let local_decls_len = mir.local_decls.push(temp_decl);
let temp = Place::Base(PlaceBase::Local(local_decls_len));
fn make_generator_state_argument_indirect<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let gen_ty = mir.local_decls.raw[1].ty;
let region = ty::ReFree(ty::FreeRegion {
mir.local_decls.raw[1].ty = ref_gen_ty;
// Add a deref to accesses of the generator state
- DerefArgVisitor.visit_mir(mir);
+ DerefArgVisitor.visit_body(mir);
}
fn make_generator_state_argument_pinned<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let ref_gen_ty = mir.local_decls.raw[1].ty;
let pin_did = tcx.lang_items().pin_type().unwrap();
mir.local_decls.raw[1].ty = pin_ref_gen_ty;
// Add the Pin field access to accesses of the generator state
- PinArgVisitor { ref_gen_ty }.visit_mir(mir);
+ PinArgVisitor { ref_gen_ty }.visit_body(mir);
}
fn replace_result_variable<'tcx>(
ret_ty: Ty<'tcx>,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
) -> Local {
let source_info = source_info(mir);
let new_ret = LocalDecl {
RenameLocalVisitor {
from: RETURN_PLACE,
to: new_ret_local,
- }.visit_mir(mir);
+ }.visit_body(mir);
new_ret_local
}
fn locals_live_across_suspend_points(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
source: MirSource<'tcx>,
movable: bool,
) -> (
// Find the MIR locals which do not use StorageLive/StorageDead statements.
// The storage of these locals are always live.
let mut ignored = StorageIgnored(BitSet::new_filled(mir.local_decls.len()));
- ignored.visit_mir(mir);
+ ignored.visit_body(mir);
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
upvars: &Vec<Ty<'tcx>>,
interior: Ty<'tcx>,
movable: bool,
- mir: &mut Mir<'tcx>)
+ mir: &mut Body<'tcx>)
-> (FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
GeneratorLayout<'tcx>,
FxHashMap<BasicBlock, liveness::LiveVarSet>)
(remap, layout, storage_liveness)
}
-fn insert_switch<'a, 'tcx>(mir: &mut Mir<'tcx>,
+fn insert_switch<'a, 'tcx>(mir: &mut Body<'tcx>,
cases: Vec<(usize, BasicBlock)>,
transform: &TransformVisitor<'a, 'tcx>,
default: TerminatorKind<'tcx>) {
fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
use crate::util::elaborate_drops::{elaborate_drop, Unwind};
use crate::util::patch::MirPatch;
use crate::shim::DropShimElaborator;
def_id: DefId,
source: MirSource<'tcx>,
gen_ty: Ty<'tcx>,
- mir: &Mir<'tcx>,
- drop_clean: BasicBlock) -> Mir<'tcx> {
+ mir: &Body<'tcx>,
+ drop_clean: BasicBlock) -> Body<'tcx> {
let mut mir = mir.clone();
let source_info = source_info(&mir);
mir
}
-fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
+fn insert_term_block<'tcx>(mir: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
let term_block = BasicBlock::new(mir.basic_blocks().len());
let source_info = source_info(mir);
mir.basic_blocks_mut().push(BasicBlockData {
}
fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
message: AssertMessage<'tcx>) -> BasicBlock {
let assert_block = BasicBlock::new(mir.basic_blocks().len());
let term = TerminatorKind::Assert {
transform: TransformVisitor<'a, 'tcx>,
def_id: DefId,
source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
// Poison the generator when it unwinds
for block in mir.basic_blocks_mut() {
let source_info = block.terminator().source_info;
dump_mir(tcx, None, "generator_resume", &0, source, mir, |_, _| Ok(()) );
}
-fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
+fn source_info<'a, 'tcx>(mir: &Body<'tcx>) -> SourceInfo {
SourceInfo {
span: mir.span,
scope: OUTERMOST_SOURCE_SCOPE,
}
}
-fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
+fn insert_clean_drop<'a, 'tcx>(mir: &mut Body<'tcx>) -> BasicBlock {
let return_block = insert_term_block(mir, TerminatorKind::Return);
// Create a block to destroy an unresumed generators. This can only destroy upvars.
drop_clean
}
-fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
+fn create_cases<'a, 'tcx, F>(mir: &mut Body<'tcx>,
transform: &TransformVisitor<'a, 'tcx>,
target: F) -> Vec<(usize, BasicBlock)>
where F: Fn(&SuspensionPoint) -> Option<BasicBlock> {
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let yield_ty = if let Some(yield_ty) = mir.yield_ty {
yield_ty
} else {
new_ret_local,
discr_ty,
};
- transform.visit_mir(mir);
+ transform.visit_body(mir);
// Update our MIR struct to reflect the changed we've made
mir.yield_ty = None;
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
Inliner { tcx, source }.run_pass(mir);
}
}
impl<'a, 'tcx> Inliner<'a, 'tcx> {
- fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
+ fn run_pass(&self, caller_mir: &mut Body<'tcx>) {
// Keep a queue of callsites to try inlining on. We take
// advantage of the fact that queries detect cycles here to
// allow us to try and fetch the fully optimized MIR of a
fn get_valid_function_call(&self,
bb: BasicBlock,
bb_data: &BasicBlockData<'tcx>,
- caller_mir: &Mir<'tcx>,
+ caller_mir: &Body<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<CallSite<'tcx>> {
// Don't inline calls that are in cleanup blocks.
fn consider_optimizing(&self,
callsite: CallSite<'tcx>,
- callee_mir: &Mir<'tcx>)
+ callee_mir: &Body<'tcx>)
-> bool
{
debug!("consider_optimizing({:?})", callsite);
fn should_inline(&self,
callsite: CallSite<'tcx>,
- callee_mir: &Mir<'tcx>)
+ callee_mir: &Body<'tcx>)
-> bool
{
debug!("should_inline({:?})", callsite);
fn inline_call(&self,
callsite: CallSite<'tcx>,
- caller_mir: &mut Mir<'tcx>,
- mut callee_mir: Mir<'tcx>) -> bool {
+ caller_mir: &mut Body<'tcx>,
+ mut callee_mir: Body<'tcx>) -> bool {
let terminator = caller_mir[callsite.bb].terminator.take().unwrap();
match terminator.kind {
// FIXME: Handle inlining of diverging calls
&self,
args: Vec<Operand<'tcx>>,
callsite: &CallSite<'tcx>,
- caller_mir: &mut Mir<'tcx>,
+ caller_mir: &mut Body<'tcx>,
) -> Vec<Local> {
let tcx = self.tcx;
&self,
arg: Operand<'tcx>,
callsite: &CallSite<'tcx>,
- caller_mir: &mut Mir<'tcx>,
+ caller_mir: &mut Body<'tcx>,
) -> Local {
// FIXME: Analysis of the usage of the arguments to avoid
// unnecessary temporaries.
//! Performs various peephole optimizations.
-use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Body, Operand, ProjectionElem, Rvalue,
+ Local};
use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
// We only run when optimizing MIR (at any level).
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
return
// `Place::ty()`).
let optimizations = {
let mut optimization_finder = OptimizationFinder::new(mir, tcx);
- optimization_finder.visit_mir(mir);
+ optimization_finder.visit_body(mir);
optimization_finder.optimizations
};
// Then carry out those optimizations.
- MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir);
+ MutVisitor::visit_body(&mut InstCombineVisitor { optimizations }, mir);
}
}
/// Finds optimization opportunities on the MIR.
struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
- mir: &'b Mir<'tcx>,
+ mir: &'b Body<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
optimizations: OptimizationList<'tcx>,
}
impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
- fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
+ fn new(mir: &'b Body<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
OptimizationFinder {
mir,
tcx,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let debugging_override = tcx.sess.opts.debugging_opts.lower_128bit_ops;
let target_default = tcx.sess.host.options.i128_lowering;
if !debugging_override.unwrap_or(target_default) {
}
impl Lower128Bit {
- fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Body<'tcx>) {
let mut new_blocks = Vec::new();
let cur_len = mir.basic_blocks().len();
use crate::build;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::mir::{Mir, MirPhase, Promoted};
+use rustc::mir::{Body, MirPhase, Promoted};
use rustc::ty::{TyCtxt, InstanceDef};
use rustc::ty::query::Providers;
use rustc::ty::steal::Steal;
tcx.arena.alloc(set)
}
-fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
let mir = build::mir_build(tcx, def_id);
tcx.alloc_steal_mir(mir)
}
-/// Where a specific Mir comes from.
+/// Where a specific `mir::Body` comes from.
#[derive(Debug, Copy, Clone)]
pub struct MirSource<'tcx> {
pub instance: InstanceDef<'tcx>,
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
source: MirSource<'tcx>,
- mir: &mut Mir<'tcx>);
+ mir: &mut Body<'tcx>);
}
pub fn run_passes(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &mut Mir<'tcx>,
+ mir: &mut Body<'tcx>,
instance: InstanceDef<'tcx>,
mir_phase: MirPhase,
passes: &[&dyn MirPass],
) {
let phase_index = mir_phase.phase_index();
- let run_passes = |mir: &mut Mir<'tcx>, promoted| {
+ let run_passes = |mir: &mut Body<'tcx>, promoted| {
if mir.phase >= mir_phase {
return;
}
}
}
-fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
// Unsafety check uses the raw mir, so make sure it is run
let _ = tcx.unsafety_check_result(def_id);
tcx.alloc_steal_mir(mir)
}
-fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
+fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind_by_hir_id(hir_id) {
// Ensure that we compute the `mir_const_qualif` for constants at
tcx.alloc_steal_mir(mir)
}
-fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
- // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
+fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
+ // `mir_borrowck` uses `mir_validated`, so we have to force it to
// execute before we can steal.
tcx.ensure().mir_borrowck(def_id);
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
no_landing_pads(tcx, mir)
}
}
-pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) {
+pub fn no_landing_pads<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Body<'tcx>) {
if tcx.sess.no_landing_pads() {
- NoLandingPads.visit_mir(mir);
+ NoLandingPads.visit_body(mir);
}
}
struct TempCollector<'tcx> {
temps: IndexVec<Local, TempState>,
span: Span,
- mir: &'tcx Mir<'tcx>,
+ mir: &'tcx Body<'tcx>,
}
impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
}
}
-pub fn collect_temps(mir: &Mir<'_>,
+pub fn collect_temps(mir: &Body<'_>,
rpo: &mut ReversePostorder<'_, '_>) -> IndexVec<Local, TempState> {
let mut collector = TempCollector {
temps: IndexVec::from_elem(TempState::Undefined, &mir.local_decls),
struct Promoter<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- source: &'a mut Mir<'tcx>,
- promoted: Mir<'tcx>,
+ source: &'a mut Body<'tcx>,
+ promoted: Body<'tcx>,
temps: &'a mut IndexVec<Local, TempState>,
/// If true, all nested temps are also kept in the
}
}
-pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
+pub fn promote_candidates<'a, 'tcx>(mir: &mut Body<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mut temps: IndexVec<Local, TempState>,
candidates: Vec<Candidate>) {
}
- // Declare return place local so that `Mir::new` doesn't complain.
+ // Declare return place local so that `mir::Body::new` doesn't complain.
let initial_locals = iter::once(
LocalDecl::new_return_place(tcx.types.never, mir.span)
).collect();
let promoter = Promoter {
- promoted: Mir::new(
+ promoted: Body::new(
IndexVec::new(),
// FIXME: maybe try to filter this to avoid blowing up
// memory usage?
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
mode: Mode,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
per_local: PerQualif<BitSet<Local>>,
}
impl<'a, 'tcx> Checker<'a, 'tcx> {
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
mode: Mode)
-> Self {
assert!(def_id.is_local());
let mir = &tcx.mir_const(def_id).borrow();
if mir.return_ty().references_error() {
- tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: Mir had errors");
+ tcx.sess.delay_span_bug(mir.span, "mir_const_qualif: MIR had errors");
return (1 << IsNotPromotable::IDX, tcx.arena.alloc(BitSet::new_empty(0)));
}
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
// There's not really any point in promoting errorful MIR.
if mir.return_ty().references_error() {
- tcx.sess.delay_span_bug(mir.span, "QualifyAndPromoteConstants: Mir had errors");
+ tcx.sess.delay_span_bug(mir.span, "QualifyAndPromoteConstants: MIR had errors");
return;
}
pub fn is_min_const_fn(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
) -> McfResult {
let mut current = def_id;
loop {
fn check_rvalue(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
rvalue: &Rvalue<'tcx>,
span: Span,
) -> McfResult {
fn check_statement(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
statement: &Statement<'tcx>,
) -> McfResult {
let span = statement.source_info.span;
}
}
-fn check_place(place: &Place<'tcx>, span: Span) -> McfResult {
+fn check_place(
+ place: &Place<'tcx>,
+ span: Span,
+) -> McfResult {
place.iterate(|place_base, place_projection| {
for proj in place_projection {
match proj.elem {
fn check_terminator(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
terminator: &Terminator<'tcx>,
) -> McfResult {
let span = terminator.source_info.span;
pub fn remove_noop_landing_pads<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &mut Mir<'tcx>)
+ mir: &mut Body<'tcx>)
{
if tcx.sess.no_landing_pads() {
return
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
remove_noop_landing_pads(tcx, mir);
}
}
fn is_nop_landing_pad(
&self,
bb: BasicBlock,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
nop_landing_pads: &BitSet<BasicBlock>,
) -> bool {
for stmt in &mir[bb].statements {
}
}
- fn remove_nop_landing_pads(&self, mir: &mut Mir<'_>) {
+ fn remove_nop_landing_pads(&self, mir: &mut Body<'_>) {
// make sure there's a single resume block
let resume_block = {
let patch = MirPatch::new(mir);
use rustc::ty::{self, TyCtxt};
use rustc::hir::def_id::DefId;
-use rustc::mir::{self, Mir, Location};
+use rustc::mir::{self, Body, Location};
use rustc_data_structures::bit_set::BitSet;
use crate::transform::{MirPass, MirSource};
impl MirPass for SanityCheck {
fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
+ src: MirSource<'tcx>, mir: &mut Body<'tcx>) {
let def_id = src.def_id();
if !tcx.has_attr(def_id, sym::rustc_mir) {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
/// expression form above, then that emits an error as well, but those
/// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
def_id: DefId,
_attributes: &[ast::Attribute],
results: &DataflowResults<'tcx, O>)
}
fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
results: &DataflowResults<'tcx, O>,
bb: mir::BasicBlock) where
O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
}
}
-pub fn simplify_cfg(mir: &mut Mir<'_>) {
+pub fn simplify_cfg(mir: &mut Body<'_>) {
CfgSimplifier::new(mir).simplify();
remove_dead_blocks(mir);
fn run_pass<'a, 'tcx>(&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, mir);
simplify_cfg(mir);
}
}
impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
- pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
+ pub fn new(mir: &'a mut Body<'tcx>) -> Self {
let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());
// we can't use mir.predecessors() here because that counts
}
}
-pub fn remove_dead_blocks(mir: &mut Mir<'_>) {
+pub fn remove_dead_blocks(mir: &mut Body<'_>) {
let mut seen = BitSet::new_empty(mir.basic_blocks().len());
for (bb, _) in traversal::preorder(mir) {
seen.insert(bb.index());
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let mut marker = DeclMarker { locals: BitSet::new_empty(mir.local_decls.len()) };
- marker.visit_mir(mir);
+ marker.visit_body(mir);
// Return pointer and arguments are always live
marker.locals.insert(RETURN_PLACE);
for arg in mir.args_iter() {
let map = make_local_map(&mut mir.local_decls, marker.locals);
// Update references to all vars and tmps now
- LocalUpdater { map }.visit_mir(mir);
+ LocalUpdater { map }.visit_body(mir);
mir.local_decls.shrink_to_fit();
}
}
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
for block in mir.basic_blocks_mut() {
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let mut patch = MirPatch::new(mir);
{
let mut visitor = UniformArrayMoveOutVisitor{mir, patch: &mut patch, tcx};
- visitor.visit_mir(mir);
+ visitor.visit_body(mir);
}
patch.apply(mir);
}
}
struct UniformArrayMoveOutVisitor<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
+ mir: &'a Body<'tcx>,
patch: &'a mut MirPatch<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_src: MirSource<'tcx>,
- mir: &mut Mir<'tcx>) {
+ mir: &mut Body<'tcx>) {
let mut patch = MirPatch::new(mir);
{
let mut visitor = RestoreDataCollector {
locals_use: IndexVec::from_elem(LocalUse::new(), &mir.local_decls),
candidates: vec![],
};
- visitor.visit_mir(mir);
+ visitor.visit_body(mir);
for candidate in &visitor.candidates {
let statement = &mir[candidate.block].statements[candidate.statement_index];
}
fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
- mir: &'a Mir<'tcx>) -> Option<(u32, &'a Place<'tcx>)> {
+ mir: &'a Body<'tcx>) -> Option<(u32, &'a Place<'tcx>)> {
if let Some(location) = local_use.first_use {
let block = &mir[location.block];
if block.statements.len() > location.statement_index {
use rustc::mir::{Local, Location};
-use rustc::mir::Mir;
+use rustc::mir::Body;
use rustc::mir::visit::PlaceContext;
use rustc::mir::visit::Visitor;
fn find_assignments(&self, local: Local) -> Vec<Location>;
}
-impl<'tcx> FindAssignments for Mir<'tcx>{
+impl<'tcx> FindAssignments for Body<'tcx>{
fn find_assignments(&self, local: Local) -> Vec<Location>{
let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
- visitor.visit_mir(self);
+ visitor.visit_body(self);
visitor.locations
}
}
//! Def-use analysis.
-use rustc::mir::{Local, Location, Mir};
+use rustc::mir::{Local, Location, Body};
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc_data_structures::indexed_vec::IndexVec;
use std::mem;
}
impl DefUseAnalysis {
- pub fn new(mir: &Mir<'_>) -> DefUseAnalysis {
+ pub fn new(mir: &Body<'_>) -> DefUseAnalysis {
DefUseAnalysis {
info: IndexVec::from_elem_n(Info::new(), mir.local_decls.len()),
}
}
- pub fn analyze(&mut self, mir: &Mir<'_>) {
+ pub fn analyze(&mut self, mir: &Body<'_>) {
self.clear();
let mut finder = DefUseFinder {
info: mem::replace(&mut self.info, IndexVec::new()),
};
- finder.visit_mir(mir);
+ finder.visit_body(mir);
self.info = finder.info
}
&self.info[local]
}
- fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'_>, mut callback: F)
+ fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Body<'_>, mut callback: F)
where F: for<'a> FnMut(&'a mut Local,
PlaceContext,
Location) {
// FIXME(pcwalton): this should update the def-use chains.
pub fn replace_all_defs_and_uses_with(&self,
local: Local,
- mir: &mut Mir<'_>,
+ mir: &mut Body<'_>,
new_local: Local) {
self.mutate_defs_and_uses(local, mir, |local, _, _| *local = new_local)
}
}
impl<F> MutateUseVisitor<F> {
- fn new(query: Local, callback: F, _: &Mir<'_>)
+ fn new(query: Local, callback: F, _: &Body<'_>)
-> MutateUseVisitor<F>
where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) {
MutateUseVisitor {
type Path : Copy + fmt::Debug;
fn patch(&mut self) -> &mut MirPatch<'tcx>;
- fn mir(&self) -> &'a Mir<'tcx>;
+ fn mir(&self) -> &'a Body<'tcx>;
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
fn param_env(&self) -> ty::ParamEnv<'tcx>;
/// Write a graphviz DOT graph of the MIR.
pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
def_id: DefId,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
w: &mut W) -> io::Result<()>
where W: Write
{
/// `init` and `fini` are callbacks for emitting additional rows of
/// data (using HTML enclosed with `<tr>` in the emitted text).
pub fn write_node_label<W: Write, INIT, FINI>(block: BasicBlock,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
w: &mut W,
num_cols: u32,
init: INIT,
}
/// Write a graphviz DOT node for the given basic block.
-fn write_node<W: Write>(block: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
+fn write_node<W: Write>(block: BasicBlock, mir: &Body<'_>, w: &mut W) -> io::Result<()> {
// Start a new node with the label to follow, in one of DOT's pseudo-HTML tables.
write!(w, r#" {} [shape="none", label=<"#, node(block))?;
write_node_label(block, mir, w, 1, |_| Ok(()), |_| Ok(()))?;
}
/// Write graphviz DOT edges with labels between the given basic block and all of its successors.
-fn write_edges<W: Write>(source: BasicBlock, mir: &Mir<'_>, w: &mut W) -> io::Result<()> {
+fn write_edges<W: Write>(source: BasicBlock, mir: &Body<'_>, w: &mut W) -> io::Result<()> {
let terminator = mir[source].terminator();
let labels = terminator.kind.fmt_successor_labels();
/// all the variables and temporaries.
fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
w: &mut W)
-> io::Result<()> {
write!(w, " label=<fn {}(", dot::escape_html(&tcx.def_path_str(def_id)))?;
/// Computes which local variables are live within the given function
/// `mir`, including drops.
pub fn liveness_of_locals<'tcx>(
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
) -> LivenessResult {
let num_live_vars = mir.local_decls.len();
tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_name: &str,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
result: &LivenessResult,
) {
if !dump_enabled(tcx, pass_name, source) {
pass_name: &str,
node_path: &str,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
result: &LivenessResult,
) {
let mut file_path = PathBuf::new();
pub fn write_mir_fn<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
w: &mut dyn Write,
result: &LivenessResult,
) -> io::Result<()> {
}
impl<'tcx> MirPatch<'tcx> {
- pub fn new(mir: &Mir<'tcx>) -> Self {
+ pub fn new(mir: &Body<'tcx>) -> Self {
let mut result = MirPatch {
patch_map: IndexVec::from_elem(None, mir.basic_blocks()),
new_blocks: vec![],
self.patch_map[bb].is_some()
}
- pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
+ pub fn terminator_loc(&self, mir: &Body<'tcx>, bb: BasicBlock) -> Location {
let offset = match bb.index().checked_sub(mir.basic_blocks().len()) {
Some(index) => self.new_blocks[index].statements.len(),
None => mir[bb].statements.len()
self.make_nop.push(loc);
}
- pub fn apply(self, mir: &mut Mir<'tcx>) {
+ pub fn apply(self, mir: &mut Body<'tcx>) {
debug!("MirPatch: make nops at: {:?}", self.make_nop);
for loc in self.make_nop {
mir.make_statement_nop(loc);
}
}
- pub fn source_info_for_location(&self, mir: &Mir<'_>, loc: Location) -> SourceInfo {
+ pub fn source_info_for_location(&self, mir: &Body<'_>, loc: Location) -> SourceInfo {
let data = match loc.block.index().checked_sub(mir.basic_blocks().len()) {
Some(new) => &self.new_blocks[new],
None => &mir[loc.block]
pass_name: &str,
disambiguator: &dyn Display,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
extra_data: F,
) where
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
node_path: &str,
disambiguator: &dyn Display,
source: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
mut extra_data: F,
) where
F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
pub fn write_mir_fn<'a, 'gcx, 'tcx, F>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
extra_data: &mut F,
w: &mut dyn Write,
) -> io::Result<()>
pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
block: BasicBlock,
- mir: &Mir<'tcx>,
+ mir: &Body<'tcx>,
extra_data: &mut F,
w: &mut dyn Write,
) -> io::Result<()>
/// Prints local variables in a scope tree.
fn write_scope_tree(
tcx: TyCtxt<'_, '_, '_>,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
scope_tree: &FxHashMap<SourceScope, Vec<SourceScope>>,
w: &mut dyn Write,
parent: SourceScope,
pub fn write_mir_intro<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
src: MirSource<'tcx>,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
w: &mut dyn Write,
) -> io::Result<()> {
write_mir_sig(tcx, src, mir, w)?;
fn write_mir_sig(
tcx: TyCtxt<'_, '_, '_>,
src: MirSource<'tcx>,
- mir: &Mir<'_>,
+ mir: &Body<'_>,
w: &mut dyn Write,
) -> io::Result<()> {
use rustc::hir::def::DefKind;
Ok(())
}
-fn write_user_type_annotations(mir: &Mir<'_>, w: &mut dyn Write) -> io::Result<()> {
+fn write_user_type_annotations(mir: &Body<'_>, w: &mut dyn Write) -> io::Result<()> {
if !mir.user_type_annotations.is_empty() {
writeln!(w, "| User Type Annotations")?;
}
}
}
- fn check_trait_or_impl_item(&self, hir_id: hir::HirId, assoc_item_kind: AssocItemKind,
- defaultness: hir::Defaultness, vis: ty::Visibility) {
+ fn check_assoc_item(
+ &self,
+ hir_id: hir::HirId,
+ assoc_item_kind: AssocItemKind,
+ defaultness: hir::Defaultness,
+ vis: ty::Visibility,
+ ) {
let mut check = self.check(hir_id, vis);
let (check_ty, is_assoc_ty) = match assoc_item_kind {
self.check(item.hir_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
- self.check_trait_or_impl_item(trait_item_ref.id.hir_id, trait_item_ref.kind,
- trait_item_ref.defaultness, item_visibility);
+ self.check_assoc_item(
+ trait_item_ref.id.hir_id,
+ trait_item_ref.kind,
+ trait_item_ref.defaultness,
+ item_visibility,
+ );
}
}
hir::ItemKind::TraitAlias(..) => {
} else {
impl_vis
};
- self.check_trait_or_impl_item(impl_item_ref.id.hir_id, impl_item_ref.kind,
- impl_item_ref.defaultness, impl_item_vis);
+ self.check_assoc_item(
+ impl_item_ref.id.hir_id,
+ impl_item_ref.kind,
+ impl_item_ref.defaultness,
+ impl_item_vis,
+ );
}
}
}
FnKind::ItemFn(_, ref header, ..) =>
(FnItemRibKind, &header.asyncness.node),
FnKind::Method(_, ref sig, _, _) =>
- (TraitOrImplItemRibKind, &sig.header.asyncness.node),
+ (AssocItemRibKind, &sig.header.asyncness.node),
FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
/// methods or associated types. Allow references to ty params that impl or trait
/// binds. Disallow any other upvars (including other ty params that are
/// upvars).
- TraitOrImplItemRibKind,
+ AssocItemRibKind,
/// We passed through a function definition. Disallow upvars.
/// Permit only those const parameters that are specified in the function's generics.
for trait_item in trait_items {
let generic_params = HasGenericParams(&trait_item.generics,
- TraitOrImplItemRibKind);
+ AssocItemRibKind);
this.with_generic_param_rib(generic_params, |this| {
match trait_item.node {
TraitItemKind::Const(ref ty, ref default) => {
// We also need a new scope for the impl item type parameters.
let generic_params = HasGenericParams(&impl_item.generics,
- TraitOrImplItemRibKind);
+ AssocItemRibKind);
this.with_generic_param_rib(generic_params, |this| {
use self::ResolutionError::*;
match impl_item.node {
seen.insert(node_id, depth);
}
}
- ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => {
+ ItemRibKind | FnItemRibKind | AssocItemRibKind => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
for rib in ribs {
match rib.kind {
- NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
+ NormalRibKind | AssocItemRibKind | ClosureRibKind(..) |
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
ConstantItemRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
}
fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
- let string = format!("{:?}", self.infcx.resolve_type_vars_if_possible(value));
+ let string = format!("{:?}", self.infcx.resolve_vars_if_possible(value));
Box::new(string)
}
use rustc::traits::WhereClause::*;
use rustc::infer::canonical::OriginalQueryValues;
- let goal = self.infcx.resolve_type_vars_if_possible(goal);
+ let goal = self.infcx.resolve_vars_if_possible(goal);
debug!("program_clauses(goal = {:?})", goal);
) -> Fallible<ChalkExClause<'tcx>> {
debug!(
"apply_answer_subst(ex_clause = {:?}, selected_goal = {:?})",
- self.infcx.resolve_type_vars_if_possible(&ex_clause),
- self.infcx.resolve_type_vars_if_possible(selected_goal)
+ self.infcx.resolve_vars_if_possible(&ex_clause),
+ self.infcx.resolve_vars_if_possible(selected_goal)
);
let (answer_subst, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() {
None => vec![],
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
- let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
+ let ty_a = infcx.resolve_vars_if_possible(&ty_a);
let mut components = smallvec![];
tcx.push_outlives_components(ty_a, &mut components);
implied_bounds_from_components(r_b, components)
None,
);
- let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value);
+ let normalized_value = infcx.resolve_vars_if_possible(&normalized_value);
let normalized_value = infcx.tcx.erase_regions(&normalized_value);
tcx.lift_to_global(&normalized_value).unwrap()
}
// Now that we know the types can be unified we find the unified type and use
// it to type the entire expression.
- let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
+ let common_type = self.resolve_vars_if_possible(&lhs_ty);
// subtyping doesn't matter here, as the value is some kind of scalar
self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
body_id,
param_env,
steps: vec![],
- cur_ty: infcx.resolve_type_vars_if_possible(&base_ty),
+ cur_ty: infcx.resolve_vars_if_possible(&base_ty),
obligations: vec![],
at_start: true,
include_raw_pointers: false,
ty, normalized_ty, obligations);
self.obligations.extend(obligations);
- Some(self.infcx.resolve_type_vars_if_possible(&normalized_ty))
+ Some(self.infcx.resolve_vars_if_possible(&normalized_ty))
}
/// Returns the final type, generating an error if it is an
/// Returns the final type we ended up with, which may well be an
/// inference variable (we will resolve it first, if possible).
pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> {
- self.infcx.resolve_type_vars_if_possible(&self.cur_ty)
+ self.infcx.resolve_vars_if_possible(&self.cur_ty)
}
pub fn step_count(&self) -> usize {
{
debug!("pointer_kind({:?}, {:?})", t, span);
- let t = self.resolve_type_vars_if_possible(&t);
+ let t = self.resolve_vars_if_possible(&t);
if t.references_error() {
return Err(ErrorReported);
let tstr = fcx.ty_to_string(self.cast_ty);
let mut err = type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0620,
"cast to unsized type: `{}` as `{}`",
- fcx.resolve_type_vars_if_possible(&self.expr_ty),
+ fcx.resolve_vars_if_possible(&self.expr_ty),
tstr);
match self.expr_ty.sty {
ty::Ref(_, _, mt) => {
let input_tys = if is_fn {
let arg_param_ty = trait_ref.skip_binder().substs.type_at(1);
- let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
+ let arg_param_ty = self.resolve_vars_if_possible(&arg_param_ty);
debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty);
match arg_param_ty.sty {
};
let ret_param_ty = projection.skip_binder().ty;
- let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
+ let ret_param_ty = self.resolve_vars_if_possible(&ret_param_ty);
debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty);
let sig = self.tcx.mk_fn_sig(
// Uncertain or unimplemented.
Ok(None) => {
if trait_ref.def_id() == unsize_did {
- let trait_ref = self.resolve_type_vars_if_possible(&trait_ref);
+ let trait_ref = self.resolve_vars_if_possible(&trait_ref);
let self_ty = trait_ref.skip_binder().self_ty();
let unsize_ty = trait_ref.skip_binder().input_types().nth(1).unwrap();
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_ref);
None
}
- fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool {
+ crate fn is_hir_id_from_struct_pattern_shorthand_field(
+ &self,
+ hir_id: hir::HirId,
+ sp: Span,
+ ) -> bool {
let cm = self.sess().source_map();
let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) {
});
if let Some(yield_span) = live_across_yield {
- let ty = self.fcx.resolve_type_vars_if_possible(&ty);
+ let ty = self.fcx.resolve_vars_if_possible(&ty);
debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
expr, scope, ty, self.expr_count, yield_span);
let base_ty = self.tables.borrow().expr_adjustments(base_expr).last()
.map_or_else(|| self.node_ty(expr.hir_id), |adj| adj.target);
- let base_ty = self.resolve_type_vars_if_possible(&base_ty);
+ let base_ty = self.resolve_vars_if_possible(&base_ty);
// Need to deref because overloaded place ops take self by-reference.
let base_ty = base_ty.builtin_deref(false)
scope: ProbeScope)
-> probe::PickResult<'tcx> {
let mode = probe::Mode::MethodCall;
- let self_ty = self.resolve_type_vars_if_possible(&self_ty);
+ let self_ty = self.resolve_vars_if_possible(&self_ty);
self.probe_for_name(span, mode, method_name, IsSuggestion(false),
self_ty, call_expr.hir_id, scope)
}
// and point at it rather than reporting the entire
// trait-ref?
result = ProbeResult::NoMatch;
- let trait_ref = self.resolve_type_vars_if_possible(&trait_ref);
+ let trait_ref = self.resolve_vars_if_possible(&trait_ref);
possibly_unsatisfied_predicates.push(trait_ref);
}
}
// Evaluate those obligations to see if they might possibly hold.
for o in candidate_obligations.into_iter().chain(sub_obligations) {
- let o = self.resolve_type_vars_if_possible(&o);
+ let o = self.resolve_vars_if_possible(&o);
if !self.predicate_may_hold(&o) {
result = ProbeResult::NoMatch;
if let &ty::Predicate::Trait(ref pred) = &o.predicate {
if let (Some(return_ty), Some(xform_ret_ty)) =
(self.return_type, probe.xform_ret_ty)
{
- let xform_ret_ty = self.resolve_type_vars_if_possible(&xform_ret_ty);
+ let xform_ret_ty = self.resolve_vars_if_possible(&xform_ret_ty);
debug!("comparing return_ty {:?} with xform ret ty {:?}",
return_ty,
probe.xform_ret_ty);
}) => {
let tcx = self.tcx;
- let actual = self.resolve_type_vars_if_possible(&rcvr_ty);
+ let actual = self.resolve_vars_if_possible(&rcvr_ty);
let ty_str = self.ty_to_string(actual);
let is_method = mode == Mode::MethodCall;
let item_kind = if is_method {
match self {
NoExpectation => NoExpectation,
ExpectCastableToType(t) => {
- ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t))
+ ExpectCastableToType(fcx.resolve_vars_if_possible(&t))
}
ExpectHasType(t) => {
- ExpectHasType(fcx.resolve_type_vars_if_possible(&t))
+ ExpectHasType(fcx.resolve_vars_if_possible(&t))
}
ExpectRvalueLikeUnsized(t) => {
- ExpectRvalueLikeUnsized(fcx.resolve_type_vars_if_possible(&t))
+ ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(&t))
}
}
}
}
/// Resolves type variables in `ty` if possible. Unlike the infcx
- /// version (resolve_type_vars_if_possible), this version will
+ /// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
/// to get more type information.
fn resolve_type_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
}
// If `ty` is a type variable, see whether we already know what it is.
- ty = self.resolve_type_vars_if_possible(&ty);
+ ty = self.resolve_vars_if_possible(&ty);
if !ty.has_infer_types() {
debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
return ty;
// indirect dependencies that don't seem worth tracking
// precisely.
self.select_obligations_where_possible(false);
- ty = self.resolve_type_vars_if_possible(&ty);
+ ty = self.resolve_vars_if_possible(&ty);
debug!("resolve_type_vars_with_obligations: ty={:?}", ty);
ty
#[inline]
pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) {
debug!("write_ty({:?}, {:?}) in fcx {}",
- id, self.resolve_type_vars_if_possible(&ty), self.tag());
+ id, self.resolve_vars_if_possible(&ty), self.tag());
self.tables.borrow_mut().node_types_mut().insert(id, ty);
if ty.references_error() {
} else {
// is the missing argument of type `()`?
let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 {
- self.resolve_type_vars_if_possible(&expected_arg_tys[0]).is_unit()
+ self.resolve_vars_if_possible(&expected_arg_tys[0]).is_unit()
} else if fn_inputs.len() == 1 && supplied_arg_count == 0 {
- self.resolve_type_vars_if_possible(&fn_inputs[0]).is_unit()
+ self.resolve_vars_if_possible(&fn_inputs[0]).is_unit()
} else {
false
};
}
ty::FnDef(..) => {
let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
- let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
+ let ptr_ty = self.resolve_vars_if_possible(&ptr_ty);
variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
}
_ => {}
// Record all the argument types, with the substitutions
// produced from the above subtyping unification.
Ok(formal_args.iter().map(|ty| {
- self.resolve_type_vars_if_possible(ty)
+ self.resolve_vars_if_possible(ty)
}).collect())
}).unwrap_or_default();
debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})",
// Find the type of `e`. Supply hints based on the type we are casting to,
// if appropriate.
let t_cast = self.to_ty_saving_user_provided_ty(t);
- let t_cast = self.resolve_type_vars_if_possible(&t_cast);
+ let t_cast = self.resolve_vars_if_possible(&t_cast);
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
- let t_cast = self.resolve_type_vars_if_possible(&t_cast);
+ let t_cast = self.resolve_vars_if_possible(&t_cast);
// Eagerly check for some obvious errors.
if t_expr.references_error() || t_cast.references_error() {
Applicability::MachineApplicable,
);
} else if !self.check_for_cast(err, expr, found, expected) {
+ let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
+ expr.hir_id,
+ expr.span,
+ );
let methods = self.get_conversion_methods(expr.span, expected, found);
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
let mut suggestions = iter::repeat(&expr_text).zip(methods.iter())
None // do not suggest code that is already there (#53348)
} else {
let method_call_list = [".to_vec()", ".to_string()"];
- if receiver.ends_with(".clone()")
+ let sugg = if receiver.ends_with(".clone()")
&& method_call_list.contains(&method_call.as_str()) {
let max_len = receiver.rfind(".").unwrap();
- Some(format!("{}{}", &receiver[..max_len], method_call))
- }
- else {
- Some(format!("{}{}", receiver, method_call))
- }
+ format!("{}{}", &receiver[..max_len], method_call)
+ } else {
+ format!("{}{}", receiver, method_call)
+ };
+ Some(if is_struct_pat_shorthand_field {
+ format!("{}: {}", receiver, sugg)
+ } else {
+ sugg
+ })
}
}).peekable();
if suggestions.peek().is_some() {
method.sig.output()
}
Err(()) => {
- let actual = self.resolve_type_vars_if_possible(&operand_ty);
+ let actual = self.resolve_vars_if_possible(&operand_ty);
if !actual.references_error() {
let mut err = struct_span_err!(self.tcx.sess, ex.span, E0600,
"cannot apply unary operator `{}` to type `{}`",
/// of b will be `&<R0>.i32` and then `*b` will require that `<R0>` be bigger than the let and
/// the `*b` expression, so we will effectively resolve `<R0>` to be the block B.
pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> {
- self.resolve_type_vars_if_possible(&unresolved_ty)
+ self.resolve_vars_if_possible(&unresolved_ty)
}
/// Try to resolve the type for the given node.
hir::ExprKind::Unary(hir::UnNeg, ref inner)
| hir::ExprKind::Unary(hir::UnNot, ref inner) => {
let inner_ty = self.fcx.node_ty(inner.hir_id);
- let inner_ty = self.fcx.resolve_type_vars_if_possible(&inner_ty);
+ let inner_ty = self.fcx.resolve_vars_if_possible(&inner_ty);
if inner_ty.is_scalar() {
let mut tables = self.fcx.tables.borrow_mut();
hir::ExprKind::Binary(ref op, ref lhs, ref rhs)
| hir::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => {
let lhs_ty = self.fcx.node_ty(lhs.hir_id);
- let lhs_ty = self.fcx.resolve_type_vars_if_possible(&lhs_ty);
+ let lhs_ty = self.fcx.resolve_vars_if_possible(&lhs_ty);
let rhs_ty = self.fcx.node_ty(rhs.hir_id);
- let rhs_ty = self.fcx.resolve_type_vars_if_possible(&rhs_ty);
+ let rhs_ty = self.fcx.resolve_vars_if_possible(&rhs_ty);
if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
let mut tables = self.fcx.tables.borrow_mut();
// All valid indexing looks like this; might encounter non-valid indexes at this point
if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).sty {
let index_ty = tables.expr_ty_adjusted(&index);
- let index_ty = self.fcx.resolve_type_vars_if_possible(&index_ty);
+ let index_ty = self.fcx.resolve_vars_if_possible(&index_ty);
if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
// Remove the method call record
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
use rustc::ty::subst::UnpackedKind;
-use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::{ReprOptions, ToPredicate};
use rustc::util::captures::Captures;
use rustc::util::nodemap::FxHashMap;
match path {
QPath::Resolved(_, ref path) => {
- let mut arg_index = 0;
- let mut found_const = false;
- for seg in &path.segments {
- if let Some(generic_args) = &seg.args {
- let args = &generic_args.args;
- for arg in args {
- if let GenericArg::Const(ct) = arg {
- if ct.value.hir_id == hir_id {
- found_const = true;
- break;
- }
- arg_index += 1;
- }
- }
- }
- }
- // Sanity check to make sure everything is as expected.
- if !found_const {
- if !fail {
- return None;
- }
- bug!("no arg matching AnonConst in path")
- }
- match path.res {
- // We've encountered an `AnonConst` in some path, so we need to
- // figure out which generic parameter it corresponds to and return
- // the relevant type.
- Res::Def(DefKind::Struct, def_id)
- | Res::Def(DefKind::Union, def_id)
- | Res::Def(DefKind::Enum, def_id)
- | Res::Def(DefKind::Fn, def_id) => {
- let generics = tcx.generics_of(def_id);
- let mut param_index = 0;
- for param in &generics.params {
- if let ty::GenericParamDefKind::Const = param.kind {
- if param_index == arg_index {
- return Some(tcx.type_of(param.def_id));
- }
- param_index += 1;
- }
- }
- // This is no generic parameter associated with the arg. This is
- // probably from an extra arg where one is not needed.
- return Some(tcx.types.err);
- }
- Res::Err => tcx.types.err,
- x => {
+ let arg_index = path.segments.iter()
+ .filter_map(|seg| seg.args.as_ref())
+ .map(|generic_args| generic_args.args.as_ref())
+ .find_map(|args| {
+ args.iter()
+ .filter(|arg| arg.is_const())
+ .enumerate()
+ .filter(|(_, arg)| arg.id() == hir_id)
+ .map(|(index, _)| index)
+ .next()
+ })
+ .or_else(|| {
if !fail {
- return None;
+ None
+ } else {
+ bug!("no arg matching AnonConst in path")
}
+ })?;
+
+ // We've encountered an `AnonConst` in some path, so we need to
+ // figure out which generic parameter it corresponds to and return
+ // the relevant type.
+ let generics = match path.res {
+ Res::Def(DefKind::Ctor(..), def_id) =>
+ tcx.generics_of(tcx.parent(def_id).unwrap()),
+ Res::Def(_, def_id) =>
+ tcx.generics_of(def_id),
+ Res::Err =>
+ return Some(tcx.types.err),
+ _ if !fail =>
+ return None,
+ x => {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"unexpected const parent path def {:?}", x
),
);
- tcx.types.err
+ return Some(tcx.types.err);
}
- }
+ };
+
+ generics.params.iter()
+ .filter(|param| {
+ if let ty::GenericParamDefKind::Const = param.kind {
+ true
+ } else {
+ false
+ }
+ })
+ .nth(arg_index)
+ .map(|param| tcx.type_of(param.def_id))
+ // This is no generic parameter associated with the arg. This is
+ // probably from an extra arg where one is not needed.
+ .unwrap_or(tcx.types.err)
}
x => {
if !fail {
path = "lib.rs"
[dependencies]
-pulldown-cmark = { version = "0.4.1", default-features = false }
+pulldown-cmark = { version = "0.5.2", default-features = false }
minifier = "0.0.30"
tempfile = "3"
parking_lot = "0.7"
fn clean(&self, cx: &DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
- expr: match self.val {
- ConstValue::Param(ty::ParamConst { name, .. }) => format!("{}", name),
- e => format!("{:?}", e), // FIXME generic consts with expressions
- },
+ expr: format!("{}", self),
}
}
}
if let Some(Event::Start(Tag::Header(level))) = event {
let mut id = String::new();
for event in &mut self.inner {
- match event {
+ match &event {
Event::End(Tag::Header(..)) => break,
- Event::Text(ref text) => id.extend(text.chars().filter_map(slugify)),
+ Event::Text(text) | Event::Code(text) => {
+ id.extend(text.chars().filter_map(slugify));
+ }
_ => {},
}
self.buf.push_back(event);
| Tag::Item
| Tag::Emphasis
| Tag::Strong
- | Tag::Code
| Tag::Link(..)
| Tag::BlockQuote => true,
_ => false,
let next_event = next_event.unwrap();
let (ret, is_in) = match next_event {
Event::Start(Tag::Paragraph) => (None, 1),
- Event::Start(Tag::Code) => (Some("`".to_owned()), 1),
- Event::End(Tag::Code) => (Some("`".to_owned()), -1),
Event::Start(Tag::Header(_)) => (None, 1),
+ Event::Code(code) => (Some(format!("`{}`", code)), 0),
Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0),
Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1),
_ => (None, 0),
use std::io;
use std::panic::{self, AssertUnwindSafe};
use std::path::PathBuf;
-use std::process::Command;
+use std::process::{self, Command};
use std::str;
use std::sync::{Arc, Mutex};
use syntax::symbol::sym;
opts
}
-fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
- cfgs: Vec<String>, libs: Vec<SearchPath>,
- cg: CodegenOptions, externs: Externs,
- should_panic: bool, no_run: bool, as_test_harness: bool,
- compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
- maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
- persist_doctests: Option<PathBuf>) {
+/// Documentation test failure modes.
+enum TestFailure {
+ /// The test failed to compile.
+ CompileError,
+ /// The test is marked `compile_fail` but compiled successfully.
+ UnexpectedCompilePass,
+ /// The test failed to compile (as expected) but the compiler output did not contain all
+ /// expected error codes.
+ MissingErrorCodes(Vec<String>),
+ /// The test binary was unable to be executed.
+ ExecutionError(io::Error),
+ /// The test binary exited with a non-zero exit code.
+ ///
+ /// This typically means an assertion in the test failed or another form of panic occurred.
+ ExecutionFailure(process::Output),
+ /// The test is marked `should_panic` but the test binary executed successfully.
+ UnexpectedRunPass,
+}
+
+fn run_test(
+ test: &str,
+ cratename: &str,
+ filename: &FileName,
+ line: usize,
+ cfgs: Vec<String>,
+ libs: Vec<SearchPath>,
+ cg: CodegenOptions,
+ externs: Externs,
+ should_panic: bool,
+ no_run: bool,
+ as_test_harness: bool,
+ compile_fail: bool,
+ mut error_codes: Vec<String>,
+ opts: &TestOptions,
+ maybe_sysroot: Option<PathBuf>,
+ linker: Option<PathBuf>,
+ edition: Edition,
+ persist_doctests: Option<PathBuf>,
+) -> Result<(), TestFailure> {
let (test, line_offset) = match panic::catch_unwind(|| {
make_test(test, Some(cratename), as_test_harness, opts, edition)
}) {
match (compile_result, compile_fail) {
(Ok(()), true) => {
- panic!("test compiled while it wasn't supposed to")
+ return Err(TestFailure::UnexpectedCompilePass);
}
(Ok(()), false) => {}
(Err(_), true) => {
- if error_codes.len() > 0 {
+ if !error_codes.is_empty() {
let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
error_codes.retain(|err| !out.contains(err));
+
+ if !error_codes.is_empty() {
+ return Err(TestFailure::MissingErrorCodes(error_codes));
+ }
}
}
(Err(_), false) => {
- panic!("couldn't compile the test")
+ return Err(TestFailure::CompileError);
}
}
- if error_codes.len() > 0 {
- panic!("Some expected error codes were not found: {:?}", error_codes);
+ if no_run {
+ return Ok(());
}
- if no_run { return }
-
// Run the code!
let mut cmd = Command::new(output_file);
match cmd.output() {
- Err(e) => panic!("couldn't run the test: {}{}", e,
- if e.kind() == io::ErrorKind::PermissionDenied {
- " - maybe your tempdir is mounted with noexec?"
- } else { "" }),
+ Err(e) => return Err(TestFailure::ExecutionError(e)),
Ok(out) => {
if should_panic && out.status.success() {
- panic!("test executable succeeded when it should have failed");
+ return Err(TestFailure::UnexpectedRunPass);
} else if !should_panic && !out.status.success() {
- panic!("test executable failed:\n{}\n{}\n",
- str::from_utf8(&out.stdout).unwrap_or(""),
- str::from_utf8(&out.stderr).unwrap_or(""));
+ return Err(TestFailure::ExecutionFailure(out));
}
}
}
+
+ Ok(())
}
/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
allow_fail: config.allow_fail,
},
testfn: testing::DynTestFn(box move || {
- run_test(
+ let res = run_test(
&test,
&cratename,
&filename,
linker,
edition,
persist_doctests
- )
+ );
+
+ if let Err(err) = res {
+ match err {
+ TestFailure::CompileError => {
+ eprint!("Couldn't compile the test.");
+ }
+ TestFailure::UnexpectedCompilePass => {
+ eprint!("Test compiled successfully, but it's marked `compile_fail`.");
+ }
+ TestFailure::UnexpectedRunPass => {
+ eprint!("Test executable succeeded, but it's marked `should_panic`.");
+ }
+ TestFailure::MissingErrorCodes(codes) => {
+ eprint!("Some expected error codes were not found: {:?}", codes);
+ }
+ TestFailure::ExecutionError(err) => {
+ eprint!("Couldn't run the test: {}", err);
+ if err.kind() == io::ErrorKind::PermissionDenied {
+ eprint!(" - maybe your tempdir is mounted with noexec?");
+ }
+ }
+ TestFailure::ExecutionFailure(out) => {
+ let reason = if let Some(code) = out.status.code() {
+ format!("exit code {}", code)
+ } else {
+ String::from("terminated by signal")
+ };
+
+ eprintln!("Test executable failed ({}).", reason);
+
+ // FIXME(#12309): An unfortunate side-effect of capturing the test
+ // executable's output is that the relative ordering between the test's
+ // stdout and stderr is lost. However, this is better than the
+ // alternative: if the test executable inherited the parent's I/O
+ // handles the output wouldn't be captured at all, even on success.
+ //
+ // The ordering could be preserved if the test process' stderr was
+ // redirected to stdout, but that functionality does not exist in the
+ // standard library, so it may not be portable enough.
+ let stdout = str::from_utf8(&out.stdout).unwrap_or_default();
+ let stderr = str::from_utf8(&out.stderr).unwrap_or_default();
+
+ if !stdout.is_empty() || !stderr.is_empty() {
+ eprintln!();
+
+ if !stdout.is_empty() {
+ eprintln!("stdout:\n{}", stdout);
+ }
+
+ if !stderr.is_empty() {
+ eprintln!("stderr:\n{}", stderr);
+ }
+ }
+ }
+ }
+
+ panic::resume_unwind(box ());
+ }
}),
});
}
/// "I'm the superhero of errors"
/// }
///
- /// fn cause(&self) -> Option<&Error> {
+ /// fn cause(&self) -> Option<&dyn Error> {
/// Some(&self.side)
/// }
/// }
///
/// let an_error = AnError;
/// assert!(0 == mem::size_of_val(&an_error));
- /// let a_boxed_error = Box::<Error>::from(an_error);
+ /// let a_boxed_error = Box::<dyn Error>::from(an_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: E) -> Box<dyn Error + 'a> {
///
/// let an_error = AnError;
/// assert!(0 == mem::size_of_val(&an_error));
- /// let a_boxed_error = Box::<Error + Send + Sync>::from(an_error);
+ /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
/// use std::mem;
///
/// let a_string_error = "a string error".to_string();
- /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_string_error);
+ /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
/// use std::mem;
///
/// let a_string_error = "a string error".to_string();
- /// let a_boxed_error = Box::<Error>::from(a_string_error);
+ /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(str_err: String) -> Box<dyn Error> {
/// use std::mem;
///
/// let a_str_error = "a str error";
- /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_str_error);
+ /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
/// use std::mem;
///
/// let a_str_error = "a str error";
- /// let a_boxed_error = Box::<Error>::from(a_str_error);
+ /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: &str) -> Box<dyn Error> {
/// use std::borrow::Cow;
///
/// let a_cow_str_error = Cow::from("a str error");
- /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_cow_str_error);
+ /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
/// use std::borrow::Cow;
///
/// let a_cow_str_error = Cow::from("a str error");
- /// let a_boxed_error = Box::<Error>::from(a_cow_str_error);
+ /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: Cow<'a, str>) -> Box<dyn Error> {
/// use std::path::Path;
///
/// // one possible implementation of walking a directory only visiting files
-/// fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<()> {
+/// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> {
/// if dir.is_dir() {
/// for entry in fs::read_dir(dir)? {
/// let entry = entry?;
/// # Examples
///
/// ```no_run
- /// # #![feature(bufreader_buffer)]
/// use std::io::{BufReader, BufRead};
/// use std::fs::File;
///
/// Ok(())
/// }
/// ```
- #[unstable(feature = "bufreader_buffer", issue = "45323")]
+ #[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap]
}
/// # Examples
///
/// ```no_run
- /// # #![feature(bufreader_buffer)]
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// // See how many bytes are currently buffered
/// let bytes_buffered = buf_writer.buffer().len();
/// ```
- #[unstable(feature = "bufreader_buffer", issue = "45323")]
+ #[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] {
&self.buf
}
assert_eq!(reader.get_ref().pos, expected);
}
+ #[test]
+ fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() {
+ // gimmick reader that returns Err after first seek
+ struct ErrAfterFirstSeekReader {
+ first_seek: bool,
+ }
+ impl Read for ErrAfterFirstSeekReader {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ for x in &mut *buf {
+ *x = 0;
+ }
+ Ok(buf.len())
+ }
+ }
+ impl Seek for ErrAfterFirstSeekReader {
+ fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
+ if self.first_seek {
+ self.first_seek = false;
+ Ok(0)
+ } else {
+ Err(io::Error::new(io::ErrorKind::Other, "oh no!"))
+ }
+ }
+ }
+
+ let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true });
+ assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..]));
+
+ // The following seek will require two underlying seeks. The first will
+ // succeed but the second will fail. This should still invalidate the
+ // buffer.
+ assert!(reader.seek(SeekFrom::Current(i64::min_value())).is_err());
+ assert_eq!(reader.buffer().len(), 0);
+ }
+
#[test]
fn test_buffered_writer() {
let inner = Vec::new();
/// let metadata = f.metadata()?;
/// let permissions = metadata.permissions();
///
- /// println!("permissions: {}", permissions.mode());
+ /// println!("permissions: {:o}", permissions.mode());
/// Ok(())
/// }
/// ```
/// let metadata = f.metadata()?;
/// let permissions = metadata.permissions();
///
- /// println!("permissions: {}", permissions.mode());
+ /// println!("permissions: {:o}", permissions.mode());
/// Ok(()) }
/// ```
#[stable(feature = "fs_ext", since = "1.1.0")]
debug!("find_width_of_character_at_span: local_begin=`{:?}`, local_end=`{:?}`",
local_begin, local_end);
+ if local_begin.sf.start_pos != local_end.sf.start_pos {
+ debug!("find_width_of_character_at_span: begin and end are in different files");
+ return 1;
+ }
+
let start_index = local_begin.pos.to_usize();
let end_index = local_end.pos.to_usize();
debug!("find_width_of_character_at_span: start_index=`{:?}`, end_index=`{:?}`",
// Test that `-Zpgo-gen` creates expected instrumentation artifacts in LLVM IR.
+// Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.
// needs-profiler-support
-// compile-flags: -Z pgo-gen -Ccodegen-units=1
+// compile-flags: -Z pgo-gen -Ccodegen-units=1 -Cpanic=abort
// CHECK: @__llvm_profile_raw_version =
// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global
// CHECK: @__profd_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global
-// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}main{{.*}} = private global
-// CHECK: @__profd_{{.*}}pgo_instrumentation{{.*}}main{{.*}} = private global
+// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_other_function{{.*}} = private global
+// CHECK: @__profd_{{.*}}pgo_instrumentation{{.*}}some_other_function{{.*}} = private global
// CHECK: @__llvm_profile_filename = {{.*}}"default_%m.profraw\00"{{.*}}
+#![crate_type="lib"]
+
#[inline(never)]
fn some_function() {
}
-fn main() {
+pub fn some_other_function() {
some_function();
}
trait Hierarchy {
type Value;
type ChildKey;
- type Children = Index<Self::ChildKey, Output=Hierarchy>;
+ type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>;
//~^ ERROR: the value of the associated types `Value` (from the trait `Hierarchy`), `ChildKey`
fn data(&self) -> Option<(Self::Value, Self::Children)>;
-include ../tools.mk
+COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)"
+
+# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
+# https://github.com/rust-lang/rust/issues/61002
+#
+# Things work fine with -Cpanic=abort though.
+ifdef IS_MSVC
+COMPILE_FLAGS+= -Cpanic=abort
+endif
+
all:
- $(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)" test.rs
+ $(RUSTC) $(COMPILE_FLAGS) test.rs
$(call RUN,test) || exit 1
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
-include ../tools.mk
+COMPILE_FLAGS=-O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)"
+
+# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
+# https://github.com/rust-lang/rust/issues/61002
+#
+# Things work fine with -Cpanic=abort though.
+ifdef IS_MSVC
+COMPILE_FLAGS+= -Cpanic=abort
+endif
+
all:
- $(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)" --emit=llvm-ir test.rs
+ $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs
# We expect symbols starting with "__llvm_profile_".
$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
# We do NOT expect the "__imp_" version of these symbols.
-include ../tools.mk
+COMPILE_FLAGS=-g -Z pgo-gen="$(TMPDIR)"
+
+# LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
+# https://github.com/rust-lang/rust/issues/61002
+#
+# Things work fine with -Cpanic=abort though.
+ifdef IS_MSVC
+COMPILE_FLAGS+= -Cpanic=abort
+endif
+
all:
- $(RUSTC) -g -Z pgo-gen="$(TMPDIR)" test.rs
+ $(RUSTC) $(COMPILE_FLAGS) test.rs
$(call RUN,test) || exit 1
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
COMMON_FLAGS=-Copt-level=s -Ccodegen-units=1
# LLVM doesn't support instrumenting binaries that use SEH:
-# https://bugs.llvm.org/show_bug.cgi?id=41279
+# https://github.com/rust-lang/rust/issues/61002
#
# Things work fine with -Cpanic=abort though.
ifdef IS_MSVC
# Checks that all the targets returned by `rustc --print target-list` are valid
# target specifications
-# TODO remove the '*ios*' case when rust-lang/rust#29812 is fixed
all:
for target in $(shell $(BARE_RUSTC) --print target-list); do \
- case $$target in \
- *ios*) \
- ;; \
- *) \
- $(BARE_RUSTC) --target $$target --print sysroot \
- ;; \
- esac \
+ $(BARE_RUSTC) --target $$target --print sysroot; \
done
/// Iterate over exprs of depth up to `depth`. The goal is to explore all "interesting"
/// combinations of expression nesting. For example, we explore combinations using `if`, but not
/// `while` or `match`, since those should print and parse in much the same way as `if`.
-fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
+fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
if depth == 0 {
f(make_x());
return;
}
}
-fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>+'static> {
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
box Invoker {
a: a,
b: b,
- } as (Box<Invokable<A>+'static>)
+ } as (Box<dyn Invokable<A>+'static>)
}
pub fn main() {
// run-pass
#![feature(box_syntax)]
-fn pairwise_sub(mut t: Box<DoubleEndedIterator<Item=isize>>) -> isize {
+fn pairwise_sub(mut t: Box<dyn DoubleEndedIterator<Item=isize>>) -> isize {
let mut result = 0;
loop {
let front = t.next();
fn boo(&self) -> Bar { Bar }
}
-fn baz(x: &Foo<A=Bar>) -> Bar {
+fn baz(x: &dyn Foo<A=Bar>) -> Bar {
x.boo()
}
pub trait Publisher<'a> {
type Output;
- fn subscribe(&mut self, _: Box<Subscriber<Input=Self::Output> + 'a>);
+ fn subscribe(&mut self, _: Box<dyn Subscriber<Input=Self::Output> + 'a>);
}
pub trait Processor<'a> : Subscriber + Publisher<'a> { }
impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
struct MyStruct<'a> {
- sub: Box<Subscriber<Input=u64> + 'a>
+ sub: Box<dyn Subscriber<Input=u64> + 'a>
}
impl<'a> Publisher<'a> for MyStruct<'a> {
type Output = u64;
- fn subscribe(&mut self, t : Box<Subscriber<Input=u64> + 'a>) {
+ fn subscribe(&mut self, t : Box<dyn Subscriber<Input=u64> + 'a>) {
self.sub = t;
}
}
}
pub fn main() {
- let x: Box<_> = box (box 3usize as Box<double>);
+ let x: Box<_> = box (box 3usize as Box<dyn double>);
assert_eq!(x.double(), 6);
}
fn main() {
trait T { fn foo(&self) {} }
- fn f<'a, V: T>(v: &'a V) -> &'a T {
- v as &'a T
+ fn f<'a, V: T>(v: &'a V) -> &'a dyn T {
+ v as &'a dyn T
}
}
impl Foo<u32> for u32 { fn foo(&self, _: u32) -> u32 { self+43 } }
impl Bar for () {}
-unsafe fn round_trip_and_call<'a>(t: *const (Foo<u32>+'a)) -> u32 {
- let foo_e : *const Foo<u16> = t as *const _;
- let r_1 = foo_e as *mut Foo<u32>;
+unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo<u32>+'a)) -> u32 {
+ let foo_e : *const dyn Foo<u16> = t as *const _;
+ let r_1 = foo_e as *mut dyn Foo<u32>;
(&*r_1).foo(0)
}
fn main() {
let x = 4u32;
- let y : &Foo<u32> = &x;
- let fl = unsafe { round_trip_and_call(y as *const Foo<u32>) };
+ let y : &dyn Foo<u32> = &x;
+ let fl = unsafe { round_trip_and_call(y as *const dyn Foo<u32>) };
assert_eq!(fl, (43+4));
let s = FooS([0,1,2]);
// coercion-cast
let mut it = vec![137].into_iter();
let itr: &mut vec::IntoIter<u32> = &mut it;
- assert_eq!((itr as &mut Iterator<Item=u32>).next(), Some(137));
- assert_eq!((itr as &mut Iterator<Item=u32>).next(), None);
+ assert_eq!((itr as &mut dyn Iterator<Item=u32>).next(), Some(137));
+ assert_eq!((itr as &mut dyn Iterator<Item=u32>).next(), None);
assert_eq!(Some(4u32) as Option<u32>, Some(4u32));
assert_eq!((1u32,2u32) as (u32,u32), (1,2));
}
}
-fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>+'static> {
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
box Invoker {
a: a,
b: b,
- } as (Box<Invokable<A>+'static>)
+ } as (Box<dyn Invokable<A>+'static>)
}
pub fn main() {
fn main() {
- assert_eq!((ToString::to_string as fn(&(ToString+'static)) -> String)(&"foo"),
+ assert_eq!((ToString::to_string as fn(&(dyn ToString+'static)) -> String)(&"foo"),
String::from("foo"));
}
let _: Box<[isize]> = Box::new({ [1, 2, 3] });
let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] });
let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] });
- let _: Box<Fn(isize) -> _> = Box::new({ |x| (x as u8) });
- let _: Box<Debug> = Box::new(if true { false } else { true });
- let _: Box<Debug> = Box::new(match true { true => 'a', false => 'b' });
+ let _: Box<dyn Fn(isize) -> _> = Box::new({ |x| (x as u8) });
+ let _: Box<dyn Debug> = Box::new(if true { false } else { true });
+ let _: Box<dyn Debug> = Box::new(match true { true => 'a', false => 'b' });
let _: &[isize] = &{ [1, 2, 3] };
let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] };
let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] };
- let _: &Fn(isize) -> _ = &{ |x| (x as u8) };
- let _: &Debug = &if true { false } else { true };
- let _: &Debug = &match true { true => 'a', false => 'b' };
+ let _: &dyn Fn(isize) -> _ = &{ |x| (x as u8) };
+ let _: &dyn Debug = &if true { false } else { true };
+ let _: &dyn Debug = &match true { true => 'a', false => 'b' };
let _: &str = &{ String::new() };
let _: &str = &if true { String::from("...") } else { 5.to_string() };
};
let _: Box<[isize]> = Box::new([1, 2, 3]);
- let _: Box<Fn(isize) -> _> = Box::new(|x| (x as u8));
+ let _: Box<dyn Fn(isize) -> _> = Box::new(|x| (x as u8));
let _: Rc<RefCell<[isize]>> = Rc::new(RefCell::new([1, 2, 3]));
- let _: Rc<RefCell<FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
+ let _: Rc<RefCell<dyn FnMut(isize) -> _>> = Rc::new(RefCell::new(|x| (x as u8)));
- let _: Vec<Box<Fn(isize) -> _>> = vec![
+ let _: Vec<Box<dyn Fn(isize) -> _>> = vec![
Box::new(|x| (x as u8)),
Box::new(|x| (x as i16 as u8)),
];
impl Trait for Bar {}
fn main() {
- let x: &[&Trait] = &[{ &Bar }];
+ let x: &[&dyn Trait] = &[{ &Bar }];
}
// Issue #25748 - the cast causes an &Encoding -> &Encoding coercion:
pub const UTF_8: &'static UTF8Encoding = &UTF8Encoding;
pub trait Encoding {}
impl Encoding for UTF8Encoding {}
-pub fn f() -> &'static Encoding { UTF_8 as &'static Encoding }
+pub fn f() -> &'static dyn Encoding { UTF_8 as &'static dyn Encoding }
// Root of the problem: &Trait -> &Trait coercions:
-const FOO: &'static Trait = &Bar;
-const BAR: &'static Trait = FOO;
+const FOO: &'static dyn Trait = &Bar;
+const BAR: &'static dyn Trait = FOO;
fn foo() { let _x = BAR; }
}
#[derive(Debug)]
-struct Pointers(*const Send, *mut Sync);
+struct Pointers(*const dyn Send, *mut dyn Sync);
macro_rules! t {
($x:expr, $expected:expr) => {
pub fn main() {
{
let x = box Cat {name: 22};
- let nyan: Box<Dummy> = x as Box<Dummy>;
+ let nyan: Box<dyn Dummy> = x as Box<dyn Dummy>;
}
unsafe {
assert_eq!(value, 22);
// Trait objects.
let a: Bar<i32> = Bar { x: &42 };
- let b: Bar<Baz> = a;
+ let b: Bar<dyn Baz> = a;
unsafe {
assert_eq!((*b.x).get(), 42);
}
assert_eq!(b[2], 3);
let a: Rc<i32> = Rc::new(42);
- let b: Rc<Baz> = a.clone();
+ let b: Rc<dyn Baz> = a.clone();
assert_eq!(b.get(), 42);
let c: Weak<i32> = Rc::downgrade(&a);
- let d: Weak<Baz> = c.clone();
+ let d: Weak<dyn Baz> = c.clone();
let _c = b.clone();
let a: Rc<RefCell<i32>> = Rc::new(RefCell::new(42));
- let b: Rc<RefCell<Baz>> = a.clone();
+ let b: Rc<RefCell<dyn Baz>> = a.clone();
assert_eq!(b.borrow().get(), 42);
// FIXME
- let c: Weak<RefCell<Baz>> = Rc::downgrade(&a) as Weak<_>;
+ let c: Weak<RefCell<dyn Baz>> = Rc::downgrade(&a) as Weak<_>;
}
impl T for S {}
pub fn main() {
- let x: &T = &S;
+ let x: &dyn T = &S;
// Test we can convert from &-ptr to *-ptr of trait objects
- let x: *const T = &S;
+ let x: *const dyn T = &S;
// Test we can convert from &-ptr to *-ptr of struct pointer (not DST)
let x: *const S = &S;
// As above, but mut
- let x: &mut T = &mut S;
- let x: *mut T = &mut S;
+ let x: &mut dyn T = &mut S;
+ let x: *mut dyn T = &mut S;
let x: *mut S = &mut S;
// Test we can change the mutability from mut to const.
- let x: &T = &mut S;
- let x: *const T = &mut S;
+ let x: &dyn T = &mut S;
+ let x: *const dyn T = &mut S;
}
// Test that zero-offset works properly
let b : Baz<usize> = Baz { a: 7 };
assert_eq!(b.a.get(), 7);
- let b : &Baz<Bar> = &b;
+ let b : &Baz<dyn Bar> = &b;
assert_eq!(b.a.get(), 7);
// Test that the field is aligned properly
assert_eq!(f.b.get(), 11);
let ptr1 : *const u8 = &f.b as *const _ as *const u8;
- let f : &Foo<Bar> = &f;
+ let f : &Foo<dyn Bar> = &f;
let ptr2 : *const u8 = &f.b as *const _ as *const u8;
assert_eq!(f.b.get(), 11);
// Test that nested DSTs work properly
let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
assert_eq!(f.b.b.get(), 17);
- let f : &Foo<Foo<Bar>> = &f;
+ let f : &Foo<Foo<dyn Bar>> = &f;
assert_eq!(f.b.b.get(), 17);
// Test that get the pointer via destructuring works
let f : Foo<usize> = Foo { a: 0, b: 11 };
- let f : &Foo<Bar> = &f;
+ let f : &Foo<dyn Bar> = &f;
let &Foo { a: _, b: ref bar } = f;
assert_eq!(bar.get(), 11);
struct T;
impl Index<usize> for T {
- type Output = Debug + 'static;
+ type Output = dyn Debug + 'static;
- fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) {
+ fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) {
static X: usize = 42;
- &X as &(Debug + 'static)
+ &X as &(dyn Debug + 'static)
}
}
pub fn main() {
// raw trait object
let x = A { f: 42 };
- let z: *const Trait = &x;
+ let z: *const dyn Trait = &x;
let r = unsafe {
(&*z).foo()
};
// raw DST struct
let p = Foo {f: A { f: 42 }};
- let o: *const Foo<Trait> = &p;
+ let o: *const Foo<dyn Trait> = &p;
let r = unsafe {
(&*o).f.foo()
};
// raw DST tuple
let p = (A { f: 42 },);
- let o: *const (Trait,) = &p;
+ let o: *const (dyn Trait,) = &p;
let r = unsafe {
(&*o).0.foo()
};
// all of the above with *mut
let mut x = A { f: 42 };
- let z: *mut Trait = &mut x;
+ let z: *mut dyn Trait = &mut x;
let r = unsafe {
(&*z).foo()
};
assert_eq!(r, 42);
let mut p = Foo {f: A { f: 42 }};
- let o: *mut Foo<Trait> = &mut p;
+ let o: *mut Foo<dyn Trait> = &mut p;
let r = unsafe {
(&*o).f.foo()
};
assert_eq!(r, 42);
let mut p = (A { f: 42 },);
- let o: *mut (Trait,) = &mut p;
+ let o: *mut (dyn Trait,) = &mut p;
let r = unsafe {
(&*o).0.foo()
};
}
// x is a fat pointer
-fn foo(x: &Fat<ToBar>) {
+fn foo(x: &Fat<dyn ToBar>) {
assert_eq!(x.0, 5);
assert_eq!(x.1, "some str");
assert_eq!(x.2.to_bar(), Bar);
assert_eq!(y.to_val(), 42);
}
-fn bar(x: &ToBar) {
+fn bar(x: &dyn ToBar) {
assert_eq!(x.to_bar(), Bar);
assert_eq!(x.to_val(), 42);
}
-fn baz(x: &Fat<Fat<ToBar>>) {
+fn baz(x: &Fat<Fat<dyn ToBar>>) {
assert_eq!(x.0, 5);
assert_eq!(x.1, "some str");
assert_eq!((x.2).0, 8);
foo(&f1);
let f2 = &f1;
foo(f2);
- let f3: &Fat<ToBar> = f2;
+ let f3: &Fat<dyn ToBar> = f2;
foo(f3);
- let f4: &Fat<ToBar> = &f1;
+ let f4: &Fat<dyn ToBar> = &f1;
foo(f4);
- let f5: &Fat<ToBar> = &(5, "some str", Bar1 {f :42});
+ let f5: &Fat<dyn ToBar> = &(5, "some str", Bar1 {f :42});
foo(f5);
// Zero size object.
- let f6: &Fat<ToBar> = &(5, "some str", Bar);
+ let f6: &Fat<dyn ToBar> = &(5, "some str", Bar);
assert_eq!(f6.2.to_bar(), Bar);
// &*
//
- let f7: Box<ToBar> = Box::new(Bar1 {f :42});
+ let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42});
bar(&*f7);
// Deep nesting
baz(&f1);
let f2 = &f1;
baz(f2);
- let f3: &Fat<Fat<ToBar>> = f2;
+ let f3: &Fat<Fat<dyn ToBar>> = f2;
baz(f3);
- let f4: &Fat<Fat<ToBar>> = &f1;
+ let f4: &Fat<Fat<dyn ToBar>> = &f1;
baz(f4);
- let f5: &Fat<Fat<ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42}));
+ let f5: &Fat<Fat<dyn ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42}));
baz(f5);
}
}
// x is a fat pointer
-fn foo(x: &Fat<ToBar>) {
+fn foo(x: &Fat<dyn ToBar>) {
assert_eq!(x.f1, 5);
assert_eq!(x.f2, "some str");
assert_eq!(x.ptr.to_bar(), Bar);
assert_eq!(y.to_val(), 42);
}
-fn bar(x: &ToBar) {
+fn bar(x: &dyn ToBar) {
assert_eq!(x.to_bar(), Bar);
assert_eq!(x.to_val(), 42);
}
-fn baz(x: &Fat<Fat<ToBar>>) {
+fn baz(x: &Fat<Fat<dyn ToBar>>) {
assert_eq!(x.f1, 5);
assert_eq!(x.f2, "some str");
assert_eq!(x.ptr.f1, 8);
foo(&f1);
let f2 = &f1;
foo(f2);
- let f3: &Fat<ToBar> = f2;
+ let f3: &Fat<dyn ToBar> = f2;
foo(f3);
- let f4: &Fat<ToBar> = &f1;
+ let f4: &Fat<dyn ToBar> = &f1;
foo(f4);
- let f5: &Fat<ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+ let f5: &Fat<dyn ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
foo(f5);
// Zero size object.
- let f6: &Fat<ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar };
+ let f6: &Fat<dyn ToBar> = &Fat { f1: 5, f2: "some str", ptr: Bar };
assert_eq!(f6.ptr.to_bar(), Bar);
// &*
//
- let f7: Box<ToBar> = Box::new(Bar1 {f :42});
+ let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42});
bar(&*f7);
// Deep nesting
baz(&f1);
let f2 = &f1;
baz(f2);
- let f3: &Fat<Fat<ToBar>> = f2;
+ let f3: &Fat<Fat<dyn ToBar>> = f2;
baz(f3);
- let f4: &Fat<Fat<ToBar>> = &f1;
+ let f4: &Fat<Fat<dyn ToBar>> = &f1;
baz(f4);
- let f5: &Fat<Fat<ToBar>> =
+ let f5: &Fat<Fat<dyn ToBar>> =
&Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} };
baz(f5);
}
fn assert_foo<T: ?Sized + Foo>() { }
-fn use_foo<T: ?Sized + Foo>(x: &Foo) {
+fn use_foo<T: ?Sized + Foo>(x: &dyn Foo) {
x.foo();
}
assert_eq!(a as usize, b as *const () as usize);
// And conversion to a void pointer/address for trait objects too.
- let a: *mut Foo = &mut Bar;
+ let a: *mut dyn Foo = &mut Bar;
let b = a as *mut ();
let c = a as *const () as usize;
let d = unsafe {
a: &'a usize
}
-type RefTo = Box<for<'r> Fn(&'r Vec<usize>) -> UsizeRef<'r>>;
+type RefTo = Box<dyn for<'r> Fn(&'r Vec<usize>) -> UsizeRef<'r>>;
fn ref_to<'a>(vec: &'a Vec<usize>) -> UsizeRef<'a> {
UsizeRef{ a: &vec[0]}
pub fn main() {
let x = box S { x: 1 };
- let y = x as Box<Foo<isize>>;
+ let y = x as Box<dyn Foo<isize>>;
assert_eq!(y.get(), 1);
}
use std::str;
use std::thread;
- pub type putter<'a> = Box<FnMut(String, String) + 'a>;
+ pub type putter<'a> = Box<dyn FnMut(String, String) + 'a>;
pub type mapper = extern fn(String, putter);
impl<'tcx> Typer<'tcx> for Tcx<'tcx> {
}
-fn g<'tcx>(typer: &Typer<'tcx>) {
+fn g<'tcx>(typer: &dyn Typer<'tcx>) {
}
fn check_static_type<'x>(tcx: &Tcx<'x>) {
fn dummy(&self) { }
}
-fn g<F>(_: F) where F: FnOnce(&Typer) {}
+fn g<F>(_: F) where F: FnOnce(&dyn Typer) {}
fn h() {
g(|typer| typer.dummy())
fn call(&self, arg: A) -> R;
}
-type FnObject<'b> = for<'a> FnLike<&'a isize, &'a isize> + 'b;
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
struct Identity;
// Parse HRTB with explicit `for` in various sorts of types:
-fn foo10(t: Box<for<'a> Get<i32, i32>>) { }
-fn foo11(t: Box<for<'a> Fn(i32) -> i32>) { }
+fn foo10(t: Box<dyn for<'a> Get<i32, i32>>) { }
+fn foo11(t: Box<dyn for<'a> Fn(i32) -> i32>) { }
fn foo20(t: for<'a> fn(i32) -> i32) { }
fn foo21(t: for<'a> unsafe fn(i32) -> i32) { }
// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would
// cause a compilation error. Issue #18772.
-fn adder(y: isize) -> Box<Fn(isize) -> isize + 'static> {
+fn adder(y: isize) -> Box<dyn Fn(isize) -> isize + 'static> {
Box::new(move |x| y + x)
}
fn call(&self, arg: A) -> R;
}
-type FnObject<'b> = for<'a> FnLike<&'a isize, &'a isize> + 'b;
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
fn main() {
}
fn call(&self, arg: A) -> R;
}
-type FnObject<'b> = for<'a> FnLike<(&'a i32,), &'a i32> + 'b;
+type FnObject<'b> = dyn for<'a> FnLike<(&'a i32,), &'a i32> + 'b;
struct Identity;
impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
}
-fn foo<'ast, G>(f: Option<&'ast usize>, g: G) where G: FnOnce(&PrinterSupport) {
+fn foo<'ast, G>(f: Option<&'ast usize>, g: G) where G: FnOnce(&dyn PrinterSupport) {
let annotation = NoAnn { f: f };
g(&annotation)
}
t!(format!("{:#4}", C), "☃123");
t!(format!("{:b}", D), "aa☃bb");
- let a: &fmt::Debug = &1;
+ let a: &dyn fmt::Debug = &1;
t!(format!("{:?}", a), "1");
fn add_usize(&self, _: usize) -> Option<Self> {
unimplemented!()
}
+
+ fn sub_usize(&self, _: usize) -> Option<Self> {
+ unimplemented!()
+ }
}
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
impl MyTrait for Box<DroppableStruct> {}
impl MyTrait for Box<DroppableEnum> {}
-struct Whatever { w: Box<MyTrait+'static> }
+struct Whatever { w: Box<dyn MyTrait+'static> }
impl Whatever {
- fn new(w: Box<MyTrait+'static>) -> Whatever {
+ fn new(w: Box<dyn MyTrait+'static>) -> Whatever {
Whatever { w: w }
}
}
fn main() {
{
let f: Box<_> = box DroppableStruct;
- let _a = Whatever::new(box f as Box<MyTrait>);
+ let _a = Whatever::new(box f as Box<dyn MyTrait>);
}
assert!(unsafe { DROPPED });
unsafe { DROPPED = false; }
{
let f: Box<_> = box DroppableEnum::DroppableVariant1;
- let _a = Whatever::new(box f as Box<MyTrait>);
+ let _a = Whatever::new(box f as Box<dyn MyTrait>);
}
assert!(unsafe { DROPPED });
}
trait Foo { fn dummy(&self) { } }
impl Foo for isize {}
-fn foo(_: [&Foo; 2]) {}
-fn foos(_: &[&Foo]) {}
+fn foo(_: [&dyn Foo; 2]) {}
+fn foos(_: &[&dyn Foo]) {}
fn foog<T>(_: &[T], _: &[T]) {}
-fn bar(_: [Box<Foo>; 2]) {}
-fn bars(_: &[Box<Foo+'static>]) {}
+fn bar(_: [Box<dyn Foo>; 2]) {}
+fn bars(_: &[Box<dyn Foo+'static>]) {}
fn main() {
- let x: [&Foo; 2] = [&1, &2];
+ let x: [&dyn Foo; 2] = [&1, &2];
foo(x);
foo([&1, &2]);
let r = &1;
- let x: [&Foo; 2] = [r; 2];
+ let x: [&dyn Foo; 2] = [r; 2];
foo(x);
foo([&1; 2]);
- let x: &[&Foo] = &[&1, &2];
+ let x: &[&dyn Foo] = &[&1, &2];
foos(x);
foos(&[&1, &2]);
- let x: &[&Foo] = &[&1, &2];
+ let x: &[&dyn Foo] = &[&1, &2];
let r = &1;
foog(x, &[r]);
- let x: [Box<Foo>; 2] = [Box::new(1), Box::new(2)];
+ let x: [Box<dyn Foo>; 2] = [Box::new(1), Box::new(2)];
bar(x);
bar([Box::new(1), Box::new(2)]);
- let x: &[Box<Foo+'static>] = &[Box::new(1), Box::new(2)];
+ let x: &[Box<dyn Foo+'static>] = &[Box::new(1), Box::new(2)];
bars(x);
bars(&[Box::new(1), Box::new(2)]);
- let x: &[Box<Foo+'static>] = &[Box::new(1), Box::new(2)];
+ let x: &[Box<dyn Foo+'static>] = &[Box::new(1), Box::new(2)];
foog(x, &[Box::new(1)]);
struct T<'a> {
- t: [&'a (Foo+'a); 2]
+ t: [&'a (dyn Foo+'a); 2]
}
let _n = T {
t: [&1, &2]
let _n = T {
t: [r; 2]
};
- let x: [&Foo; 2] = [&1, &2];
+ let x: [&dyn Foo; 2] = [&1, &2];
let _n = T {
t: x
};
struct F<'b> {
- t: &'b [&'b (Foo+'b)]
+ t: &'b [&'b (dyn Foo+'b)]
}
let _n = F {
t: &[&1, &2]
};
let r = &1;
- let r: [&Foo; 2] = [r; 2];
+ let r: [&dyn Foo; 2] = [r; 2];
let _n = F {
t: &r
};
- let x: [&Foo; 2] = [&1, &2];
+ let x: [&dyn Foo; 2] = [&1, &2];
let _n = F {
t: &x
};
struct M<'a> {
- t: &'a [Box<Foo+'static>]
+ t: &'a [Box<dyn Foo+'static>]
}
let _n = M {
t: &[Box::new(1), Box::new(2)]
};
- let x: [Box<Foo>; 2] = [Box::new(1), Box::new(2)];
+ let x: [Box<dyn Foo>; 2] = [Box::new(1), Box::new(2)];
let _n = M {
t: &x
};
fn next(&mut self) -> Option<isize> { None }
}
-fn do_something_with(a : &mut T<isize>) {
+fn do_something_with(a : &mut dyn T<isize>) {
println!("{:?}", a.next())
}
fn dummy(&self) -> T { panic!() }
}
-struct S<T> {f: Box<X<T>+'static>,
- g: Box<X<T>+'static>}
+struct S<T> {f: Box<dyn X<T>+'static>,
+ g: Box<dyn X<T>+'static>}
struct F;
impl X<isize> for F {
struct S {x:()}
-fn test(slot: &mut Option<Box<FnMut() -> Box<FnMut()>>>) -> () {
+fn test(slot: &mut Option<Box<dyn FnMut() -> Box<dyn FnMut()>>>) -> () {
let a = slot.take();
let _a = match a {
// `{let .. a(); }` would break
// run-pass
fn main() {
- fn test() -> Box<std::any::Any + 'static> { Box::new(1) }
+ fn test() -> Box<dyn std::any::Any + 'static> { Box::new(1) }
println!("{:?}", test())
}
TypeId::of::<FooFnPtr>(),
TypeId::of::<FooNil>(),
TypeId::of::<FooTuple>(),
- TypeId::of::<FooTrait>(),
+ TypeId::of::<dyn FooTrait>(),
TypeId::of::<FooStruct>(),
TypeId::of::<FooEnum>()
]
// pretty-expanded FIXME #23616
struct Foo<'a> {
- listener: Box<FnMut() + 'a>,
+ listener: Box<dyn FnMut() + 'a>,
}
impl<'a> Foo<'a> {
fn main() {
let v: Box<_> = box B1;
- let _c: Box<A> = v.clone();
+ let _c: Box<dyn A> = v.clone();
}
// pretty-expanded FIXME #23616
fn main() {
- send::<Box<Foo>>(Box::new(Output(0)));
- Test::<Box<Foo>>::foo(Box::new(Output(0)));
- Test::<Box<Foo>>::new().send(Box::new(Output(0)));
+ send::<Box<dyn Foo>>(Box::new(Output(0)));
+ Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
+ Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
}
fn send<T>(_: T) {}
impl SomeTrait for Meow {}
struct Foo<'a> {
- x: &'a SomeTrait,
- y: &'a SomeTrait,
+ x: &'a dyn SomeTrait,
+ y: &'a dyn SomeTrait,
}
impl<'a> Foo<'a> {
- pub fn new<'b>(x: &'b SomeTrait, y: &'b SomeTrait) -> Foo<'b> { Foo { x: x, y: y } }
+ pub fn new<'b>(x: &'b dyn SomeTrait, y: &'b dyn SomeTrait) -> Foo<'b> { Foo { x: x, y: y } }
}
fn main() {
let r = Meow;
let s = Meow;
- let q = Foo::new(&r as &SomeTrait, &s as &SomeTrait);
+ let q = Foo::new(&r as &dyn SomeTrait, &s as &dyn SomeTrait);
}
struct CharPredMatcher<'a, 'b> {
str: &'a str,
- pred: Box<FnMut(char) -> bool + 'b>,
+ pred: Box<dyn FnMut(char) -> bool + 'b>,
}
impl<'a, 'b> Matcher for CharPredMatcher<'a, 'b> {
struct Bar;
-impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar {
- extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
+impl<'a> std::ops::Fn<(&'a (dyn Foo+'a),)> for Bar {
+ extern "rust-call" fn call(&self, _: (&'a dyn Foo,)) {}
}
-impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar {
- extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) }
+impl<'a> std::ops::FnMut<(&'a (dyn Foo+'a),)> for Bar {
+ extern "rust-call" fn call_mut(&mut self, a: (&'a dyn Foo,)) { self.call(a) }
}
-impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar {
+impl<'a> std::ops::FnOnce<(&'a (dyn Foo+'a),)> for Bar {
type Output = ();
- extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) }
+ extern "rust-call" fn call_once(self, a: (&'a dyn Foo,)) { self.call(a) }
}
struct Baz;
// Check struct instantiation (Box<TraitWithSend> will only have Send if TraitWithSend has Send)
#[allow(dead_code)]
-struct Blah { x: Box<TraitWithSend> }
+struct Blah { x: Box<dyn TraitWithSend> }
impl TraitWithSend for Blah {}
// Struct instantiation 2-levels deep
#[allow(dead_code)]
-struct IndirectBlah { x: Box<IndirectTraitWithSend> }
+struct IndirectBlah { x: Box<dyn IndirectTraitWithSend> }
impl TraitWithSend for IndirectBlah {}
impl IndirectTraitWithSend for IndirectBlah {}
fn test_trait<T: Send + ?Sized>() { println!("got here!") }
fn main() {
- test_trait::<TraitWithSend>();
- test_trait::<IndirectTraitWithSend>();
+ test_trait::<dyn TraitWithSend>();
+ test_trait::<dyn IndirectTraitWithSend>();
}
assert_eq!(cc().unwrap(), 3);
assert_eq!(dd().unwrap(), 3);
- let i = box 32isize as Box<A>;
+ let i = box 32isize as Box<dyn A>;
assert_eq!(i.aaa(), 3);
- let i = box 32isize as Box<A>;
+ let i = box 32isize as Box<dyn A>;
assert_eq!(i.bbb(), 3);
- let i = box 32isize as Box<A>;
+ let i = box 32isize as Box<dyn A>;
assert_eq!(i.ccc().unwrap(), 3);
- let i = box 32isize as Box<A>;
+ let i = box 32isize as Box<dyn A>;
assert_eq!(i.ddd().unwrap(), 3);
}
}
fn main() {
- let mut f = box Foo { foo: 42 } as Box<FnMut() -> u32>;
+ let mut f = box Foo { foo: 42 } as Box<dyn FnMut() -> u32>;
assert_eq!(f.call_mut(()), 42);
- let mut f = box Foo { foo: 40 } as Box<FnMut(u32) -> u32>;
+ let mut f = box Foo { foo: 40 } as Box<dyn FnMut(u32) -> u32>;
assert_eq!(f.call_mut((2,)), 42);
- let mut f = box Foo { foo: 40 } as Box<FnMut(u32, u32) -> u32>;
+ let mut f = box Foo { foo: 40 } as Box<dyn FnMut(u32, u32) -> u32>;
assert_eq!(f.call_mut((1, 1)), 42);
}
}
fn main() {
- let _ = &foo as &Any;
+ let _ = &foo as &dyn Any;
}
use std::io::{self, Write};
-fn f(wr: &mut Write) {
+fn f(wr: &mut dyn Write) {
wr.write_all(b"hello").ok().expect("failed");
}
fn main() {
- let mut wr = box io::stdout() as Box<Write>;
+ let mut wr = box io::stdout() as Box<dyn Write>;
f(&mut wr);
}
impl<'a, S: ?Sized> Str for &'a S where S: Str {}
fn main() {
- let _: &Str = &"x";
+ let _: &dyn Str = &"x";
}
trait Aaa { fn dummy(&self) { } }
-impl<'a> Aaa for &'a mut (Aaa + 'a) {}
+impl<'a> Aaa for &'a mut (dyn Aaa + 'a) {}
struct Bar<'a> {
- writer: &'a mut (Aaa + 'a),
+ writer: &'a mut (dyn Aaa + 'a),
}
-fn baz(_: &mut Aaa) {
+fn baz(_: &mut dyn Aaa) {
}
fn foo<'a>(mut bar: Bar<'a>) {
// run-pass
-fn action(mut cb: Box<FnMut(usize) -> usize>) -> usize {
+fn action(mut cb: Box<dyn FnMut(usize) -> usize>) -> usize {
cb(1)
}
box_4: fn () -> Box<[i8; 4]>,
) {
println!("Hello World 1");
- let _: Box<Boo> = match 3 {
+ let _: Box<dyn Boo> = match 3 {
1 => box_1(),
2 => box_2(),
3 => box_3(),
// pretty-expanded FIXME #23616
fn main() {
- let functions: [Box<Fn() -> Option<()>>; 1] = [Box::new(|| None)];
+ let functions: [Box<dyn Fn() -> Option<()>>; 1] = [Box::new(|| None)];
let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect();
}
use std::fmt;
fn main() {
- let a: &fmt::Debug = &1;
+ let a: &dyn fmt::Debug = &1;
format!("{:?}", a);
}
#![allow(unused_mut)]
#![allow(unused_variables)]
fn main() {
- let mut shrinker: Box<Iterator<Item=i32>> = Box::new(vec![1].into_iter());
+ let mut shrinker: Box<dyn Iterator<Item=i32>> = Box::new(vec![1].into_iter());
println!("{:?}", shrinker.next());
for v in shrinker { assert!(false); }
- let mut shrinker: &mut Iterator<Item=i32> = &mut vec![1].into_iter();
+ let mut shrinker: &mut dyn Iterator<Item=i32> = &mut vec![1].into_iter();
println!("{:?}", shrinker.next());
for v in shrinker { assert!(false); }
}
// str
std::intrinsics::type_name::<str>(),
// Trait
- std::intrinsics::type_name::<Send>(),
+ std::intrinsics::type_name::<dyn Send>(),
// Newtype
std::intrinsics::type_name::<NT>(),
// DST
fn main() {
let v = vec![1, 2, 3];
- let boxed: Box<Iterator<Item=i32>> = Box::new(v.into_iter());
+ let boxed: Box<dyn Iterator<Item=i32>> = Box::new(v.into_iter());
assert_eq!(boxed.max(), Some(3));
let v = vec![1, 2, 3];
- let boxed: &mut Iterator<Item=i32> = &mut v.into_iter();
+ let boxed: &mut dyn Iterator<Item=i32> = &mut v.into_iter();
assert_eq!(boxed.max(), Some(3));
}
// run-pass
-fn test(it: &mut Iterator<Item=i32>) {
+fn test(it: &mut dyn Iterator<Item=i32>) {
for x in it {
assert_eq!(x, 1)
}
static generations: usize = 1024+256+128+49;
-fn spawn(mut f: Box<FnMut() + 'static + Send>) {
+fn spawn(mut f: Box<dyn FnMut() + 'static + Send>) {
Builder::new().stack_size(32 * 1024).spawn(move|| f());
}
-fn child_no(x: usize) -> Box<FnMut() + 'static + Send> {
+fn child_no(x: usize) -> Box<dyn FnMut() + 'static + Send> {
Box::new(move|| {
if x < generations {
spawn(child_no(x+1));
// pretty-expanded FIXME #23616
// This used to cause an ICE because the retslot for the "return" had the wrong type
-fn testcase<'a>() -> Box<Iterator<Item=usize> + 'a> {
+fn testcase<'a>() -> Box<dyn Iterator<Item=usize> + 'a> {
return Box::new((0..3).map(|i| { return i; }));
}
}
}
-fn f<A>(x: Box<clam<A>>, a: A) {
+fn f<A>(x: Box<dyn clam<A>>, a: A) {
x.chowder(a);
}
pub fn main() {
let c = foo(42);
- let d: Box<clam<isize>> = box c as Box<clam<isize>>;
+ let d: Box<dyn clam<isize>> = box c as Box<dyn clam<isize>>;
f(d, c.x);
}
}
}
-fn check_trait_obj(val: &Foo<Get>) {
+fn check_trait_obj(val: &Foo<dyn Get>) {
match *val {
Foo { a, ref inner } => {
assert_eq!(a, 32);
check_dst_val(foo);
check_both(foo);
- let foo: &Foo<Get> = &Foo { a: 32, inner: 32 };
+ let foo: &Foo<dyn Get> = &Foo { a: 32, inner: 32 };
check_trait_obj(foo);
}
}
fn main() {
- let mut x: Box<Iterator<Item=Token>> = Box::new(Counter { value: 22 });
+ let mut x: Box<dyn Iterator<Item=Token>> = Box::new(Counter { value: 22 });
assert_eq!(x.next().unwrap().value, 22);
}
impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
-fn wants_foo(f: Box<Foo>) -> i32 {
+fn wants_foo(f: Box<dyn Foo>) -> i32 {
f(42)
}
}
pub struct Listener<'a> {
- pub announce: Option<Box<FnMut(&mut Registry) + 'a>>,
- pub remove: Option<Box<FnMut(&mut Registry) + 'a>>,
+ pub announce: Option<Box<dyn FnMut(&mut Registry) + 'a>>,
+ pub remove: Option<Box<dyn FnMut(&mut Registry) + 'a>>,
}
impl<'a> Drop for Registry<'a> {
pub trait ToRouting {
type Input;
- type Routing : ?Sized = Routing<Self::Input, Output=()>;
+ type Routing : ?Sized = dyn Routing<Self::Input, Output=()>;
fn to_routing(self) -> Self::Routing;
}
let mut drops = 0;
{
- let _: Rc<Send> = Rc::new(Foo(&mut drops));
+ let _: Rc<dyn Send> = Rc::new(Foo(&mut drops));
}
assert_eq!(1, drops);
drops = 0;
{
- let y = &Holder(Foo(&mut drops)) as &Holder<Trait>;
+ let y = &Holder(Foo(&mut drops)) as &Holder<dyn Trait>;
// this used to cause an extra drop of the Foo instance
let x = &y.0;
}
}
}
-const FUNC: &'static Fn(&mut Foo) -> () = &Foo::x;
+const FUNC: &'static dyn Fn(&mut Foo) -> () = &Foo::x;
fn main() {
let mut foo = Foo { a: 137 };
// run-pass
-struct Parser<'a>(Box<FnMut(Parser) + 'a>);
+struct Parser<'a>(Box<dyn FnMut(Parser) + 'a>);
fn main() {
let _x = Parser(Box::new(|_|{}));
let mut x = 0;
{
let wrapper = Box::new(Wrapper(&mut x, 123));
- let _: Box<Wrapper<Send>> = wrapper;
+ let _: Box<Wrapper<dyn Send>> = wrapper;
}
assert_eq!(432, x)
}
pub struct FooBar;
impl Foo<'static> for FooBar {}
-fn test(foobar: FooBar) -> Box<Foo<'static>> {
+fn test(foobar: FooBar) -> Box<dyn Foo<'static>> {
Box::new(foobar)
}
struct NonOrd;
fn main() {
- let _: Box<Iterator<Item = _>> = Box::new(vec![NonOrd].into_iter());
+ let _: Box<dyn Iterator<Item = _>> = Box::new(vec![NonOrd].into_iter());
}
let data = [1, 2, 3];
let iter = data.iter();
let x = MyRc { _ptr: &iter, _boo: PhantomData };
- let _y: MyRc<Iterator<Item=&u32>> = x;
+ let _y: MyRc<dyn Iterator<Item=&u32>> = x;
}
// run-pass
fn main() {
- const _C: &'static Fn() = &||{};
+ const _C: &'static dyn Fn() = &||{};
}
}
impl<A> hax for A { }
-fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax+'static> {
- box x as Box<hax+'static>
+fn perform_hax<T: 'static>(x: Box<T>) -> Box<dyn hax+'static> {
+ box x as Box<dyn hax+'static>
}
fn deadcode() {
}
impl<A> hax for A { }
-fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax+'static> {
- box x as Box<hax+'static>
+fn perform_hax<T: 'static>(x: Box<T>) -> Box<dyn hax+'static> {
+ box x as Box<dyn hax+'static>
}
fn deadcode() {
// run-pass
-static PLUS_ONE: &'static (Fn(i32) -> i32 + Sync) = (&|x: i32| { x + 1 })
- as &'static (Fn(i32) -> i32 + Sync);
+static PLUS_ONE: &'static (dyn Fn(i32) -> i32 + Sync) = (&|x: i32| { x + 1 })
+ as &'static (dyn Fn(i32) -> i32 + Sync);
fn main() {
assert_eq!(PLUS_ONE(2), 3);
// let y = box ({a: 4});
// let z = box ({a: 4} as it);
// let z = box ({a: true} as it);
- let z: Box<_> = box (box true as Box<it>);
+ let z: Box<_> = box (box true as Box<dyn it>);
// x.f();
// y.f();
// (*z).f();
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-type Connection = Box<FnMut(Vec<u8>) + 'static>;
+type Connection = Box<dyn FnMut(Vec<u8>) + 'static>;
fn f() -> Option<Connection> {
let mock_connection: Connection = Box::new(|_| {});
pub enum Handler {
Default,
#[allow(dead_code)]
- Custom(*mut Box<Fn()>),
+ Custom(*mut Box<dyn Fn()>),
}
fn main() {
}
#[inline(never)]
-pub fn take(h: Handler, f: Box<Fn()>) -> Box<Fn()> {
+pub fn take(h: Handler, f: Box<dyn Fn()>) -> Box<dyn Fn()> {
unsafe {
match h {
Handler::Custom(ptr) => *Box::from_raw(ptr),
// run-pass
fn main() {
- &0u8 as *const u8 as *const PartialEq<u8>;
+ &0u8 as *const u8 as *const dyn PartialEq<u8>;
&[0u8] as *const [u8; 1] as *const [u8];
}
fn foo<T>() -> T { loop {} }
fn test() {
- let ref mut a: &mut FnMut((i8,), i16) = foo();
+ let ref mut a: &mut dyn FnMut((i8,), i16) = foo();
a((0,), 0);
}
struct Bar<T: ?Sized>(T);
-fn unsize_fat_ptr<'a>(x: &'a Bar<Foo + Send + 'a>) -> &'a Bar<Foo + 'a> {
+fn unsize_fat_ptr<'a>(x: &'a Bar<dyn Foo + Send + 'a>) -> &'a Bar<dyn Foo + 'a> {
x
}
-fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
+fn unsize_nested_fat_ptr(x: Arc<dyn Foo + Send>) -> Arc<dyn Foo> {
x
}
fn main() {
- let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
+ let x: Box<Bar<dyn Foo + Send>> = Box::new(Bar([1,2]));
assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);
- let x: Arc<Foo + Send> = Arc::new([3, 4]);
+ let x: Arc<dyn Foo + Send> = Arc::new([3, 4]);
assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]);
}
fn main() {
let ball = TheType { t: PhantomData };
- let handle: &Shape<()> = &ball;
+ let handle: &dyn Shape<()> = &ball;
}
where Option<T>: Ord { *x < *x }
}
impl Foo<X> for () {}
- let _ = &() as &Foo<X>;
+ let _ = &() as &dyn Foo<X>;
}
fn main() {
let foo: &Foo<i32> = &Foo { a: 1, b: false, c: 2i32 };
- let foo_unsized: &Foo<Send> = foo;
+ let foo_unsized: &Foo<dyn Send> = foo;
assert_eq!(mem::size_of_val(foo), mem::size_of_val(foo_unsized));
}
// Make sure this compiles without getting a linker error because of missing
// drop-glue because the collector missed adding drop-glue for the closure:
-fn create_fn() -> Box<Fn()> {
+fn create_fn() -> Box<dyn Fn()> {
let text = String::new();
Box::new(move || { let _ = &text; })
// correctly
fn main() {
- let x : Vec<Box<Fn()>> = vec![Box::new(|| ())];
+ let x : Vec<Box<dyn Fn()>> = vec![Box::new(|| ())];
x[0]()
}
fn to_string(&self) -> String;
}
- fn to_string(t: Box<Text>) {
+ fn to_string(t: Box<dyn Text>) {
println!("{}", (*t).to_string());
}
}
}
-fn print_t(t: &T) {
+fn print_t(t: &dyn T) {
t.print();
}
pub fn main() {
let s: Box<S> = box S { s: 5 };
print_s(&*s);
- let t: Box<T> = s as Box<T>;
+ let t: Box<dyn T> = s as Box<dyn T>;
print_t(&*t);
}
impl Bar for () {}
fn main() {
- (&() as &Bar).print(); // Segfault
+ (&() as &dyn Bar).print(); // Segfault
}
struct LocalG<T>(T);
fn main() {
- let virtual_localc : &Fn(_) -> LocalC = &LocalC;
+ let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
assert_eq!(virtual_localc(1), LocalC(1));
- let virtual_localg : &Fn(_) -> LocalG<u32> = &LocalG;
+ let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
assert_eq!(virtual_localg(1), LocalG(1));
- let virtual_remotec : &Fn(_) -> RemoteC = &RemoteC;
+ let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
assert_eq!(virtual_remotec(1), RemoteC(1));
- let virtual_remoteg : &Fn(_) -> RemoteG<u32> = &RemoteG;
+ let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
assert_eq!(virtual_remoteg(1), RemoteG(1));
}
pub struct Foo;
impl Iterator for Foo {
- type Item = Box<Trait>;
- fn next(&mut self) -> Option<Box<Trait>> {
+ type Item = Box<dyn Trait>;
+ fn next(&mut self) -> Option<Box<dyn Trait>> {
extern crate issue_41053;
impl ::Trait for issue_41053::Test {
fn foo(&self) {}
impl Tc for bool {}
fn main() {
- let _: &[&Tc] = &[&true];
+ let _: &[&dyn Tc] = &[&true];
}
trait Baz {
}
-impl Foo for (Bar, Baz) { }
+impl Foo for (Bar, dyn Baz) { }
fn main() {
- <(Bar, Baz) as Foo>::foo()
+ <(Bar, dyn Baz) as Foo>::foo()
}
fn foo() {
let b = mk::<
- Forward<(Box<Future<Error = u32>>,)>,
+ Forward<(Box<dyn Future<Error = u32>>,)>,
>();
b.map_err(|_| ()).join();
}
use std::io;
pub fn main() {
- let stdout = &mut io::stdout() as &mut io::Write;
+ let stdout = &mut io::stdout() as &mut dyn io::Write;
stdout.write(b"Hello!");
}
// run-pass
#![allow(unused_variables)]
-fn id<'c, 'b>(f: &'c &'b Fn(&i32)) -> &'c &'b Fn(&'static i32) {
+fn id<'c, 'b>(f: &'c &'b dyn Fn(&i32)) -> &'c &'b dyn Fn(&'static i32) {
f
}
fn main() {
- let f: &Fn(&i32) = &|x| {};
+ let f: &dyn Fn(&i32) = &|x| {};
id(&f);
}
fn debug_name(&self) -> String { self.name.clone() }
}
-fn print_name(x: &Debuggable)
+fn print_name(x: &dyn Debuggable)
{
println!("debug_name = {}", x.debug_name());
}
pub fn main() {
let thing = Thing::new();
- print_name(&thing as &Debuggable);
+ print_name(&thing as &dyn Debuggable);
}
}
pub struct Scheduler {
- event_loop: Box<EventLoop+'static>,
+ event_loop: Box<dyn EventLoop+'static>,
}
impl Scheduler {
- pub fn new(event_loop: Box<EventLoop+'static>) -> Scheduler {
+ pub fn new(event_loop: Box<dyn EventLoop+'static>) -> Scheduler {
Scheduler {
event_loop: event_loop,
}
}
pub fn main() {
- let _sched = Scheduler::new(box UvEventLoop::new() as Box<EventLoop>);
+ let _sched = Scheduler::new(box UvEventLoop::new() as Box<dyn EventLoop>);
}
pub fn main() {
let snoopy = box Dog{name: "snoopy".to_string()};
let bubbles = box Dog{name: "bubbles".to_string()};
- let barker = [snoopy as Box<Barks>, bubbles as Box<Barks>];
+ let barker = [snoopy as Box<dyn Barks>, bubbles as Box<dyn Barks>];
for pup in &barker {
println!("{}", pup.bark());
}
struct Outer<'a> {
- inner: &'a (Inner+'a)
+ inner: &'a (dyn Inner+'a)
}
impl<'a> Outer<'a> {
- fn new(inner: &Inner) -> Outer {
+ fn new(inner: &dyn Inner) -> Outer {
Outer {
inner: inner
}
pub fn main() {
let inner: isize = 5;
- let outer = Outer::new(&inner as &Inner);
+ let outer = Outer::new(&inner as &dyn Inner);
outer.inner.print();
}
}
pub struct MyContainer<'a, T:'a> {
- foos: Vec<&'a (MyTrait<T>+'a)> ,
+ foos: Vec<&'a (dyn MyTrait<T>+'a)> ,
}
impl<'a, T> MyContainer<'a, T> {
- pub fn add (&mut self, foo: &'a MyTrait<T>) {
+ pub fn add (&mut self, foo: &'a dyn MyTrait<T>) {
self.foos.push(foo);
}
}
fn main() {
let a = A;
- let br = &a as &B;
+ let br = &a as &dyn B;
br.f();
}
pub fn main() {
let g : Box<HashMap<isize,isize>> = box HashMap::new();
- let _g2 : Box<Graph<isize,isize>> = g as Box<Graph<isize,isize>>;
+ let _g2 : Box<dyn Graph<isize,isize>> = g as Box<dyn Graph<isize,isize>>;
}
}
}
-fn squarei<'a>(x: isize, op: &'a mut OpInt) -> isize { op.call(x, x) }
+fn squarei<'a>(x: isize, op: &'a mut dyn OpInt) -> isize { op.call(x, x) }
fn muli(x:isize, y:isize) -> isize { x * y }
let mut f = |x, y| muli(x, y);
{
let g = &mut f;
- let h = g as &mut OpInt;
+ let h = g as &mut dyn OpInt;
squarei(3, h);
}
}
#![feature(box_syntax)]
pub enum Thing {
- A(Box<Foo+'static>)
+ A(Box<dyn Foo+'static>)
}
pub trait Foo {
impl Foo for Struct {}
pub fn main() {
- match Thing::A(box Struct as Box<Foo+'static>) {
+ match Thing::A(box Struct as Box<dyn Foo + 'static>) {
Thing::A(_a) => 0,
};
}
}
impl<'a> B<'a> {
- fn get_pa(&self) -> &'a IDummy { self.pa as &'a IDummy }
+ fn get_pa(&self) -> &'a dyn IDummy { self.pa as &'a dyn IDummy }
}
pub fn main() {
impl FooBar for Bar {}
trait Test {
- fn get_immut(&self) -> &FooBar;
- fn get_mut(&mut self) -> &mut FooBar;
+ fn get_immut(&self) -> &dyn FooBar;
+ fn get_mut(&mut self) -> &mut dyn FooBar;
}
macro_rules! generate_test { ($type_:path, $slf:ident, $field:expr) => (
impl Test for $type_ {
- fn get_immut(&$slf) -> &FooBar {
- &$field as &FooBar
+ fn get_immut(&$slf) -> &dyn FooBar {
+ &$field as &dyn FooBar
}
- fn get_mut(&mut $slf) -> &mut FooBar {
- &mut $field as &mut FooBar
+ fn get_mut(&mut $slf) -> &mut dyn FooBar {
+ &mut $field as &mut dyn FooBar
}
}
)}
struct B;
impl A for B {}
-fn foo(_: &mut A) {}
+fn foo(_: &mut dyn A) {}
pub fn main() {
let mut b = B;
- foo(&mut b as &mut A);
+ foo(&mut b as &mut dyn A);
}
impl A for B {}
struct C<'a> {
- foo: &'a mut (A+'a),
+ foo: &'a mut (dyn A+'a),
}
-fn foo(a: &mut A) {
+fn foo(a: &mut dyn A) {
C{ foo: a };
}
Ident {name: 0x6789ABCD }
}
-pub fn light_fuse(fld: Box<bomb>) {
+pub fn light_fuse(fld: Box<dyn bomb>) {
int3!();
let f = || {
int3!();
}
pub fn main() {
- let b = box S as Box<bomb>;
+ let b = box S as Box<dyn bomb>;
light_fuse(b);
}
pub fn main() {
let n = X;
- let s = &n as &Super;
+ let s = &n as &dyn Super;
assert_eq!(s.bar(),"super bar".to_string());
assert_eq!(s.foo(),"base foo".to_string());
assert_eq!(s.foo1(),"base foo1".to_string());
}
fn main() {
- let (a, b) = (&5u8 as &Bar, &9u8 as &Bar);
- let (c, d): (&Bar, &Bar) = (a, b);
+ let (a, b) = (&5u8 as &dyn Bar, &9u8 as &dyn Bar);
+ let (c, d): (&dyn Bar, &dyn Bar) = (a, b);
- let (a, b) = (Box::new(5u8) as Box<Bar>, Box::new(9u8) as Box<Bar>);
- let (c, d): (&Bar, &Bar) = (&*a, &*b);
+ let (a, b) = (Box::new(5u8) as Box<dyn Bar>, Box::new(9u8) as Box<dyn Bar>);
+ let (c, d): (&dyn Bar, &dyn Bar) = (&*a, &*b);
- let (c, d): (&Bar, &Bar) = (&5, &9);
+ let (c, d): (&dyn Bar, &dyn Bar) = (&5, &9);
}
struct A { a: Box<isize> }
-fn foo() -> Box<FnMut() -> isize + 'static> {
+fn foo() -> Box<dyn FnMut() -> isize + 'static> {
let k: Box<_> = Box::new(22);
let _u = A {a: k.clone()};
let result = || 22;
use std::fmt;
struct Foo<'a> {
- writer: &'a mut (Write+'a),
+ writer: &'a mut (dyn Write+'a),
other: &'a str,
}
fn main() {
let mut w = Vec::new();
- write!(&mut w as &mut Write, "").unwrap();
+ write!(&mut w as &mut dyn Write, "").unwrap();
write!(&mut w, "").unwrap(); // should coerce
println!("ok");
let x: m!() = m!();
std::cell::Cell::<m!()>::new(m!());
- impl<T> std::ops::Index<m!()> for Trait<(m!(), T)>
+ impl<T> std::ops::Index<m!()> for dyn Trait<(m!(), T)>
where T: Trait<m!()>
{
type Output = m!();
pub struct S<T>(T);
impl Service for ClientMap {
- type Request = S<Box<Fn(i32)>>;
+ type Request = S<Box<dyn Fn(i32)>>;
fn call(&self, _req: Self::Request) {}
}
impl Service for ClientMap2 {
- type Request = (Box<Fn(i32)>,);
+ type Request = (Box<dyn Fn(i32)>,);
fn call(&self, _req: Self::Request) {}
}
x.extension_method(a)
}
-fn test5(x: &Bar, a: isize) -> isize {
+fn test5(x: &dyn Bar, a: isize) -> isize {
// Test calling method on trait object
x.extension_method(a)
}
f(x, y)
}
-fn test_fn_object(f: &Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
+fn test_fn_object(f: &dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
f(x, y)
}
-fn test_fn_impl(f: &&Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
+fn test_fn_impl(f: &&dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
// This call goes through the Fn implementation for &Fn provided in
// core::ops::impls. It expands to a static Fn::call() that calls the
// Fn::call() implementation of the object shim underneath.
let closure = |x: i32, y: i32| { r*(x + (y*2)) };
assert_eq!(test_fn_const_call(&closure), 294);
assert_eq!(test_closure(&closure, 100, 1), 306);
- let function_object = &closure as &Fn(i32, i32) -> i32;
+ let function_object = &closure as &dyn Fn(i32, i32) -> i32;
assert_eq!(test_fn_object(function_object, 100, 2), 312);
assert_eq!(test_fn_impl(&function_object, 100, 3), 318);
assert_eq!(test_fn_direct_call(&closure, 100, 4), 324);
}
// Make sure we actually codegen a version of the function
-pub fn do_stuff(mut f: Foo<Box<Iterator<Item=u32>>, Box<Iterator<Item=u32>>>) {
+pub fn do_stuff(mut f: Foo<Box<dyn Iterator<Item=u32>>, Box<dyn Iterator<Item=u32>>>) {
let _x = f.next();
}
use std::ops::CoerceUnsized;
use std::marker::Unsize;
-fn identity_coercion(x: &(Fn(u32)->u32 + Send)) -> &Fn(u32)->u32 {
+fn identity_coercion(x: &(dyn Fn(u32)->u32 + Send)) -> &dyn Fn(u32)->u32 {
x
}
fn fn_coercions(f: &fn(u32) -> u32) ->
(unsafe fn(u32) -> u32,
- &(Fn(u32) -> u32+Send))
+ &(dyn Fn(u32) -> u32+Send))
{
(*f, f)
}
p
}
-fn coerce_fat_ptr_wrapper(p: PtrWrapper<Fn(u32) -> u32+Send>)
- -> PtrWrapper<Fn(u32) -> u32> {
+fn coerce_fat_ptr_wrapper(p: PtrWrapper<dyn Fn(u32) -> u32+Send>)
+ -> PtrWrapper<dyn Fn(u32) -> u32> {
p
}
let z = coerce_fat_ptr_wrapper(PtrWrapper(2,3,(),&square_local));
assert_eq!((z.3)(6), 36);
- let z: PtrWrapper<Fn(u32) -> u32> =
+ let z: PtrWrapper<dyn Fn(u32) -> u32> =
coerce_ptr_wrapper_poly(PtrWrapper(2,3,(),&square_local));
assert_eq!((z.3)(6), 36);
}
}
}
-fn compare_foo<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> ComparisonResults {
+fn compare_foo<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> ComparisonResults {
ComparisonResults {
lt: a < b,
le: a <= b,
}
}
-fn simple_eq<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> bool {
+fn simple_eq<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> bool {
let result = a == b;
result
}
let u32_ = (4u32, 5u32);
// check ordering for ptrs
- let buf: &mut [*const Foo] = &mut [
+ let buf: &mut [*const dyn Foo] = &mut [
&u8_, &u8_.0,
&u32_, &u32_.0,
];
}
}
-fn g(x: Box<Trait>) {
+fn g(x: Box<dyn Trait>) {
x.printme();
- let y: &Trait = &*x;
+ let y: &dyn Trait = &*x;
y.printme();
}
fn main() {
f(box 1234);
- g(box Struct as Box<Trait>);
+ g(box Struct as Box<dyn Trait>);
}
// pretty-expanded FIXME #23616
-fn unique() -> Box<FnMut()+'static> { return Box::new(|| ()); }
+fn unique() -> Box<dyn FnMut()+'static> { return Box::new(|| ()); }
pub fn main() {
}
// pretty-expanded FIXME #23616
-fn unique() -> Box<FnMut()+'static> { Box::new(|| ()) }
+fn unique() -> Box<dyn FnMut()+'static> { Box::new(|| ()) }
pub fn main() {
}
}
struct SomeStruct {
- t: Box<Test>,
- u: Box<Test+'static>,
+ t: Box<dyn Test>,
+ u: Box<dyn Test+'static>,
}
-fn a(t: Box<Test>, mut ss: SomeStruct) {
+fn a(t: Box<dyn Test>, mut ss: SomeStruct) {
ss.t = t;
}
-fn b(t: Box<Test+'static>, mut ss: SomeStruct) {
+fn b(t: Box<dyn Test+'static>, mut ss: SomeStruct) {
ss.t = t;
}
-fn c(t: Box<Test>, mut ss: SomeStruct) {
+fn c(t: Box<dyn Test>, mut ss: SomeStruct) {
ss.u = t;
}
-fn d(t: Box<Test+'static>, mut ss: SomeStruct) {
+fn d(t: Box<dyn Test+'static>, mut ss: SomeStruct) {
ss.u = t;
}
}
struct SomeStruct<'a> {
- t: &'a Box<Test>,
- u: &'a Box<Test+'a>,
+ t: &'a Box<dyn Test>,
+ u: &'a Box<dyn Test+'a>,
}
-fn a<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
+fn a<'a>(t: &'a Box<dyn Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn b<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
+fn b<'a>(t: &'a Box<dyn Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs
-fn d<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+fn d<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
}
struct SomeStruct<'a> {
- t: &'a mut Test,
- u: &'a mut (Test+'a),
+ t: &'a mut dyn Test,
+ u: &'a mut (dyn Test+'a),
}
-fn a<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
+fn a<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn b<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
+fn b<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) {
ss.u = t;
}
-fn c<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
+fn c<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn d<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
+fn d<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) {
ss.u = t;
}
}
struct SomeStruct<'a> {
- t: &'a Test,
- u: &'a (Test+'a),
+ t: &'a dyn Test,
+ u: &'a (dyn Test+'a),
}
-fn a<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
+fn a<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn b<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
+fn b<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) {
ss.u = t;
}
-fn c<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
+fn c<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn d<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
+fn d<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) {
ss.u = t;
}
-fn e<'a>(_: &'a (Display+'static)) {}
+fn e<'a>(_: &'a (dyn Display+'static)) {}
fn main() {
// Inside a function body, we can just infer both
// lifetimes, to allow &'tmp (Display+'static).
- e(&0 as &Display);
+ e(&0 as &dyn Display);
}
fn main() {
let x = 22;
- let x1: &SomeTrait<SomeType=i32> = &x;
+ let x1: &dyn SomeTrait<SomeType=i32> = &x;
let y = get_int(x1);
assert_eq!(x, y);
}
}
}
-fn do_it_mut(obj: &mut Foo) {
+fn do_it_mut(obj: &mut dyn Foo) {
let x = obj.bar();
let y = obj.foo();
assert_eq!(x, y);
do_it_imm(obj, y);
}
-fn do_it_imm(obj: &Foo, v: usize) {
+fn do_it_imm(obj: &dyn Foo, v: usize) {
let y = obj.foo();
assert_eq!(v, y);
}
pub fn main() {
let mut x: usize = 22;
- let obj = &mut x as &mut Foo;
+ let obj = &mut x as &mut dyn Foo;
do_it_mut(obj);
do_it_imm(obj, 23);
do_it_mut(obj);
}
pub fn main() {
- let foos: Vec<Box<FooTrait>> = vec![
- box BarStruct{ x: 0 } as Box<FooTrait>,
- box BarStruct{ x: 1 } as Box<FooTrait>,
- box BarStruct{ x: 2 } as Box<FooTrait>
+ let foos: Vec<Box<dyn FooTrait>> = vec![
+ box BarStruct{ x: 0 } as Box<dyn FooTrait>,
+ box BarStruct{ x: 1 } as Box<dyn FooTrait>,
+ box BarStruct{ x: 2 } as Box<dyn FooTrait>
];
for i in 0..foos.len() {
}
pub fn main() {
- let foo = box BarStruct{ x: 22 } as Box<FooTrait>;
+ let foo = box BarStruct{ x: 22 } as Box<dyn FooTrait>;
assert_eq!(22, foo.foo());
}
// This is a bit tricky due to rust-call ABI.
-fn foo(f: &mut FnMut(isize) -> isize) -> isize {
+fn foo(f: &mut dyn FnMut(isize) -> isize) -> isize {
f(22)
}
// This is a bit tricky due to rust-call ABI.
-fn foo(f: &mut FnMut(isize, isize) -> isize) -> isize {
+fn foo(f: &mut dyn FnMut(isize, isize) -> isize) -> isize {
f(1, 2)
}
// This is a bit tricky due to rust-call ABI.
-fn foo(f: &mut FnMut() -> isize) -> isize {
+fn foo(f: &mut dyn FnMut() -> isize) -> isize {
f()
}
assert::<Box<[u8]>>();
trait Trait: UnwindSafe {}
- assert::<Box<Trait>>();
+ assert::<Box<dyn Trait>>();
fn bar<T>() {
assert::<Mutex<T>>();
fn test_single1() {
use foo1::Bar;
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
fn test_list1() {
use foo1::{Bar,Baz};
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
fn test_glob1() {
use foo1::*;
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
// private type, public value
use foo3::Bar;
Bar();
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
fn test_list3() {
use foo3::{Bar,Baz};
Bar();
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
fn test_glob3() {
use foo3::*;
Bar();
- let _x: Box<Bar>;
+ let _x: Box<dyn Bar>;
}
fn main() {
let mut u32_ = (4u32, 5u32);
// check ordering for ptrs
- let buf: &mut [*const Foo] = &mut [
+ let buf: &mut [*const dyn Foo] = &mut [
&u8_, &u8_.0,
&u32_, &u32_.0,
];
assert_inorder(buf);
// check ordering for mut ptrs
- let buf: &mut [*mut Foo] = &mut [
+ let buf: &mut [*mut dyn Foo] = &mut [
&mut u8_, &mut u8_.0,
&mut u32_, &mut u32_.0,
];
fn dummy(&self) { }
}
-fn foo<'a>(x: Box<Foo + 'a>) {
+fn foo<'a>(x: Box<dyn Foo + 'a>) {
}
fn bar<'a, T: 'a>() {
}
}
-fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
- box v as Box<SomeTrait+'a>
+fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait+'a> {
+ box v as Box<dyn SomeTrait+'a>
}
fn main() {
#![allow(non_camel_case_types)]
struct closure_box<'a> {
- cl: Box<FnMut() + 'a>,
+ cl: Box<dyn FnMut() + 'a>,
}
-fn box_it<'a>(x: Box<FnMut() + 'a>) -> closure_box<'a> {
+fn box_it<'a>(x: Box<dyn FnMut() + 'a>) -> closure_box<'a> {
closure_box {cl: x}
}
fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
}
-fn foo(conv: &AstConv) { }
+fn foo(conv: &dyn AstConv) { }
-fn bar<'tcx>(conv: &AstConv<'tcx>) {
+fn bar<'tcx>(conv: &dyn AstConv<'tcx>) {
foo(conv)
}
(l,s)
}
-fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) {
+fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) {
let l = x.long();
let s = x.short();
(l,s)
}
struct Struct1<'e> {
- f: &'e (Trait<'e>+'e)
+ f: &'e (dyn Trait<'e>+'e)
}
fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (isize,isize) {
}
struct Struct2<'h, 'i:'h> {
- f: &'h (Trait<'i>+'h)
+ f: &'h (dyn Trait<'i>+'h)
}
-fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> isize {
+fn object_invoke2<'j, 'k>(x: &'k dyn Trait<'j>) -> isize {
x.short()
}
}
}
-impl<'t> MakerTrait for Box<Trait<'t>+'static> {
- fn mk() -> Box<Trait<'t>+'static> {
+impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> {
+ fn mk() -> Box<dyn Trait<'t>+'static> {
let tup: Box<(isize, isize)> = box (4,5);
- tup as Box<Trait>
+ tup as Box<dyn Trait>
}
}
pub fn main() {
let t = (2,3);
- let o = &t as &Trait;
+ let o = &t as &dyn Trait;
let s1 = Struct1 { f: o };
let s2 = Struct2 { f: o };
assert_eq!(poly_invoke(&t), (2,3));
assert_eq!(object_invoke2(&t), 3);
assert_eq!(field_invoke2(&s2), 3);
- let m : Box<Trait> = make_val();
+ let m : Box<dyn Trait> = make_val();
// assert_eq!(object_invoke1(&*m), (4,5));
// ~~~~~~~~~~~~~~~~~~~
// this call yields a compilation error; see compile-fail/dropck-object-cycle.rs
// that `x` is in.
// pretty-expanded FIXME #23616
-fn has_same_region(f: Box<for<'a> FnMut(&'a isize, Box<FnMut(&'a isize)>)>) {
+fn has_same_region(f: Box<dyn for<'a> FnMut(&'a isize, Box<dyn FnMut(&'a isize)>)>) {
// `f` should be the type that `wants_same_region` wants, but
// right now the compiler complains that it isn't.
wants_same_region(f);
}
-fn wants_same_region(_f: Box<for<'b> FnMut(&'b isize, Box<FnMut(&'b isize)>)>) {
+fn wants_same_region(_f: Box<dyn for<'b> FnMut(&'b isize, Box<dyn FnMut(&'b isize)>)>) {
}
pub fn main() {
#![allow(unused_variables)]
// Should pass region checking.
-fn ok(f: Box<FnMut(&usize)>) {
+fn ok(f: Box<dyn FnMut(&usize)>) {
// Here, g is a function that can accept a usize pointer with
// lifetime r, and f is a function that can accept a usize pointer
// with any lifetime. The assignment g = f should be OK (i.e.,
// f's type should be a subtype of g's type), because f can be
// used in any context that expects g's type. But this currently
// fails.
- let mut g: Box<for<'r> FnMut(&'r usize)> = Box::new(|x| { });
+ let mut g: Box<dyn for<'r> FnMut(&'r usize)> = Box::new(|x| { });
g = f;
}
// This version is the same as above, except that here, g's type is
// inferred.
-fn ok_inferred(f: Box<FnMut(&usize)>) {
- let mut g: Box<for<'r> FnMut(&'r usize)> = Box::new(|_| {});
+fn ok_inferred(f: Box<dyn FnMut(&usize)>) {
+ let mut g: Box<dyn for<'r> FnMut(&'r usize)> = Box::new(|_| {});
g = f;
}
// contains region pointers
// pretty-expanded FIXME #23616
-struct foo(Box<FnMut(&isize)+'static>);
+struct foo(Box<dyn FnMut(&isize)+'static>);
fn take_foo<T:'static>(x: T) {}
pub fn main() {
fn explicit() {
- fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<for<'a> FnMut(&'a isize)>) {}
- test(Some(box |_f: Box<for<'a> FnMut(&'a isize)>| {}));
+ fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn for<'a> FnMut(&'a isize)>) {}
+ test(Some(box |_f: Box<dyn for<'a> FnMut(&'a isize)>| {}));
}
// The code below is shorthand for the code above (and more likely
// to represent what one encounters in practice).
fn implicit() {
- fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box< FnMut(& isize)>) {}
- test(Some(box |_f: Box< FnMut(& isize)>| {}));
+ fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn FnMut(& isize)>) {}
+ test(Some(box |_f: Box<dyn FnMut(& isize)>| {}));
}
explicit();
use std::rc::Rc;
#[derive(Clone)]
-enum CachedMir<'mir> {
+enum Cached<'mir> {
Ref(&'mir String),
Owned(Rc<String>),
}
-impl<'mir> CachedMir<'mir> {
+impl<'mir> Cached<'mir> {
fn get_ref<'a>(&'a self) -> &'a String {
match *self {
- CachedMir::Ref(r) => r,
- CachedMir::Owned(ref rc) => &rc,
+ Cached::Ref(r) => r,
+ Cached::Owned(ref rc) => &rc,
}
}
}
fn elaborate_bounds(
&mut self,
- mut mk_cand: Box<for<'b> FnMut(&mut Foo<'b, 'tcx>) -> isize>)
+ mut mk_cand: Box<dyn for<'b> FnMut(&mut Foo<'b, 'tcx>) -> isize>)
-> isize
{
mk_cand(self)
#![allow(non_camel_case_types)]
struct closure_box<'a> {
- cl: Box<FnMut() + 'a>,
+ cl: Box<dyn FnMut() + 'a>,
}
-fn box_it<'a>(x: Box<FnMut() + 'a>) -> closure_box<'a> {
+fn box_it<'a>(x: Box<dyn FnMut() + 'a>) -> closure_box<'a> {
closure_box {cl: x}
}
fn n(&self) -> u8 { *self.g }
}
-fn extension<'e>(x: &'e E<'e>) -> Box<M+'e> {
+fn extension<'e>(x: &'e E<'e>) -> Box<dyn M+'e> {
loop {
let p = P { g: x.m() };
- return Box::new(p) as Box<M+'e>;
+ return Box::new(p) as Box<dyn M+'e>;
}
}
use std::error::Error;
fn main() {
- let _err1: Box<Error + Send + Sync> = From::from("test".to_string());
- let _err2: Box<Error> = From::from("test".to_string());
- let _err3: Box<Error + Send + Sync + 'static> = From::from("test");
- let _err4: Box<Error> = From::from("test");
+ let _err1: Box<dyn Error + Send + Sync> = From::from("test".to_string());
+ let _err2: Box<dyn Error> = From::from("test".to_string());
+ let _err3: Box<dyn Error + Send + Sync + 'static> = From::from("test");
+ let _err4: Box<dyn Error> = From::from("test");
}
use std::string::ToString;
use cci_class_cast::kitty::cat;
-fn print_out(thing: Box<ToString>, expected: String) {
+fn print_out(thing: Box<dyn ToString>, expected: String) {
let actual = (*thing).to_string();
println!("{}", actual);
assert_eq!(actual.to_string(), expected);
}
pub fn main() {
- let nyan: Box<ToString> = box cat(0, 2, "nyan".to_string()) as Box<ToString>;
+ let nyan: Box<dyn ToString> = box cat(0, 2, "nyan".to_string()) as Box<dyn ToString>;
print_out(nyan, "nyan".to_string());
}
}
-fn annoy_neighbors(critter: &mut noisy) {
+fn annoy_neighbors(critter: &mut dyn noisy) {
for _i in 0_usize..10 { critter.speak(); }
}
pub fn main() {
let mut nyan = cat(0, 2, "nyan".to_string());
- let mut nyan: &mut noisy = &mut nyan;
+ let mut nyan: &mut dyn noisy = &mut nyan;
nyan.speak();
}
}
}
-fn print_out(thing: Box<ToString>, expected: String) {
+fn print_out(thing: Box<dyn ToString>, expected: String) {
let actual = (*thing).to_string();
println!("{}", actual);
assert_eq!(actual.to_string(), expected);
}
pub fn main() {
- let nyan: Box<ToString> = box cat(0, 2, "nyan".to_string()) as Box<ToString>;
+ let nyan: Box<dyn ToString> = box cat(0, 2, "nyan".to_string()) as Box<dyn ToString>;
print_out(nyan, "nyan".to_string());
}
assert_eq!(size_of::<&mut [isize]>(), size_of::<Option<&mut [isize]>>());
// Traits - Box<Trait> / &Trait / &mut Trait
- assert_eq!(size_of::<Box<Trait>>(), size_of::<Option<Box<Trait>>>());
- assert_eq!(size_of::<&Trait>(), size_of::<Option<&Trait>>());
- assert_eq!(size_of::<&mut Trait>(), size_of::<Option<&mut Trait>>());
+ assert_eq!(size_of::<Box<dyn Trait>>(), size_of::<Option<Box<dyn Trait>>>());
+ assert_eq!(size_of::<&dyn Trait>(), size_of::<Option<&dyn Trait>>());
+ assert_eq!(size_of::<&mut dyn Trait>(), size_of::<Option<&mut dyn Trait>>());
// Pointers - Box<T>
assert_eq!(size_of::<Box<isize>>(), size_of::<Option<Box<isize>>>());
}
struct SomeStruct<'a> {
- t: Ref<'a,Test>,
- u: Ref<'a,Test+'a>,
+ t: Ref<'a, dyn Test>,
+ u: Ref<'a, dyn Test+'a>,
}
-fn a<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
+fn a<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn b<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
+fn b<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
-fn c<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
+fn c<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn d<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
+fn d<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
-fn e<'a>(_: Ref<'a, Display+'static>) {}
-fn g<'a, 'b>(_: Ref2<'a, 'b, Display+'static>) {}
+fn e<'a>(_: Ref<'a, dyn Display+'static>) {}
+fn g<'a, 'b>(_: Ref2<'a, 'b, dyn Display+'static>) {}
fn main() {
// Inside a function body, we can just infer all
// lifetimes, to allow Ref<'tmp, Display+'static>
// and Ref2<'tmp, 'tmp, Display+'static>.
- let x = &0 as &(Display+'static);
- let r: Ref<Display> = Ref { r: x };
- let r2: Ref2<Display> = Ref2 { a: x, b: x };
+ let x = &0 as &(dyn Display+'static);
+ let r: Ref<dyn Display> = Ref { r: x };
+ let r2: Ref2<dyn Display> = Ref2 { a: x, b: x };
e(r);
g(r2);
}
}
struct SomeStruct<'a> {
- t: &'a MyBox<Test>,
- u: &'a MyBox<Test+'a>,
+ t: &'a MyBox<dyn Test>,
+ u: &'a MyBox<dyn Test+'a>,
}
struct MyBox<T:?Sized> {
b: Box<T>
}
-fn a<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
+fn a<'a>(t: &'a MyBox<dyn Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
-fn b<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
+fn b<'a>(t: &'a MyBox<dyn Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
// see also compile-fail/object-lifetime-default-from-rptr-box-error.rs
-fn d<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+fn d<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
take_auto_unsafe(AutoBool(true));
/// Auto traits are allowed in trait object bounds.
- let _: &(Send + Auto) = &0;
+ let _: &(dyn Send + Auto) = &0;
}
fn bar(&self) {}
}
-impl Trait {
+impl dyn Trait {
fn baz(_: &Foo) {}
}
// Should work even if Trait::baz doesn't exist.
// N.B: `<Trait>::bar` would be ambiguous.
- <Trait>::baz(&Foo);
+ <dyn Trait>::baz(&Foo);
}
struct Type<A> { a: PhantomData<A> }
-fn as_trait<A>(t: &Type<A>) -> &Trait<A> { loop { } }
+fn as_trait<A>(t: &Type<A>) -> &dyn Trait<A> { loop { } }
fn want<A,T:Trait<A>+?Sized>(t: &T) { }
}
}
-fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<repeat<A>+'static> {
- box v as Box<repeat<A>+'static> // No
+fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<dyn repeat<A>+'static> {
+ box v as Box<dyn repeat<A>+'static> // No
}
pub fn main() {
trait Wrap {
fn get(&self) -> isize;
- fn wrap(self: Box<Self>) -> Box<Any+'static>;
+ fn wrap(self: Box<Self>) -> Box<dyn Any+'static>;
}
impl Wrap for isize {
fn get(&self) -> isize {
*self
}
- fn wrap(self: Box<isize>) -> Box<Any+'static> {
- self as Box<Any+'static>
+ fn wrap(self: Box<isize>) -> Box<dyn Any+'static> {
+ self as Box<dyn Any+'static>
}
}
-fn is<T:Any>(x: &Any) -> bool {
+fn is<T:Any>(x: &dyn Any) -> bool {
x.is::<T>()
}
fn main() {
- let x = box 22isize as Box<Wrap>;
+ let x = box 22isize as Box<dyn Wrap>;
println!("x={}", x.get());
let y = x.wrap();
}
pub trait D<'a, T> { fn get(self) -> &'a T; }
}
-fn foo1<T>(_: &(A<T> + Send)) {}
-fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
-fn foo3<T>(_: Box<B<isize, usize> + 'static>) {}
-fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
-fn foo5<'a, T>(_: Box<foo::D<'a, T> + 'static + Send>) {}
+fn foo1<T>(_: &(dyn A<T> + Send)) {}
+fn foo2<T>(_: Box<dyn A<T> + Send + Sync>) {}
+fn foo3<T>(_: Box<dyn B<isize, usize> + 'static>) {}
+fn foo4<'a, T>(_: Box<dyn C<'a, T> + 'static + Send>) {}
+fn foo5<'a, T>(_: Box<dyn foo::D<'a, T> + 'static + Send>) {}
pub fn main() {}
trait Foo {
}
-fn b(_x: Box<Foo+Send>) {
+fn b(_x: Box<dyn Foo+Send>) {
}
-fn c(x: Box<Foo+Sync+Send>) {
+fn c(x: Box<dyn Foo+Sync+Send>) {
e(x);
}
-fn d(x: Box<Foo+Send>) {
+fn d(x: Box<dyn Foo+Send>) {
e(x);
}
-fn e(x: Box<Foo>) {
+fn e(x: Box<dyn Foo>) {
e(x);
}
use std::thread;
trait Pet {
- fn name(&self, blk: Box<FnMut(&str)>);
+ fn name(&self, blk: Box<dyn FnMut(&str)>);
fn num_legs(&self) -> usize;
fn of_good_pedigree(&self) -> bool;
}
}
impl Pet for Catte {
- fn name(&self, mut blk: Box<FnMut(&str)>) { blk(&self.name) }
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
fn num_legs(&self) -> usize { 4 }
fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 }
}
impl Pet for Dogge {
- fn name(&self, mut blk: Box<FnMut(&str)>) { blk(&self.name) }
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
fn num_legs(&self) -> usize { 4 }
fn of_good_pedigree(&self) -> bool {
self.bark_decibels < 70 || self.tricks_known > 20
}
}
impl Pet for Goldfyshe {
- fn name(&self, mut blk: Box<FnMut(&str)>) { blk(&self.name) }
+ fn name(&self, mut blk: Box<dyn FnMut(&str)>) { blk(&self.name) }
fn num_legs(&self) -> usize { 0 }
fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 }
}
swim_speed: 998,
name: "alec_guinness".to_string(),
};
- let arc = Arc::new(vec![box catte as Box<Pet+Sync+Send>,
- box dogge1 as Box<Pet+Sync+Send>,
- box fishe as Box<Pet+Sync+Send>,
- box dogge2 as Box<Pet+Sync+Send>]);
+ let arc = Arc::new(vec![box catte as Box<dyn Pet+Sync+Send>,
+ box dogge1 as Box<dyn Pet+Sync+Send>,
+ box fishe as Box<dyn Pet+Sync+Send>,
+ box dogge2 as Box<dyn Pet+Sync+Send>]);
let (tx1, rx1) = channel();
let arc1 = arc.clone();
let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); });
t3.join();
}
-fn check_legs(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
+fn check_legs(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
let mut legs = 0;
for pet in arc.iter() {
legs += pet.num_legs();
}
assert!(legs == 12);
}
-fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
+fn check_names(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
for pet in arc.iter() {
pet.name(Box::new(|name| {
assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
}))
}
}
-fn check_pedigree(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
+fn check_pedigree(arc: Arc<Vec<Box<dyn Pet+Sync+Send>>>) {
for pet in arc.iter() {
assert!(pet.of_good_pedigree());
}
trait T<X: U> { fn get(self) -> X; }
trait S2<Y: U> {
- fn m(x: Box<T<Y>+'static>) {}
+ fn m(x: Box<dyn T<Y>+'static>) {}
}
struct St<X: U> {
- f: Box<T<X>+'static>,
+ f: Box<dyn T<X>+'static>,
}
impl<X: U> St<X> {
pub fn main() {
let a = Struct { x: 1, y: 2 };
- let b: Box<Trait<&'static str>> = Box::new(a);
+ let b: Box<dyn Trait<&'static str>> = Box::new(a);
b.f("Mary");
- let c: &Trait<&'static str> = &a;
+ let c: &dyn Trait<&'static str> = &a;
c.f("Joe");
}
}
}
-fn foo(mut a: Box<Write>) {}
+fn foo(mut a: Box<dyn Write>) {}
pub fn main() {
let a = Struct { x: 1, y: 2 };
- let b: Box<Trait> = Box::new(a);
+ let b: Box<dyn Trait> = Box::new(a);
b.f();
- let c: &Trait = &a;
+ let c: &dyn Trait = &a;
c.f();
let out = io::stdout();
}
mod Bar {
- impl<'a> ::Foo::Trait+'a {
+ impl<'a> dyn (::Foo::Trait) + 'a {
fn bar(&self) { self.foo() }
}
}
fn t(&self) {}
}
-impl<'a> T+'a {
+impl<'a> dyn T+'a {
fn foo(&self) {
unsafe { COUNT *= 2; }
}
impl<'a> Bar<'a> for Foo {}
fn main() {
- let x: &T = &42;
+ let x: &dyn T = &42;
x.foo();
T::foo(x);
unsafe { assert_eq!(COUNT, 12); }
// Cross-crait case
- let x: &Bar = &Foo;
+ let x: &dyn Bar = &Foo;
x.bar();
}
pub fn main() {
let a = &A { x: 3 };
- let afoo = a as &Foo;
- let abar = a as &Bar;
+ let afoo = a as &dyn Foo;
+ let abar = a as &dyn Bar;
assert_eq!(afoo.f(), 10);
assert_eq!(abar.g(), 20);
}
pub fn main() {
let a = &A { x: 3 };
- let afoo = a as &Foo;
- let abar = a as &Bar;
+ let afoo = a as &dyn Foo;
+ let abar = a as &dyn Bar;
assert_eq!(afoo.f(), 10);
assert_eq!(abar.g(), 20);
assert_eq!(abar.f(), 10);
// Future::forget in vtables, otherwise there's an infinite type
// recursion through <Map<...> as Future>::forget.
fn forget(self) where Self: Sized {
- Box::new(Map(self)) as Box<Future>;
+ Box::new(Map(self)) as Box<dyn Future>;
}
}
* task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1',
* src/librustc/middle/subst.rs:58
*/
- t: Box<Trait2<A2>+'static>
+ t: Box<dyn Trait2<A2>+'static>
}
impl<A1, A2, A3> Impl<A1, A2, A3> {
}
pub fn main() {
- let a = box () as Box<Trait<u8, u8>>;
+ let a = box () as Box<dyn Trait<u8, u8>>;
assert_eq!(a.method(Type::Constant((1, 2))), 0);
}
static BYTE: u8 = 33;
fn main() {
- let x: &('static + Display) = &BYTE;
- let y: Box<'static + Display> = Box::new(BYTE);
+ let x: &(dyn 'static + Display) = &BYTE;
+ let y: Box<dyn 'static + Display> = Box::new(BYTE);
let xstr = format!("{}", x);
let ystr = format!("{}", y);
assert_eq!(xstr, "33");
fn n(&self) -> u8 { *self.g }
}
-fn extension<'e>(x: &'e E<'e>) -> Box<M+'e> {
+fn extension<'e>(x: &'e E<'e>) -> Box<dyn M+'e> {
loop {
let p = P { g: x.m() };
- return Box::new(p) as Box<M+'e>;
+ return Box::new(p) as Box<dyn M+'e>;
}
}
pub fn main() {
let a = A { x: 3 };
- let b = (&a) as &Foo;
+ let b = (&a) as &dyn Foo;
assert_eq!(b.f(), 3);
}
fn want_foo<B:?Sized+Foo>() { }
fn main() {
- want_foo::<Bar>();
+ want_foo::<dyn Bar>();
}
impl A for Aimpl { }
fn main() {
- let a = &Aimpl as &A;
+ let a = &Aimpl as &dyn A;
assert!(*a == Foo);
}
impl CompareToInts for i64 { }
-fn with_obj(c: &CompareToInts) -> bool {
+fn with_obj(c: &dyn CompareToInts) -> bool {
c.same_as(22_i64) && c.same_as(22_u64)
}
}
fn main() {
- let a: &Foo = &22;
+ let a: &dyn Foo = &22;
assert_eq!(Foo::test(a), 22);
}
// unsize trait
let x: &Bar = &Bar;
- let _ = x as &Foo;
- let _ = x as *const Foo;
+ let _ = x as &dyn Foo;
+ let _ = x as *const dyn Foo;
let x: &mut Bar = &mut Bar;
- let _ = x as &mut Foo;
- let _ = x as *mut Foo;
+ let _ = x as &mut dyn Foo;
+ let _ = x as *mut dyn Foo;
let x: Box<Bar> = Box::new(Bar);
- let _ = x as Box<Foo>;
+ let _ = x as Box<dyn Foo>;
// functions
fn baz(_x: i32) {}
- let _ = &baz as &Fn(i32);
+ let _ = &baz as &dyn Fn(i32);
let x = |_x: i32| {};
- let _ = &x as &Fn(i32);
+ let _ = &x as &dyn Fn(i32);
}
// subtyping
fn good(s: &String) -> Foo { Foo(s) }
fn bad1(s: String) -> Option<&'static str> {
- let a: Box<Any> = Box::new(good as fn(&String) -> Foo);
+ let a: Box<dyn Any> = Box::new(good as fn(&String) -> Foo);
a.downcast_ref::<fn(&String) -> Foo<'static>>().map(|f| f(&s).0)
}
}
fn bad2(s: String) -> Option<&'static str> {
- let a: Box<Any> = Box::new(Box::new(s) as Box<for<'a> AsStr<'a, 'a>>);
- a.downcast_ref::<Box<for<'a> AsStr<'a, 'static>>>().map(|x| x.get())
+ let a: Box<dyn Any> = Box::new(Box::new(s) as Box<dyn for<'a> AsStr<'a, 'a>>);
+ a.downcast_ref::<Box<dyn for<'a> AsStr<'a, 'static>>>().map(|x| x.get())
}
fn main() {
assert!(e != f);
// Make sure lifetime parameters of items are not ignored.
- let g = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'a>>();
- let h = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'static>>();
- let i = TypeId::of::<for<'a, 'b> fn(&'a Trait<'b>) -> Struct<'b>>();
+ let g = TypeId::of::<for<'a> fn(&'a dyn Trait<'a>) -> Struct<'a>>();
+ let h = TypeId::of::<for<'a> fn(&'a dyn Trait<'a>) -> Struct<'static>>();
+ let i = TypeId::of::<for<'a, 'b> fn(&'a dyn Trait<'b>) -> Struct<'b>>();
assert!(g != h);
assert!(g != i);
assert!(h != i);
}
// Boxed unboxed closures
{
- let a = TypeId::of::<Box<Fn(&'static isize, &'static isize)>>();
- let b = TypeId::of::<Box<for<'a> Fn(&'static isize, &'a isize)>>();
- let c = TypeId::of::<Box<for<'a, 'b> Fn(&'a isize, &'b isize)>>();
- let d = TypeId::of::<Box<for<'a, 'b> Fn(&'b isize, &'a isize)>>();
+ let a = TypeId::of::<Box<dyn Fn(&'static isize, &'static isize)>>();
+ let b = TypeId::of::<Box<dyn for<'a> Fn(&'static isize, &'a isize)>>();
+ let c = TypeId::of::<Box<dyn for<'a, 'b> Fn(&'a isize, &'b isize)>>();
+ let d = TypeId::of::<Box<dyn for<'a, 'b> Fn(&'b isize, &'a isize)>>();
assert!(a != b);
assert!(a != c);
assert!(a != d);
assert_eq!(c, d);
// Make sure De Bruijn indices are handled correctly
- let e = TypeId::of::<Box<for<'a> Fn(Box<Fn(&'a isize) -> &'a isize>)>>();
- let f = TypeId::of::<Box<Fn(Box<for<'a> Fn(&'a isize) -> &'a isize>)>>();
+ let e = TypeId::of::<Box<dyn for<'a> Fn(Box<dyn Fn(&'a isize) -> &'a isize>)>>();
+ let f = TypeId::of::<Box<dyn Fn(Box<dyn for<'a> Fn(&'a isize) -> &'a isize>)>>();
assert!(e != f);
}
// Raw unboxed closures
fn get(&self) -> &T;
}
-impl Get<MyShow + 'static> for Wrap<T> {
- fn get(&self) -> &(MyShow + 'static) {
+impl Get<dyn MyShow + 'static> for Wrap<T> {
+ fn get(&self) -> &(dyn MyShow + 'static) {
static x: usize = 42;
&x
}
}
trait MyShow { fn dummy(&self) { } }
-impl<'a> MyShow for &'a (MyShow + 'a) { }
+impl<'a> MyShow for &'a (dyn MyShow + 'a) { }
impl MyShow for usize { }
-fn constrain<'a>(rc: RefCell<&'a (MyShow + 'a)>) { }
+fn constrain<'a>(rc: RefCell<&'a (dyn MyShow + 'a)>) { }
fn main() {
let mut collection: Wrap<_> = WrapNone;
f()
}
-fn b(f: &mut FnMut() -> i32) -> i32 {
+fn b(f: &mut dyn FnMut() -> i32) -> i32 {
a(f)
}
f()
}
-fn b(f: &Fn() -> i32) -> i32 {
+fn b(f: &dyn Fn() -> i32) -> i32 {
a(f)
}
use std::ops::FnMut;
- fn make_adder(x: i32) -> Box<FnMut(i32)->i32+'static> {
+ fn make_adder(x: i32) -> Box<dyn FnMut(i32)->i32+'static> {
(box move |y: i32| -> i32 { x + y }) as
- Box<FnMut(i32)->i32+'static>
+ Box<dyn FnMut(i32)->i32+'static>
}
pub fn main() {
use std::ops::FnMut;
-fn make_adder(x: isize) -> Box<FnMut(isize)->isize + 'static> {
+fn make_adder(x: isize) -> Box<dyn FnMut(isize)->isize + 'static> {
Box::new(move |y| { x + y })
}
// run-pass
use std::ops::FnMut;
-fn make_adder(x: isize) -> Box<FnMut(isize)->isize + 'static> {
+fn make_adder(x: isize) -> Box<dyn FnMut(isize)->isize + 'static> {
Box::new(move |y| { x + y })
}
(*f)(&x)
}
-fn call_it_boxed(f: &Fn(&isize) -> isize, x: isize) -> isize {
+fn call_it_boxed(f: &dyn Fn(&isize) -> isize, x: isize) -> isize {
f(&x)
}
impl ToPrimitive for i32 {}
impl ToPrimitive for usize {}
-fn doit<T>(val: T, f: &Fn(T)) { f(val) }
+fn doit<T>(val: T, f: &dyn Fn(T)) { f(val) }
pub fn main() {
doit(0, &|x /*: isize*/ | { x.to_int(); });
}
}
-impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> Fn<(A,)> for YCombinator<F,A,R> {
+impl<A,R,F : Fn(&dyn Fn(A) -> R, A) -> R> Fn<(A,)> for YCombinator<F,A,R> {
extern "rust-call" fn call(&self, (arg,): (A,)) -> R {
(self.func)(self, arg)
}
}
-impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
+impl<A,R,F : Fn(&dyn Fn(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) }
}
-impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+impl<A,R,F : Fn(&dyn Fn(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
type Output = R;
extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) }
}
fn main() {
- let factorial = |recur: &Fn(u32) -> u32, arg: u32| -> u32 {
+ let factorial = |recur: &dyn Fn(u32) -> u32, arg: u32| -> u32 {
if arg == 0 {1} else {arg * recur(arg-1)}
};
let factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial);
f(x) + 3
}
-fn call_box(f: &mut FnMut(i32) -> i32, x: i32) -> i32 {
+fn call_box(f: &mut dyn FnMut(i32) -> i32, x: i32) -> i32 {
f(x) + 3
}
// monomorphize correctly (issue #16791)
fn main(){
- fn bar<'a, T:Clone+'a> (t: T) -> Box<FnMut()->T + 'a> {
+ fn bar<'a, T:Clone+'a> (t: T) -> Box<dyn FnMut()->T + 'a> {
Box::new(move || t.clone())
}
// pretty-expanded FIXME #23616
fn main() {
- let task: Box<Fn(isize) -> isize> = Box::new(|x| x);
+ let task: Box<dyn Fn(isize) -> isize> = Box::new(|x| x);
task(0);
- let mut task: Box<FnMut(isize) -> isize> = Box::new(|x| x);
+ let mut task: Box<dyn FnMut(isize) -> isize> = Box::new(|x| x);
task(0);
call(|x| x, 22);
}
fn main() {
- let x: &Getter<(i32,), (i32,)> = &Identity;
+ let x: &dyn Getter<(i32,), (i32,)> = &Identity;
let (y,) = x.get((22,));
assert_eq!(y, 22);
}
impl EventLoop for UvEventLoop { }
pub fn main() {
- let loop_: Box<EventLoop> = box UvEventLoop { uvio: 0 } as Box<EventLoop>;
+ let loop_: Box<dyn EventLoop> = box UvEventLoop { uvio: 0 } as Box<dyn EventLoop>;
let _loop2_ = loop_;
}
trait T4<X> {
fn dummy(&self) { }
- fn m1(&self, x: &T4<X>, y: X);
- fn m2(&self, x: &T5<X>, y: X);
+ fn m1(&self, x: &dyn T4<X>, y: X);
+ fn m2(&self, x: &dyn T5<X>, y: X);
}
trait T5<X: ?Sized> {
fn dummy(&self) { }
// not an error (for now)
- fn m1(&self, x: &T4<X>);
- fn m2(&self, x: &T5<X>);
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
}
trait T6<X: T> {
fn dummy(&self) { }
- fn m1(&self, x: &T4<X>);
- fn m2(&self, x: &T5<X>);
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
}
trait T7<X: ?Sized+T> {
fn dummy(&self) { }
// not an error (for now)
- fn m1(&self, x: &T4<X>);
- fn m2(&self, x: &T5<X>);
+ fn m1(&self, x: &dyn T4<X>);
+ fn m2(&self, x: &dyn T5<X>);
}
// The last field in a struct may be unsized
pub type Cmd<'a> = &'a isize;
pub type DecodeInlinedItem<'a> =
- Box<for<'tcx> FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx isize, ()> + 'a>;
+ Box<dyn for<'tcx> FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx isize, ()> + 'a>;
fn foo(d: DecodeInlinedItem) {
}
--- /dev/null
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// failure-status: 101
+
+/// ```compile_fail
+/// println!("Hello");
+/// ```
+pub struct Foo;
--- /dev/null
+
+running 1 test
+test $DIR/failed-doctest-compile-fail.rs - Foo (line 8) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-compile-fail.rs - Foo (line 8) stdout ----
+Test compiled successfully, but it's marked `compile_fail`.
+
+failures:
+ $DIR/failed-doctest-compile-fail.rs - Foo (line 8)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+
--- /dev/null
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// failure-status: 101
+
+/// ```compile_fail,E0004
+/// let x: () = 5i32;
+/// ```
+pub struct Foo;
--- /dev/null
+
+running 1 test
+test $DIR/failed-doctest-missing-codes.rs - Foo (line 8) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-missing-codes.rs - Foo (line 8) stdout ----
+error[E0308]: mismatched types
+ --> $DIR/failed-doctest-missing-codes.rs:9:13
+ |
+3 | let x: () = 5i32;
+ | ^^^^ expected (), found i32
+ |
+ = note: expected type `()`
+ found type `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
+Some expected error codes were not found: ["E0004"]
+
+failures:
+ $DIR/failed-doctest-missing-codes.rs - Foo (line 8)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101
-// rustc-env:RUST_BACKTRACE=0
// doctest fails at runtime
/// ```
+/// println!("stdout 1");
+/// eprintln!("stderr 1");
+/// println!("stdout 2");
+/// eprintln!("stderr 2");
/// panic!("oh no");
/// ```
pub struct SomeStruct;
running 2 tests
-test $DIR/failed-doctest-output.rs - OtherStruct (line 17) ... FAILED
-test $DIR/failed-doctest-output.rs - SomeStruct (line 11) ... FAILED
+test $DIR/failed-doctest-output.rs - OtherStruct (line 20) ... FAILED
+test $DIR/failed-doctest-output.rs - SomeStruct (line 10) ... FAILED
failures:
----- $DIR/failed-doctest-output.rs - OtherStruct (line 17) stdout ----
+---- $DIR/failed-doctest-output.rs - OtherStruct (line 20) stdout ----
error[E0425]: cannot find value `no` in this scope
- --> $DIR/failed-doctest-output.rs:18:1
+ --> $DIR/failed-doctest-output.rs:21:1
|
3 | no
| ^^ not found in this scope
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
-thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13
+Couldn't compile the test.
+---- $DIR/failed-doctest-output.rs - SomeStruct (line 10) stdout ----
+Test executable failed (exit code 101).
+
+stdout:
+stdout 1
+stdout 2
+
+stderr:
+stderr 1
+stderr 2
+thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:7:1
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
----- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
-thread '$DIR/failed-doctest-output.rs - SomeStruct (line 11)' panicked at 'test executable failed:
-
-thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
-note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
-
-', src/librustdoc/test.rs:342:17
failures:
- $DIR/failed-doctest-output.rs - OtherStruct (line 17)
- $DIR/failed-doctest-output.rs - SomeStruct (line 11)
+ $DIR/failed-doctest-output.rs - OtherStruct (line 20)
+ $DIR/failed-doctest-output.rs - SomeStruct (line 10)
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
--- /dev/null
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// failure-status: 101
+
+/// ```should_panic
+/// println!("Hello, world!");
+/// ```
+pub struct Foo;
--- /dev/null
+
+running 1 test
+test $DIR/failed-doctest-should-panic.rs - Foo (line 8) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-should-panic.rs - Foo (line 8) stdout ----
+Test executable succeeded, but it's marked `should_panic`.
+
+failures:
+ $DIR/failed-doctest-should-panic.rs - Foo (line 8)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
+
error: aborting due to previous error
-thread '$DIR/unparseable-doc-test.rs - foo (line 6)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13
-note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
-
+Couldn't compile the test.
failures:
$DIR/unparseable-doc-test.rs - foo (line 6)
--- /dev/null
+// ignore-tidy-linelength
+
+#![feature(const_generics)]
+
+#![crate_name = "foo"]
+
+use std::ops::Add;
+
+// @has foo/struct.Simd.html '//pre[@class="rust struct"]' 'pub struct Simd<T, const WIDTH: usize>'
+pub struct Simd<T, const WIDTH: usize> {
+ inner: T,
+}
+
+// @has foo/struct.Simd.html '//div[@id="implementations-list"]/h3/code' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
+impl Add for Simd<u8, 16> {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self::Output {
+ Self { inner: 0 }
+ }
+}
--- /dev/null
+// ignore-tidy-linelength
+
+#![feature(const_generics)]
+
+#![crate_name = "foo"]
+
+pub enum Order {
+ Sorted,
+ Unsorted,
+}
+
+// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
+pub struct VSet<T, const ORDER: Order> {
+ inner: Vec<T>,
+}
+
+// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
+impl <T> VSet<T, {Order::Sorted}> {
+ pub fn new() -> Self {
+ Self { inner: Vec::new() }
+ }
+}
+
+// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
+impl <T> VSet<T, {Order::Unsorted}> {
+ pub fn new() -> Self {
+ Self { inner: Vec::new() }
+ }
+}
+++ /dev/null
-#![feature(const_generics)]
-#![crate_name = "foo"]
-
-// ignore-tidy-linelength
-
-pub enum Order {
- Sorted,
- Unsorted,
-}
-
-// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
-pub struct VSet<T, const ORDER: Order> {
- inner: Vec<T>,
-}
-
-// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
-impl <T> VSet<T, {Order::Sorted}> {
- pub fn new() -> Self {
- Self { inner: Vec::new() }
- }
-}
-
-// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
-impl <T> VSet<T, {Order::Unsorted}> {
- pub fn new() -> Self {
- Self { inner: Vec::new() }
- }
-}
--- /dev/null
+// This code caused a panic in `pulldown-cmark` 0.4.1.
+
+pub const BASIC_UNICODE: bool = true;
+
+
+/// # `BASIC_UNICODE`: `A` `|`
+/// ```text
+/// ```
+pub const BASIC_FONTS: bool = true;
fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
// Nested
-fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
+fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
-fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
+fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
// Mixed
-fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
-fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
+fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
+fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
note: required by `g1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
|
-LL | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
note: required by `g1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:34:1
|
-LL | fn g1<F>(_: F) where F: Fn(&(), Box<Fn(&())>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
note: required by `g3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
|
-LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
note: required by `g3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:36:1
|
-LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<Fn(&())>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
note: required by `h1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
|
-LL | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
note: required by `h1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
|
-LL | fn h1<F>(_: F) where F: Fn(&(), Box<Fn(&())>, &(), fn(&(), &())) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
note: required by `h2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
|
-LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
note: required by `h2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:41:1
|
-LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<Fn(&())>, &'t0 (), fn(&(), &())) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 22 previous errors
fn main() {
loop {
|_: [_; break]| {} //~ ERROR: `break` outside of loop
+ //~^ ERROR mismatched types
}
loop {
|_: [_; continue]| {} //~ ERROR: `continue` outside of loop
+ //~^ ERROR mismatched types
}
}
| ^^^^^ cannot break outside of a loop
error[E0268]: `continue` outside of loop
- --> $DIR/array-break-length.rs:7:17
+ --> $DIR/array-break-length.rs:8:17
|
LL | |_: [_; continue]| {}
| ^^^^^^^^ cannot break outside of a loop
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/array-break-length.rs:3:9
+ |
+LL | |_: [_; break]| {}
+ | ^^^^^^^^^^^^^^^^^^ expected (), found closure
+ |
+ = note: expected type `()`
+ found type `[closure@$DIR/array-break-length.rs:3:9: 3:27]`
+
+error[E0308]: mismatched types
+ --> $DIR/array-break-length.rs:8:9
+ |
+LL | |_: [_; continue]| {}
+ | ^^^^^^^^^^^^^^^^^^^^^ expected (), found closure
+ |
+ = note: expected type `()`
+ found type `[closure@$DIR/array-break-length.rs:8:9: 8:30]`
+
+error: aborting due to 4 previous errors
-For more information about this error, try `rustc --explain E0268`.
+Some errors have detailed explanations: E0268, E0308.
+For more information about an error, try `rustc --explain E0268`.
const N: usize;
}
-impl Trait {
+impl dyn Trait {
//~^ ERROR the trait `Trait` cannot be made into an object [E0038]
const fn n() -> usize { Self::N }
}
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/associated-const-in-trait.rs:9:6
|
-LL | impl Trait {
- | ^^^^^ the trait `Trait` cannot be made into an object
+LL | impl dyn Trait {
+ | ^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot contain associated consts like `N`
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
}
-fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) {
//~^ ERROR ambiguous associated type
//~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified
}
| ^^^^^^^^ ambiguous associated type `Color`
error[E0221]: ambiguous associated type `Color` in bounds of `BoxCar`
- --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:33
+ --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37
|
LL | type Color;
| ----------- ambiguous `Color` from `Vehicle`
LL | type Color;
| ----------- ambiguous `Color` from `Box`
...
-LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
- | ^^^^^^^^^^^ ambiguous associated type `Color`
+LL | fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) {
+ | ^^^^^^^^^^^ ambiguous associated type `Color`
error[E0191]: the value of the associated type `Color` (from the trait `Vehicle`) must be specified
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:26
LL | type Color;
| ----------- `Color` defined here
...
-LL | fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
- | ^^^^^^^^^^^^^^^^^^^ associated type `Color` must be specified
+LL | fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ associated type `Color` must be specified
error[E0221]: ambiguous associated type `Color` in bounds of `C`
--> $DIR/associated-type-projection-from-multiple-supertraits.rs:28:29
}
-pub fn baz(x: &Foo<A=Bar>) {
+pub fn baz(x: &dyn Foo<A=Bar>) {
let _: Bar = x.boo();
}
}
pub fn main() {
- let a = &42isize as &Foo<A=usize, B=char>;
+ let a = &42isize as &dyn Foo<A=usize, B=char>;
- let b = &42isize as &Foo<A=usize>;
+ let b = &42isize as &dyn Foo<A=usize>;
//~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
- let c = &42isize as &Foo<B=char>;
+ let c = &42isize as &dyn Foo<B=char>;
//~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
- let d = &42isize as &Foo;
+ let d = &42isize as &dyn Foo;
//~^ ERROR the value of the associated types `A` (from the trait `Foo`), `B` (from the trait
}
LL | type B;
| ------- `B` defined here
...
-LL | let b = &42isize as &Foo<A=usize>;
- | ^^^^^^^^^^^^ associated type `B` must be specified
+LL | let b = &42isize as &dyn Foo<A=usize>;
+ | ^^^^^^^^^^^^^^^^ associated type `B` must be specified
error[E0191]: the value of the associated type `A` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:26:26
LL | type A;
| ------- `A` defined here
...
-LL | let c = &42isize as &Foo<B=char>;
- | ^^^^^^^^^^^ associated type `A` must be specified
+LL | let c = &42isize as &dyn Foo<B=char>;
+ | ^^^^^^^^^^^^^^^ associated type `A` must be specified
error[E0191]: the value of the associated types `A` (from the trait `Foo`), `B` (from the trait `Foo`) must be specified
--> $DIR/associated-types-incomplete-object.rs:29:26
LL | type B;
| ------- `B` defined here
...
-LL | let d = &42isize as &Foo;
- | ^^^
+LL | let d = &42isize as &dyn Foo;
+ | ^^^^^^^
| |
| associated type `A` must be specified
| associated type `B` must be specified
trait I32Iterator = Iterator<Item = i32>;
fn main() {
- let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
+ let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
//~^ ERROR type mismatch
}
error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
- --> $DIR/associated-types-overridden-binding-2.rs:6:39
+ --> $DIR/associated-types-overridden-binding-2.rs:6:43
|
-LL | let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
- | ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
+LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
+ | ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
|
= note: expected type `u32`
found type `i32`
trait U32Iterator = I32Iterator<Item = u32>;
fn main() {
- let _: &I32Iterator<Item = u32>;
+ let _: &dyn I32Iterator<Item = u32>;
}
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
- --> $DIR/bound-lifetime-constrained.rs:28:56
+ --> $DIR/bound-lifetime-constrained.rs:28:60
|
-LL | fn object1(_: Box<for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
- | ^^^^^^^
+LL | fn object1(_: Box<dyn for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
+ | ^^^^^^^
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
- --> $DIR/bound-lifetime-constrained.rs:33:35
+ --> $DIR/bound-lifetime-constrained.rs:33:39
|
-LL | fn object2(_: Box<for<'a> Fn() -> <() as Foo<'a>>::Item>) {
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | fn object2(_: Box<dyn for<'a> Fn() -> <() as Foo<'a>>::Item>) {
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
}
#[cfg(object)]
-fn object1(_: Box<for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
+fn object1(_: Box<dyn for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32>) {
//[object]~^ ERROR E0582
}
#[cfg(object)]
-fn object2(_: Box<for<'a> Fn() -> <() as Foo<'a>>::Item>) {
+fn object2(_: Box<dyn for<'a> Fn() -> <() as Foo<'a>>::Item>) {
//[object]~^ ERROR E0582
}
| ^^^^^^^^^^^^
error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types
- --> $DIR/bound-lifetime-in-binding-only.rs:27:27
+ --> $DIR/bound-lifetime-in-binding-only.rs:27:31
|
-LL | fn angle3(_: &for<'a> Foo<Item=&'a i32>) {
- | ^^^^^^^^^^^^
+LL | fn angle3(_: &dyn for<'a> Foo<Item=&'a i32>) {
+ | ^^^^^^^^^^^^
error: aborting due to 4 previous errors
| ^^^^^^^
error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
- --> $DIR/bound-lifetime-in-binding-only.rs:47:31
+ --> $DIR/bound-lifetime-in-binding-only.rs:47:35
|
-LL | fn paren3(_: &for<'a> Fn() -> &'a i32) {
- | ^^^^^^^
+LL | fn paren3(_: &dyn for<'a> Fn() -> &'a i32) {
+ | ^^^^^^^
error: aborting due to 4 previous errors
}
#[cfg(angle)]
-fn angle3(_: &for<'a> Foo<Item=&'a i32>) {
+fn angle3(_: &dyn for<'a> Foo<Item=&'a i32>) {
//[angle]~^ ERROR binding for associated type `Item` references lifetime `'a`
}
}
#[cfg(paren)]
-fn paren3(_: &for<'a> Fn() -> &'a i32) {
+fn paren3(_: &dyn for<'a> Fn() -> &'a i32) {
//[paren]~^ ERROR binding for associated type `Output` references lifetime `'a`
}
struct Parameterized<'a> { x: &'a str }
#[cfg(ok)]
-fn ok1(_: &for<'a> Fn(&Parameterized<'a>) -> &'a i32) {
+fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) {
}
#[cfg(ok)]
-fn ok2(_: &for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) {
+fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) {
}
#[rustc_error]
async fn get_future<C: ?Sized + MyClosure>(_stream: MyStream<C>) {}
async fn f() {
- let messages: MyStream<FnMut()> = unimplemented!();
+ let messages: MyStream<dyn FnMut()> = unimplemented!();
await!(get_future(messages));
}
}
async fn __receive<WantFn, Fut>(want: WantFn) -> ()
- where Fut: Future<Output = ()>, WantFn: Fn(&Box<Send + 'static>) -> Fut,
+ where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut,
{
await!(lazy(|_| ()));
}
fn do_something(&self);
}
-async fn my_task(obj: Arc<SomeTrait>) {
+async fn my_task(obj: Arc<dyn SomeTrait>) {
unimplemented!()
}
trait Trait {}
pub fn main() {
- let x: Vec<Trait + Sized> = Vec::new();
+ let x: Vec<dyn Trait + Sized> = Vec::new();
//~^ ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR the size for values of type
//~| ERROR the size for values of type
error[E0225]: only auto traits can be used as additional traits in a trait object
- --> $DIR/bad-sized.rs:4:24
+ --> $DIR/bad-sized.rs:4:28
|
-LL | let x: Vec<Trait + Sized> = Vec::new();
- | ----- ^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
- | first non-auto trait
- | trait alias used in trait object type (first use)
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ----- ^^^^^
+ | | |
+ | | additional non-auto trait
+ | | trait alias used in trait object type (additional use)
+ | first non-auto trait
+ | trait alias used in trait object type (first use)
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/bad-sized.rs:4:12
|
-LL | let x: Vec<Trait + Sized> = Vec::new();
- | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn Trait`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required by `std::vec::Vec`
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
- --> $DIR/bad-sized.rs:4:33
+ --> $DIR/bad-sized.rs:4:37
|
-LL | let x: Vec<Trait + Sized> = Vec::new();
- | ^^^^^^^^ doesn't have a size known at compile-time
+LL | let x: Vec<dyn Trait + Sized> = Vec::new();
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn Trait`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
fn f2(&mut self);
}
-fn test(x: &mut Foo) {
+fn test(x: &mut dyn Foo) {
let y = x.f1();
x.f2(); //~ ERROR cannot borrow `*x` as mutable
y.use_ref();
trait Foo { fn dummy(&self); }
-fn consume(_: Box<Foo>) {
+fn consume(_: Box<dyn Foo>) {
}
-fn foo(b: Box<Foo+Send>) {
+fn foo(b: Box<dyn Foo + Send>) {
consume(b);
consume(b); //~ ERROR use of moved value
}
error[E0382]: use of moved value: `b`
--> $DIR/borrowck-consume-upcast-box.rs:10:13
|
-LL | fn foo(b: Box<Foo+Send>) {
+LL | fn foo(b: Box<dyn Foo + Send>) {
| - move occurs because `b` has type `std::boxed::Box<dyn Foo + std::marker::Send>`, which does not implement the `Copy` trait
LL | consume(b);
| - value moved here
// closure may outlive the current function, but it borrows `books`,
// which is owned by the current function
-fn foo<'a>(x: &'a i32) -> Box<FnMut()+'a> {
+fn foo<'a>(x: &'a i32) -> Box<dyn FnMut() + 'a> {
let mut books = vec![1,2,3];
Box::new(|| books.push(4))
//~^ ERROR E0373
// check that borrowck looks inside consts/statics
-static FN : &'static (Fn() -> (Box<Fn()->Box<i32>>) + Sync) = &|| {
+static FN : &'static (dyn Fn() -> (Box<dyn Fn()->Box<i32>>) + Sync) = &|| {
let x = Box::new(0);
Box::new(|| x) //~ ERROR cannot move out of captured variable in an `Fn` closure
};
fn mut_borrowed(&mut self) -> &();
}
-fn borrowed_receiver(x: &Foo) {
+fn borrowed_receiver(x: &dyn Foo) {
let y = x.borrowed();
let z = x.borrowed();
z.use_ref();
y.use_ref();
}
-fn mut_borrowed_receiver(x: &mut Foo) {
+fn mut_borrowed_receiver(x: &mut dyn Foo) {
let y = x.borrowed();
let z = x.mut_borrowed(); //~ ERROR cannot borrow
y.use_ref();
}
-fn mut_owned_receiver(mut x: Box<Foo>) {
+fn mut_owned_receiver(mut x: Box<dyn Foo>) {
let y = x.borrowed();
let z = &mut x; //~ ERROR cannot borrow
y.use_ref();
}
-fn imm_owned_receiver(mut x: Box<Foo>) {
+fn imm_owned_receiver(mut x: Box<dyn Foo>) {
let y = x.borrowed();
let z = &x;
z.use_ref();
fn main() {
let x: &i32;
- let y = x as *const Foo; //~ ERROR [E0381]
+ let y = x as *const dyn Foo; //~ ERROR [E0381]
}
error[E0381]: borrow of possibly uninitialized variable: `x`
--> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13
|
-LL | let y = x as *const Foo;
+LL | let y = x as *const dyn Foo;
| ^ use of possibly uninitialized `*x`
error: aborting due to previous error
-fn with_int(f: &mut FnMut(&isize)) {
+fn with_int(f: &mut dyn FnMut(&isize)) {
}
fn main() {
error[E0382]: use of moved value: `f`
--> $DIR/two-phase-nonrecv-autoref.rs:80:11
|
-LL | fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+LL | fn twice_ten_oo(f: Box<dyn FnOnce(i32) -> i32>) {
| - move occurs because `f` has type `std::boxed::Box<dyn std::ops::FnOnce(i32) -> i32>`, which does not implement the `Copy` trait
LL | f(f(10));
| - ^ value used here after move
//[g2p]~^^ ERROR use of moved value: `f`
}
- fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
+ fn twice_ten_om(f: &mut dyn FnMut(i32) -> i32) {
f(f(10));
//[nll]~^ ERROR cannot borrow `*f` as mutable more than once at a time
//[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
}
- fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
+ fn twice_ten_oi(f: &mut dyn Fn(i32) -> i32) {
f(f(10));
}
- fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
+ fn twice_ten_oo(f: Box<dyn FnOnce(i32) -> i32>) {
f(f(10));
//[nll]~^ ERROR use of moved value: `f`
//[g2p]~^^ ERROR use of moved value: `f`
type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context
type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context
type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
-type E = for<T> Fn(); //~ ERROR only lifetime parameters can be used in this context
+type E = dyn for<T> Fn(); //~ ERROR only lifetime parameters can be used in this context
fn main() {}
| ^
error: only lifetime parameters can be used in this context
- --> $DIR/bounds-lifetime.rs:5:14
+ --> $DIR/bounds-lifetime.rs:5:18
|
-LL | type E = for<T> Fn();
- | ^
+LL | type E = dyn for<T> Fn();
+ | ^
error: aborting due to 5 previous errors
fn main() {
- &1 as Send; //~ ERROR cast to unsized
- Box::new(1) as Send; //~ ERROR cast to unsized
+ &1 as dyn Send; //~ ERROR cast to unsized
+ Box::new(1) as dyn Send; //~ ERROR cast to unsized
}
error[E0620]: cast to unsized type: `&{integer}` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5
|
-LL | &1 as Send;
- | ^^^^^^----
+LL | &1 as dyn Send;
+ | ^^^^^^--------
| |
- | help: try casting to a reference instead: `&Send`
+ | help: try casting to a reference instead: `&dyn Send`
error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5
|
-LL | Box::new(1) as Send;
- | ^^^^^^^^^^^^^^^----
+LL | Box::new(1) as dyn Send;
+ | ^^^^^^^^^^^^^^^--------
| |
- | help: try casting to a `Box` instead: `Box<Send>`
+ | help: try casting to a `Box` instead: `Box<dyn Send>`
error: aborting due to 2 previous errors
x
}
fn bar() -> Box<impl fmt::Debug+?Sized> {
- let y: Box<fmt::Debug> = Box::new([0]);
+ let y: Box<dyn fmt::Debug> = Box::new([0]);
y
}
}
fn main() {
- let nyan: Box<Noisy> = box cat(0, 2, "nyan".to_string()) as Box<Noisy>;
+ let nyan: Box<dyn Noisy> = box cat(0, 2, "nyan".to_string()) as Box<dyn Noisy>;
nyan.eat(); //~ ERROR no method named `eat` found
}
-fn foo() -> Box<Fn()> {
+fn foo() -> Box<dyn Fn()> {
let num = 5;
let closure = || { //~ ERROR expected a closure that
-fn get_closure() -> Box<Fn() -> Vec<u8>> {
+fn get_closure() -> Box<dyn Fn() -> Vec<u8>> {
let vec = vec![1u8, 2u8];
let closure = move || { //~ ERROR expected a closure
|_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop
+ //~^ ERROR mismatched types
while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop
+ //~^ ERROR mismatched types
}
| ^^^^^^^^ cannot break outside of a loop
error[E0268]: `break` outside of loop
- --> $DIR/closure-array-break-length.rs:6:19
+ --> $DIR/closure-array-break-length.rs:7:19
|
LL | while |_: [_; break]| {} {}
| ^^^^^ cannot break outside of a loop
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+ --> $DIR/closure-array-break-length.rs:4:11
+ |
+LL | while |_: [_; continue]| {} {}
+ | ^^^^^^^^^^^^^^^^^^^^^ expected bool, found closure
+ |
+ = note: expected type `bool`
+ found type `[closure@$DIR/closure-array-break-length.rs:4:11: 4:32]`
+
+error[E0308]: mismatched types
+ --> $DIR/closure-array-break-length.rs:7:11
+ |
+LL | while |_: [_; break]| {} {}
+ | ^^^^^^^^^^^^^^^^^^ expected bool, found closure
+ |
+ = note: expected type `bool`
+ found type `[closure@$DIR/closure-array-break-length.rs:7:11: 7:29]`
+
+error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0268`.
+Some errors have detailed explanations: E0268, E0308.
+For more information about an error, try `rustc --explain E0268`.
// Point at the captured immutable outer variable
-fn foo(mut f: Box<FnMut()>) {
+fn foo(mut f: Box<dyn FnMut()>) {
f();
}
// Point at the captured immutable outer variable
-fn foo(mut f: Box<FnMut()>) {
+fn foo(mut f: Box<dyn FnMut()>) {
f();
}
#![allow(dead_code)]
trait C {}
-impl C { fn f() {} } //~ ERROR duplicate
-impl C { fn f() {} }
+impl dyn C { fn f() {} } //~ ERROR duplicate
+impl dyn C { fn f() {} }
fn main() { }
error[E0592]: duplicate definitions with name `f`
- --> $DIR/coherence-overlapping-inherent-impl-trait.rs:4:10
+ --> $DIR/coherence-overlapping-inherent-impl-trait.rs:4:14
|
-LL | impl C { fn f() {} }
- | ^^^^^^^^^ duplicate definitions for `f`
-LL | impl C { fn f() {} }
- | --------- other definition for `f`
+LL | impl dyn C { fn f() {} }
+ | ^^^^^^^^^ duplicate definitions for `f`
+LL | impl dyn C { fn f() {} }
+ | --------- other definition for `f`
error: aborting due to previous error
trait Foo { }
-type Bar = Foo;
+type Bar = dyn Foo;
let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types
let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
//~^ ERROR mismatched types
- let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>; //~ ERROR mismatched types
- let _ = box if true { false } else { true }: Box<Debug>; //~ ERROR mismatched types
- let _ = box match true { true => 'a', false => 'b' }: Box<Debug>; //~ ERROR mismatched types
+ let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types
+ let _ = box if true { false } else { true }: Box<dyn Debug>; //~ ERROR mismatched types
+ let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>; //~ ERROR mismatched types
let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types
let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types
let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
//~^ ERROR mismatched types
- let _ = &{ |x| (x as u8) }: &Fn(i32) -> _; //~ ERROR mismatched types
- let _ = &if true { false } else { true }: &Debug; //~ ERROR mismatched types
- let _ = &match true { true => 'a', false => 'b' }: &Debug; //~ ERROR mismatched types
+ let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; //~ ERROR mismatched types
+ let _ = &if true { false } else { true }: &dyn Debug; //~ ERROR mismatched types
+ let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; //~ ERROR mismatched types
let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types
- let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>; //~ ERROR mismatched types
+ let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types
let _ = vec![
Box::new(|x| (x as u8)),
box |x| (x as i16 as u8),
- ]: Vec<Box<Fn(i32) -> _>>;
+ ]: Vec<Box<dyn Fn(i32) -> _>>;
}
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:13:13
|
-LL | let _ = box { |x| (x as u8) }: Box<Fn(i32) -> _>;
+LL | let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>;
| ^^^^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
|
= note: expected type `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:14:13
|
-LL | let _ = box if true { false } else { true }: Box<Debug>;
+LL | let _ = box if true { false } else { true }: Box<dyn Debug>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found bool
|
= note: expected type `std::boxed::Box<dyn std::fmt::Debug>`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:15:13
|
-LL | let _ = box match true { true => 'a', false => 'b' }: Box<Debug>;
+LL | let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found char
|
= note: expected type `std::boxed::Box<dyn std::fmt::Debug>`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:21:13
|
-LL | let _ = &{ |x| (x as u8) }: &Fn(i32) -> _;
+LL | let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _;
| ^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
|
= note: expected type `&dyn std::ops::Fn(i32) -> u8`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:22:13
|
-LL | let _ = &if true { false } else { true }: &Debug;
+LL | let _ = &if true { false } else { true }: &dyn Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found bool
|
= note: expected type `&dyn std::fmt::Debug`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:23:13
|
-LL | let _ = &match true { true => 'a', false => 'b' }: &Debug;
+LL | let _ = &match true { true => 'a', false => 'b' }: &dyn Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::fmt::Debug, found char
|
= note: expected type `&dyn std::fmt::Debug`
error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:26:13
|
-LL | let _ = Box::new(|x| (x as u8)): Box<Fn(i32) -> _>;
+LL | let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
| ^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
|
= note: expected type `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
|
-LL | impl NotObjectSafe for NotObjectSafe { }
+LL | impl NotObjectSafe for dyn NotObjectSafe { }
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
|
= note: method `eq` references the `Self` type in its arguments or return type
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
|
-LL | impl NotObjectSafe for NotObjectSafe { }
+LL | impl NotObjectSafe for dyn NotObjectSafe { }
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
|
= note: method `eq` references the `Self` type in its arguments or return type
// If the trait is not object-safe, we give a more tailored message
// because we're such schnuckels:
trait NotObjectSafe { fn eq(&self, other: Self); }
-impl NotObjectSafe for NotObjectSafe { }
+impl NotObjectSafe for dyn NotObjectSafe { }
//[old]~^ ERROR E0038
//[re]~^^ ERROR E0038
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Foo`
--> $DIR/coherence-impl-trait-for-trait.rs:13:1
|
-LL | impl Foo for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
+LL | impl Foo for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Bar`
--> $DIR/coherence-impl-trait-for-trait.rs:16:1
|
-LL | impl Bar for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
+LL | impl Bar for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Baz`
--> $DIR/coherence-impl-trait-for-trait.rs:19:1
|
-LL | impl Baz for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
+LL | impl Baz for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
error: aborting due to 3 previous errors
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Foo`
--> $DIR/coherence-impl-trait-for-trait.rs:13:1
|
-LL | impl Foo for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
+LL | impl Foo for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo`
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Bar`
--> $DIR/coherence-impl-trait-for-trait.rs:16:1
|
-LL | impl Bar for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
+LL | impl Bar for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar`
error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Baz`
--> $DIR/coherence-impl-trait-for-trait.rs:19:1
|
-LL | impl Baz for Baz { }
- | ^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
+LL | impl Baz for dyn Baz { }
+ | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz`
error: aborting due to 3 previous errors
trait Baz: Bar { }
// Supertraits of Baz are not legal:
-impl Foo for Baz { }
+impl Foo for dyn Baz { }
//[old]~^ ERROR E0371
//[re]~^^ ERROR E0371
-impl Bar for Baz { }
+impl Bar for dyn Baz { }
//[old]~^ ERROR E0371
//[re]~^^ ERROR E0371
-impl Baz for Baz { }
+impl Baz for dyn Baz { }
//[old]~^ ERROR E0371
//[re]~^^ ERROR E0371
// But other random traits are:
trait Other { }
-impl Other for Baz { } // OK, Other not a supertrait of Baz
+impl Other for dyn Baz { } // OK, Other not a supertrait of Baz
fn main() { }
}
struct BoxedObj {
- boxed_closure: Box<FnOnce() -> u32>,
+ boxed_closure: Box<dyn FnOnce() -> u32>,
}
struct Wrapper<F> where F: FnMut() -> u32 {
0
}
-fn check_expression() -> Obj<Box<FnOnce() -> u32>> {
- Obj { closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32>, not_closure: 42 }
+fn check_expression() -> Obj<Box<dyn FnOnce() -> u32>> {
+ Obj { closure: Box::new(|| 42_u32) as Box<dyn FnOnce() -> u32>, not_closure: 42 }
}
fn main() {
let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
- let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnOnce() -> u32> };
+ let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<dyn FnOnce() -> u32> };
boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
// test expression writing in the notes
struct Example {
- example: Box<Fn(i32) -> i32>
+ example: Box<dyn Fn(i32) -> i32>
}
fn main() {
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+pub trait Foo {
+ fn foo(&self);
+}
+
+
+impl<T, const N: usize> Foo for [T; N] {
+ fn foo(&self) {
+ let _ = &self;
+ }
+}
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/broken-mir-1.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::fmt::Debug;
+
+#[derive(Debug)]
+struct S<T: Debug, const N: usize>([T; N]); //~ ERROR `[T; _]` doesn't implement `std::fmt::Debug`
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/broken-mir-2.rs:1:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
+error[E0277]: `[T; _]` doesn't implement `std::fmt::Debug`
+ --> $DIR/broken-mir-2.rs:7:36
+ |
+LL | struct S<T: Debug, const N: usize>([T; N]);
+ | ^^^^^^ `[T; _]` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+ |
+ = help: the trait `std::fmt::Debug` is not implemented for `[T; _]`
+ = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; _]`
+ = note: required for the cast to the object type `dyn std::fmt::Debug`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
+// compile-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
-// We should probably be able to infer the types here. However, this test is checking that we don't
-// get an ICE in this case. It may be modified later to not be an error.
+// This test confirms that the types can be inferred correctly for this example with const
+// generics. Previously this would ICE, and more recently error.
struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);
fn main() {
let _ = Foo::<3>([1, 2, 3]); //~ ERROR type annotations needed
+ //~^ ERROR mismatched types
}
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
- --> $DIR/cannot-infer-type-for-const-param.rs:1:12
+ --> $DIR/cannot-infer-type-for-const-param.rs:2:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
-error[E0282]: type annotations needed
- --> $DIR/cannot-infer-type-for-const-param.rs:10:19
- |
-LL | let _ = Foo::<3>([1, 2, 3]);
- | ^ cannot infer type for `{integer}`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::fmt::Display;
+
+fn print_slice<T: Display, const N: usize>(slice: &[T; N]) {
+ for x in slice.iter() {
+ println!("{}", x);
+ }
+}
+
+fn main() {
+ print_slice(&[1, 2, 3]);
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/fn-taking-const-generic-array.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// compile-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Generic<const V: usize>;
+
+fn main() {
+ let _ = Generic::<0>;
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/issue-60818-struct-constructors.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::fmt;
+
+struct Array<T, const N: usize>([T; N]);
+
+impl<T: fmt::Debug, const N: usize> fmt::Debug for Array<T, {N}> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries(self.0.iter()).finish()
+ }
+}
+
+fn main() {
+ assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]");
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/uninferred-consts-during-codegen-1.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::fmt;
+
+struct Array<T>(T);
+
+impl<T: fmt::Debug, const N: usize> fmt::Debug for Array<[T; N]> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_list().entries((&self.0 as &[T]).iter()).finish()
+ }
+}
+
+fn main() {
+ assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]");
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/uninferred-consts-during-codegen-2.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
const IDX: usize = 3;
const VAL: i32 = ARR[IDX];
const BONG: [i32; (ARR[0] - 41) as usize] = [5];
-const BLUB: [i32; (ARR[0] - 40) as usize] = [5]; //~ ERROR: mismatched types
-const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99]; //~ ERROR: mismatched types
+const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
+//~^ ERROR: mismatched types
+//~| expected an array with a fixed size of 2 elements, found one with 1 element
+const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
+//~^ ERROR: mismatched types
+//~| expected an array with a fixed size of 1 element, found one with 2 elements
fn main() {
let _ = VAL;
--> $DIR/const-array-oob-arith.rs:7:45
|
LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
- | ^^^ expected an array with a fixed size of 2 elements, found one with 1 elements
+ | ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
|
= note: expected type `[i32; 2]`
found type `[i32; 1]`
error[E0308]: mismatched types
- --> $DIR/const-array-oob-arith.rs:8:44
+ --> $DIR/const-array-oob-arith.rs:10:44
|
LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
- | ^^^^^^^ expected an array with a fixed size of 1 elements, found one with 2 elements
+ | ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
|
= note: expected type `[i32; 1]`
found type `[i32; 2]`
bar: for<'a> fn(&'a Foo) -> u32,
}
-const FOO: &Bar = &Foo { foo: 128, bar: false };
+const FOO: &dyn Bar = &Foo { foo: 128, bar: false };
const G: Fat = unsafe { Transmute { t: FOO }.u };
const F: Option<for<'a> fn(&'a mut Foo)> = G.1.drop;
const H: for<'a> fn(&'a Foo) -> u32 = G.1.bar;
// compile-pass
-pub const STATIC_TRAIT: &Test = &();
+pub const STATIC_TRAIT: &dyn Test = &();
fn main() {}
use std::mem;
-const BAD_UPVAR: &FnOnce() = &{ //~ ERROR it is undefined behavior to use this value
+const BAD_UPVAR: &dyn FnOnce() = &{ //~ ERROR it is undefined behavior to use this value
let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
let another_var = 13;
move || { let _ = bad_ref; let _ = another_var; }
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-upvars.rs:6:1
|
-LL | / const BAD_UPVAR: &FnOnce() = &{
+LL | / const BAD_UPVAR: &dyn FnOnce() = &{
LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) };
LL | | let another_var = 13;
LL | | move || { let _ = bad_ref; let _ = another_var; }
repr: DynRepr,
repr2: DynRepr2,
bad: BadDynRepr,
- rust: &'static Trait,
+ rust: &'static dyn Trait,
}
trait Trait {}
//~^ ERROR it is undefined behavior to use this value
// bad trait object
-const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
//~^ ERROR it is undefined behavior to use this value
// bad trait object
-const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
//~^ ERROR it is undefined behavior to use this value
// bad trait object
-const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
//~^ ERROR it is undefined behavior to use this value
// bad data *inside* the trait object
-const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
//~^ ERROR it is undefined behavior to use this value
// bad data *inside* the slice
error[E0080]: it is undefined behavior to use this value
--> $DIR/union-ub-fat-ptr.rs:97:1
|
-LL | const D: &Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in 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 rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
--> $DIR/union-ub-fat-ptr.rs:100:1
|
-LL | const E: &Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in vtable
+LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop fn in 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 rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
--> $DIR/union-ub-fat-ptr.rs:103:1
|
-LL | const F: &Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
+LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-pointer vtable in fat pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
error[E0080]: it is undefined behavior to use this value
--> $DIR/union-ub-fat-ptr.rs:107:1
|
-LL | const G: &Trait = &unsafe { BoolTransmute { val: 3 }.bl };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
+LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .<deref>.<dyn-downcast>, but expected something less or equal to 1
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
- --> $SRC_DIR/libcore/mem.rs:LL:COL
+ --> $SRC_DIR/libcore/mem/mod.rs:LL:COL
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
use std::fmt::Debug;
-const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
+const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
//~^ ERROR the size for values of type
const CONST_FOO: str = *"foo";
//~^ ERROR the size for values of type
-static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
+static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
//~^ ERROR the size for values of type
static STATIC_BAR: str = *"bar";
error[E0277]: the size for values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:3:16
|
-LL | const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
- | ^^^^^^^^^^ doesn't have a size known at compile-time
+LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync));
+ | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error[E0277]: the size for values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:9:18
|
-LL | static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
- | ^^^^^^^^^^ doesn't have a size known at compile-time
+LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
+ | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:144:41
|
-LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
const fn no_unsafe() { unsafe {} }
-const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
+const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
//~^ ERROR trait bounds other than `Sized`
const fn no_fn_ptrs(_x: fn()) {}
error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:144:41
|
-LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
impl Trait for Foo {}
pub fn main() {
- let x: Box<Trait> = Box::new(Foo);
- let _y: &Trait = x; //~ ERROR E0308
- //~| expected type `&dyn Trait`
- //~| found type `std::boxed::Box<dyn Trait>`
+ let x: Box<dyn Trait> = Box::new(Foo);
+ let _y: &dyn Trait = x; //~ ERROR E0308
+ //~| expected type `&dyn Trait`
+ //~| found type `std::boxed::Box<dyn Trait>`
}
error[E0308]: mismatched types
- --> $DIR/cross-borrow-trait.rs:10:22
+ --> $DIR/cross-borrow-trait.rs:10:26
|
-LL | let _y: &Trait = x;
- | ^
- | |
- | expected &dyn Trait, found struct `std::boxed::Box`
- | help: consider borrowing here: `&x`
+LL | let _y: &dyn Trait = x;
+ | ^
+ | |
+ | expected &dyn Trait, found struct `std::boxed::Box`
+ | help: consider borrowing here: `&x`
|
= note: expected type `&dyn Trait`
found type `std::boxed::Box<dyn Trait>`
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(Foo)]
-pub fn derive_foo(input: TokenStream) -> TokenStream {
- input
-}
-
-#[proc_macro_derive(Bar)]
-pub fn derive_bar(input: TokenStream) -> TokenStream {
- panic!("lolnope");
-}
-
-#[proc_macro_derive(WithHelper, attributes(helper))]
-pub fn with_helper(input: TokenStream) -> TokenStream {
- TokenStream::new()
-}
-
-#[proc_macro_attribute]
-pub fn helper(_: TokenStream, input: TokenStream) -> TokenStream {
- input
-}
+++ /dev/null
-// compile-pass
-// aux-build:plugin.rs
-
-extern crate plugin;
-
-mod inner {
- use plugin::WithHelper;
-
- #[derive(WithHelper)]
- struct S;
-}
-
-fn main() {}
+++ /dev/null
-// aux-build:plugin.rs
-
-#[macro_use(WithHelper)]
-extern crate plugin;
-
-use plugin::helper;
-
-#[derive(WithHelper)]
-#[helper] //~ ERROR `helper` is ambiguous
-struct S;
-
-fn main() {}
+++ /dev/null
-error[E0659]: `helper` is ambiguous (derive helper attribute vs any other name)
- --> $DIR/helper-attr-blocked-by-import-ambig.rs:9:3
- |
-LL | #[helper]
- | ^^^^^^ ambiguous name
- |
-note: `helper` could refer to the derive helper attribute defined here
- --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:10
- |
-LL | #[derive(WithHelper)]
- | ^^^^^^^^^^
-note: `helper` could also refer to the attribute macro imported here
- --> $DIR/helper-attr-blocked-by-import-ambig.rs:6:5
- |
-LL | use plugin::helper;
- | ^^^^^^^^^^^^^^
- = help: use `crate::helper` to refer to this attribute macro unambiguously
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0659`.
+++ /dev/null
-// compile-pass
-// aux-build:plugin.rs
-
-#[macro_use(WithHelper)]
-extern crate plugin;
-
-use self::one::*;
-use self::two::*;
-
-mod helper {}
-
-mod one {
- use helper;
-
- #[derive(WithHelper)]
- #[helper]
- struct One;
-}
-
-mod two {
- use helper;
-
- #[derive(WithHelper)]
- #[helper]
- struct Two;
-}
-
-fn main() {}
+++ /dev/null
-// aux-build:plugin.rs
-
-
-#[macro_use] extern crate plugin;
-
-#[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked
-struct Baz {
- a: i32,
- b: i32,
-}
-
-fn main() {}
+++ /dev/null
-error: proc-macro derive panicked
- --> $DIR/issue-36935.rs:6:15
- |
-LL | #[derive(Foo, Bar)]
- | ^^^
- |
- = help: message: lolnope
-
-error: aborting due to previous error
-
#![test_runner(crate::foo_runner)]
#[cfg(test)]
-fn foo_runner(ts: &[&Fn(usize)->()]) {
+fn foo_runner(ts: &[&dyn Fn(usize)->()]) {
for (i, t) in ts.iter().enumerate() {
t(i);
}
// Test a cycle where a type parameter on a trait has a default that
// again references the trait.
-trait Foo<X = Box<Foo>> {
+trait Foo<X = Box<dyn Foo>> {
//~^ ERROR cycle detected
}
error[E0391]: cycle detected when processing `Foo::X`
- --> $DIR/cycle-trait-default-type-trait.rs:4:19
+ --> $DIR/cycle-trait-default-type-trait.rs:4:23
|
-LL | trait Foo<X = Box<Foo>> {
- | ^^^
+LL | trait Foo<X = Box<dyn Foo>> {
+ | ^^^
|
= note: ...which again requires processing `Foo::X`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/cycle-trait-default-type-trait.rs:4:1
|
-LL | trait Foo<X = Box<Foo>> {
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait Foo<X = Box<dyn Foo>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
// if n > m, it's a type mismatch error.
// n < m
- let &x = &(&1isize as &T);
- let &x = &&(&1isize as &T);
- let &&x = &&(&1isize as &T);
+ let &x = &(&1isize as &dyn T);
+ let &x = &&(&1isize as &dyn T);
+ let &&x = &&(&1isize as &dyn T);
// n == m
- let &x = &1isize as &T; //~ ERROR type `&dyn T` cannot be dereferenced
- let &&x = &(&1isize as &T); //~ ERROR type `&dyn T` cannot be dereferenced
- let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<dyn T>` cannot be dereferenced
+ let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced
+ let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced
+ let box x = box 1isize as Box<dyn T>;
+ //~^ ERROR type `std::boxed::Box<dyn T>` cannot be dereferenced
// n > m
- let &&x = &1isize as &T;
+ let &&x = &1isize as &dyn T;
//~^ ERROR mismatched types
//~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
- let &&&x = &(&1isize as &T);
+ let &&&x = &(&1isize as &dyn T);
//~^ ERROR mismatched types
//~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
- let box box x = box 1isize as Box<T>;
+ let box box x = box 1isize as Box<dyn T>;
//~^ ERROR mismatched types
//~| expected type `dyn T`
//~| found type `std::boxed::Box<_>`
error[E0033]: type `&dyn T` cannot be dereferenced
--> $DIR/destructure-trait-ref.rs:26:9
|
-LL | let &x = &1isize as &T;
+LL | let &x = &1isize as &dyn T;
| ^^ type `&dyn T` cannot be dereferenced
error[E0033]: type `&dyn T` cannot be dereferenced
--> $DIR/destructure-trait-ref.rs:27:10
|
-LL | let &&x = &(&1isize as &T);
+LL | let &&x = &(&1isize as &dyn T);
| ^^ type `&dyn T` cannot be dereferenced
error[E0033]: type `std::boxed::Box<dyn T>` cannot be dereferenced
--> $DIR/destructure-trait-ref.rs:28:9
|
-LL | let box x = box 1isize as Box<T>;
+LL | let box x = box 1isize as Box<dyn T>;
| ^^^^^ type `std::boxed::Box<dyn T>` cannot be dereferenced
error[E0308]: mismatched types
- --> $DIR/destructure-trait-ref.rs:31:10
+ --> $DIR/destructure-trait-ref.rs:32:10
|
-LL | let &&x = &1isize as &T;
+LL | let &&x = &1isize as &dyn T;
| ^^
| |
| expected trait T, found reference
found type `&_`
error[E0308]: mismatched types
- --> $DIR/destructure-trait-ref.rs:36:11
+ --> $DIR/destructure-trait-ref.rs:37:11
|
-LL | let &&&x = &(&1isize as &T);
+LL | let &&&x = &(&1isize as &dyn T);
| ^^
| |
| expected trait T, found reference
found type `&_`
error[E0308]: mismatched types
- --> $DIR/destructure-trait-ref.rs:41:13
+ --> $DIR/destructure-trait-ref.rs:42:13
|
-LL | let box box x = box 1isize as Box<T>;
+LL | let box box x = box 1isize as Box<dyn T>;
| ^^^^^ expected trait T, found struct `std::boxed::Box`
|
= note: expected type `dyn T`
+#![allow(bare_trait_objects)]
+
trait Foo {}
struct Bar<'a> {
error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
- --> $DIR/E0178.rs:4:8
+ --> $DIR/E0178.rs:6:8
|
LL | w: &'a Foo + Copy,
| ^^^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + Copy)`
error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`
- --> $DIR/E0178.rs:5:8
+ --> $DIR/E0178.rs:7:8
|
LL | x: &'a Foo + 'a,
| ^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + 'a)`
error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo`
- --> $DIR/E0178.rs:6:8
+ --> $DIR/E0178.rs:8:8
|
LL | y: &'a mut Foo + 'a,
| ^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'a mut (Foo + 'a)`
error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo`
- --> $DIR/E0178.rs:7:8
+ --> $DIR/E0178.rs:9:8
|
LL | z: fn() -> Foo + 'a,
| ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
// Qualified paths cannot appear in bounds, so the recovery
// should apply to the whole sum and not `(Send)`.
-type G = 'static + (Send)::AssocTy;
+type G = dyn 'static + (Send)::AssocTy;
//~^ ERROR missing angle brackets in associated item path
//~| ERROR ambiguous associated type
error: missing angle brackets in associated item path
--> $DIR/bad-assoc-ty.rs:27:10
|
-LL | type G = 'static + (Send)::AssocTy;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<'static + (Send)>::AssocTy`
+LL | type G = dyn 'static + (Send)::AssocTy;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<dyn 'static + (Send)>::AssocTy`
error: missing angle brackets in associated item path
--> $DIR/bad-assoc-ty.rs:44:10
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:27:10
|
-LL | type G = 'static + (Send)::AssocTy;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy`
+LL | type G = dyn 'static + (Send)::AssocTy;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy`
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:33:10
-impl X { //~ ERROR cannot be made into an object
+impl dyn X { //~ ERROR cannot be made into an object
//~^ ERROR missing
Y
}
error: missing `fn`, `type`, or `const` for impl-item declaration
- --> $DIR/issue-40006.rs:1:9
+ --> $DIR/issue-40006.rs:1:13
|
-LL | impl X {
- | _________^
+LL | impl dyn X {
+ | _____________^
LL | |
LL | | Y
| |____^ missing `fn`, `type`, or `const`
error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-40006.rs:1:6
|
-LL | impl X {
- | ^ the trait `X` cannot be made into an object
+LL | impl dyn X {
+ | ^^^^^ the trait `X` cannot be made into an object
|
= note: method `xxx` has no receiver
+#![allow(bare_trait_objects)]
+
fn main() {
let _: &Copy + 'static; //~ ERROR expected a path
//~^ ERROR cannot be made into an object
error[E0178]: expected a path on the left-hand side of `+`, not `&Copy`
- --> $DIR/trait-object-reference-without-parens-suggestion.rs:2:12
+ --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
|
LL | let _: &Copy + 'static;
| ^^^^^^^^^^^^^^^ help: try adding parentheses: `&(Copy + 'static)`
error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy`
- --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
+ --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12
|
LL | let _: &'static Copy + 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'static (Copy + 'static)`
error[E0038]: the trait `std::marker::Copy` cannot be made into an object
- --> $DIR/trait-object-reference-without-parens-suggestion.rs:2:12
+ --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
|
LL | let _: &Copy + 'static;
| ^^^^^ the trait `std::marker::Copy` cannot be made into an object
}
trait Obj<'a> : HasId {
- fn set0(&self, b: &'a Box<Obj<'a>>);
- fn set1(&self, b: &'a Box<Obj<'a>>);
+ fn set0(&self, b: &'a Box<dyn Obj<'a>>);
+ fn set1(&self, b: &'a Box<dyn Obj<'a>>);
}
struct O<'a> {
id: Id,
- obj0: CheckId<Cell<Option<&'a Box<Obj<'a>>>>>,
- obj1: CheckId<Cell<Option<&'a Box<Obj<'a>>>>>,
+ obj0: CheckId<Cell<Option<&'a Box<dyn Obj<'a>>>>>,
+ obj1: CheckId<Cell<Option<&'a Box<dyn Obj<'a>>>>>,
}
impl<'a> HasId for O<'a> {
}
}
-impl<'a> HasId for Cell<Option<&'a Box<Obj<'a>>>> {
+impl<'a> HasId for Cell<Option<&'a Box<dyn Obj<'a>>>> {
fn count(&self) -> usize {
match self.get() {
None => 1,
}
impl<'a> Obj<'a> for O<'a> {
- fn set0(&self, b: &'a Box<Obj<'a>>) {
+ fn set0(&self, b: &'a Box<dyn Obj<'a>>) {
self.obj0.v.set(Some(b))
}
- fn set1(&self, b: &'a Box<Obj<'a>>) {
+ fn set1(&self, b: &'a Box<dyn Obj<'a>>) {
self.obj1.v.set(Some(b))
}
}
fn f() {
- let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
+ let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
o1.set0(&o2); //~ ERROR `o2` does not live long enough
o1.set1(&o3); //~ ERROR `o3` does not live long enough
o2.set0(&o2); //~ ERROR `o2` does not live long enough
error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:111:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o2` is borrowed for `'static`
LL | o1.set0(&o2);
| ^^^ borrowed value does not live long enough
...
error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:112:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o3` is borrowed for `'static`
LL | o1.set0(&o2);
LL | o1.set1(&o3);
| ^^^ borrowed value does not live long enough
error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:113:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o2` is borrowed for `'static`
...
LL | o2.set0(&o2);
| ^^^ borrowed value does not live long enough
error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:114:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o3` is borrowed for `'static`
...
LL | o2.set1(&o3);
| ^^^ borrowed value does not live long enough
error[E0597]: `o1` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:115:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o1` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o1` is borrowed for `'static`
...
LL | o3.set0(&o1);
| ^^^ borrowed value does not live long enough
error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:116:13
|
-LL | let (o1, o2, o3): (Box<Obj>, Box<Obj>, Box<Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
+ | -------- cast requires that `o2` is borrowed for `'static`
...
LL | o3.set1(&o2);
| ^^^ borrowed value does not live long enough
pub fn main() {
// Assignment.
- let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
- let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+ let f5: &mut Fat<dyn ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+ let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = *z;
//~^ ERROR the size for values of type
pub fn main() {
// Assignment.
- let f5: &mut Fat<ToBar> = &mut (5, "some str", Bar1 {f :42});
- let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+ let f5: &mut Fat<dyn ToBar> = &mut (5, "some str", Bar1 {f :42});
+ let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
//~| expected type `dyn ToBar`
pub fn main() {
// Assignment.
- let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
- let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+ let f5: &mut Fat<dyn ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
+ let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
//~| expected type `dyn ToBar`
// With a trait.
let f1 = Fat { ptr: Foo };
let f2: &Fat<Foo> = &f1;
- let f3: &Fat<Bar> = f2;
+ let f3: &Fat<dyn Bar> = f2;
//~^ ERROR `Foo: Bar` is not satisfied
// Tuple with a vec of isize.
// Tuple with a trait.
let f1 = (Foo,);
let f2: &(Foo,) = &f1;
- let f3: &(Bar,) = f2;
+ let f3: &(dyn Bar,) = f2;
//~^ ERROR `Foo: Bar` is not satisfied
}
found type `&Fat<[isize; 3]>`
error[E0277]: the trait bound `Foo: Bar` is not satisfied
- --> $DIR/dst-bad-coerce1.rs:22:25
+ --> $DIR/dst-bad-coerce1.rs:22:29
|
-LL | let f3: &Fat<Bar> = f2;
- | ^^ the trait `Bar` is not implemented for `Foo`
+LL | let f3: &Fat<dyn Bar> = f2;
+ | ^^ the trait `Bar` is not implemented for `Foo`
|
= note: required for the cast to the object type `dyn Bar`
found type `&([isize; 3],)`
error[E0277]: the trait bound `Foo: Bar` is not satisfied
- --> $DIR/dst-bad-coerce1.rs:34:23
+ --> $DIR/dst-bad-coerce1.rs:34:27
|
-LL | let f3: &(Bar,) = f2;
- | ^^ the trait `Bar` is not implemented for `Foo`
+LL | let f3: &(dyn Bar,) = f2;
+ | ^^ the trait `Bar` is not implemented for `Foo`
|
= note: required for the cast to the object type `dyn Bar`
// With a trait.
let f1 = Fat { ptr: Foo };
let f2: &Fat<Foo> = &f1;
- let f3: &mut Fat<Bar> = f2; //~ ERROR mismatched types
+ let f3: &mut Fat<dyn Bar> = f2; //~ ERROR mismatched types
// Tuple with a vec of ints.
let f1 = ([1, 2, 3],);
// Tuple with a trait.
let f1 = (Foo,);
let f2: &(Foo,) = &f1;
- let f3: &mut (Bar,) = f2; //~ ERROR mismatched types
+ let f3: &mut (dyn Bar,) = f2; //~ ERROR mismatched types
}
found type `&Fat<[isize; 3]>`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coerce2.rs:20:29
+ --> $DIR/dst-bad-coerce2.rs:20:33
|
-LL | let f3: &mut Fat<Bar> = f2;
- | ^^ types differ in mutability
+LL | let f3: &mut Fat<dyn Bar> = f2;
+ | ^^ types differ in mutability
|
= note: expected type `&mut Fat<dyn Bar>`
found type `&Fat<Foo>`
found type `&([isize; 3],)`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coerce2.rs:30:27
+ --> $DIR/dst-bad-coerce2.rs:30:31
|
-LL | let f3: &mut (Bar,) = f2;
- | ^^ types differ in mutability
+LL | let f3: &mut (dyn Bar,) = f2;
+ | ^^ types differ in mutability
|
= note: expected type `&mut (dyn Bar,)`
found type `&(Foo,)`
// With a trait.
let f1 = Fat { ptr: Foo };
let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
- let f3: &'a Fat<Bar> = f2;
+ let f3: &'a Fat<dyn Bar> = f2;
// Tuple with a vec of ints.
let f1 = ([1, 2, 3],);
// Tuple with a trait.
let f1 = (Foo,);
let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough
- let f3: &'a (Bar,) = f2;
+ let f3: &'a (dyn Bar,) = f2;
}
pub fn main() {
...
LL | let f2: &Fat<Foo> = &f1;
| ^^^ borrowed value does not live long enough
-LL | let f3: &'a Fat<Bar> = f2;
- | ------------ type annotation requires that `f1` is borrowed for `'a`
+LL | let f3: &'a Fat<dyn Bar> = f2;
+ | ---------------- type annotation requires that `f1` is borrowed for `'a`
...
LL | }
| - `f1` dropped here while still borrowed
...
LL | let f2: &(Foo,) = &f1;
| ^^^ borrowed value does not live long enough
-LL | let f3: &'a (Bar,) = f2;
- | ---------- type annotation requires that `f1` is borrowed for `'a`
+LL | let f3: &'a (dyn Bar,) = f2;
+ | -------------- type annotation requires that `f1` is borrowed for `'a`
LL | }
| - `f1` dropped here while still borrowed
// Test that we cannot convert from *-ptr to &S and &T
let x: *const S = &S;
let y: &S = x; //~ ERROR mismatched types
- let y: &T = x; //~ ERROR mismatched types
+ let y: &dyn T = x; //~ ERROR mismatched types
// Test that we cannot convert from *-ptr to &S and &T (mut version)
let x: *mut S = &mut S;
let y: &S = x; //~ ERROR mismatched types
- let y: &T = x; //~ ERROR mismatched types
+ let y: &dyn T = x; //~ ERROR mismatched types
// Test that we cannot convert an immutable ptr to a mutable one using *-ptrs
- let x: &mut T = &S; //~ ERROR mismatched types
- let x: *mut T = &S; //~ ERROR mismatched types
+ let x: &mut dyn T = &S; //~ ERROR mismatched types
+ let x: *mut dyn T = &S; //~ ERROR mismatched types
let x: *mut S = &S; //~ ERROR mismatched types
}
found type `*const S`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coercions.rs:15:17
+ --> $DIR/dst-bad-coercions.rs:15:21
|
-LL | let y: &T = x;
- | ^
- | |
- | expected &dyn T, found *-ptr
- | help: consider borrowing here: `&x`
+LL | let y: &dyn T = x;
+ | ^
+ | |
+ | expected &dyn T, found *-ptr
+ | help: consider borrowing here: `&x`
|
= note: expected type `&dyn T`
found type `*const S`
found type `*mut S`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coercions.rs:20:17
+ --> $DIR/dst-bad-coercions.rs:20:21
|
-LL | let y: &T = x;
- | ^
- | |
- | expected &dyn T, found *-ptr
- | help: consider borrowing here: `&x`
+LL | let y: &dyn T = x;
+ | ^
+ | |
+ | expected &dyn T, found *-ptr
+ | help: consider borrowing here: `&x`
|
= note: expected type `&dyn T`
found type `*mut S`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coercions.rs:23:21
+ --> $DIR/dst-bad-coercions.rs:23:25
|
-LL | let x: &mut T = &S;
- | ^^ types differ in mutability
+LL | let x: &mut dyn T = &S;
+ | ^^ types differ in mutability
|
= note: expected type `&mut dyn T`
found type `&S`
error[E0308]: mismatched types
- --> $DIR/dst-bad-coercions.rs:24:21
+ --> $DIR/dst-bad-coercions.rs:24:25
|
-LL | let x: *mut T = &S;
- | ^^ types differ in mutability
+LL | let x: *mut dyn T = &S;
+ | ^^ types differ in mutability
|
= note: expected type `*mut dyn T`
found type `&S`
struct T;
impl Index<usize> for T {
- type Output = Debug + 'static;
+ type Output = dyn Debug + 'static;
- fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) {
+ fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) {
static x: usize = 42;
&x
}
impl Foo for [u8] {}
fn test1<T: ?Sized + Foo>(t: &T) {
- let u: &Foo = t;
+ let u: &dyn Foo = t;
//~^ ERROR the size for values of type
}
fn test2<T: ?Sized + Foo>(t: &T) {
- let v: &Foo = t as &Foo;
+ let v: &dyn Foo = t as &dyn Foo;
//~^ ERROR the size for values of type
}
fn test3() {
- let _: &[&Foo] = &["hi"];
+ let _: &[&dyn Foo] = &["hi"];
//~^ ERROR the size for values of type
}
fn test4(x: &[u8]) {
- let _: &Foo = x as &Foo;
+ let _: &dyn Foo = x as &dyn Foo;
//~^ ERROR the size for values of type
}
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/dst-object-from-unsized-type.rs:8:19
+ --> $DIR/dst-object-from-unsized-type.rs:8:23
|
-LL | let u: &Foo = t;
- | ^ doesn't have a size known at compile-time
+LL | let u: &dyn Foo = t;
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required for the cast to the object type `dyn Foo`
error[E0277]: the size for values of type `T` cannot be known at compilation time
- --> $DIR/dst-object-from-unsized-type.rs:13:19
+ --> $DIR/dst-object-from-unsized-type.rs:13:23
|
-LL | let v: &Foo = t as &Foo;
- | ^ doesn't have a size known at compile-time
+LL | let v: &dyn Foo = t as &dyn Foo;
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required for the cast to the object type `dyn Foo`
error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/dst-object-from-unsized-type.rs:18:24
+ --> $DIR/dst-object-from-unsized-type.rs:18:28
|
-LL | let _: &[&Foo] = &["hi"];
- | ^^^^ doesn't have a size known at compile-time
+LL | let _: &[&dyn Foo] = &["hi"];
+ | ^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required for the cast to the object type `dyn Foo`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
- --> $DIR/dst-object-from-unsized-type.rs:23:19
+ --> $DIR/dst-object-from-unsized-type.rs:23:23
|
-LL | let _: &Foo = x as &Foo;
- | ^ doesn't have a size known at compile-time
+LL | let _: &dyn Foo = x as &dyn Foo;
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
fn main() {
let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
//~^ ERROR mismatched types
- let ts: Vec<&T> = vec![&a, &b, &c];
+ let ts: Vec<&dyn T> = vec![&a, &b, &c];
// There is no E0277 error above, as `a`, `b` and `c` are `TyErr`
}
}
fn main() {
- let trait_obj: &SomeTrait = SomeTrait;
+ let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| method `foo` has no receiver
error[E0423]: expected value, found trait `SomeTrait`
- --> $DIR/E0033-teach.rs:8:33
+ --> $DIR/E0033-teach.rs:8:37
|
-LL | let trait_obj: &SomeTrait = SomeTrait;
- | ^^^^^^^^^ not a value
+LL | let trait_obj: &dyn SomeTrait = SomeTrait;
+ | ^^^^^^^^^ not a value
error[E0038]: the trait `SomeTrait` cannot be made into an object
--> $DIR/E0033-teach.rs:8:20
|
-LL | let trait_obj: &SomeTrait = SomeTrait;
- | ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
+LL | let trait_obj: &dyn SomeTrait = SomeTrait;
+ | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: method `foo` has no receiver
}
fn main() {
- let trait_obj: &SomeTrait = SomeTrait;
+ let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| method `foo` has no receiver
error[E0423]: expected value, found trait `SomeTrait`
- --> $DIR/E0033.rs:6:33
+ --> $DIR/E0033.rs:6:37
|
-LL | let trait_obj: &SomeTrait = SomeTrait;
- | ^^^^^^^^^ not a value
+LL | let trait_obj: &dyn SomeTrait = SomeTrait;
+ | ^^^^^^^^^ not a value
error[E0038]: the trait `SomeTrait` cannot be made into an object
--> $DIR/E0033.rs:6:20
|
-LL | let trait_obj: &SomeTrait = SomeTrait;
- | ^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
+LL | let trait_obj: &dyn SomeTrait = SomeTrait;
+ | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: method `foo` has no receiver
fn foo(&self) -> Self;
}
-fn call_foo(x: Box<Trait>) {
+fn call_foo(x: Box<dyn Trait>) {
//~^ ERROR E0038
let y = x.foo();
}
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/E0038.rs:5:1
|
-LL | fn call_foo(x: Box<Trait>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
+LL | fn call_foo(x: Box<dyn Trait>) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: method `foo` references the `Self` type in its arguments or return type
trait MyTrait { fn foo() {} }
-impl Drop for MyTrait {
+impl Drop for dyn MyTrait {
//~^ ERROR E0120
fn drop(&mut self) {}
}
error[E0120]: the Drop trait may only be implemented on structures
--> $DIR/E0120.rs:3:15
|
-LL | impl Drop for MyTrait {
- | ^^^^^^^ implementing Drop requires a struct
+LL | impl Drop for dyn MyTrait {
+ | ^^^^^^^^^^^ implementing Drop requires a struct
error: aborting due to previous error
type Bar;
}
-type Foo = Trait; //~ ERROR E0191
+type Foo = dyn Trait; //~ ERROR E0191
fn main() {}
LL | type Bar;
| --------- `Bar` defined here
...
-LL | type Foo = Trait;
- | ^^^^^ associated type `Bar` must be specified
+LL | type Foo = dyn Trait;
+ | ^^^^^^^^^ associated type `Bar` must be specified
error: aborting due to previous error
type Bar;
}
-type Foo = Trait<F=i32>; //~ ERROR E0220
- //~| ERROR E0191
+type Foo = dyn Trait<F=i32>; //~ ERROR E0220
+ //~| ERROR E0191
fn main() {
}
error[E0220]: associated type `F` not found for `Trait`
- --> $DIR/E0220.rs:5:18
+ --> $DIR/E0220.rs:5:22
|
-LL | type Foo = Trait<F=i32>;
- | ^^^^^ associated type `F` not found
+LL | type Foo = dyn Trait<F=i32>;
+ | ^^^^^ associated type `F` not found
error[E0191]: the value of the associated type `Bar` (from the trait `Trait`) must be specified
--> $DIR/E0220.rs:5:12
LL | type Bar;
| --------- `Bar` defined here
...
-LL | type Foo = Trait<F=i32>;
- | ^^^^^^^^^^^^ associated type `Bar` must be specified
+LL | type Foo = dyn Trait<F=i32>;
+ | ^^^^^^^^^^^^^^^^ associated type `Bar` must be specified
error: aborting due to 2 previous errors
trait A<T=Self> {}
-fn together_we_will_rule_the_galaxy(son: &A) {}
+fn together_we_will_rule_the_galaxy(son: &dyn A) {}
//~^ ERROR E0393
fn main() {
error[E0393]: the type parameter `T` must be explicitly specified
- --> $DIR/E0393.rs:3:43
+ --> $DIR/E0393.rs:3:47
|
-LL | fn together_we_will_rule_the_galaxy(son: &A) {}
- | ^ missing reference to `T`
+LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {}
+ | ^ missing reference to `T`
|
= note: because of the default `Self` reference, type parameters must be specified on object types
trait Wedding<'t>: 't { }
struct Prince<'kiss, 'SnowWhite> {
- child: Box<Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
+ child: Box<dyn Wedding<'kiss> + 'SnowWhite>, //~ ERROR E0478
}
fn main() {
error[E0478]: lifetime bound not satisfied
--> $DIR/E0478.rs:4:5
|
-LL | child: Box<Wedding<'kiss> + 'SnowWhite>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | child: Box<dyn Wedding<'kiss> + 'SnowWhite>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 3:22
--> $DIR/E0478.rs:3:22
type Unit = ();
-fn test() -> Box<Iterator<Item = (), Item = Unit>> {
+fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> {
//~^ ERROR is already specified
Box::new(None.into_iter())
}
fn main() {
- let _: &Iterator<Item = i32, Item = i32>;
+ let _: &dyn Iterator<Item = i32, Item = i32>;
test();
}
| `Item` bound here first
error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
- --> $DIR/E0719.rs:6:38
+ --> $DIR/E0719.rs:6:42
|
-LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
- | --------- ^^^^^^^^^^^ re-bound here
- | |
- | `Item` bound here first
+LL | fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> {
+ | --------- ^^^^^^^^^^^ re-bound here
+ | |
+ | `Item` bound here first
error: aborting due to 2 previous errors
q as *const [i32]; //~ ERROR cannot cast
// #21397
- let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR casting
+ let t: *mut (dyn Trait + 'static) = 0 as *mut _; //~ ERROR casting
let mut fail: *const str = 0 as *const str; //~ ERROR casting
}
| ^^^^^^^^^^^^^^^^^
error[E0606]: casting `usize` as `*mut (dyn Trait + 'static)` is invalid
- --> $DIR/fat-ptr-cast.rs:22:37
+ --> $DIR/fat-ptr-cast.rs:22:41
|
-LL | let t: *mut (Trait + 'static) = 0 as *mut _;
- | ^^^^^^^^^^^
+LL | let t: *mut (dyn Trait + 'static) = 0 as *mut _;
+ | ^^^^^^^^^^^
error[E0606]: casting `usize` as `*const str` is invalid
--> $DIR/fat-ptr-cast.rs:23:32
struct TwoStrs(str, str) where str: Sized; //~ ERROR
-fn unsized_local() where Dst<A>: Sized { //~ ERROR
- let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+fn unsized_local() where Dst<dyn A>: Sized { //~ ERROR
+ let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
}
fn return_str() -> str where str: Sized { //~ ERROR
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
--> $DIR/feature-gate-trivial_bounds.rs:55:1
|
-LL | / fn unsized_local() where Dst<A>: Sized {
-LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+LL | / fn unsized_local() where Dst<dyn A>: Sized {
+LL | | let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
LL | | }
| |_^ doesn't have a size known at compile-time
|
-fn f(f: FnOnce()) {}
+fn f(f: dyn FnOnce()) {}
//~^ ERROR E0277
fn main() {
error[E0277]: the size for values of type `(dyn std::ops::FnOnce() + 'static)` cannot be known at compilation time
--> $DIR/feature-gate-unsized_locals.rs:1:6
|
-LL | fn f(f: FnOnce()) {}
+LL | fn f(f: dyn FnOnce()) {}
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
fn main() {
- let _ : &(Send,) = &((),);
+ let _ : &(dyn Send,) = &((),);
//~^ ERROR unsized tuple coercion is not stable enough
}
error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change
- --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:24
+ --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:28
|
-LL | let _ : &(Send,) = &((),);
- | ^^^^^^
+LL | let _ : &(dyn Send,) = &((),);
+ | ^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/42877
= help: add #![feature(unsized_tuple_coercion)] to the crate attributes to enable
fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
fn main() {
- let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
+ let _: () = (box |_: isize| {}) as Box<dyn FnOnce(isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
//~| found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
- let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
+ let _: () = (box |_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
//~| found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
- let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
+ let _: () = (box || -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected type `()`
//~| found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:6:17
|
-LL | let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+LL | let _: () = (box |_: isize| {}) as Box<dyn FnOnce(isize)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
|
= note: expected type `()`
found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:10:17
|
-LL | let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+LL | let _: () = (box |_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
|
= note: expected type `()`
found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:14:17
|
-LL | let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
+LL | let _: () = (box || -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `std::boxed::Box`
|
= note: expected type `()`
found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32);
//~^ ERROR lifetime bounds cannot be used in this context
-type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+type T1 = Box<dyn for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
//~^ ERROR lifetime bounds cannot be used in this context
fn main() {
let _ : Option<for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32> = None;
//~^ ERROR lifetime bounds cannot be used in this context
- let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+ let _ : Option<Box<dyn for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
//~^ ERROR lifetime bounds cannot be used in this context
}
| ^^^
error: lifetime bounds cannot be used in this context
- --> $DIR/higher-lifetime-bounds.rs:61:29
+ --> $DIR/higher-lifetime-bounds.rs:61:33
|
-LL | type T1 = Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
- | ^^^
+LL | type T1 = Box<dyn for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>;
+ | ^^^
error: lifetime bounds cannot be used in this context
--> $DIR/higher-lifetime-bounds.rs:65:34
| ^^^
error: lifetime bounds cannot be used in this context
- --> $DIR/higher-lifetime-bounds.rs:67:38
+ --> $DIR/higher-lifetime-bounds.rs:67:42
|
-LL | let _ : Option<Box<for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
- | ^^^
+LL | let _ : Option<Box<dyn for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None;
+ | ^^^
error: aborting due to 11 previous errors
--- /dev/null
+// Test to show what happens if we were not careful and allowed invariant
+// lifetimes to escape though an impl trait.
+//
+// Specifically we swap a long lived and short lived reference, giving us a
+// dangling pointer.
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+trait Swap: Sized {
+ fn swap(self, other: Self);
+}
+
+impl<T> Swap for &mut T {
+ fn swap(self, other: Self) {
+ std::mem::swap(self, other);
+ }
+}
+
+impl<T> Swap for Rc<RefCell<T>> {
+ fn swap(self, other: Self) {
+ <RefCell<T>>::swap(&self, &other);
+ }
+}
+
+// Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and
+// `&'a mut &'l T` are the same type.
+fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
+ //~^ ERROR hidden type
+ x
+}
+
+fn dangle_ref() -> &'static [i32; 3] {
+ let mut res = &[4, 5, 6];
+ let x = [1, 2, 3];
+ hide_ref(&mut res).swap(hide_ref(&mut &x));
+ res
+}
+
+// Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>`
+// and `Rc<RefCell<&'l T>>` are the same type.
+//
+// This is different to the previous example because the concrete return type
+// only has a single lifetime.
+fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
+ //~^ ERROR hidden type
+ x
+}
+
+fn dangle_rc_refcell() -> &'static [i32; 3] {
+ let long = Rc::new(RefCell::new(&[4, 5, 6]));
+ let x = [1, 2, 3];
+ let short = Rc::new(RefCell::new(&x));
+ hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short));
+ let res: &'static [i32; 3] = *long.borrow();
+ res
+}
+
+fn main() {
+ // both will print nonsense values.
+ println!("{:?}", dangle_ref());
+ println!("{:?}", dangle_rc_refcell())
+}
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/hidden-lifetimes.rs:28:54
+ |
+LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
+ | ^^^^^^^^^^^^^^
+ |
+note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17
+ --> $DIR/hidden-lifetimes.rs:28:17
+ |
+LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
+ | ^^
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/hidden-lifetimes.rs:45:70
+ |
+LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
+ | ^^^^^^^^^^^^^^
+ |
+note: hidden type `std::rc::Rc<std::cell::RefCell<&'b T>>` captures the lifetime 'b as defined on the function body at 45:24
+ --> $DIR/hidden-lifetimes.rs:45:24
+ |
+LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
+ | ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
--- /dev/null
+// Test that multiple liftimes are allowed in impl trait types.
+// compile-pass
+
+trait X<'x>: Sized {}
+
+impl<U> X<'_> for U {}
+
+fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a {
+ x
+}
+
+fn main() {}
mod m {
use iso1::any as are_you_okay1;
use ::iso2::any as are_you_okay2;
- type AreYouOkay1 = iso3::any::Any;
- type AreYouOkay2 = ::iso4::any::Any;
+ type AreYouOkay1 = dyn iso3::any::Any;
+ type AreYouOkay2 = dyn (::iso4::any::Any);
use core::any as are_you_okay3;
use ::core::any as are_you_okay4;
- type AreYouOkay3 = core::any::Any;
- type AreYouOkay4 = ::core::any::Any;
+ type AreYouOkay3 = dyn core::any::Any;
+ type AreYouOkay4 = dyn (::core::any::Any);
}
fn main() {}
struct Struct;
impl Deref for Struct {
- type Target = Trait;
- fn deref(&self) -> &Trait {
+ type Target = dyn Trait;
+ fn deref(&self) -> &dyn Trait {
unimplemented!();
}
}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl-2.rs:8:5
|
-LL | fn deref(&self) -> &Trait {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn deref(&self) -> &dyn Trait {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
--> $DIR/mismatched_trait_impl-2.rs:8:5
|
-LL | / fn deref(&self) -> &Trait {
+LL | / fn deref(&self) -> &dyn Trait {
LL | | unimplemented!();
LL | | }
| |_____^
--- /dev/null
+// compile-pass
+
+// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
+// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
+// symbol mangling fix produces the correct result.
+
+fn dummy() {}
+
+mod llvm {
+ pub(crate) struct Foo;
+}
+mod foo {
+ pub(crate) struct Foo<T>(T);
+
+ impl Foo<::llvm::Foo> {
+ pub(crate) fn foo() {
+ for _ in 0..0 {
+ for _ in &[::dummy()] {
+ ::dummy();
+ ::dummy();
+ ::dummy();
+ }
+ }
+ }
+ }
+
+ pub(crate) fn foo() {
+ Foo::foo();
+ Foo::foo();
+ }
+}
+
+pub fn foo() {
+ foo::foo();
+}
+
+fn main() {}
|
LL | fn test<'x>(x: &'x isize) {
| -- lifetime `'x` defined here
-LL | drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+LL | drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
LL | x
| ^ returning this value requires that `'x` must outlive `'static`
fn test<'x>(x: &'x isize) {
- drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
x //~ ERROR E0312
}));
}
LL | x
| ^
|
-note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 2:65...
- --> $DIR/issue-10291.rs:2:65
+note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 2:69...
+ --> $DIR/issue-10291.rs:2:69
|
-LL | drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
- | _________________________________________________________________^
+LL | drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ | _____________________________________________________________________^
LL | | x
LL | | }));
| |_____^
pub mod two_tuple {
pub trait T { fn dummy(&self) { } }
- pub struct P<'a>(&'a (T + 'a), &'a (T + 'a));
- pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
+ pub struct P<'a>(&'a (dyn T + 'a), &'a (dyn T + 'a));
+ pub fn f<'a>(car: &'a dyn T, cdr: &'a dyn T) -> P<'a> {
P(car, cdr)
}
}
pub mod two_fields {
pub trait T { fn dummy(&self) { } }
- pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) }
- pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
+ pub struct P<'a> { car: &'a (dyn T + 'a), cdr: &'a (dyn T + 'a) }
+ pub fn f<'a>(car: &'a dyn T, cdr: &'a dyn T) -> P<'a> {
P{ car: car, cdr: cdr }
}
}
use std::vec;
pub struct Container<'a> {
- reader: &'a mut Read
+ reader: &'a mut dyn Read
}
impl<'a> Container<'a> {
- pub fn wrap<'s>(reader: &'s mut io::Read) -> Container<'s> {
+ pub fn wrap<'s>(reader: &'s mut dyn io::Read) -> Container<'s> {
Container { reader: reader }
}
pub fn for_stdin<'a>() -> Container<'a> {
let mut r = io::stdin();
- Container::wrap(&mut r as &mut io::Read)
+ Container::wrap(&mut r as &mut dyn io::Read)
}
fn main() {
#![feature(box_syntax)]
struct Test {
- func: Box<FnMut()+'static>
+ func: Box<dyn FnMut() + 'static>
}
fn main() {
- let closure: Box<Fn()+'static> = Box::new(|| ());
+ let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
let test = box Test { func: closure }; //~ ERROR mismatched types
}
impl<'a, T> A for B<'a, T> {}
-fn foo(_: &A) {}
+fn foo(_: &dyn A) {}
fn bar<G>(b: &B<G>) {
foo(b); // Coercion should work
- foo(b as &A); // Explicit cast should work as well
+ foo(b as &dyn A); // Explicit cast should work as well
}
fn main() {}
}
struct A<'a> {
- p: &'a (X+'a)
+ p: &'a (dyn X + 'a)
}
-fn make_a<'a>(p: &'a X) -> A<'a> {
+fn make_a<'a>(p: &'a dyn X) -> A<'a> {
A { p: p }
}
trait Foo {
- fn bar(&mut self, other: &mut Foo);
+ fn bar(&mut self, other: &mut dyn Foo);
}
struct Baz;
impl Foo for Baz {
- fn bar(&mut self, other: &Foo) {}
+ fn bar(&mut self, other: &dyn Foo) {}
//~^ ERROR method `bar` has an incompatible type for trait
//~| expected type `fn(&mut Baz, &mut dyn Foo)`
//~| found type `fn(&mut Baz, &dyn Foo)`
error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/issue-13033.rs:8:30
|
-LL | fn bar(&mut self, other: &mut Foo);
- | -------- type in trait
+LL | fn bar(&mut self, other: &mut dyn Foo);
+ | ------------ type in trait
...
-LL | fn bar(&mut self, other: &Foo) {}
- | ^^^^ types differ in mutability
+LL | fn bar(&mut self, other: &dyn Foo) {}
+ | ^^^^^^^^ types differ in mutability
|
= note: expected type `fn(&mut Baz, &mut dyn Foo)`
found type `fn(&mut Baz, &dyn Foo)`
help: consider change the type to match the mutability in trait
|
-LL | fn bar(&mut self, other: &mut Foo) {}
- | ^^^^^^^^
+LL | fn bar(&mut self, other: &mut dyn Foo) {}
+ | ^^^^^^^^^^^^
error: aborting due to previous error
// ignore-cloudabi no std::process
-fn foo(_: Box<FnMut()>) {}
+fn foo(_: Box<dyn FnMut()>) {}
fn main() {
foo(loop {
trait ResponseHook {
fn get(&self);
}
-fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
+fn foo(res : Box<dyn ResponseHook>) { res.get } //~ ERROR attempted to take value of method
fn main() {}
error[E0615]: attempted to take value of method `get` on type `std::boxed::Box<(dyn ResponseHook + 'static)>`
- --> $DIR/issue-13853-2.rs:5:39
+ --> $DIR/issue-13853-2.rs:5:43
|
-LL | fn foo(res : Box<ResponseHook>) { res.get }
- | ^^^ help: use parentheses to call the method: `get()`
+LL | fn foo(res : Box<dyn ResponseHook>) { res.get }
+ | ^^^ help: use parentheses to call the method: `get()`
error: aborting due to previous error
impl Foo for A {}
-struct B<'a>(&'a (Foo+'a));
+struct B<'a>(&'a (dyn Foo + 'a));
-fn foo<'a>(a: &Foo) -> B<'a> {
+fn foo<'a>(a: &dyn Foo) -> B<'a> {
B(a) //~ ERROR explicit lifetime required in the type of `a` [E0621]
}
error[E0621]: explicit lifetime required in the type of `a`
--> $DIR/issue-14285.rs:12:5
|
-LL | fn foo<'a>(a: &Foo) -> B<'a> {
- | ---- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)`
+LL | fn foo<'a>(a: &dyn Foo) -> B<'a> {
+ | -------- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)`
LL | B(a)
| ^^^^ lifetime `'a` required
fn main() {
- let _x = "test" as &::std::any::Any;
+ let _x = "test" as &dyn (::std::any::Any);
//~^ ERROR the size for values of type
}
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-14366.rs:2:14
|
-LL | let _x = "test" as &::std::any::Any;
+LL | let _x = "test" as &dyn (::std::any::Any);
| ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
pub trait Reader {}
enum Wrapper<'a> {
- WrapReader(&'a (Reader + 'a))
+ WrapReader(&'a (dyn Reader + 'a))
}
trait Wrap<'a> {
impl<'a, R: Reader> Wrap<'a> for &'a mut R {
fn wrap(self) -> Wrapper<'a> {
- Wrapper::WrapReader(self as &'a mut Reader)
+ Wrapper::WrapReader(self as &'a mut dyn Reader)
}
}
}
}
-impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
- extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+impl<'b> Fn<(&'b mut (dyn Response + 'b),)> for SendFile {
+ extern "rust-call" fn call(&self, (_res,): (&'b mut (dyn Response + 'b),)) {}
}
-impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile {
- extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) {
+impl<'b> FnMut<(&'b mut (dyn Response + 'b),)> for SendFile {
+ extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (dyn Response+'b),)) {
self.call((_res,))
}
}
-impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile {
+impl<'b> FnOnce<(&'b mut (dyn Response + 'b),)> for SendFile {
type Output = ();
- extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) {
+ extern "rust-call" fn call_once(self, (_res,): (&'b mut (dyn Response+'b),)) {
self.call((_res,))
}
}
// compile-pass
#![allow(dead_code)]
struct Parser<'a, I, O> {
- parse: Box<FnMut(I) -> Result<O, String> + 'a>
+ parse: Box<dyn FnMut(I) -> Result<O, String> + 'a>
}
impl<'a, I: 'a, O: 'a> Parser<'a, I, O> {
use std::any::Any;
-fn foo<T: Any>(value: &T) -> Box<Any> {
- Box::new(value) as Box<Any>
+fn foo<T: Any>(value: &T) -> Box<dyn Any> {
+ Box::new(value) as Box<dyn Any>
//~^ ERROR explicit lifetime required in the type of `value` [E0621]
}
error[E0621]: explicit lifetime required in the type of `value`
--> $DIR/issue-16922.rs:4:5
|
-LL | fn foo<T: Any>(value: &T) -> Box<Any> {
+LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
| -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
-LL | Box::new(value) as Box<Any>
+LL | Box::new(value) as Box<dyn Any>
| ^^^^^^^^^^^^^^^ lifetime `'static` required
error: aborting due to previous error
// compile-pass
// skip-codegen
-fn cb<'a,T>(_x: Box<Fn((&'a i32, &'a (Vec<&'static i32>, bool))) -> T>) -> T {
+fn cb<'a,T>(_x: Box<dyn Fn((&'a i32, &'a (Vec<&'static i32>, bool))) -> T>) -> T {
panic!()
}
let _foo = &[1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
- let _bar = Box::new(1_usize) as std::fmt::Debug;
+ let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
//~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
- let _baz = 1_usize as std::fmt::Debug;
+ let _baz = 1_usize as dyn std::fmt::Debug;
//~^ ERROR cast to unsized type: `usize` as `dyn std::fmt::Debug`
let _quux = [1_usize, 2] as [usize];
error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:5:16
|
-LL | let _bar = Box::new(1_usize) as std::fmt::Debug;
- | ^^^^^^^^^^^^^^^^^^^^^---------------
+LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
+ | ^^^^^^^^^^^^^^^^^^^^^-------------------
| |
- | help: try casting to a `Box` instead: `Box<std::fmt::Debug>`
+ | help: try casting to a `Box` instead: `Box<dyn std::fmt::Debug>`
error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:8:16
|
-LL | let _baz = 1_usize as std::fmt::Debug;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let _baz = 1_usize as dyn std::fmt::Debug;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> $DIR/issue-17441.rs:8:16
|
-LL | let _baz = 1_usize as std::fmt::Debug;
+LL | let _baz = 1_usize as dyn std::fmt::Debug;
| ^^^^^^^
error[E0620]: cast to unsized type: `[usize; 2]` as `[usize]`
}
fn main() {
- let x:G<Bar>;
+ let x:G<dyn Bar>;
}
pub trait AbstractRenderer {}
fn _create_render(_: &()) ->
- AbstractRenderer
+ dyn AbstractRenderer
//~^ ERROR the size for values of type
{
match 0 {
error[E0277]: the size for values of type `(dyn AbstractRenderer + 'static)` cannot be known at compilation time
--> $DIR/issue-18107.rs:4:5
|
-LL | AbstractRenderer
- | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+LL | dyn AbstractRenderer
+ | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn AbstractRenderer + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
impl<T: Send + Sync> Promisable for T {}
pub fn propagate<'a, T, E, F, G>(mut action: F)
- -> Box<FnMut(Result<T, E>) -> Result<T, E> + 'a>
+ -> Box<dyn FnMut(Result<T, E>) -> Result<T, E> + 'a>
where
T: Promisable + Clone + 'a,
E: Promisable + Clone + 'a,
fn foo(&self) -> i32 { 0 }
}
-impl<'a> T + 'a {
+impl<'a> dyn T + 'a {
fn foo(&self) -> i32 { 1 }
}
fn foo(&self);
}
-impl<'a> T + 'a {
+impl<'a> dyn T + 'a {
fn foo(&self) {}
}
}
fn main() {
- let x: &T = &0i32;
+ let x: &dyn T = &0i32;
x.foo(); //~ ERROR multiple applicable items in scope [E0034]
}
}
trait Push<'c> {
- fn push<'f: 'c>(&self, push: Box<FnMut() + 'f>);
+ fn push<'f: 'c>(&self, push: Box<dyn FnMut() + 'f>);
}
-impl<'c> Push<'c> for RefCell<Vec<Box<FnMut() + 'c>>> {
- fn push<'f: 'c>(&self, fun: Box<FnMut() + 'f>) {
+impl<'c> Push<'c> for RefCell<Vec<Box<dyn FnMut() + 'c>>> {
+ fn push<'f: 'c>(&self, fun: Box<dyn FnMut() + 'f>) {
self.borrow_mut().push(fun)
}
}
type Item = bool;
}
-fn print_x(_: &Foo<Item=bool>, extra: &str) {
+fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
println!("{}", extra);
}
error[E0061]: this function takes 2 parameters but 1 parameter was supplied
--> $DIR/issue-18819.rs:16:5
|
-LL | fn print_x(_: &Foo<Item=bool>, extra: &str) {
- | ------------------------------------------- defined here
+LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
+ | ----------------------------------------------- defined here
...
LL | print_x(X);
| ^^^^^^^^^^ expected 2 parameters
-type FuncType<'f> = Fn(&isize) -> isize + 'f;
+type FuncType<'f> = dyn Fn(&isize) -> isize + 'f;
fn ho_func(f: Option<FuncType>) {
//~^ ERROR the size for values of type
struct MyString<'a>(&'a String);
struct B {
- list: Vec<Box<fmt::Debug>>,
+ list: Vec<Box<dyn fmt::Debug>>,
}
trait A<'a> {
}
#[inline(never)]
-fn foo(b: &Bar) {
+fn foo(b: &dyn Bar) {
//~^ ERROR E0038
b.foo(&0)
}
fn main() {
let mut thing = Thing;
- let test: &Bar = &mut thing;
+ let test: &dyn Bar = &mut thing;
foo(test);
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-18959.rs:11:1
|
-LL | fn foo(b: &Bar) {
- | ^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn foo(b: &dyn Bar) {
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
pub trait Foo : Send { }
pub struct MyFoo {
- children: Vec<Box<Foo>>,
+ children: Vec<Box<dyn Foo>>,
}
impl Foo for MyFoo { }
}
struct Bar {
- foos: &'static [&'static (Qiz + 'static)]
+ foos: &'static [&'static (dyn Qiz + 'static)]
//~^ ERROR E0038
}
error[E0038]: the trait `Qiz` cannot be made into an object
--> $DIR/issue-19380.rs:11:3
|
-LL | foos: &'static [&'static (Qiz + 'static)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
+LL | foos: &'static [&'static (dyn Qiz + 'static)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
|
= note: method `qiz` has no receiver
impl Component for Engine {}
trait Env {
- fn get_component_type_id(&self, type_id: TypeId) -> Option<Fp<Component>>;
+ fn get_component_type_id(&self, type_id: TypeId) -> Option<Fp<dyn Component>>;
}
-impl<'a> Env+'a {
+impl<'a> dyn Env + 'a {
fn get_component<T: Component>(&self) -> Option<Fp<T>> {
let x = self.get_component_type_id(TypeId::of::<T>());
None
}
trait Figment {
- fn init(&mut self, env: &Env);
+ fn init(&mut self, env: &dyn Env);
}
struct MyFigment;
impl Figment for MyFigment {
- fn init(&mut self, env: &Env) {
+ fn init(&mut self, env: &dyn Env) {
let engine = env.get_component::<Engine>();
}
}
fn dummy(&self) { }
}
-fn bar(x: &Foo) {}
+fn bar(x: &dyn Foo) {}
//~^ ERROR the associated type `A` (from the trait `Foo`) must be specified
pub fn main() {}
LL | type A;
| ------- `A` defined here
...
-LL | fn bar(x: &Foo) {}
- | ^^^ associated type `A` must be specified
+LL | fn bar(x: &dyn Foo) {}
+ | ^^^^^^^ associated type `A` must be specified
error: aborting due to previous error
fn main() {
let mut thing = Thing;
- let test: &mut Bar = &mut thing;
+ let test: &mut dyn Bar = &mut thing;
//~^ ERROR E0038
//~| ERROR E0038
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-19538.rs:17:15
|
-LL | let test: &mut Bar = &mut thing;
- | ^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | let test: &mut dyn Bar = &mut thing;
+ | ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
error[E0038]: the trait `Bar` cannot be made into an object
- --> $DIR/issue-19538.rs:17:26
+ --> $DIR/issue-19538.rs:17:30
|
-LL | let test: &mut Bar = &mut thing;
- | ^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | let test: &mut dyn Bar = &mut thing;
+ | ^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
enum Bar<T> { Bla(T) }
struct Baz<'a> {
- inner: for<'b> Foo<Bar<&'b ()>> + 'a,
+ inner: dyn for<'b> Foo<Bar<&'b ()>> + 'a,
}
fn main() {}
-fn changer<'a>(mut things: Box<Iterator<Item=&'a mut u8>>) {
+fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
//~^ ERROR the size for values of type
}
let _ = x
//~^ ERROR `Array` cannot be made into an object
as
- &Array;
+ &dyn Array;
//~^ ERROR `Array` cannot be made into an object
}
error[E0038]: the trait `Array` cannot be made into an object
--> $DIR/issue-20692.rs:7:5
|
-LL | &Array;
- | ^^^^^^ the trait `Array` cannot be made into an object
+LL | &dyn Array;
+ | ^^^^^^^^^^ the trait `Array` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
pub trait Publisher<'a> {
type Output;
- fn subscribe(&mut self, _: Box<Subscriber<Input=Self::Output> + 'a>);
+ fn subscribe(&mut self, _: Box<dyn Subscriber<Input=Self::Output> + 'a>);
}
pub trait Processor<'a> : Subscriber + Publisher<'a> { }
impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
struct MyStruct<'a> {
- sub: Box<Subscriber<Input=u64> + 'a>
+ sub: Box<dyn Subscriber<Input=u64> + 'a>
}
impl<'a> Publisher<'a> for MyStruct<'a> {
type Output = u64;
- fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+ fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
// Not obvious, but there is an implicit lifetime here -------^
//~^^ ERROR cannot infer
//~| ERROR mismatched types
error[E0308]: mismatched types
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
note: the anonymous lifetime #2 defined on the method body at 28:5...
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
error[E0308]: mismatched types
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5...
--> $DIR/issue-20831-debruijn.rs:28:5
|
-LL | / fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | / fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
LL | | // Not obvious, but there is an implicit lifetime here -------^
LL | |
LL | |
trait Foo {}
-impl<'a> Foo for Foo+'a {}
+impl<'a> Foo for dyn Foo + 'a {}
//~^ ERROR the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
fn main() {}
error[E0371]: the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
--> $DIR/issue-20939.rs:3:1
|
-LL | impl<'a> Foo for Foo+'a {}
- | ^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Foo + 'a)` automatically implements trait `Foo`
+LL | impl<'a> Foo for dyn Foo + 'a {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Foo + 'a)` automatically implements trait `Foo`
error: aborting due to previous error
fn dummy(&self) { }
}
-impl<'a, T> Iterator for &'a mut (Iterator<Item=T> + 'a) {
+impl<'a, T> Iterator for &'a mut (dyn Iterator<Item=T> + 'a) {
type Item = T;
}
fn main() {
let x = &10 as
- &Add;
+ &dyn Add;
//~^ ERROR E0393
//~| ERROR E0191
}
error[E0393]: the type parameter `Rhs` must be explicitly specified
- --> $DIR/issue-21950.rs:5:14
+ --> $DIR/issue-21950.rs:5:18
|
-LL | &Add;
- | ^^^ missing reference to `Rhs`
+LL | &dyn Add;
+ | ^^^ missing reference to `Rhs`
|
= note: because of the default `Self` reference, type parameters must be specified on object types
error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Add`) must be specified
--> $DIR/issue-21950.rs:5:14
|
-LL | &Add;
- | ^^^ associated type `Output` must be specified
+LL | &dyn Add;
+ | ^^^^^^^ associated type `Output` must be specified
error: aborting due to 2 previous errors
fn main() {
let ptr: *mut () = 0 as *mut _;
- let _: &mut Fn() = unsafe {
- &mut *(ptr as *mut Fn())
+ let _: &mut dyn Fn() = unsafe {
+ &mut *(ptr as *mut dyn Fn())
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `()`
};
}
error[E0277]: expected a `std::ops::Fn<()>` closure, found `()`
--> $DIR/issue-22034.rs:8:16
|
-LL | &mut *(ptr as *mut Fn())
+LL | &mut *(ptr as *mut dyn Fn())
| ^^^ expected an `Fn<()>` closure, found `()`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `()`
fn main() {
- 0 as &std::any::Any; //~ ERROR non-primitive cast
+ 0 as &dyn std::any::Any; //~ ERROR non-primitive cast
}
error[E0605]: non-primitive cast: `i32` as `&(dyn std::any::Any + 'static)`
--> $DIR/issue-22289.rs:2:5
|
-LL | 0 as &std::any::Any;
- | ^^^^^^^^^^^^^^^^^^^
+LL | 0 as &dyn std::any::Any;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
return None;
}
let i = y * self.columns() + x;
- let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
+ let indexer = &(*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
//~^ERROR non-primitive cast
Some(indexer.index(i))
}
error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index<usize, Output = <Self as std::ops::Index<usize>>::Output>`
--> $DIR/issue-22312.rs:11:24
|
-LL | let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let indexer = &(*self as &dyn Index<usize, Output = <Self as Index<usize>>::Output>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
trait A<T=Self> {}
-fn f(a: &A) {}
+fn f(a: &dyn A) {}
//~^ ERROR E0393
fn main() {}
error[E0393]: the type parameter `T` must be explicitly specified
- --> $DIR/issue-22370.rs:3:10
+ --> $DIR/issue-22370.rs:3:14
|
-LL | fn f(a: &A) {}
- | ^ missing reference to `T`
+LL | fn f(a: &dyn A) {}
+ | ^ missing reference to `T`
|
= note: because of the default `Self` reference, type parameters must be specified on object types
type A;
}
-type I<'a> = &'a (Foo + 'a);
+type I<'a> = &'a (dyn Foo + 'a);
//~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
fn main() {}
LL | type A;
| ------- `A` defined here
...
-LL | type I<'a> = &'a (Foo + 'a);
- | ^^^^^^^^ associated type `A` must be specified
+LL | type I<'a> = &'a (dyn Foo + 'a);
+ | ^^^^^^^^^^^^ associated type `A` must be specified
error: aborting due to previous error
use std::ops::{Add, Sub};
-type Test = Add +
+type Test = dyn Add +
//~^ ERROR E0393
//~| ERROR E0191
Sub;
= note: because of the default `Self` reference, type parameters must be specified on object types
error[E0393]: the type parameter `Rhs` must be explicitly specified
- --> $DIR/issue-22560.rs:3:13
+ --> $DIR/issue-22560.rs:3:17
|
-LL | type Test = Add +
- | ^^^ missing reference to `Rhs`
+LL | type Test = dyn Add +
+ | ^^^ missing reference to `Rhs`
|
= note: because of the default `Self` reference, type parameters must be specified on object types
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/issue-22560.rs:6:13
|
-LL | type Test = Add +
- | ---
- | |
- | first non-auto trait
- | trait alias used in trait object type (first use)
+LL | type Test = dyn Add +
+ | ---
+ | |
+ | first non-auto trait
+ | trait alias used in trait object type (first use)
...
LL | Sub;
| ^^^
error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified
--> $DIR/issue-22560.rs:3:13
|
-LL | type Test = Add +
+LL | type Test = dyn Add +
| _____________^
| |_____________|
| |
use std::collections::hash_map::Entry::Vacant;
pub fn foo() {
- type F = Box<Fn(&()) + 'static>;
+ type F = Box<dyn Fn(&()) + 'static>;
let mut map: HashMap<(), F> = HashMap::new();
let x: &mut F = match map.entry(()) {
Vacant(_) => unimplemented!(),
}
fn push_process<P>(process: P) where P: Process<'static> {
- let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process));
+ let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
//~^ ERROR is not an iterator
}
error[E0277]: `<P as Process<'_>>::Item` is not an iterator
- --> $DIR/issue-22872.rs:20:36
+ --> $DIR/issue-22872.rs:20:40
|
-LL | let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
+LL | let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
|
= help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item`
= help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound
fn main()
{
fn h(x:i32) -> i32 {3*x}
- let mut vfnfer:Vec<Box<Any>> = vec![];
+ let mut vfnfer:Vec<Box<dyn Any>> = vec![];
vfnfer.push(box h);
- println!("{:?}",(vfnfer[0] as Fn)(3));
+ println!("{:?}",(vfnfer[0] as dyn Fn)(3));
//~^ ERROR the precise format of `Fn`-family traits'
//~| ERROR wrong number of type arguments: expected 1, found 0 [E0107]
//~| ERROR the value of the associated type `Output` (from the trait `std::ops::FnOnce`)
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
- --> $DIR/issue-23024.rs:9:35
+ --> $DIR/issue-23024.rs:9:39
|
-LL | println!("{:?}",(vfnfer[0] as Fn)(3));
- | ^^
+LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3));
+ | ^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29625
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
error[E0107]: wrong number of type arguments: expected 1, found 0
- --> $DIR/issue-23024.rs:9:35
+ --> $DIR/issue-23024.rs:9:39
|
-LL | println!("{:?}",(vfnfer[0] as Fn)(3));
- | ^^ expected 1 type argument
+LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3));
+ | ^^ expected 1 type argument
error[E0191]: the value of the associated type `Output` (from the trait `std::ops::FnOnce`) must be specified
--> $DIR/issue-23024.rs:9:35
|
-LL | println!("{:?}",(vfnfer[0] as Fn)(3));
- | ^^ associated type `Output` must be specified
+LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3));
+ | ^^^^^^ associated type `Output` must be specified
error: aborting due to 3 previous errors
fn main()
{
fn bar(x:i32) ->i32 { 3*x };
- let b:Box<Any> = Box::new(bar as fn(_)->_);
+ let b:Box<dyn Any> = Box::new(bar as fn(_)->_);
b.downcast_ref::<fn(_)->_>(); //~ ERROR E0282
}
pub enum Expr<'var, VAR> {
Let(Box<Expr<'var, VAR>>,
- Box<for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>)
+ Box<dyn for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>)
}
pub fn add<'var, VAR>
pub struct Struct;
impl Struct {
- pub fn function(funs: Vec<Fn() -> ()>) {}
+ pub fn function(funs: Vec<dyn Fn() -> ()>) {}
//~^ ERROR the size for values of type
}
error[E0277]: the size for values of type `(dyn std::ops::Fn() + 'static)` cannot be known at compilation time
--> $DIR/issue-23281.rs:4:5
|
-LL | pub fn function(funs: Vec<Fn() -> ()>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+LL | pub fn function(funs: Vec<dyn Fn() -> ()>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
fn main() {
- static foo: Fn() -> u32 = || -> u32 {
+ static foo: dyn Fn() -> u32 = || -> u32 {
//~^ ERROR the size for values of type
0
};
error[E0277]: the size for values of type `(dyn std::ops::Fn() -> u32 + 'static)` cannot be known at compilation time
--> $DIR/issue-24446.rs:2:17
|
-LL | static foo: Fn() -> u32 = || -> u32 {
- | ^^^^^^^^^^^ doesn't have a size known at compile-time
+LL | static foo: dyn Fn() -> u32 = || -> u32 {
+ | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::Fn() -> u32 + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
-const x: &'static Fn() = &|| println!("ICE here");
+const x: &'static dyn Fn() = &|| println!("ICE here");
fn main() {}
fn main() {
let _ = &()
- as &Map<Key=u32,MapValue=u32>;
+ as &dyn Map<Key=u32,MapValue=u32>;
//~^ ERROR E0038
}
error[E0038]: the trait `Map` cannot be made into an object
--> $DIR/issue-26056.rs:20:13
|
-LL | as &Map<Key=u32,MapValue=u32>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Map` cannot be made into an object
+LL | as &dyn Map<Key=u32,MapValue=u32>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Map` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
-fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
+fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
//~^ ERROR missing lifetime specifier [E0106]
fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
error[E0106]: missing lifetime specifier
- --> $DIR/issue-26638.rs:1:58
+ --> $DIR/issue-26638.rs:1:62
|
-LL | fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
- | ^ expected lifetime parameter
+LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+ | ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
let data = [1, 2, 3];
let iter = data.iter();
let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) };
- let _y: MyRc<Iterator<Item=&u32>> = x;
+ let _y: MyRc<dyn Iterator<Item=&u32>> = x;
}
use std::rc::Rc;
pub struct Callbacks {
- callbacks: Vec<Rc<RefCell<FnMut(i32)>>>,
+ callbacks: Vec<Rc<RefCell<dyn FnMut(i32)>>>,
}
impl Callbacks {
#![allow(dead_code)]
use std::rc::Rc;
-fn test1() -> Rc<for<'a> Fn(&'a usize) + 'static> {
+fn test1() -> Rc<dyn for<'a> Fn(&'a usize) + 'static> {
if let Some(_) = Some(1) {
loop{}
} else {
}
}
-fn test2() -> *mut (for<'a> Fn(&'a usize) + 'static) {
+fn test2() -> *mut (dyn for<'a> Fn(&'a usize) + 'static) {
if let Some(_) = Some(1) {
loop{}
} else {
pub trait Bar: Foo<Assoc=()> {
fn new(&self, b: &
- Bar //~ ERROR the trait `Bar` cannot be made into an object
+ dyn Bar //~ ERROR the trait `Bar` cannot be made into an object
<Assoc=()>
);
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-28576.rs:7:12
|
-LL | / Bar
+LL | / dyn Bar
LL | | <Assoc=()>
| |________________________^ the trait `Bar` cannot be made into an object
|
fn read_board_grid<rdr:'static + Read>(mut input: rdr)
-> Vec<Vec<square>> {
- let mut input: &mut Read = &mut input;
+ let mut input: &mut dyn Read = &mut input;
let mut grid = Vec::new();
let mut line = [0; 10];
input.read(&mut line);
fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() {
- size_of_copy::<Misc+Copy>();
+ size_of_copy::<dyn Misc + Copy>();
//~^ ERROR only auto traits can be used as additional traits in a trait object
//~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
}
error[E0225]: only auto traits can be used as additional traits in a trait object
- --> $DIR/issue-32963.rs:8:25
+ --> $DIR/issue-32963.rs:8:31
|
-LL | size_of_copy::<Misc+Copy>();
- | ---- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
- | first non-auto trait
- | trait alias used in trait object type (first use)
+LL | size_of_copy::<dyn Misc + Copy>();
+ | ---- ^^^^
+ | | |
+ | | additional non-auto trait
+ | | trait alias used in trait object type (additional use)
+ | first non-auto trait
+ | trait alias used in trait object type (first use)
error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
--> $DIR/issue-32963.rs:8:5
|
-LL | size_of_copy::<Misc+Copy>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
+LL | size_of_copy::<dyn Misc + Copy>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `dyn Misc`
|
note: required by `size_of_copy`
--> $DIR/issue-32963.rs:5:1
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
- let o : Box<::std::marker()::Send> = Box::new(1);
+ let o : Box<dyn (::std::marker()::Send)> = Box::new(1);
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
- let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
+ let o : Box<dyn Send + ::std::marker()::Sync> = Box::new(1);
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
}
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
error: parenthesized type parameters may only be used with a `Fn` trait
- --> $DIR/issue-32995.rs:20:30
+ --> $DIR/issue-32995.rs:20:35
|
-LL | let o : Box<::std::marker()::Send> = Box::new(1);
- | ^^
+LL | let o : Box<dyn (::std::marker()::Send)> = Box::new(1);
+ | ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
error: parenthesized type parameters may only be used with a `Fn` trait
- --> $DIR/issue-32995.rs:24:37
+ --> $DIR/issue-32995.rs:24:41
|
-LL | let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
- | ^^
+LL | let o : Box<dyn Send + ::std::marker()::Sync> = Box::new(1);
+ | ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
/// Implementations for all traits in std are provided.
pub unsafe trait Trait {}
-unsafe impl Trait for ::std::any::Any + Send { }
-unsafe impl Trait for ::std::any::Any + Sync { }
-unsafe impl Trait for ::std::any::Any + Send + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Sync { }
-unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send + Sync { }
-unsafe impl Trait for ::std::error::Error + Send { }
-unsafe impl Trait for ::std::error::Error + Sync { }
-unsafe impl Trait for ::std::error::Error + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Binary + Send { }
-unsafe impl Trait for ::std::fmt::Binary + Sync { }
-unsafe impl Trait for ::std::fmt::Binary + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Debug + Send { }
-unsafe impl Trait for ::std::fmt::Debug + Sync { }
-unsafe impl Trait for ::std::fmt::Debug + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Display + Send { }
-unsafe impl Trait for ::std::fmt::Display + Sync { }
-unsafe impl Trait for ::std::fmt::Display + Send + Sync { }
-unsafe impl Trait for ::std::fmt::LowerExp + Send { }
-unsafe impl Trait for ::std::fmt::LowerExp + Sync { }
-unsafe impl Trait for ::std::fmt::LowerExp + Send + Sync { }
-unsafe impl Trait for ::std::fmt::LowerHex + Send { }
-unsafe impl Trait for ::std::fmt::LowerHex + Sync { }
-unsafe impl Trait for ::std::fmt::LowerHex + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Octal + Send { }
-unsafe impl Trait for ::std::fmt::Octal + Sync { }
-unsafe impl Trait for ::std::fmt::Octal + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Pointer + Send { }
-unsafe impl Trait for ::std::fmt::Pointer + Sync { }
-unsafe impl Trait for ::std::fmt::Pointer + Send + Sync { }
-unsafe impl Trait for ::std::fmt::UpperExp + Send { }
-unsafe impl Trait for ::std::fmt::UpperExp + Sync { }
-unsafe impl Trait for ::std::fmt::UpperExp + Send + Sync { }
-unsafe impl Trait for ::std::fmt::UpperHex + Send { }
-unsafe impl Trait for ::std::fmt::UpperHex + Sync { }
-unsafe impl Trait for ::std::fmt::UpperHex + Send + Sync { }
-unsafe impl Trait for ::std::fmt::Write + Send { }
-unsafe impl Trait for ::std::fmt::Write + Sync { }
-unsafe impl Trait for ::std::fmt::Write + Send + Sync { }
-unsafe impl Trait for ::std::hash::Hasher + Send { }
-unsafe impl Trait for ::std::hash::Hasher + Sync { }
-unsafe impl Trait for ::std::hash::Hasher + Send + Sync { }
-unsafe impl Trait for ::std::io::BufRead + Send { }
-unsafe impl Trait for ::std::io::BufRead + Sync { }
-unsafe impl Trait for ::std::io::BufRead + Send + Sync { }
-unsafe impl Trait for ::std::io::Read + Send { }
-unsafe impl Trait for ::std::io::Read + Sync { }
-unsafe impl Trait for ::std::io::Read + Send + Sync { }
-unsafe impl Trait for ::std::io::Seek + Send { }
-unsafe impl Trait for ::std::io::Seek + Sync { }
-unsafe impl Trait for ::std::io::Seek + Send + Sync { }
-unsafe impl Trait for ::std::io::Write + Send { }
-unsafe impl Trait for ::std::io::Write + Sync { }
-unsafe impl Trait for ::std::io::Write + Send + Sync { }
-unsafe impl<T, I> Trait for ::std::iter::IntoIterator<IntoIter=I, Item=T> { }
-unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send { }
-unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Sync { }
-unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send + Sync { }
-unsafe impl Trait for ::std::marker::Send + Send { }
-unsafe impl Trait for ::std::marker::Send + Sync { }
-unsafe impl Trait for ::std::marker::Send + Send + Sync { }
-unsafe impl Trait for ::std::marker::Sync + Send { }
-unsafe impl Trait for ::std::marker::Sync + Sync { }
-unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
-unsafe impl Trait for ::std::ops::Drop + Send { }
-unsafe impl Trait for ::std::ops::Drop + Sync { }
-unsafe impl Trait for ::std::ops::Drop + Send + Sync { }
-unsafe impl Trait for ::std::string::ToString + Send { }
-unsafe impl Trait for ::std::string::ToString + Sync { }
-unsafe impl Trait for ::std::string::ToString + Send + Sync { }
+unsafe impl Trait for dyn (::std::any::Any) + Send { }
+unsafe impl Trait for dyn (::std::any::Any) + Sync { }
+unsafe impl Trait for dyn (::std::any::Any) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::Borrow<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::borrow::BorrowMut<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsMut<T>) + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Sync { }
+unsafe impl<T: ?Sized> Trait for dyn (::std::convert::AsRef<T>) + Send + Sync { }
+unsafe impl Trait for dyn (::std::error::Error) + Send { }
+unsafe impl Trait for dyn (::std::error::Error) + Sync { }
+unsafe impl Trait for dyn (::std::error::Error) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Binary) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Debug) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Display) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Octal) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Pointer) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Send { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Sync { }
+unsafe impl Trait for dyn (::std::fmt::Write) + Send + Sync { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Send { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Sync { }
+unsafe impl Trait for dyn (::std::hash::Hasher) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Send { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Sync { }
+unsafe impl Trait for dyn (::std::io::BufRead) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Read) + Send { }
+unsafe impl Trait for dyn (::std::io::Read) + Sync { }
+unsafe impl Trait for dyn (::std::io::Read) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Seek) + Send { }
+unsafe impl Trait for dyn (::std::io::Seek) + Sync { }
+unsafe impl Trait for dyn (::std::io::Seek) + Send + Sync { }
+unsafe impl Trait for dyn (::std::io::Write) + Send { }
+unsafe impl Trait for dyn (::std::io::Write) + Sync { }
+unsafe impl Trait for dyn (::std::io::Write) + Send + Sync { }
+unsafe impl<T, I> Trait for dyn (::std::iter::IntoIterator<IntoIter=I, Item=T>) { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Sync { }
+unsafe impl<T> Trait for dyn (::std::iter::Iterator<Item=T>) + Send + Sync { }
+unsafe impl Trait for dyn (::std::marker::Send) + Send { }
+unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+unsafe impl Trait for dyn (::std::marker::Sync) + Sync { }
+unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+unsafe impl Trait for dyn (::std::ops::Drop) + Send { }
+unsafe impl Trait for dyn (::std::ops::Drop) + Sync { }
+unsafe impl Trait for dyn (::std::ops::Drop) + Send + Sync { }
+unsafe impl Trait for dyn (::std::string::ToString) + Send { }
+unsafe impl Trait for dyn (::std::string::ToString) + Sync { }
+unsafe impl Trait for dyn (::std::string::ToString) + Send + Sync { }
fn assert_trait<T: Trait + ?Sized>() {}
fn main() {
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
--> $DIR/issue-33140-traitobject-crate.rs:85:1
|
-LL | unsafe impl Trait for ::std::marker::Send + Sync { }
- | ------------------------------------------------ first implementation here
-LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+ | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
|
note: lint level defined here
--> $DIR/issue-33140-traitobject-crate.rs:3:9
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
--> $DIR/issue-33140-traitobject-crate.rs:86:1
|
-LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
- | ------------------------------------------------------- first implementation here
-LL | unsafe impl Trait for ::std::marker::Sync + Send { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ------------------------------------------------------------- first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
--> $DIR/issue-33140-traitobject-crate.rs:88:1
|
-LL | unsafe impl Trait for ::std::marker::Sync + Send { }
- | ------------------------------------------------ first implementation here
-LL | unsafe impl Trait for ::std::marker::Sync + Sync { }
-LL | unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Sync { }
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
}
fn main() {
- assert_eq!(<Send+Sync>::xyz(), false);
- assert_eq!(<Sync+Send>::xyz(), true);
- assert_eq!(<Send+Sync>::uvw(), false);
- assert_eq!(<Sync+Send+Sync>::uvw(), true);
- assert_eq!(<Foo<Send+Sync>>::abc(), false);
- assert_eq!(<Foo<Sync+Send>>::abc(), true);
+ assert_eq!(<dyn Send + Sync>::xyz(), false);
+ assert_eq!(<dyn Sync + Send>::xyz(), true);
+ assert_eq!(<dyn Send + Sync>::uvw(), false);
+ assert_eq!(<dyn Sync + Send+ Sync>::uvw(), true);
+ assert_eq!(<Foo<dyn Send + Sync>>::abc(), false);
+ assert_eq!(<Foo<dyn Sync + Send>>::abc(), true);
}
fn main() {
- let t: &(u8, fmt::Debug) = any();
+ let t: &(u8, dyn fmt::Debug) = any();
println!("{:?}", &t.1);
}
pub struct Path;
-type rsrc_loader = Box<FnMut(&Path) -> Result<String, String>>;
+type rsrc_loader = Box<dyn FnMut(&Path) -> Result<String, String>>;
fn tester()
{
pub struct MTFn;
impl<'a> MethodType for MTFn { //~ ERROR E0207
- type GetProp = fmt::Debug + 'a;
+ type GetProp = dyn fmt::Debug + 'a;
}
-fn bad(a: Box<<MTFn as MethodType>::GetProp>) -> Box<fmt::Debug+'static> {
+fn bad(a: Box<<MTFn as MethodType>::GetProp>) -> Box<dyn fmt::Debug+'static> {
a
}
-fn dangling(a: &str) -> Box<fmt::Debug> {
+fn dangling(a: &str) -> Box<dyn fmt::Debug> {
bad(Box::new(a))
}
// `value` field of `Node<Send>`).
struct Node<T: ?Sized + Send> {
- next: Option<Box<Node<Send>>>,
+ next: Option<Box<Node<dyn Send>>>,
value: T,
}
-fn clear(head: &mut Option<Box<Node<Send>>>) {
+fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
match head.take() {
Some(node) => *head = node.next,
None => (),
type Ty;
}
-fn _ice(param: Box<for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
let _e: (usize, usize) = unsafe{mem::transmute(param)};
}
fn wait(&self) where Self: Sized;
}
- impl Future for Box<Future> {
+ impl Future for Box<dyn Future> {
fn wait(&self) { }
}
}
//use private::Future;
-fn bar(arg: Box<private::Future>) {
+fn bar(arg: Box<dyn private::Future>) {
arg.wait();
//~^ ERROR the `wait` method cannot be invoked on a trait object
}
use std::sync::mpsc::Sender;
type RingBuffer = Vec<f64> ;
-type SamplesFn = Box<FnMut(&RingBuffer) + Send>;
+type SamplesFn = Box<dyn FnMut(&RingBuffer) + Send>;
enum Msg
{
fn main() {
- let _m: &Broken<Assoc=()> = &();
+ let _m: &dyn Broken<Assoc=()> = &();
}
trait Add {
fn to_int(&self) -> isize;
- fn add_dynamic(&self, other: &Add) -> isize;
+ fn add_dynamic(&self, other: &dyn Add) -> isize;
}
impl Add for isize {
fn to_int(&self) -> isize { *self }
- fn add_dynamic(&self, other: &Add) -> isize {
+ fn add_dynamic(&self, other: &dyn Add) -> isize {
self.to_int() + other.to_int() //~ ERROR multiple applicable items in scope
}
}
// compile-pass
#![warn(unused)]
-type Z = for<'x> Send;
+type Z = dyn for<'x> Send;
//~^ WARN type alias is never used
warning: type alias is never used: `Z`
--> $DIR/issue-37515.rs:5:1
|
-LL | type Z = for<'x> Send;
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | type Z = dyn for<'x> Send;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/issue-37515.rs:3:9
trait A<T>: std::ops::Add<Self> + Sized {}
trait B<T>: A<T> {}
-trait C<T>: A<B<T, Output=usize>> {}
+trait C<T>: A<dyn B<T, Output=usize>> {}
//~^ ERROR the trait `B` cannot be made into an object
fn main() {}
error[E0038]: the trait `B` cannot be made into an object
--> $DIR/issue-38404.rs:3:15
|
-LL | trait C<T>: A<B<T, Output=usize>> {}
- | ^^^^^^^^^^^^^^^^^^ the trait `B` cannot be made into an object
+LL | trait C<T>: A<dyn B<T, Output=usize>> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^ the trait `B` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
}
fn main() {
- let _f: Box<Foo> = //~ ERROR `Foo` cannot be made into an object
+ let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
Box::new(()); //~ ERROR `Foo` cannot be made into an object
}
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/issue-38604.rs:14:13
|
-LL | let _f: Box<Foo> =
- | ^^^^^^^^ the trait `Foo` cannot be made into an object
+LL | let _f: Box<dyn Foo> =
+ | ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
fn main() {
let bar: fn(&mut u32) = |_| {};
- fn foo(x: Box<Fn(&i32)>) {}
- let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
+ fn foo(x: Box<dyn Fn(&i32)>) {}
+ let bar = Box::new(|x: &i32| {}) as Box<dyn Fn(_)>;
foo(bar); //~ ERROR E0308
}
trait Trait {}
-fn get_function<'a>() -> &'a Fn() -> Trait { panic!("") }
+fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") }
fn main() {
- let t : &Trait = &get_function()();
+ let t : &dyn Trait = &get_function()();
//~^ ERROR cannot move a value of type dyn Trait
}
error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined
- --> $DIR/issue-41139.rs:6:23
+ --> $DIR/issue-41139.rs:6:27
|
-LL | let t : &Trait = &get_function()();
- | ^^^^^^^^^^^^^^^^
+LL | let t : &dyn Trait = &get_function()();
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
//~^ ERROR the size for values of type
}
-pub fn f(_: ToString) {}
+pub fn f(_: dyn ToString) {}
//~^ ERROR the size for values of type
fn main() { }
= help: unsized locals are gated as an unstable feature
error[E0277]: the size for values of type `(dyn std::string::ToString + 'static)` cannot be known at compilation time
- --> $DIR/issue-42312.rs:8:23
+ --> $DIR/issue-42312.rs:8:27
|
-LL | pub fn f(_: ToString) {}
- | ^ doesn't have a size known at compile-time
+LL | pub fn f(_: dyn ToString) {}
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::string::ToString + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
fn id<T>(t: T) -> T { t }
-fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
id(Box::new(|| *v))
//~^ ERROR E0373
//~| ERROR E0507
error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/issue-4335.rs:6:20
|
-LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
| - captured outer variable
LL | id(Box::new(|| *v))
| ^^ cannot move out of captured variable in an `FnMut` closure
let x: *const _ = 0 as _; //~ ERROR cannot cast
let x: *const _ = 0 as *const _; //~ ERROR cannot cast
- let y: Option<*const fmt::Debug> = Some(x) as _;
+ let y: Option<*const dyn fmt::Debug> = Some(x) as _;
let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
}
}
pub enum TraitWrapper {
- A(Box<MyTrait+'static>),
+ A(Box<dyn MyTrait + 'static>),
}
-fn get_tw_map(tw: &TraitWrapper) -> &MyTrait {
+fn get_tw_map(tw: &TraitWrapper) -> &dyn MyTrait {
match *tw {
TraitWrapper::A(box ref map) => map, //~ ERROR cannot be dereferenced
}
}
impl Builder {
- pub fn with_a(&mut self, _a: fn() -> ::a::A) {}
+ pub fn with_a(&mut self, _a: fn() -> dyn (::a::A)) {}
}
}
pub fn main() {
// Check that this does not segfault.
- <X as X>::foo(&());
+ <dyn X as X>::foo(&());
}
}
fn main() {
- (&5isize as &Foo).foo();
+ (&5isize as &dyn Foo).foo();
//~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
}
error[E0599]: no method named `foo` found for type `&dyn Foo` in the current scope
- --> $DIR/issue-5153.rs:10:23
+ --> $DIR/issue-5153.rs:10:27
|
-LL | (&5isize as &Foo).foo();
- | ^^^
+LL | (&5isize as &dyn Foo).foo();
+ | ^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `foo`, perhaps you need to implement it:
fn f() { }
-struct S(Box<FnMut()>);
+struct S(Box<dyn FnMut()>);
pub static C: S = S(f); //~ ERROR mismatched types
fn g() { }
-type T = Box<FnMut()>;
+type T = Box<dyn FnMut()>;
pub static D: T = g; //~ ERROR mismatched types
fn main() {}
//compile-pass
struct Foo {
- bar: for<'r> Fn(usize, &'r FnMut())
+ bar: dyn for<'r> Fn(usize, &'r dyn FnMut())
}
fn main() {
impl Stage for Enum {}
-pub static ARRAY: [(&Stage, &str); 1] = [
+pub static ARRAY: [(&dyn Stage, &str); 1] = [
(&Enum::A, ""),
];
fn out_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
fn in_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
- fn out_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+ fn out_neighbors(&'a self, u: &Self::Node) -> Box<dyn Iterator<Item = Self::Node>> {
Box::new(self.out_edges(u).map(|e| e.target()))
//~^ ERROR cannot infer
}
- fn in_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+ fn in_neighbors(&'a self, u: &Self::Node) -> Box<dyn Iterator<Item = Self::Node>> {
Box::new(self.in_edges(u).map(|e| e.target()))
//~^ ERROR cannot infer
}
trait A {}
struct Struct {
- r: A+'static
+ r: dyn A + 'static
}
-fn new_struct(r: A+'static)
+fn new_struct(r: dyn A + 'static)
-> Struct { //~^ ERROR the size for values of type
//~^ ERROR the size for values of type
Struct { r: r }
error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
--> $DIR/issue-5883.rs:7:15
|
-LL | fn new_struct(r: A+'static)
+LL | fn new_struct(r: dyn A + 'static)
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
//~^ ERROR type arguments are not allowed for this type
let c1 = A {};
- c1::<Into<B>>;
+ c1::<dyn Into<B>>;
//~^ ERROR type arguments are not allowed for this type
}
error[E0109]: type arguments are not allowed for this type
--> $DIR/issue-60989.rs:16:10
|
-LL | c1::<Into<B>>;
- | ^^^^^^^ type argument not allowed
+LL | c1::<dyn Into<B>>;
+ | ^^^^^^^^^^^ type argument not allowed
error: aborting due to 2 previous errors
}
struct A {
- v: Box<Foo + Send>,
+ v: Box<dyn Foo + Send>,
}
fn main() {
- let a = A {v: box B{v: None} as Box<Foo+Send>};
+ let a = A {v: box B{v: None} as Box<dyn Foo + Send>};
//~^ ERROR `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
}
error[E0277]: `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
--> $DIR/issue-7013.rs:26:19
|
-LL | let a = A {v: box B{v: None} as Box<Foo+Send>};
+LL | let a = A {v: box B{v: None} as Box<dyn Foo + Send>};
| ^^^^^^^^^^^^^^ `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
|
= help: within `B`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::RefCell<A>>`
impl<T: 'static> A for T {}
-fn owned2<T: 'static>(a: Box<T>) { a as Box<A>; }
-fn owned3<T: 'static>(a: Box<T>) { box a as Box<A>; }
+fn owned2<T: 'static>(a: Box<T>) { a as Box<dyn A>; }
+fn owned3<T: 'static>(a: Box<T>) { box a as Box<dyn A>; }
fn write(&mut self, b: &[u8]) -> Result<(), ()>;
}
-fn foo(a: &mut Writer) {
+fn foo(a: &mut dyn Writer) {
a.write(&[]).unwrap();
}
}
impl X for isize {}
- pub struct Z<'a>(Enum<&'a (X+'a)>);
- fn foo() { let x: isize = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
+ pub struct Z<'a>(Enum<&'a (dyn X + 'a)>);
+ fn foo() { let x: isize = 42; let z = Z(Enum::A(&x as &dyn X)); let _ = z; }
}
mod b {
}
impl X for isize {}
struct Y<'a>{
- x:Option<&'a (X+'a)>,
+ x:Option<&'a (dyn X + 'a)>,
}
fn bar() {
let x: isize = 42;
- let _y = Y { x: Some(&x as &X) };
+ let _y = Y { x: Some(&x as &dyn X) };
}
}
mod c {
pub trait X { fn f(&self); }
impl X for isize { fn f(&self) {} }
- pub struct Z<'a>(Option<&'a (X+'a)>);
- fn main() { let x: isize = 42; let z = Z(Some(&x as &X)); let _ = z; }
+ pub struct Z<'a>(Option<&'a (dyn X + 'a)>);
+ fn main() { let x: isize = 42; let z = Z(Some(&x as &dyn X)); let _ = z; }
}
pub fn main() {}
assert_copy::<Box<&'a mut isize>>(); //~ ERROR : std::marker::Copy` is not satisfied
// borrowed object types are generally ok
- assert_copy::<&'a Dummy>();
- assert_copy::<&'a (Dummy+Send)>();
- assert_copy::<&'static (Dummy+Send)>();
+ assert_copy::<&'a dyn Dummy>();
+ assert_copy::<&'a (dyn Dummy + Send)>();
+ assert_copy::<&'static (dyn Dummy + Send)>();
// owned object types are not ok
- assert_copy::<Box<Dummy>>(); //~ ERROR : std::marker::Copy` is not satisfied
- assert_copy::<Box<Dummy+Send>>(); //~ ERROR : std::marker::Copy` is not satisfied
+ assert_copy::<Box<dyn Dummy>>(); //~ ERROR : std::marker::Copy` is not satisfied
+ assert_copy::<Box<dyn Dummy + Send>>(); //~ ERROR : std::marker::Copy` is not satisfied
// mutable object types are not ok
- assert_copy::<&'a mut (Dummy+Send)>(); //~ ERROR : std::marker::Copy` is not satisfied
+ assert_copy::<&'a mut (dyn Dummy + Send)>(); //~ ERROR : std::marker::Copy` is not satisfied
// unsafe ptrs are ok
assert_copy::<*const isize>();
error[E0277]: the trait bound `std::boxed::Box<dyn Dummy>: std::marker::Copy` is not satisfied
--> $DIR/kindck-copy.rs:42:5
|
-LL | assert_copy::<Box<Dummy>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy>`
+LL | assert_copy::<Box<dyn Dummy>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy>`
|
note: required by `assert_copy`
--> $DIR/kindck-copy.rs:5:1
error[E0277]: the trait bound `std::boxed::Box<dyn Dummy + std::marker::Send>: std::marker::Copy` is not satisfied
--> $DIR/kindck-copy.rs:43:5
|
-LL | assert_copy::<Box<Dummy+Send>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy + std::marker::Send>`
+LL | assert_copy::<Box<dyn Dummy + Send>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<dyn Dummy + std::marker::Send>`
|
note: required by `assert_copy`
--> $DIR/kindck-copy.rs:5:1
error[E0277]: the trait bound `&'a mut (dyn Dummy + std::marker::Send + 'a): std::marker::Copy` is not satisfied
--> $DIR/kindck-copy.rs:46:5
|
-LL | assert_copy::<&'a mut (Dummy+Send)>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)`
+LL | assert_copy::<&'a mut (dyn Dummy + Send)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `&'a mut (dyn Dummy + std::marker::Send + 'a)`
|
note: required by `assert_copy`
--> $DIR/kindck-copy.rs:5:1
error[E0277]: `T` cannot be sent between threads safely
--> $DIR/kindck-impl-type-params.rs:18:13
|
-LL | let a = &t as &Gettable<T>;
+LL | let a = &t as &dyn Gettable<T>;
| ^^ `T` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `T`
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/kindck-impl-type-params.rs:18:13
|
-LL | let a = &t as &Gettable<T>;
+LL | let a = &t as &dyn Gettable<T>;
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
= note: required for the cast to the object type `dyn Gettable<T>`
error[E0277]: `T` cannot be sent between threads safely
- --> $DIR/kindck-impl-type-params.rs:25:27
+ --> $DIR/kindck-impl-type-params.rs:25:31
|
-LL | let a: &Gettable<T> = &t;
- | ^^ `T` cannot be sent between threads safely
+LL | let a: &dyn Gettable<T> = &t;
+ | ^^ `T` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `T`
= help: consider adding a `where T: std::marker::Send` bound
= note: required for the cast to the object type `dyn Gettable<T>`
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
- --> $DIR/kindck-impl-type-params.rs:25:27
+ --> $DIR/kindck-impl-type-params.rs:25:31
|
-LL | let a: &Gettable<T> = &t;
- | ^^ the trait `std::marker::Copy` is not implemented for `T`
+LL | let a: &dyn Gettable<T> = &t;
+ | ^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
--> $DIR/kindck-impl-type-params.rs:38:13
|
-LL | let a = t as Box<Gettable<String>>;
+LL | let a = t as Box<dyn Gettable<String>>;
| ^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
= note: required because of the requirements on the impl of `Gettable<std::string::String>` for `S<std::string::String>`
= note: required for the cast to the object type `dyn Gettable<std::string::String>`
error[E0277]: the trait bound `foo3::Foo: std::marker::Copy` is not satisfied
- --> $DIR/kindck-impl-type-params.rs:46:33
+ --> $DIR/kindck-impl-type-params.rs:46:37
|
-LL | let a: Box<Gettable<Foo>> = t;
- | ^ the trait `std::marker::Copy` is not implemented for `foo3::Foo`
+LL | let a: Box<dyn Gettable<Foo>> = t;
+ | ^ the trait `std::marker::Copy` is not implemented for `foo3::Foo`
|
= note: required because of the requirements on the impl of `Gettable<foo3::Foo>` for `S<foo3::Foo>`
= note: required for the cast to the object type `dyn Gettable<foo3::Foo>`
fn f<T>(val: T) {
let t: S<T> = S(marker::PhantomData);
- let a = &t as &Gettable<T>;
+ let a = &t as &dyn Gettable<T>;
//~^ ERROR `T` cannot be sent between threads safely
//~| ERROR : std::marker::Copy` is not satisfied
}
fn g<T>(val: T) {
let t: S<T> = S(marker::PhantomData);
- let a: &Gettable<T> = &t;
+ let a: &dyn Gettable<T> = &t;
//~^ ERROR `T` cannot be sent between threads safely
//~| ERROR : std::marker::Copy` is not satisfied
}
fn foo<'a>() {
let t: S<&'a isize> = S(marker::PhantomData);
- let a = &t as &Gettable<&'a isize>;
+ let a = &t as &dyn Gettable<&'a isize>;
//~^ ERROR does not fulfill
}
fn foo2<'a>() {
let t: Box<S<String>> = box S(marker::PhantomData);
- let a = t as Box<Gettable<String>>;
+ let a = t as Box<dyn Gettable<String>>;
//~^ ERROR : std::marker::Copy` is not satisfied
}
struct Foo; // does not impl Copy
let t: Box<S<Foo>> = box S(marker::PhantomData);
- let a: Box<Gettable<Foo>> = t;
+ let a: Box<dyn Gettable<Foo>> = t;
//~^ ERROR : std::marker::Copy` is not satisfied
}
error[E0277]: `T` cannot be sent between threads safely
--> $DIR/kindck-impl-type-params.rs:18:13
|
-LL | let a = &t as &Gettable<T>;
+LL | let a = &t as &dyn Gettable<T>;
| ^^ `T` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `T`
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/kindck-impl-type-params.rs:18:13
|
-LL | let a = &t as &Gettable<T>;
+LL | let a = &t as &dyn Gettable<T>;
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
= note: required for the cast to the object type `dyn Gettable<T>`
error[E0277]: `T` cannot be sent between threads safely
- --> $DIR/kindck-impl-type-params.rs:25:27
+ --> $DIR/kindck-impl-type-params.rs:25:31
|
-LL | let a: &Gettable<T> = &t;
- | ^^ `T` cannot be sent between threads safely
+LL | let a: &dyn Gettable<T> = &t;
+ | ^^ `T` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `T`
= help: consider adding a `where T: std::marker::Send` bound
= note: required for the cast to the object type `dyn Gettable<T>`
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
- --> $DIR/kindck-impl-type-params.rs:25:27
+ --> $DIR/kindck-impl-type-params.rs:25:31
|
-LL | let a: &Gettable<T> = &t;
- | ^^ the trait `std::marker::Copy` is not implemented for `T`
+LL | let a: &dyn Gettable<T> = &t;
+ | ^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
error[E0477]: the type `&'a isize` does not fulfill the required lifetime
--> $DIR/kindck-impl-type-params.rs:32:13
|
-LL | let a = &t as &Gettable<&'a isize>;
+LL | let a = &t as &dyn Gettable<&'a isize>;
| ^^
|
= note: type must satisfy the static lifetime
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
--> $DIR/kindck-impl-type-params.rs:38:13
|
-LL | let a = t as Box<Gettable<String>>;
+LL | let a = t as Box<dyn Gettable<String>>;
| ^ the trait `std::marker::Copy` is not implemented for `std::string::String`
|
= note: required because of the requirements on the impl of `Gettable<std::string::String>` for `S<std::string::String>`
= note: required for the cast to the object type `dyn Gettable<std::string::String>`
error[E0277]: the trait bound `foo3::Foo: std::marker::Copy` is not satisfied
- --> $DIR/kindck-impl-type-params.rs:46:33
+ --> $DIR/kindck-impl-type-params.rs:46:37
|
-LL | let a: Box<Gettable<Foo>> = t;
- | ^ the trait `std::marker::Copy` is not implemented for `foo3::Foo`
+LL | let a: Box<dyn Gettable<Foo>> = t;
+ | ^ the trait `std::marker::Copy` is not implemented for `foo3::Foo`
|
= note: required because of the requirements on the impl of `Gettable<foo3::Foo>` for `S<foo3::Foo>`
= note: required for the cast to the object type `dyn Gettable<foo3::Foo>`
fn b() {
let x: Box<_> = box 3;
let y = &x;
- let z = &x as &Foo;
+ let z = &x as &dyn Foo;
//~^ ERROR E0038
//~| ERROR E0038
}
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/kindck-inherited-copy-bound.rs:24:19
|
-LL | let z = &x as &Foo;
- | ^^^^ the trait `Foo` cannot be made into an object
+LL | let z = &x as &dyn Foo;
+ | ^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/kindck-inherited-copy-bound.rs:24:13
|
-LL | let z = &x as &Foo;
+LL | let z = &x as &dyn Foo;
| ^^ the trait `Foo` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
// careful with object types, who knows what they close over...
fn object_ref_with_static_bound_not_ok() {
- assert_send::<&'static (Dummy+'static)>();
+ assert_send::<&'static (dyn Dummy + 'static)>();
//~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn box_object_with_no_bound_not_ok<'a>() {
- assert_send::<Box<Dummy>>();
+ assert_send::<Box<dyn Dummy>>();
//~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
fn object_with_send_bound_ok() {
- assert_send::<&'static (Dummy+Sync)>();
- assert_send::<Box<Dummy+Send>>();
+ assert_send::<&'static (dyn Dummy + Sync)>();
+ assert_send::<Box<dyn Dummy + Send>>();
}
fn main() { }
error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
--> $DIR/kindck-send-object.rs:12:5
|
-LL | assert_send::<&'static (Dummy+'static)>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+LL | assert_send::<&'static (dyn Dummy + 'static)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
error[E0277]: `dyn Dummy` cannot be sent between threads safely
--> $DIR/kindck-send-object.rs:17:5
|
-LL | assert_send::<Box<Dummy>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+LL | assert_send::<Box<dyn Dummy>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
--> $DIR/kindck-send-object1.rs:10:5
|
-LL | assert_send::<&'a Dummy>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+LL | assert_send::<&'a dyn Dummy>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)`
= note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)`
error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
--> $DIR/kindck-send-object1.rs:29:5
|
-LL | assert_send::<Box<Dummy+'a>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
+LL | assert_send::<Box<dyn Dummy + 'a>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>`
// careful with object types, who knows what they close over...
fn test51<'a>() {
- assert_send::<&'a Dummy>();
+ assert_send::<&'a dyn Dummy>();
//~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
}
fn test52<'a>() {
- assert_send::<&'a (Dummy+Sync)>();
+ assert_send::<&'a (dyn Dummy + Sync)>();
//~^ ERROR does not fulfill the required lifetime
}
// ...unless they are properly bounded
fn test60() {
- assert_send::<&'static (Dummy+Sync)>();
+ assert_send::<&'static (dyn Dummy + Sync)>();
}
fn test61() {
- assert_send::<Box<Dummy+Send>>();
+ assert_send::<Box<dyn Dummy + Send>>();
}
// closure and object types can have lifetime bounds which make
// them not ok
fn test_71<'a>() {
- assert_send::<Box<Dummy+'a>>();
+ assert_send::<Box<dyn Dummy + 'a>>();
//~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely
}
error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
--> $DIR/kindck-send-object1.rs:10:5
|
-LL | assert_send::<&'a Dummy>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+LL | assert_send::<&'a dyn Dummy>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'a)`
= note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn Dummy + 'a)`
error[E0477]: the type `&'a (dyn Dummy + std::marker::Sync + 'a)` does not fulfill the required lifetime
--> $DIR/kindck-send-object1.rs:14:5
|
-LL | assert_send::<&'a (Dummy+Sync)>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | assert_send::<&'a (dyn Dummy + Sync)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: type must satisfy the static lifetime
error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
--> $DIR/kindck-send-object1.rs:29:5
|
-LL | assert_send::<Box<Dummy+'a>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
+LL | assert_send::<Box<dyn Dummy + 'a>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn Dummy + 'a)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn Dummy + 'a)>`
trait Dummy { }
fn test50() {
- assert_send::<&'static Dummy>();
+ assert_send::<&'static dyn Dummy>();
//~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn test53() {
- assert_send::<Box<Dummy>>();
+ assert_send::<Box<dyn Dummy>>();
//~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
// ...unless they are properly bounded
fn test60() {
- assert_send::<&'static (Dummy+Sync)>();
+ assert_send::<&'static (dyn Dummy + Sync)>();
}
fn test61() {
- assert_send::<Box<Dummy+Send>>();
+ assert_send::<Box<dyn Dummy + Send>>();
}
fn main() { }
error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
--> $DIR/kindck-send-object2.rs:7:5
|
-LL | assert_send::<&'static Dummy>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+LL | assert_send::<&'static dyn Dummy>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Dummy + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `&'static (dyn Dummy + 'static)`
error[E0277]: `dyn Dummy` cannot be sent between threads safely
--> $DIR/kindck-send-object2.rs:12:5
|
-LL | assert_send::<Box<Dummy>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+LL | assert_send::<Box<dyn Dummy>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn Dummy`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Dummy>`
error[E0521]: borrowed data escapes outside of function
--> $DIR/lifetime-bound-will-change-warning.rs:34:5
|
-LL | fn test2<'a>(x: &'a Box<Fn()+'a>) {
+LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
| - `x` is a reference that is only valid in the function body
LL | // but ref_obj will not, so warn.
LL | ref_obj(x)
error[E0521]: borrowed data escapes outside of function
--> $DIR/lifetime-bound-will-change-warning.rs:39:5
|
-LL | fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
| - `x` is a reference that is only valid in the function body
LL | // same as test2, but cross crate
LL | lib::ref_obj(x)
extern crate lifetime_bound_will_change_warning_lib as lib;
-fn just_ref(x: &Fn()) {
+fn just_ref(x: &dyn Fn()) {
}
-fn ref_obj(x: &Box<Fn()>) {
+fn ref_obj(x: &Box<dyn Fn()>) {
// this will change to &Box<Fn()+'static>...
// Note: no warning is issued here, because the type of `x` will change to 'static
if false { ref_obj(x); }
}
-fn test1<'a>(x: &'a Box<Fn()+'a>) {
+fn test1<'a>(x: &'a Box<dyn Fn() + 'a>) {
// just_ref will stay the same.
just_ref(&**x)
}
-fn test1cc<'a>(x: &'a Box<Fn()+'a>) {
+fn test1cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
// same as test1, but cross-crate
lib::just_ref(&**x)
}
-fn test2<'a>(x: &'a Box<Fn()+'a>) {
+fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
// but ref_obj will not, so warn.
ref_obj(x) //~ ERROR mismatched types
}
-fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
// same as test2, but cross crate
lib::ref_obj(x) //~ ERROR mismatched types
}
-fn test3<'a>(x: &'a Box<Fn()+'static>) {
+fn test3<'a>(x: &'a Box<dyn Fn() + 'static>) {
// here, we have a 'static bound, so even when ref_obj changes, no error results
ref_obj(x)
}
-fn test3cc<'a>(x: &'a Box<Fn()+'static>) {
+fn test3cc<'a>(x: &'a Box<dyn Fn() + 'static>) {
// same as test3, but cross crate
lib::ref_obj(x)
}
note: the lifetime 'a as defined on the function body at 32:10...
--> $DIR/lifetime-bound-will-change-warning.rs:32:10
|
-LL | fn test2<'a>(x: &'a Box<Fn()+'a>) {
+LL | fn test2<'a>(x: &'a Box<dyn Fn() + 'a>) {
| ^^
= note: ...does not necessarily outlive the static lifetime
note: the lifetime 'a as defined on the function body at 37:12...
--> $DIR/lifetime-bound-will-change-warning.rs:37:12
|
-LL | fn test2cc<'a>(x: &'a Box<Fn()+'a>) {
+LL | fn test2cc<'a>(x: &'a Box<dyn Fn() + 'a>) {
| ^^
= note: ...does not necessarily outlive the static lifetime
use std::error::Error;
-fn foo() -> impl Future<Item=(), Error=Box<Error>> {
+fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
//~^ ERROR missing lifetime
Ok(())
}
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-trait.rs:8:44
|
-LL | fn foo() -> impl Future<Item=(), Error=Box<Error>> {
- | ^^^^^ help: consider giving it a 'static lifetime: `Error + 'static`
+LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
+ | ^^^^^^^^^ help: consider giving it a 'static lifetime: `dyn Error + 'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
|
-LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
- | - help: consider changing this to be mutable: `mut y`
+LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+ | - help: consider changing this to be mutable: `mut y`
LL | y.push(z);
| ^ cannot borrow as mutable
error: lifetime may not live long enough
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
|
-LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
- | - - let's call the lifetime of this reference `'1`
- | |
- | let's call the lifetime of this reference `'2`
+LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+ | - - let's call the lifetime of this reference `'1`
+ | |
+ | let's call the lifetime of this reference `'2`
LL | y.push(z);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2`
-fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
y.push(z); //~ ERROR lifetime mismatch
}
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:10
|
-LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
- | --- --- these two types are declared with different lifetimes...
+LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+ | --- --- these two types are declared with different lifetimes...
LL | y.push(z);
| ^ ...but data from `z` flows into `y` here
--- /dev/null
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+extern {
+ #[linkage="external"]
+ pub static collision: *const i32;
+}
--- /dev/null
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+#[linkage="external"]
+pub static EXTERN: u32 = 0;
--- /dev/null
+// rust-lang/rust#61232: We used to ICE when trying to detect a
+// collision on the symbol generated for the external linkage item in
+// an extern crate.
+
+// aux-build:def_colliding_external.rs
+
+extern crate def_colliding_external as dep1;
+
+#[no_mangle]
+pub static _rust_extern_with_linkage_collision: i32 = 0;
+
+mod dep2 {
+ #[no_mangle]
+ pub static collision: usize = 0;
+}
+
+fn main() {
+ unsafe {
+ println!("{:p}", &dep1::collision);
+ }
+}
--- /dev/null
+error: symbol `collision` is already defined
+ --> $DIR/auxiliary/def_colliding_external.rs:6:5
+ |
+LL | pub static collision: *const i32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(linkage)]
+
+mod dep1 {
+ extern {
+ #[linkage="external"]
+ #[no_mangle]
+ pub static collision: *const i32; //~ ERROR symbol `collision` is already defined
+ }
+}
+
+#[no_mangle]
+pub static _rust_extern_with_linkage_collision: i32 = 0;
+
+mod dep2 {
+ #[no_mangle]
+ pub static collision: usize = 0;
+}
+
+fn main() {
+ unsafe {
+ println!("{:p}", &dep1::collision);
+ }
+}
--- /dev/null
+error: symbol `collision` is already defined
+ --> $DIR/linkage-detect-local-generated-name-collision.rs:7:9
+ |
+LL | pub static collision: *const i32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// rust-lang/rust#59548: We used to ICE when trying to use a static
+// with a type that violated its own `#[linkage]`.
+
+// aux-build:def_illtyped_external.rs
+
+extern crate def_illtyped_external as dep;
+
+fn main() {
+ println!("{:p}", &dep::EXTERN);
+}
--- /dev/null
+error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+ --> $DIR/auxiliary/def_illtyped_external.rs:5:1
+ |
+LL | pub static EXTERN: u32 = 0;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// FIXME https://github.com/rust-lang/rust/issues/59774
+// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
+// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// ignore-sgx no weak linkages permitted
+
+#![feature(linkage)]
+
+extern {
+ #[linkage = "extern_weak"] static foo: i32;
+ //~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+}
+
+fn main() {
+ println!("{}", unsafe { foo });
+}
--- /dev/null
+error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+ --> $DIR/linkage2.rs:9:32
+ |
+LL | #[linkage = "extern_weak"] static foo: i32;
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// FIXME https://github.com/rust-lang/rust/issues/59774
+// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
+// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+
+#![feature(linkage)]
+
+extern {
+ #[linkage = "foo"] static foo: *const i32;
+ //~^ ERROR: invalid linkage specified
+}
+
+fn main() {
+ println!("{:?}", unsafe { foo });
+}
--- /dev/null
+error: invalid linkage specified
+ --> $DIR/linkage3.rs:8:24
+ |
+LL | #[linkage = "foo"] static foo: *const i32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+#[linkage = "external"]
+static foo: isize = 0;
+//~^^ ERROR: the `linkage` attribute is experimental and not portable
+
+fn main() {}
--- /dev/null
+error[E0658]: the `linkage` attribute is experimental and not portable across platforms
+ --> $DIR/linkage4.rs:1:1
+ |
+LL | #[linkage = "external"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: for more information, see https://github.com/rust-lang/rust/issues/29603
+ = help: add #![feature(linkage)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// FIXME https://github.com/rust-lang/rust/issues/59774
-// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// ignore-sgx no weak linkages permitted
-
-#![feature(linkage)]
-
-extern {
- #[linkage = "extern_weak"] static foo: i32;
- //~^ ERROR: must have type `*const T` or `*mut T`
-}
-
-fn main() {
- println!("{}", unsafe { foo });
-}
+++ /dev/null
-error: must have type `*const T` or `*mut T`
- --> $DIR/linkage2.rs:9:32
- |
-LL | #[linkage = "extern_weak"] static foo: i32;
- | ^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// FIXME https://github.com/rust-lang/rust/issues/59774
-// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-
-#![feature(linkage)]
-
-extern {
- #[linkage = "foo"] static foo: *const i32;
- //~^ ERROR: invalid linkage specified
-}
-
-fn main() {
- println!("{:?}", unsafe { foo });
-}
+++ /dev/null
-error: invalid linkage specified
- --> $DIR/linkage3.rs:8:24
- |
-LL | #[linkage = "foo"] static foo: *const i32;
- | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-#[linkage = "external"]
-static foo: isize = 0;
-//~^^ ERROR: the `linkage` attribute is experimental and not portable
-
-fn main() {}
+++ /dev/null
-error[E0658]: the `linkage` attribute is experimental and not portable across platforms
- --> $DIR/linkage4.rs:1:1
- |
-LL | #[linkage = "external"]
- | ^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/29603
- = help: add #![feature(linkage)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
pub fn char_type(p: char); //~ ERROR uses type `char`
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
- pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
+ pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
--> $DIR/lint-ctypes.rs:54:26
|
-LL | pub fn trait_type(p: &Clone);
- | ^^^^^^
+LL | pub fn trait_type(p: &dyn Clone);
+ | ^^^^^^^^^^
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--> $DIR/lint-ctypes.rs:55:26
}
pub fn foo() {
- let a: &inner::Trait = &1_isize;
+ let a: &dyn inner::Trait = &1_isize;
a.f();
}
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated();
foo.trait_deprecated_text();
foo.trait_deprecated_unstable();
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated();
foo.trait_deprecated_text();
foo.trait_unstable();
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
//~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
- type A = TraitWithAssociatedTypes<
+ type A = dyn TraitWithAssociatedTypes<
TypeUnstable = u8,
TypeDeprecated = u16,
//~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated'
foo.trait_deprecated_text(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
foo.trait_deprecated_unstable(); //~ WARN use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable'
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated'
foo.trait_deprecated_text(); //~ WARN use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
foo.trait_unstable();
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
//~^ ERROR use of unstable library feature
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
- type A = TraitWithAssociatedTypes<
+ type A = dyn TraitWithAssociatedTypes<
TypeUnstable = u8, //~ ERROR use of unstable library feature
TypeDeprecated = u16,
>;
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated();
foo.trait_deprecated_text();
foo.trait_stable();
<Foo as Trait>::trait_stable(&foo);
}
- fn test_method_object(foo: &Trait) {
+ fn test_method_object(foo: &dyn Trait) {
foo.trait_deprecated();
foo.trait_deprecated_text();
foo.trait_unstable();
}
}
-impl Foo for Box<Foo+'static> {
+impl Foo for Box<dyn Foo + 'static> {
fn bar(&self) { //~ ERROR function cannot return without recursing
loop {
self.bar()
}
}
-impl Foo2 for Box<Foo2+'static> {
+impl Foo2 for Box<dyn Foo2 + 'static> {
fn bar(&self) { //~ ERROR function cannot return without recursing
loop {
Foo2::bar(self)
let z = 3_i8;
'a: loop {
- let b = Box::new(|x: &i8| *x) as Box<for <'a> Fn(&'a i8) -> i8>;
+ let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
//~^ WARN lifetime name `'a` shadows a label name that is already in scope
assert_eq!((*b)(&z), z);
break 'a;
warning: lifetime name `'a` shadows a label name that is already in scope
- --> $DIR/loops-reject-lifetime-shadowing-label.rs:21:51
+ --> $DIR/loops-reject-lifetime-shadowing-label.rs:21:55
|
LL | 'a: loop {
| -- first declared here
-LL | let b = Box::new(|x: &i8| *x) as Box<for <'a> Fn(&'a i8) -> i8>;
- | ^^ lifetime 'a already in scope
+LL | let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
+ | ^^ lifetime 'a already in scope
trait Foo<T, U> { }
fn foo(
- x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
- y: &for<'a> Foo<&'a u8, &'a u8>,
+ x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>,
+ y: &dyn for<'a> Foo<&'a u8, &'a u8>,
) {
let z = match 22 {
0 => x,
}
fn bar(
- x: &for<'a, 'b> Foo<&'a u8, &'b u8>,
- y: &for<'a> Foo<&'a u8, &'a u8>,
+ x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>,
+ y: &dyn for<'a> Foo<&'a u8, &'a u8>,
) {
// Accepted with explicit case:
let z = match 22 {
- 0 => x as &for<'a> Foo<&'a u8, &'a u8>,
+ 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>,
_ => y,
};
}
fn main() {
let x: Box<HashMap<isize, isize>> = box HashMap::new();
- let x: Box<Map<isize, isize>> = x;
- let y: Box<Map<usize, isize>> = Box::new(x);
+ let x: Box<dyn Map<isize, isize>> = x;
+ let y: Box<dyn Map<usize, isize>> = Box::new(x);
//~^ ERROR `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
}
error[E0277]: the trait bound `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
- --> $DIR/map-types.rs:17:37
+ --> $DIR/map-types.rs:17:41
|
-LL | let y: Box<Map<usize, isize>> = Box::new(x);
- | ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `std::boxed::Box<dyn Map<isize, isize>>`
+LL | let y: Box<dyn Map<usize, isize>> = Box::new(x);
+ | ^^^^^^^^^^^ the trait `Map<usize, isize>` is not implemented for `std::boxed::Box<dyn Map<isize, isize>>`
|
= note: required for the cast to the object type `dyn Map<usize, isize>`
// 'late lifetimes here belong to nested types not to the tested functions.
fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8),
- _: Box<for<'late> Fn(&'late u8)>)
+ _: Box<dyn for<'late> Fn(&'late u8)>)
-> &'a u8 { loop {} }
fn early_tricky_implicit<'a>(_: fn(&u8),
- _: Box<Fn(&u8)>)
+ _: Box<dyn Fn(&u8)>)
-> &'a u8 { loop {} }
}
let v = 0 as *const u8;
let fat_v : *const [u8] = unsafe { &*(0 as *const [u8; 1])};
let fat_sv : *const [i8] = unsafe { &*(0 as *const [i8; 1])};
- let foo: &Foo = &f;
+ let foo: &dyn Foo = &f;
let _ = v as &u8; //~ ERROR non-primitive cast
let _ = v as E; //~ ERROR non-primitive cast
let _ = 42usize as *const [u8]; //~ ERROR is invalid
let _ = v as *const [u8]; //~ ERROR cannot cast
- let _ = fat_v as *const Foo; //~ ERROR the size for values of type
+ let _ = fat_v as *const dyn Foo; //~ ERROR the size for values of type
let _ = foo as *const str; //~ ERROR is invalid
let _ = foo as *mut str; //~ ERROR is invalid
let _ = main as *mut str; //~ ERROR is invalid
let _ = fat_sv as usize; //~ ERROR is invalid
let a : *const str = "hello";
- let _ = a as *const Foo; //~ ERROR the size for values of type
+ let _ = a as *const dyn Foo; //~ ERROR the size for values of type
// check no error cascade
let _ = main.f as *const u32; //~ ERROR no field
- let cf: *const Foo = &0;
+ let cf: *const dyn Foo = &0;
let _ = cf as *const [u16]; //~ ERROR is invalid
- let _ = cf as *const Bar; //~ ERROR is invalid
+ let _ = cf as *const dyn Bar; //~ ERROR is invalid
vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
}
error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid
--> $DIR/cast-rfc0401.rs:69:13
|
-LL | let _ = cf as *const Bar;
- | ^^^^^^^^^^^^^^^^
+LL | let _ = cf as *const dyn Bar;
+ | ^^^^^^^^^^^^^^^^^^^^
|
= note: vtable kinds may not match
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/cast-rfc0401.rs:53:13
|
-LL | let _ = fat_v as *const Foo;
+LL | let _ = fat_v as *const dyn Foo;
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/cast-rfc0401.rs:62:13
|
-LL | let _ = a as *const Foo;
+LL | let _ = a as *const dyn Foo;
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
trait Trait { }
-fn function(t: &mut Trait) {
- t as *mut Trait
+fn function(t: &mut dyn Trait) {
+ t as *mut dyn Trait
//~^ ERROR: mismatched types
}
error[E0308]: mismatched types
--> $DIR/issue-19109.rs:4:5
|
-LL | fn function(t: &mut Trait) {
- | - help: try adding a return type: `-> *mut dyn Trait`
-LL | t as *mut Trait
- | ^^^^^^^^^^^^^^^ expected (), found *-ptr
+LL | fn function(t: &mut dyn Trait) {
+ | - help: try adding a return type: `-> *mut dyn Trait`
+LL | t as *mut dyn Trait
+ | ^^^^^^^^^^^^^^^^^^^ expected (), found *-ptr
|
= note: expected type `()`
found type `*mut dyn Trait`
fn dummy(&self) { }
}
-fn a(_x: Box<Foo+Send>) {
+fn a(_x: Box<dyn Foo + Send>) {
}
-fn c(x: Box<Foo+Sync+Send>) {
+fn c(x: Box<dyn Foo + Sync + Send>) {
a(x);
}
-fn d(x: Box<Foo>) {
+fn d(x: Box<dyn Foo>) {
a(x); //~ ERROR mismatched types [E0308]
}
// This struct is needed to create the
// otherwise infinite type of a fn that
// accepts itself as argument:
- c: Box<FnMut(&mut R, bool) + 'a>
+ c: Box<dyn FnMut(&mut R, bool) + 'a>
}
fn innocent_looking_victim() {
let _ = {
let tmp0 = 3;
let tmp1 = &tmp0;
- box tmp1 as Box<Foo + '_>
+ box tmp1 as Box<dyn Foo + '_>
};
//~^^^ ERROR `tmp0` does not live long enough
}
|
LL | let tmp1 = &tmp0;
| ^^^^^ borrowed value does not live long enough
-LL | box tmp1 as Box<Foo + '_>
- | ------------------------- borrow later captured here by trait object
+LL | box tmp1 as Box<dyn Foo + '_>
+ | ----------------------------- borrow later captured here by trait object
LL | };
| - `tmp0` dropped here while still borrowed
}
trait GenericVec<T> {
- fn unwrap<'a, 'b>(vec: &'b AnyVec<'a>) -> &'b [T] where T: 'a;
+ fn unwrap<'a, 'b>(vec: &'b dyn AnyVec<'a>) -> &'b [T] where T: 'a;
}
struct Scratchpad<'a> {
- buffers: RefCell<Box<AnyVec<'a>>>,
+ buffers: RefCell<Box<dyn AnyVec<'a>>>,
}
impl<'a> Scratchpad<'a> {
trait Foo {}
fn take_foo<F:Foo>(f: F) {}
-fn take_object(f: Box<Foo>) { take_foo(f); }
+fn take_object(f: Box<dyn Foo>) { take_foo(f); }
//~^ ERROR `std::boxed::Box<dyn Foo>: Foo` is not satisfied
fn main() {}
error[E0277]: the trait bound `std::boxed::Box<dyn Foo>: Foo` is not satisfied
- --> $DIR/object-does-not-impl-trait.rs:6:31
+ --> $DIR/object-does-not-impl-trait.rs:6:35
|
-LL | fn take_object(f: Box<Foo>) { take_foo(f); }
- | ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box<dyn Foo>`
+LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+ | ^^^^^^^^ the trait `Foo` is not implemented for `std::boxed::Box<dyn Foo>`
|
note: required by `take_foo`
--> $DIR/object-does-not-impl-trait.rs:5:1
r: &'a &'b T
}
-fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
+fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
-fn b(t: Ref2<Test>) {
+fn b(t: Ref2<dyn Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
-fn c(t: Ref2<&Test>) {
+fn c(t: Ref2<&dyn Test>) {
// In this case, the &'a overrides.
}
-fn d(t: Ref2<Ref1<Test>>) {
+fn d(t: Ref2<Ref1<dyn Test>>) {
// In this case, the lifetime parameter from the Ref1 overrides.
}
-fn e(t: Ref2<Ref0<Test>>) {
+fn e(t: Ref2<Ref0<dyn Test>>) {
// In this case, Ref2 is ambiguous, but Ref0 overrides with 'static.
}
-fn f(t: &Ref2<Test>) {
+fn f(t: &Ref2<dyn Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/object-lifetime-default-ambiguous.rs:23:27
+ --> $DIR/object-lifetime-default-ambiguous.rs:23:28
|
-LL | fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
- | ^^^^
+LL | fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) {
+ | ^^^^^^^^
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
--> $DIR/object-lifetime-default-ambiguous.rs:27:14
|
-LL | fn b(t: Ref2<Test>) {
- | ^^^^
+LL | fn b(t: Ref2<dyn Test>) {
+ | ^^^^^^^^
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
--> $DIR/object-lifetime-default-ambiguous.rs:43:15
|
-LL | fn f(t: &Ref2<Test>) {
- | ^^^^
+LL | fn f(t: &Ref2<dyn Test>) {
+ | ^^^^^^^^
error: aborting due to 3 previous errors
error: lifetime may not live long enough
--> $DIR/object-lifetime-default-elision.rs:71:5
|
-LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
}
struct SomeStruct<'a> {
- r: Box<SomeTrait+'a>
+ r: Box<dyn SomeTrait+'a>
}
fn deref<T>(ss: &T) -> T {
loop { }
}
-fn load0<'a>(ss: &'a Box<SomeTrait>) -> Box<SomeTrait> {
+fn load0<'a>(ss: &'a Box<dyn SomeTrait>) -> Box<dyn SomeTrait> {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a Box<SomeTrait+'b>) -> Box<SomeTrait+'a>
deref(ss)
}
-fn load1(ss: &SomeTrait) -> &SomeTrait {
+fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a)
ss
}
-fn load2<'a>(ss: &'a SomeTrait) -> &SomeTrait {
+fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait {
// Same as `load1` but with an explicit name thrown in for fun.
ss
}
-fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a)
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
--> $DIR/object-lifetime-default-elision.rs:54:10
|
-LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/object-lifetime-default-elision.rs:71:5
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
--> $DIR/object-lifetime-default-elision.rs:54:13
|
-LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
= note: ...so that the expression is assignable:
expected &'b (dyn SomeTrait + 'b)
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10...
--> $DIR/object-lifetime-default-elision.rs:54:10
|
-LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/object-lifetime-default-elision.rs:71:5
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13...
--> $DIR/object-lifetime-default-elision.rs:54:13
|
-LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
+LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
| ^^
= note: ...so that the expression is assignable:
expected &'b (dyn SomeTrait + 'b)
error[E0621]: explicit lifetime required in the type of `ss`
--> $DIR/object-lifetime-default-from-box-error.rs:18:5
|
-LL | fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
| --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
...
LL | ss.r
error[E0621]: explicit lifetime required in the type of `ss`
--> $DIR/object-lifetime-default-from-box-error.rs:31:5
|
-LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
+LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<dyn SomeTrait+'b>) {
| --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>`
...
LL | ss.r = b;
}
struct SomeStruct<'a> {
- r: Box<SomeTrait+'a>
+ r: Box<dyn SomeTrait+'a>
}
-fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
}
-fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
+fn store(ss: &mut SomeStruct, b: Box<dyn SomeTrait>) {
// No error: b is bounded by 'static which outlives the
// (anonymous) lifetime on the struct.
ss.r = b;
}
-fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
+fn store1<'b>(ss: &mut SomeStruct, b: Box<dyn SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.
ss.r = b; //~ ERROR explicit lifetime required in the type of `ss` [E0621]
error[E0621]: explicit lifetime required in the type of `ss`
--> $DIR/object-lifetime-default-from-box-error.rs:18:5
|
-LL | fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
+LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
| --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
...
LL | ss.r
error[E0621]: explicit lifetime required in the type of `ss`
--> $DIR/object-lifetime-default-from-box-error.rs:31:12
|
-LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
+LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<dyn SomeTrait+'b>) {
| --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>`
...
LL | ss.r = b;
error: lifetime may not live long enough
--> $DIR/object-lifetime-default-from-rptr-box-error.rs:15:5
|
-LL | fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+LL | fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
| -- lifetime `'a` defined here
LL | ss.t = t;
| ^^^^^^^^ assignment requires that `'a` must outlive `'static`
}
struct SomeStruct<'a> {
- t: &'a Box<Test>,
+ t: &'a Box<dyn Test>,
}
-fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t; //~ ERROR mismatched types
}
note: the lifetime 'a as defined on the function body at 14:6...
--> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6
|
-LL | fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+LL | fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) {
| ^^
= note: ...does not necessarily outlive the static lifetime
error: lifetime may not live long enough
--> $DIR/object-lifetime-default-from-rptr-struct-error.rs:21:5
|
-LL | fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
| -- lifetime `'a` defined here
LL | ss.t = t;
| ^^^^^^^^ assignment requires that `'a` must outlive `'static`
}
struct SomeStruct<'a> {
- t: &'a MyBox<Test>,
- u: &'a MyBox<Test+'a>,
+ t: &'a MyBox<dyn Test>,
+ u: &'a MyBox<dyn Test + 'a>,
}
struct MyBox<T:?Sized> {
b: Box<T>
}
-fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t; //~ ERROR mismatched types
}
note: the lifetime 'a as defined on the function body at 20:6...
--> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6
|
-LL | fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) {
| ^^
= note: ...does not necessarily outlive the static lifetime
error: lifetime may not live long enough
--> $DIR/object-lifetime-default-mybox.rs:27:5
|
-LL | fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
+LL | fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>,
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
error[E0521]: borrowed data escapes outside of function
--> $DIR/object-lifetime-default-mybox.rs:31:5
|
-LL | fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
| -- `ss` is a reference that is only valid in the function body
LL | load0(ss)
| ^^^^^^^^^ `ss` escapes the function body here
loop { }
}
-fn load0(ss: &MyBox<SomeTrait>) -> MyBox<SomeTrait> {
+fn load0(ss: &MyBox<dyn SomeTrait>) -> MyBox<dyn SomeTrait> {
deref(ss)
}
-fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
- b: &'b MyBox<SomeTrait>)
- -> &'b MyBox<SomeTrait>
+fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>,
+ b: &'b MyBox<dyn SomeTrait>)
+ -> &'b MyBox<dyn SomeTrait>
{
a //~ ERROR lifetime mismatch
}
-fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
load0(ss) //~ ERROR mismatched types
}
error[E0623]: lifetime mismatch
--> $DIR/object-lifetime-default-mybox.rs:27:5
|
-LL | fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
- | -------------------- this parameter and the return type are declared with different lifetimes...
-LL | b: &'b MyBox<SomeTrait>)
-LL | -> &'b MyBox<SomeTrait>
- | --------------------
+LL | fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>,
+ | ------------------------ this parameter and the return type are declared with different lifetimes...
+LL | b: &'b MyBox<dyn SomeTrait>)
+LL | -> &'b MyBox<dyn SomeTrait>
+ | ------------------------
LL | {
LL | a
| ^ ...but data from `a` is returned here
note: the lifetime 'a as defined on the function body at 30:10...
--> $DIR/object-lifetime-default-mybox.rs:30:10
|
-LL | fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
+LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> {
| ^^
= note: ...does not necessarily outlive the static lifetime
fn owned(self: Box<Self>);
}
-fn borrowed_receiver(x: &Foo) {
+fn borrowed_receiver(x: &dyn Foo) {
x.borrowed();
x.borrowed_mut(); // See [1]
x.owned(); //~ ERROR no method named `owned` found
}
-fn borrowed_mut_receiver(x: &mut Foo) {
+fn borrowed_mut_receiver(x: &mut dyn Foo) {
x.borrowed();
x.borrowed_mut();
x.owned(); //~ ERROR no method named `owned` found
}
-fn owned_receiver(x: Box<Foo>) {
+fn owned_receiver(x: Box<dyn Foo>) {
x.borrowed();
x.borrowed_mut(); // See [1]
x.managed(); //~ ERROR no method named `managed` found
const X: usize;
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-associated-consts.rs:9:1
|
-LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: the trait cannot contain associated consts like `X`
fn baz(self: Self);
}
-fn use_bar(t: Box<Bar>) {
+fn use_bar(t: Box<dyn Bar>) {
t.bar() //~ ERROR cannot move a value of type dyn Bar
}
fn baz(self: Self) where Self : Sized;
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
t // legal
}
-fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
- t as &Bar // legal
+fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
+ t as &dyn Bar // legal
}
-fn make_baz<T:Baz>(t: &T) -> &Baz {
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
t // legal
}
-fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
- t as &Baz // legal
+fn make_baz_explicit<T:Baz>(t: &T) -> &dyn Baz {
+ t as &dyn Baz // legal
}
-fn make_quux<T:Quux>(t: &T) -> &Quux {
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
t
}
-fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
- t as &Quux
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+ t as &dyn Quux
}
where Self : Sized;
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
}
-fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
+fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
- t as &Bar
+ t as &dyn Bar
}
-fn make_quux<T:Quux>(t: &T) -> &Quux {
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
t
}
-fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
- t as &Quux
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+ t as &dyn Quux
}
fn main() {
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-generics.rs:14:1
|
-LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` has generic type parameters
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-generics.rs:19:1
|
-LL | fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` has generic type parameters
//#[derive(PartialEq)]
#[derive(Debug)]
struct SExpr<'x> {
- elements: Vec<Box<Expr+ 'x>>,
+ elements: Vec<Box<dyn Expr + 'x>>,
//~^ ERROR E0038
}
}
fn main() {
- let a: Box<Expr> = Box::new(SExpr::new());
- let b: Box<Expr> = Box::new(SExpr::new());
+ let a: Box<dyn Expr> = Box::new(SExpr::new());
+ let b: Box<dyn Expr> = Box::new(SExpr::new());
// assert_eq!(a , b);
}
error[E0038]: the trait `Expr` cannot be made into an object
--> $DIR/object-safety-issue-22040.rs:12:23
|
-LL | elements: Vec<Box<Expr+ 'x>>,
- | ^^^^^^^^ the trait `Expr` cannot be made into an object
+LL | elements: Vec<Box<dyn Expr + 'x>>,
+ | ^^^^^^^^^^^^^ the trait `Expr` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
fn get(&self, s: &Self) -> Self where Self : Sized;
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
loop { }
}
-fn make_baz<T:Baz>(t: &T) -> &Baz {
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
//~^ ERROR E0038
t
}
-fn make_quux<T:Quux>(t: &T) -> &Quux {
+fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
t
}
-fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
- t as &Quux
+fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
+ t as &dyn Quux
}
fn main() {
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-mentions-Self.rs:17:1
|
-LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` references the `Self` type in its arguments or return type
error[E0038]: the trait `Baz` cannot be made into an object
--> $DIR/object-safety-mentions-Self.rs:22:1
|
-LL | fn make_baz<T:Baz>(t: &T) -> &Baz {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
+LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
|
= note: method `bar` references the `Self` type in its arguments or return type
fn foo();
}
-fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
+fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
//~^ ERROR E0038
loop { }
}
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety-no-static.rs:8:1
|
-LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<Foo+'static> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo` has no receiver
trait Bar<T> {
}
-fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> {
t
}
-fn make_baz<T:Baz>(t: &T) -> &Baz {
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
t
}
fn bar<T>(&self, t: T);
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
loop { }
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-sized-2.rs:10:1
|
-LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
fn bar<T>(&self, t: T);
}
-fn make_bar<T:Bar>(t: &T) -> &Bar {
+fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
}
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-sized.rs:8:1
|
-LL | fn make_bar<T:Bar>(t: &T) -> &Bar {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
trait Baz : Bar<Self> {
}
-fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+fn make_bar<T:Bar<u32>>(t: &T) -> &dyn Bar<u32> {
t
}
-fn make_baz<T:Baz>(t: &T) -> &Baz {
+fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
//~^ ERROR E0038
t
}
error[E0038]: the trait `Baz` cannot be made into an object
--> $DIR/object-safety-supertrait-mentions-Self.rs:15:31
|
-LL | fn make_baz<T:Baz>(t: &T) -> &Baz {
- | ^^^ the trait `Baz` cannot be made into an object
+LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+ | ^^^^^^^ the trait `Baz` cannot be made into an object
|
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
// compile-pass
+#![allow(bare_trait_objects)]
+
type A = Box<(Fn(u8) -> u8) + 'static + Send + Sync>; // OK (but see #39318)
fn main() {}
// compile-flags: -Z continue-parse-after-error
#![feature(box_syntax)]
+#![allow(bare_trait_objects)]
use std::fmt::Debug;
// compile-flags: -Z continue-parse-after-error
#![feature(optin_builtin_traits)]
+#![allow(bare_trait_objects)]
auto trait Auto {}
error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
- --> $DIR/trait-object-bad-parens.rs:8:16
+ --> $DIR/trait-object-bad-parens.rs:9:16
|
LL | let _: Box<((Auto)) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
- --> $DIR/trait-object-bad-parens.rs:10:16
+ --> $DIR/trait-object-bad-parens.rs:11:16
|
LL | let _: Box<(Auto + Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
- --> $DIR/trait-object-bad-parens.rs:12:16
+ --> $DIR/trait-object-bad-parens.rs:13:16
|
LL | let _: Box<(Auto +) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
- --> $DIR/trait-object-bad-parens.rs:14:16
+ --> $DIR/trait-object-bad-parens.rs:15:16
|
LL | let _: Box<(dyn Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^ expected a path
// compile-flags: -Z continue-parse-after-error
+#![allow(bare_trait_objects)]
+
trait Trait {}
fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not supported
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:5:21
+ --> $DIR/trait-object-lifetime-parens.rs:7:21
|
LL | fn f<'a, T: Trait + ('a)>() {}
| ^^^^ help: remove the parentheses
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:8:24
+ --> $DIR/trait-object-lifetime-parens.rs:10:24
|
LL | let _: Box<Trait + ('a)>;
| ^^^^ help: remove the parentheses
error: expected `:`, found `)`
- --> $DIR/trait-object-lifetime-parens.rs:9:19
+ --> $DIR/trait-object-lifetime-parens.rs:11:19
|
LL | let _: Box<('a) + Trait>;
| ^ expected `:`
error: chained comparison operators require parentheses
- --> $DIR/trait-object-lifetime-parens.rs:9:15
+ --> $DIR/trait-object-lifetime-parens.rs:11:15
|
LL | let _: Box<('a) + Trait>;
| ^^^^^^^^^^^^^^^
= help: or use `(...)` if you meant to specify fn arguments
error: expected type, found `'a`
- --> $DIR/trait-object-lifetime-parens.rs:9:17
+ --> $DIR/trait-object-lifetime-parens.rs:11:17
|
LL | let _: Box<('a) + Trait>;
| - ^^
+#![allow(bare_trait_objects)]
+
trait Trait<'a> {}
fn main() {
error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>`
- --> $DIR/trait-object-polytrait-priority.rs:4:12
+ --> $DIR/trait-object-polytrait-priority.rs:6:12
|
LL | let _: &for<'a> Trait<'a> + 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&(for<'a> Trait<'a> + 'static)`
fn main() {
let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
//~^ ERROR `?Trait` is not permitted in trait object types
+ //~| WARN trait objects without an explicit `dyn` are deprecated
let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
+ //~^ WARN trait objects without an explicit `dyn` are deprecated
let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
//~^ ERROR use of undeclared lifetime name `'a`
//~| ERROR `?Trait` is not permitted in trait object types
+ //~| WARN trait objects without an explicit `dyn` are deprecated
}
| ^^^^^^^^
error: `?Trait` is not permitted in trait object types
- --> $DIR/trait-object-trait-parens.rs:9:47
+ --> $DIR/trait-object-trait-parens.rs:11:47
|
LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
| ^^^^^^^^
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/trait-object-trait-parens.rs:6:16
+ |
+LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (Copy) + (?Sized) + (for<'a> Trait<'a>)`
+ |
+ = note: #[warn(bare_trait_objects)] on by default
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/trait-object-trait-parens.rs:9:16
+ |
+LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (?Sized) + (for<'a> Trait<'a>) + (Copy)`
+
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/trait-object-trait-parens.rs:11:16
+ |
+LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn (for<'a> Trait<'a>) + (Copy) + (?Sized)`
+
error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/trait-object-trait-parens.rs:9:31
+ --> $DIR/trait-object-trait-parens.rs:11:31
|
LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>;
| ^^ undeclared lifetime
mod m {
pub trait PubPrincipal {}
auto trait PrivNonPrincipal {}
- pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
+ pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
}
fn main() {
pub trait PubPrincipal {}
auto trait PrivNonPrincipal {}
-pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
+pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
//~^ WARN private trait `PrivNonPrincipal` in public interface
//~| WARN this was previously accepted
warning: private trait `PrivNonPrincipal` in public interface (error E0445)
--> $DIR/private-in-public-non-principal.rs:6:1
|
-LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(private_in_public)] on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
pub fn leak_anon3() -> impl TraitWithAssocTy<AssocTy = Alias> { 0 }
- pub fn leak_dyn1() -> Box<Trait + 'static> { Box::new(0) }
- pub fn leak_dyn2() -> Box<TraitWithTyParam<Alias>> { Box::new(0) }
- pub fn leak_dyn3() -> Box<TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
+ pub fn leak_dyn1() -> Box<dyn Trait + 'static> { Box::new(0) }
+ pub fn leak_dyn2() -> Box<dyn TraitWithTyParam<Alias>> { Box::new(0) }
+ pub fn leak_dyn3() -> Box<dyn TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
}
mod adjust {
-// aux-build:attr_proc_macro.rs
+// aux-build:test-macros.rs
-extern crate attr_proc_macro;
-use attr_proc_macro::*;
+#[macro_use]
+extern crate test_macros;
-#[attr_proc_macro] // OK
+#[identity_attr] // OK
#[derive(Clone)]
struct Before;
#[derive(Clone)]
-#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
+#[identity_attr] //~ ERROR macro attributes must be placed before `#[derive]`
struct After;
fn main() {}
error: macro attributes must be placed before `#[derive]`
--> $DIR/attribute-order-restricted.rs:11:1
|
-LL | #[attr_proc_macro]
- | ^^^^^^^^^^^^^^^^^^
+LL | #[identity_attr]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
-// aux-build:attribute-with-error.rs
+// aux-build:test-macros.rs
#![feature(custom_inner_attributes)]
-extern crate attribute_with_error;
+#[macro_use]
+extern crate test_macros;
-use attribute_with_error::foo;
-
-#[foo]
+#[recollect_attr]
fn test1() {
let a: i32 = "foo";
//~^ ERROR: mismatched types
}
fn test2() {
- #![foo]
+ #![recollect_attr]
// FIXME: should have a type error here and assert it works but it doesn't
}
trait A {
- // FIXME: should have a #[foo] attribute here and assert that it works
+ // FIXME: should have a #[recollect_attr] attribute here and assert that it works
fn foo(&self) {
let a: i32 = "foo";
//~^ ERROR: mismatched types
struct B;
impl A for B {
- #[foo]
+ #[recollect_attr]
fn foo(&self) {
let a: i32 = "foo";
//~^ ERROR: mismatched types
}
}
-#[foo]
+#[recollect_attr]
fn main() {
}
error[E0308]: mismatched types
- --> $DIR/attribute-with-error.rs:11:18
+ --> $DIR/attribute-with-error.rs:10:18
|
LL | let a: i32 = "foo";
| ^^^^^ expected i32, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/attribute-with-error.rs:13:18
+ --> $DIR/attribute-with-error.rs:12:18
|
LL | let b: i32 = "f'oo";
| ^^^^^^ expected i32, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/attribute-with-error.rs:26:22
+ --> $DIR/attribute-with-error.rs:25:22
|
LL | let a: i32 = "foo";
| ^^^^^ expected i32, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/attribute-with-error.rs:36:22
+ --> $DIR/attribute-with-error.rs:35:22
|
LL | let a: i32 = "foo";
| ^^^^^ expected i32, found reference
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream {
- input
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn foo(_attr: TokenStream, input: TokenStream) -> TokenStream {
- input.into_iter().collect()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro]
-pub fn bang_proc_macro(input: TokenStream) -> TokenStream {
- input
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(A)]
-pub fn derive_a(_: TokenStream) -> TokenStream {
- "".parse().unwrap()
-}
-
-#[proc_macro_derive(B)]
-pub fn derive_b(_: TokenStream) -> TokenStream {
- "".parse().unwrap()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(A)]
-pub fn derive_a(input: TokenStream) -> TokenStream {
- "".parse().unwrap()
-}
#[macro_export]
-macro_rules! my_attr { () => () }
+macro_rules! empty_helper { () => () }
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::*;
-
-#[proc_macro_derive(MyTrait, attributes(my_attr))]
-pub fn foo(_: TokenStream) -> TokenStream {
- TokenStream::new()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::*;
-
-#[proc_macro_attribute]
-pub fn my_attr(_: TokenStream, input: TokenStream) -> TokenStream {
- input
-}
-
-#[proc_macro_derive(MyTrait, attributes(my_attr))]
-pub fn derive(input: TokenStream) -> TokenStream {
- TokenStream::new()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_derive(A)]
-pub fn derive_a(_input: TokenStream) -> TokenStream {
- panic!("nope!");
-}
#[macro_export]
macro_rules! external {
() => {
- dollar_crate::m! {
+ print_bang! {
struct M($crate::S);
}
- #[dollar_crate::a]
+ #[print_attr]
struct A($crate::S);
- #[derive(dollar_crate::d)]
+ #[derive(Print)]
struct D($crate::S);
};
}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::TokenStream;
-
-#[proc_macro]
-pub fn m_empty(input: TokenStream) -> TokenStream {
- println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input);
- println!("PROC MACRO INPUT: {:#?}", input);
- TokenStream::new()
-}
-
-#[proc_macro]
-pub fn m(input: TokenStream) -> TokenStream {
- println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input);
- println!("PROC MACRO INPUT: {:#?}", input);
- input.into_iter().collect()
-}
-
-#[proc_macro_attribute]
-pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream {
- println!("ATTRIBUTE INPUT (PRETTY-PRINTED): {}", input);
- println!("ATTRIBUTE INPUT: {:#?}", input);
- input.into_iter().collect()
-}
-
-#[proc_macro_derive(d)]
-pub fn d(input: TokenStream) -> TokenStream {
- println!("DERIVE INPUT (PRETTY-PRINTED): {}", input);
- println!("DERIVE INPUT: {:#?}", input);
- input.into_iter().collect()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn emit_unchanged(_args: TokenStream, input: TokenStream) -> TokenStream {
- input
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::*;
-
-#[proc_macro_derive(MyTrait, attributes(my_attr))]
-pub fn foo(_: TokenStream) -> TokenStream {
- TokenStream::new()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-use proc_macro::*;
-
-#[proc_macro_attribute]
-pub fn doit(_: TokenStream, input: TokenStream) -> TokenStream {
- input.into_iter().collect()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::*;
-
-#[proc_macro_attribute]
-pub fn foo(_: TokenStream, item: TokenStream) -> TokenStream {
- item.into_iter().collect()
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::*;
-
-#[proc_macro]
-pub fn m(a: TokenStream) -> TokenStream {
- a
-}
-
-#[proc_macro_attribute]
-pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream {
- b
-}
+++ /dev/null
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn foo(_: TokenStream, input: TokenStream) -> TokenStream {
- input.into_iter().collect()
-}
// force-host
// no-prefer-dynamic
+// Proc macros commonly used by tests.
+// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
+
#![crate_type = "proc-macro"]
extern crate proc_macro;
-
use proc_macro::TokenStream;
+// Macro that return empty token stream.
+
+#[proc_macro]
+pub fn empty(_: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
#[proc_macro_attribute]
-pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
- assert!(_attr.to_string().is_empty());
- input
+pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+#[proc_macro_derive(Empty, attributes(empty_helper))]
+pub fn empty_derive(_: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
+
+// Macro that panics.
+
+#[proc_macro]
+pub fn panic_bang(_: TokenStream) -> TokenStream {
+ panic!("panic-bang");
}
#[proc_macro_attribute]
-pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream {
- assert!(_attr.to_string().is_empty());
- assert!(!_input.to_string().is_empty());
- "".parse().unwrap()
+pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+ panic!("panic-attr");
+}
+
+#[proc_macro_derive(Panic, attributes(panic_helper))]
+pub fn panic_derive(_: TokenStream) -> TokenStream {
+ panic!("panic-derive");
}
+// Macros that return the input stream.
+
#[proc_macro]
-pub fn emit_input(input: TokenStream) -> TokenStream {
+pub fn identity(input: TokenStream) -> TokenStream {
input
}
+
+#[proc_macro_attribute]
+pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(Identity, attributes(identity_helper))]
+pub fn identity_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+// Macros that iterate and re-collect the input stream.
+
+#[proc_macro]
+pub fn recollect(input: TokenStream) -> TokenStream {
+ input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ input.into_iter().collect()
+}
+
+#[proc_macro_derive(Recollect, attributes(recollect_helper))]
+pub fn recollect_derive(input: TokenStream) -> TokenStream {
+ input.into_iter().collect()
+}
+
+// Macros that print their input in the original and re-collected forms (if they differ).
+
+fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
+ let input_display = format!("{}", input);
+ let input_debug = format!("{:#?}", input);
+ let recollected = input.into_iter().collect();
+ let recollected_display = format!("{}", recollected);
+ let recollected_debug = format!("{:#?}", recollected);
+ println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
+ if recollected_display != input_display {
+ println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
+ }
+ println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
+ if recollected_debug != input_debug {
+ println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
+ }
+ recollected
+}
+
+#[proc_macro]
+pub fn print_bang(input: TokenStream) -> TokenStream {
+ print_helper(input, "BANG")
+}
+
+#[proc_macro_attribute]
+pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ print_helper(input, "ATTR")
+}
+
+#[proc_macro_derive(Print, attributes(print_helper))]
+pub fn print_derive(input: TokenStream) -> TokenStream {
+ print_helper(input, "DERIVE")
+}
// compile-pass
-// aux-build:derive-helper-shadowed.rs
+// aux-build:test-macros.rs
// aux-build:derive-helper-shadowed-2.rs
#[macro_use]
-extern crate derive_helper_shadowed;
-#[macro_use(my_attr)]
+extern crate test_macros;
+#[macro_use(empty_helper)]
extern crate derive_helper_shadowed_2;
-macro_rules! my_attr { () => () }
+macro_rules! empty_helper { () => () }
-#[derive(MyTrait)]
-#[my_attr] // OK
+#[derive(Empty)]
+#[empty_helper] // OK
struct S;
fn main() {}
-// aux-build:derive-helper-shadowing.rs
+// aux-build:test-macros.rs
-extern crate derive_helper_shadowing;
-use derive_helper_shadowing::*;
+#[macro_use]
+extern crate test_macros;
-#[my_attr] //~ ERROR `my_attr` is ambiguous
-#[derive(MyTrait)]
+use test_macros::empty_attr as empty_helper;
+
+#[empty_helper] //~ ERROR `empty_helper` is ambiguous
+#[derive(Empty)]
struct S {
// FIXME No ambiguity, attributes in non-macro positions are not resolved properly
- #[my_attr]
+ #[empty_helper]
field: [u8; {
// FIXME No ambiguity, derive helpers are not put into scope for non-attributes
- use my_attr;
+ use empty_helper;
// FIXME No ambiguity, derive helpers are not put into scope for inner items
- #[my_attr]
+ #[empty_helper]
struct U;
mod inner {
- #[my_attr] //~ ERROR attribute `my_attr` is currently unknown
+ #[empty_helper] //~ ERROR attribute `empty_helper` is currently unknown
struct V;
}
-error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future
- --> $DIR/derive-helper-shadowing.rs:20:15
+error[E0658]: The attribute `empty_helper` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/derive-helper-shadowing.rs:22:15
|
-LL | #[my_attr]
- | ^^^^^^^
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error[E0659]: `my_attr` is ambiguous (derive helper attribute vs any other name)
- --> $DIR/derive-helper-shadowing.rs:6:3
+error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+ --> $DIR/derive-helper-shadowing.rs:8:3
|
-LL | #[my_attr]
- | ^^^^^^^ ambiguous name
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
|
-note: `my_attr` could refer to the derive helper attribute defined here
- --> $DIR/derive-helper-shadowing.rs:7:10
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:9:10
|
-LL | #[derive(MyTrait)]
- | ^^^^^^^
-note: `my_attr` could also refer to the attribute macro imported here
- --> $DIR/derive-helper-shadowing.rs:4:5
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:6:5
|
-LL | use derive_helper_shadowing::*;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: use `crate::my_attr` to refer to this attribute macro unambiguously
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
error: aborting due to 2 previous errors
--- /dev/null
+// compile-pass
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+
+mod inner {
+ use test_macros::Empty;
+
+ #[derive(Empty)]
+ struct S;
+}
+
+fn main() {}
-// aux-build:derive-a.rs
-
-#![allow(warnings)]
+// aux-build:test-macros.rs
#[macro_use]
-extern crate derive_a;
+extern crate test_macros;
-#[derive_A] //~ ERROR attribute `derive_A` is currently unknown
+#[derive_Empty] //~ ERROR attribute `derive_Empty` is currently unknown
struct A;
fn main() {}
-error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future
- --> $DIR/derive-still-gated.rs:8:3
+error[E0658]: The attribute `derive_Empty` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/derive-still-gated.rs:6:3
|
-LL | #[derive_A]
- | ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive`
+LL | #[derive_Empty]
+ | ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
// compile-pass
// edition:2018
-// aux-build:dollar-crate.rs
+// aux-build:test-macros.rs
// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
-extern crate dollar_crate;
+#[macro_use]
+extern crate test_macros;
type S = u8;
macro_rules! m {
() => {
- dollar_crate::m_empty! {
+ print_bang! {
struct M($crate::S);
}
- #[dollar_crate::a]
+ #[print_attr]
struct A($crate::S);
};
}
-PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
-PROC MACRO INPUT: TokenStream [
+PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #2 bytes(LO..HI),
},
]
-ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
-ATTRIBUTE INPUT: TokenStream [
+PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
// edition:2018
-// aux-build:dollar-crate.rs
+// aux-build:test-macros.rs
// aux-build:dollar-crate-external.rs
// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
-extern crate dollar_crate;
+#[macro_use]
+extern crate test_macros;
extern crate dollar_crate_external;
type S = u8;
mod local {
- use crate::dollar_crate;
-
macro_rules! local {
() => {
- dollar_crate::m! {
+ print_bang! {
struct M($crate::S);
}
- #[dollar_crate::a]
+ #[print_attr]
struct A($crate::S);
- #[derive(dollar_crate::d)]
+ #[derive(Print)]
struct D($crate::S); //~ ERROR the name `D` is defined multiple times
};
}
error[E0428]: the name `D` is defined multiple times
- --> $DIR/dollar-crate.rs:27:13
+ --> $DIR/dollar-crate.rs:26:13
|
LL | struct D($crate::S);
| ^^^^^^^^^^^^^^^^^^^^
= note: `D` must be defined only once in the type namespace of this module
error[E0428]: the name `D` is defined multiple times
- --> $DIR/dollar-crate.rs:37:5
+ --> $DIR/dollar-crate.rs:36:5
|
LL | dollar_crate_external::external!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
-PROC MACRO INPUT: TokenStream [
+PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #2 bytes(LO..HI),
},
]
-ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
-ATTRIBUTE INPUT: TokenStream [
+PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #2 bytes(LO..HI),
},
]
-DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S);
-DERIVE INPUT: TokenStream [
+PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ;
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #2 bytes(LO..HI),
},
]
-PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ;
-PROC MACRO INPUT: TokenStream [
+PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #10 bytes(LO..HI),
span: #10 bytes(LO..HI),
},
]
-ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S);
-ATTRIBUTE INPUT: TokenStream [
+PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #10 bytes(LO..HI),
span: #10 bytes(LO..HI),
},
]
-DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S);
-DERIVE INPUT: TokenStream [
+PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ;
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #10 bytes(LO..HI),
--- /dev/null
+// aux-build:test-macros.rs
+
+#[macro_use(Empty)]
+extern crate test_macros;
+use test_macros::empty_attr as empty_helper;
+
+#[derive(Empty)]
+#[empty_helper] //~ ERROR `empty_helper` is ambiguous
+struct S;
+
+fn main() {}
--- /dev/null
+error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:5:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
--- /dev/null
+// compile-pass
+// aux-build:test-macros.rs
+
+#[macro_use(Empty)]
+extern crate test_macros;
+
+use self::one::*;
+use self::two::*;
+
+mod empty_helper {}
+
+mod one {
+ use empty_helper;
+
+ #[derive(Empty)]
+ #[empty_helper]
+ struct One;
+}
+
+mod two {
+ use empty_helper;
+
+ #[derive(Empty)]
+ #[empty_helper]
+ struct Two;
+}
+
+fn main() {}
-// aux-build:derive-a.rs
+// aux-build:test-macros.rs
-#![allow(warnings)]
+extern crate test_macros;
-#[macro_use]
-extern crate derive_a;
-
-use derive_a::derive_a;
-//~^ ERROR: unresolved import `derive_a::derive_a`
+use test_macros::empty_derive;
+//~^ ERROR: unresolved import `test_macros::empty_derive`
fn main() {}
-error[E0432]: unresolved import `derive_a::derive_a`
- --> $DIR/import.rs:8:5
+error[E0432]: unresolved import `test_macros::empty_derive`
+ --> $DIR/import.rs:5:5
|
-LL | use derive_a::derive_a;
- | ^^^^^^^^^^^^^^^^^^ no `derive_a` in the root
+LL | use test_macros::empty_derive;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root
error: aborting due to previous error
--- /dev/null
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked
+struct Baz {
+ a: i32,
+ b: i32,
+}
+
+fn main() {}
--- /dev/null
+error: proc-macro derive panicked
+ --> $DIR/issue-36935.rs:6:20
+ |
+LL | #[derive(Identity, Panic)]
+ | ^^^^^
+ |
+ = help: message: panic-derive
+
+error: aborting due to previous error
+
-// aux-build:derive-a-b.rs
+// aux-build:test-macros.rs
#[macro_use]
-extern crate derive_a_b;
+extern crate test_macros;
fn main() {
// Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
-// aux-build:issue-41211.rs
+// aux-build:test-macros.rs
// FIXME: https://github.com/rust-lang/rust/issues/41430
// This is a temporary regression test for the ICE reported in #41211
#![feature(custom_inner_attributes)]
-#![emit_unchanged]
-//~^ ERROR attribute `emit_unchanged` is currently unknown to the compiler
+#![identity_attr]
+//~^ ERROR attribute `identity_attr` is currently unknown to the compiler
//~| ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro
-extern crate issue_41211;
-use issue_41211::emit_unchanged;
+extern crate test_macros;
+use test_macros::identity_attr;
fn main() {}
-error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future
+error[E0658]: The attribute `identity_attr` is currently unknown to the compiler and may have meaning added to it in the future
--> $DIR/issue-41211.rs:8:4
|
-LL | #![emit_unchanged]
- | ^^^^^^^^^^^^^^
+LL | #![identity_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
error: inconsistent resolution for a macro: first custom attribute, then attribute macro
--> $DIR/issue-41211.rs:8:4
|
-LL | #![emit_unchanged]
- | ^^^^^^^^^^^^^^
+LL | #![identity_attr]
+ | ^^^^^^^^^^^^^
error: aborting due to 2 previous errors
// compile-pass
-// aux-build:issue-53481.rs
+// aux-build:test-macros.rs
#[macro_use]
-extern crate issue_53481;
+extern crate test_macros;
mod m1 {
- use m2::MyTrait;
+ use m2::Empty;
- #[derive(MyTrait)]
+ #[derive(Empty)]
struct A {}
}
mod m2 {
- pub type MyTrait = u8;
+ pub type Empty = u8;
- #[derive(MyTrait)]
- #[my_attr]
+ #[derive(Empty)]
+ #[empty_helper]
struct B {}
}
-// aux-build:derive-panic.rs
-// compile-flags:--error-format human
+// aux-build:test-macros.rs
#[macro_use]
-extern crate derive_panic;
+extern crate test_macros;
-#[derive(A)]
+#[derive(Panic)]
//~^ ERROR: proc-macro derive panicked
struct Foo;
error: proc-macro derive panicked
- --> $DIR/load-panic.rs:7:10
+ --> $DIR/load-panic.rs:6:10
|
-LL | #[derive(A)]
- | ^
+LL | #[derive(Panic)]
+ | ^^^^^
|
- = help: message: nope!
+ = help: message: panic-derive
error: aborting due to previous error
-// aux-build:macro-brackets.rs
+// aux-build:test-macros.rs
-extern crate macro_brackets as bar;
-use bar::doit;
+#[macro_use]
+extern crate test_macros;
macro_rules! id {
($($t:tt)*) => ($($t)*)
}
-#[doit]
+#[identity_attr]
id![static X: u32 = 'a';]; //~ ERROR: mismatched types
// compile-pass
-// aux-build:attr_proc_macro.rs
+// aux-build:test-macros.rs
-#[macro_use] extern crate attr_proc_macro;
+#[macro_use]
+extern crate test_macros;
-#[attr_proc_macro]
+#[identity_attr]
struct Foo;
fn main() {
// compile-pass
-// aux-build:bang_proc_macro.rs
+// aux-build:test-macros.rs
#![feature(proc_macro_hygiene)]
#[macro_use]
-extern crate bang_proc_macro;
+extern crate test_macros;
fn main() {
- bang_proc_macro!(println!("Hello, world!"));
+ identity!(println!("Hello, world!"));
}
// aux-build:test-macros.rs
// ignore-wasm32
+#[macro_use]
extern crate test_macros;
-use test_macros::{nop_attr, no_output, emit_input};
-
fn main() {
assert_eq!(unsafe { rust_get_test_int() }, 0isize);
assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
#[link(name = "rust_test_helpers", kind = "static")]
extern {
- #[no_output]
+ #[empty_attr]
//~^ ERROR macro invocations in `extern {}` blocks are experimental
fn some_definitely_unknown_symbol_which_should_be_removed();
- #[nop_attr]
+ #[identity_attr]
//~^ ERROR macro invocations in `extern {}` blocks are experimental
fn rust_get_test_int() -> isize;
- emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+ identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
}
error[E0658]: macro invocations in `extern {}` blocks are experimental
- --> $DIR/macros-in-extern.rs:15:5
+ --> $DIR/macros-in-extern.rs:14:5
|
-LL | #[no_output]
- | ^^^^^^^^^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
- --> $DIR/macros-in-extern.rs:19:5
+ --> $DIR/macros-in-extern.rs:18:5
|
-LL | #[nop_attr]
- | ^^^^^^^^^^^
+LL | #[identity_attr]
+ | ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
- --> $DIR/macros-in-extern.rs:23:5
+ --> $DIR/macros-in-extern.rs:22:5
|
-LL | emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
-// aux-build:nested-item-spans.rs
+// aux-build:test-macros.rs
-extern crate nested_item_spans;
+#[macro_use]
+extern crate test_macros;
-use nested_item_spans::foo;
-
-#[foo]
+#[recollect_attr]
fn another() {
fn bar() {
let x: u32 = "x"; //~ ERROR: mismatched types
}
fn main() {
- #[foo]
+ #[recollect_attr]
fn bar() {
let x: u32 = "x"; //~ ERROR: mismatched types
}
error[E0308]: mismatched types
- --> $DIR/nested-item-spans.rs:10:22
+ --> $DIR/nested-item-spans.rs:9:22
|
LL | let x: u32 = "x";
| ^^^ expected u32, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/nested-item-spans.rs:19:22
+ --> $DIR/nested-item-spans.rs:18:22
|
LL | let x: u32 = "x";
| ^^^ expected u32, found reference
-// aux-build:derive-a.rs
+// aux-build:test-macros.rs
#![feature(rustc_attrs)]
#![warn(unused_extern_crates)]
-extern crate derive_a;
+extern crate test_macros;
//~^ WARN unused extern crate
#[rustc_error]
warning: unused extern crate
--> $DIR/no-macro-use-attr.rs:6:1
|
-LL | extern crate derive_a;
- | ^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+LL | extern crate test_macros;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
|
note: lint level defined here
--> $DIR/no-macro-use-attr.rs:4:9
-// aux-build:proc-macro-gates.rs
+// aux-build:test-macros.rs
// gate-test-proc_macro_hygiene
#![feature(stmt_expr_attributes)]
-extern crate proc_macro_gates as foo;
-
-use foo::*;
+#[macro_use]
+extern crate test_macros;
fn _test_inner() {
- #![a] //~ ERROR: non-builtin inner attributes are unstable
+ #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
}
-#[a] //~ ERROR: custom attributes cannot be applied to modules
+#[empty_attr] //~ ERROR: custom attributes cannot be applied to modules
mod _test2 {}
mod _test2_inner {
- #![a] //~ ERROR: custom attributes cannot be applied to modules
+ #![empty_attr] //~ ERROR: custom attributes cannot be applied to modules
//~| ERROR: non-builtin inner attributes are unstable
}
-#[a = "y"] //~ ERROR: must only be followed by a delimiter token
+#[empty_attr = "y"] //~ ERROR: must only be followed by a delimiter token
fn _test3() {}
fn attrs() {
// Statement, item
- #[a] // OK
+ #[empty_attr] // OK
struct S;
// Statement, macro
- #[a] //~ ERROR: custom attributes cannot be applied to statements
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
println!();
// Statement, semi
- #[a] //~ ERROR: custom attributes cannot be applied to statements
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
S;
// Statement, local
- #[a] //~ ERROR: custom attributes cannot be applied to statements
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
let _x = 2;
// Expr
- let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions
+ let _x = #[identity_attr] 2; //~ ERROR: custom attributes cannot be applied to expressions
// Opt expr
- let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions
+ let _x = [#[identity_attr] 2]; //~ ERROR: custom attributes cannot be applied to expressions
// Expr macro
- let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions
+ let _x = #[identity_attr] println!();
+ //~^ ERROR: custom attributes cannot be applied to expressions
}
fn main() {
- let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
- if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns
+ let _x: identity!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
+ if let identity!(Some(_x)) = Some(3) {}
+ //~^ ERROR: procedural macros cannot be expanded to patterns
- m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements
- m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements
+ empty!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements
+ empty!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements
- let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions
- let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions
+ let _x = identity!(3); //~ ERROR: procedural macros cannot be expanded to expressions
+ let _x = [empty!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions
}
error[E0658]: non-builtin inner attributes are unstable
- --> $DIR/proc-macro-gates.rs:11:5
+ --> $DIR/proc-macro-gates.rs:10:5
|
-LL | #![a]
- | ^^^^^
+LL | #![empty_attr]
+ | ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54726
= help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
error[E0658]: non-builtin inner attributes are unstable
- --> $DIR/proc-macro-gates.rs:18:5
+ --> $DIR/proc-macro-gates.rs:17:5
|
-LL | #![a]
- | ^^^^^
+LL | #![empty_attr]
+ | ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54726
= help: add #![feature(custom_inner_attributes)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to modules
- --> $DIR/proc-macro-gates.rs:14:1
+ --> $DIR/proc-macro-gates.rs:13:1
|
-LL | #[a]
- | ^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to modules
- --> $DIR/proc-macro-gates.rs:18:5
+ --> $DIR/proc-macro-gates.rs:17:5
|
-LL | #![a]
- | ^^^^^
+LL | #![empty_attr]
+ | ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token
- --> $DIR/proc-macro-gates.rs:22:1
+ --> $DIR/proc-macro-gates.rs:21:1
|
-LL | #[a = "y"]
- | ^^^^^^^^^^
+LL | #[empty_attr = "y"]
+ | ^^^^^^^^^^^^^^^^^^^
error[E0658]: custom attributes cannot be applied to statements
- --> $DIR/proc-macro-gates.rs:31:5
+ --> $DIR/proc-macro-gates.rs:30:5
|
-LL | #[a]
- | ^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to statements
- --> $DIR/proc-macro-gates.rs:35:5
+ --> $DIR/proc-macro-gates.rs:34:5
|
-LL | #[a]
- | ^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to statements
- --> $DIR/proc-macro-gates.rs:39:5
+ --> $DIR/proc-macro-gates.rs:38:5
|
-LL | #[a]
- | ^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to expressions
- --> $DIR/proc-macro-gates.rs:43:14
+ --> $DIR/proc-macro-gates.rs:42:14
|
-LL | let _x = #[a] 2;
- | ^^^^
+LL | let _x = #[identity_attr] 2;
+ | ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to expressions
- --> $DIR/proc-macro-gates.rs:46:15
+ --> $DIR/proc-macro-gates.rs:45:15
|
-LL | let _x = [#[a] 2];
- | ^^^^
+LL | let _x = [#[identity_attr] 2];
+ | ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: custom attributes cannot be applied to expressions
- --> $DIR/proc-macro-gates.rs:49:14
+ --> $DIR/proc-macro-gates.rs:48:14
|
-LL | let _x = #[a] println!();
- | ^^^^
+LL | let _x = #[identity_attr] println!();
+ | ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to types
--> $DIR/proc-macro-gates.rs:53:13
|
-LL | let _x: m!(u32) = 3;
- | ^^^^^^^
+LL | let _x: identity!(u32) = 3;
+ | ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to patterns
--> $DIR/proc-macro-gates.rs:54:12
|
-LL | if let m!(Some(_x)) = Some(3) {}
- | ^^^^^^^^^^^^
+LL | if let identity!(Some(_x)) = Some(3) {}
+ | ^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to statements
- --> $DIR/proc-macro-gates.rs:56:5
+ --> $DIR/proc-macro-gates.rs:57:5
|
-LL | m!(struct S;);
- | ^^^^^^^^^^^^^^
+LL | empty!(struct S;);
+ | ^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to statements
- --> $DIR/proc-macro-gates.rs:57:5
+ --> $DIR/proc-macro-gates.rs:58:5
|
-LL | m!(let _x = 3;);
- | ^^^^^^^^^^^^^^^^
+LL | empty!(let _x = 3;);
+ | ^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to expressions
- --> $DIR/proc-macro-gates.rs:59:14
+ --> $DIR/proc-macro-gates.rs:60:14
|
-LL | let _x = m!(3);
- | ^^^^^
+LL | let _x = identity!(3);
+ | ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to expressions
- --> $DIR/proc-macro-gates.rs:60:15
+ --> $DIR/proc-macro-gates.rs:61:15
|
-LL | let _x = [m!(3)];
- | ^^^^^
+LL | let _x = [empty!(3)];
+ | ^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable
-// aux-build:proc-macro-gates.rs
+// aux-build:test-macros.rs
#![feature(stmt_expr_attributes)]
-extern crate proc_macro_gates as foo;
-
-use foo::*;
+#[macro_use]
+extern crate test_macros;
// NB. these errors aren't the best errors right now, but they're definitely
// intended to be errors. Somehow using a custom attribute in these positions
// should either require a feature gate or not be allowed on stable.
-fn _test6<#[a] T>() {}
+fn _test6<#[empty_attr] T>() {}
//~^ ERROR: unknown to the compiler
fn _test7() {
match 1 {
- #[a] //~ ERROR: unknown to the compiler
+ #[empty_attr] //~ ERROR: unknown to the compiler
0 => {}
_ => {}
}
-error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future
- --> $DIR/proc-macro-gates2.rs:13:11
+error[E0658]: The attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/proc-macro-gates2.rs:12:11
|
-LL | fn _test6<#[a] T>() {}
- | ^^^^
+LL | fn _test6<#[empty_attr] T>() {}
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future
- --> $DIR/proc-macro-gates2.rs:18:9
+error[E0658]: The attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future
+ --> $DIR/proc-macro-gates2.rs:17:9
|
-LL | #[a]
- | ^^^^
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable
// aux-build:derive-foo.rs
// aux-build:derive-clona.rs
-// aux-build:attr_proc_macro.rs
-// aux-build:bang_proc_macro.rs
+// aux-build:test-macros.rs
#![feature(custom_attribute)]
extern crate derive_foo;
#[macro_use]
extern crate derive_clona;
-extern crate attr_proc_macro;
-extern crate bang_proc_macro;
+extern crate test_macros;
-use attr_proc_macro::attr_proc_macro;
-use bang_proc_macro::bang_proc_macro;
+use test_macros::empty as bang_proc_macro;
+use test_macros::empty_attr as attr_proc_macro;
macro_rules! FooWithLongNam {
() => {}
error: cannot find derive macro `FooWithLongNan` in this scope
- --> $DIR/resolve-error.rs:26:10
+ --> $DIR/resolve-error.rs:24:10
|
LL | #[derive(FooWithLongNan)]
| ^^^^^^^^^^^^^^ help: try: `FooWithLongName`
error: cannot find derive macro `Dlone` in this scope
- --> $DIR/resolve-error.rs:36:10
+ --> $DIR/resolve-error.rs:34:10
|
LL | #[derive(Dlone)]
| ^^^^^ help: try: `Clone`
error: cannot find derive macro `Dlona` in this scope
- --> $DIR/resolve-error.rs:40:10
+ --> $DIR/resolve-error.rs:38:10
|
LL | #[derive(Dlona)]
| ^^^^^ help: try: `Clona`
error: cannot find derive macro `attr_proc_macra` in this scope
- --> $DIR/resolve-error.rs:44:10
+ --> $DIR/resolve-error.rs:42:10
|
LL | #[derive(attr_proc_macra)]
| ^^^^^^^^^^^^^^^
error: cannot find macro `FooWithLongNama!` in this scope
- --> $DIR/resolve-error.rs:49:5
+ --> $DIR/resolve-error.rs:47:5
|
LL | FooWithLongNama!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
error: cannot find macro `attr_proc_macra!` in this scope
- --> $DIR/resolve-error.rs:52:5
+ --> $DIR/resolve-error.rs:50:5
|
LL | attr_proc_macra!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
error: cannot find macro `Dlona!` in this scope
- --> $DIR/resolve-error.rs:55:5
+ --> $DIR/resolve-error.rs:53:5
|
LL | Dlona!();
| ^^^^^
error: cannot find macro `bang_proc_macrp!` in this scope
- --> $DIR/resolve-error.rs:58:5
+ --> $DIR/resolve-error.rs:56:5
|
LL | bang_proc_macrp!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
-// aux-build:derive-a.rs
+// aux-build:test-macros.rs
#[macro_use]
-extern crate derive_a;
+extern crate test_macros;
#[macro_use]
-extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times
+extern crate test_macros; //~ ERROR the name `test_macros` is defined multiple times
fn main() {}
-error[E0259]: the name `derive_a` is defined multiple times
+error[E0259]: the name `test_macros` is defined multiple times
--> $DIR/shadow.rs:6:1
|
-LL | extern crate derive_a;
- | ---------------------- previous import of the extern crate `derive_a` here
+LL | extern crate test_macros;
+ | ------------------------- previous import of the extern crate `test_macros` here
LL | #[macro_use]
-LL | extern crate derive_a;
- | ^^^^^^^^^^^^^^^^^^^^^^ `derive_a` reimported here
+LL | extern crate test_macros;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ `test_macros` reimported here
|
- = note: `derive_a` must be defined only once in the type namespace of this module
+ = note: `test_macros` must be defined only once in the type namespace of this module
error: aborting due to previous error
//~ ERROR mismatched types
-// aux-build:span-preservation.rs
+// aux-build:test-macros.rs
// For each of these, we should get the appropriate type mismatch error message,
// and the function should be echoed.
-extern crate span_preservation as foo;
+#[macro_use]
+extern crate test_macros;
-use foo::foo;
-
-#[foo]
+#[recollect_attr]
fn a() {
let x: usize = "hello";;;;; //~ ERROR mismatched types
}
-#[foo]
+#[recollect_attr]
fn b(x: Option<isize>) -> usize {
match x {
Some(x) => { return x }, //~ ERROR mismatched types
}
}
-#[foo]
+#[recollect_attr]
fn c() {
struct Foo {
a: usize
// FIXME: This doesn't work at the moment. See the one below. The pretty-printer
// injects a "C" between `extern` and `fn` which causes a "probably_eq"
// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST.
-#[foo]
+#[recollect_attr]
extern fn bar() {
0
}
-#[foo]
+#[recollect_attr]
extern "C" fn baz() {
0 //~ ERROR mismatched types
}
found type `{integer}`
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:13:20
+ --> $DIR/span-preservation.rs:12:20
|
LL | let x: usize = "hello";;;;;
| ^^^^^^^ expected usize, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:19:29
+ --> $DIR/span-preservation.rs:18:29
|
LL | fn b(x: Option<isize>) -> usize {
| ----- expected `usize` because of return type
| ^ expected usize, found isize
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:35:22
+ --> $DIR/span-preservation.rs:34:22
|
LL | let x = Foo { a: 10isize };
| ^^^^^^^ expected usize, found isize
error[E0560]: struct `c::Foo` has no field named `b`
- --> $DIR/span-preservation.rs:36:26
+ --> $DIR/span-preservation.rs:35:26
|
LL | let y = Foo { a: 10, b: 10isize };
| ^ `c::Foo` does not have this field
= note: available fields are: `a`
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:49:5
+ --> $DIR/span-preservation.rs:48:5
|
LL | extern "C" fn baz() {
| - possibly return type missing here?
// TOP-LEVEL FN'S
fn escaping_borrow_of_fn_params_1() {
- fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
}
fn escaping_borrow_of_fn_params_2() {
- fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
}
fn move_of_fn_params() {
- fn g<'a>(x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = move |t: bool| if t { x } else { y };
return Box::new(f);
};
fn escaping_borrow_of_method_params_1() {
struct S;
impl S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
fn escaping_borrow_of_method_params_2() {
struct S;
impl S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
fn move_of_method_params() {
struct S;
impl S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = move |t: bool| if t { x } else { y };
return Box::new(f);
}
// TRAIT IMPL METHODS
fn escaping_borrow_of_trait_impl_params_1() {
- trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
struct S;
impl T for S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
}
fn escaping_borrow_of_trait_impl_params_2() {
- trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
struct S;
impl T for S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
}
fn move_of_trait_impl_params() {
- trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a>; }
+ trait T { fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a>; }
struct S;
impl T for S {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = move |t: bool| if t { x } else { y };
return Box::new(f);
}
fn escaping_borrow_of_trait_default_params_1() {
struct S;
trait T {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
fn escaping_borrow_of_trait_default_params_2() {
struct S;
trait T {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`)
//~^ ERROR E0373
//~| ERROR E0373
fn move_of_trait_default_params() {
struct S;
trait T {
- fn g<'a>(&self, x: usize, y:usize) -> Box<Fn(bool) -> usize + 'a> {
+ fn g<'a>(&self, x: usize, y:usize) -> Box<dyn Fn(bool) -> usize + 'a> {
let f = move |t: bool| if t { x } else { y };
return Box::new(f);
}
struct Foo<'a,'b,'c> { //~ ERROR parameter `'c` is never used
// All of these are ok, because we can derive exactly one bound:
- a: Box<IsStatic>,
- b: Box<Is<'static>>,
- c: Box<Is<'a>>,
- d: Box<IsSend>,
- e: Box<Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
- f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599.
- g: Box<SomeTrait+'a>,
+ a: Box<dyn IsStatic>,
+ b: Box<dyn Is<'static>>,
+ c: Box<dyn Is<'a>>,
+ d: Box<dyn IsSend>,
+ e: Box<dyn Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
+ f: Box<dyn SomeTrait>, // OK, defaults to 'static due to RFC 599.
+ g: Box<dyn SomeTrait+'a>,
- z: Box<Is<'a>+'b+'c>,
+ z: Box<dyn Is<'a>+'b+'c>,
//~^ ERROR only a single explicit lifetime bound is permitted
//~| ERROR lifetime bound not satisfied
}
error[E0226]: only a single explicit lifetime bound is permitted
- --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:22
+ --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:26
|
-LL | z: Box<Is<'a>+'b+'c>,
- | ^^
+LL | z: Box<dyn Is<'a>+'b+'c>,
+ | ^^
error[E0478]: lifetime bound not satisfied
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:5
|
-LL | z: Box<Is<'a>+'b+'c>,
- | ^^^^^^^^^^^^^^^^^^^^
+LL | z: Box<dyn Is<'a>+'b+'c>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 11:15
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15
error: lifetime may not live long enough
--> $DIR/region-object-lifetime-2.rs:10:5
|
-LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
}
// Borrowed receiver but two distinct lifetimes, we get an error.
-fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:42...
--> $DIR/region-object-lifetime-2.rs:9:42
|
-LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-2.rs:10:5
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 9:45...
--> $DIR/region-object-lifetime-2.rs:9:45
|
-LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
+LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-2.rs:10:5
error: lifetime may not live long enough
--> $DIR/region-object-lifetime-4.rs:12:5
|
-LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
// Here we have two distinct lifetimes, but we try to return a pointer
// with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error.
-fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 11:41...
--> $DIR/region-object-lifetime-4.rs:11:41
|
-LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-4.rs:12:5
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 11:44...
--> $DIR/region-object-lifetime-4.rs:11:44
|
-LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
+LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-4.rs:12:5
// Here, the object is bounded by an anonymous lifetime and returned
// as `&'static`, so you get an error.
-fn owned_receiver(x: Box<Foo>) -> &'static () {
+fn owned_receiver(x: Box<dyn Foo>) -> &'static () {
x.borrowed() //~ ERROR cannot return value referencing local data `*x`
}
error[E0621]: explicit lifetime required in the type of `v`
--> $DIR/region-object-lifetime-in-coercion.rs:8:12
|
-LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
+LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
-LL | let x: Box<Foo + 'static> = Box::new(v);
- | ^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+LL | let x: Box<dyn Foo + 'static> = Box::new(v);
+ | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
error[E0621]: explicit lifetime required in the type of `v`
--> $DIR/region-object-lifetime-in-coercion.rs:14:5
|
-LL | fn b(v: &[u8]) -> Box<Foo + 'static> {
+LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
LL | Box::new(v)
| ^^^^^^^^^^^ lifetime `'static` required
error[E0621]: explicit lifetime required in the type of `v`
--> $DIR/region-object-lifetime-in-coercion.rs:21:5
|
-LL | fn c(v: &[u8]) -> Box<Foo> {
+LL | fn c(v: &[u8]) -> Box<dyn Foo> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
...
LL | Box::new(v)
error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:26:5
|
-LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
trait Foo {}
impl<'a> Foo for &'a [u8] {}
-fn a(v: &[u8]) -> Box<Foo + 'static> {
- let x: Box<Foo + 'static> = Box::new(v);
+fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
+ let x: Box<dyn Foo + 'static> = Box::new(v);
//~^ ERROR explicit lifetime required in the type of `v` [E0621]
x
}
-fn b(v: &[u8]) -> Box<Foo + 'static> {
+fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
Box::new(v)
//~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
-fn c(v: &[u8]) -> Box<Foo> {
+fn c(v: &[u8]) -> Box<dyn Foo> {
// same as previous case due to RFC 599
Box::new(v)
//~^ ERROR explicit lifetime required in the type of `v` [E0621]
}
-fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
Box::new(v)
//~^ ERROR cannot infer an appropriate lifetime due to conflicting
}
-fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
Box::new(v) // OK, thanks to 'a:'b
}
error[E0621]: explicit lifetime required in the type of `v`
- --> $DIR/region-object-lifetime-in-coercion.rs:8:33
+ --> $DIR/region-object-lifetime-in-coercion.rs:8:37
|
-LL | fn a(v: &[u8]) -> Box<Foo + 'static> {
+LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
-LL | let x: Box<Foo + 'static> = Box::new(v);
- | ^^^^^^^^^^^ lifetime `'static` required
+LL | let x: Box<dyn Foo + 'static> = Box::new(v);
+ | ^^^^^^^^^^^ lifetime `'static` required
error[E0621]: explicit lifetime required in the type of `v`
--> $DIR/region-object-lifetime-in-coercion.rs:14:5
|
-LL | fn b(v: &[u8]) -> Box<Foo + 'static> {
+LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
LL | Box::new(v)
| ^^^^^^^^^^^ lifetime `'static` required
error[E0621]: explicit lifetime required in the type of `v`
--> $DIR/region-object-lifetime-in-coercion.rs:21:5
|
-LL | fn c(v: &[u8]) -> Box<Foo> {
+LL | fn c(v: &[u8]) -> Box<dyn Foo> {
| ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
...
LL | Box::new(v)
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 25:6...
--> $DIR/region-object-lifetime-in-coercion.rs:25:6
|
-LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^
= note: ...so that the expression is assignable:
expected &[u8]
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 25:9...
--> $DIR/region-object-lifetime-in-coercion.rs:25:9
|
-LL | fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
+LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
| ^^
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn Foo + 'b)>
fn as_item(&self) -> &Self::Item;
}
-fn bad1<T: Iter>(v: T) -> Box<X+'static>
+fn bad1<T: Iter>(v: T) -> Box<dyn X + 'static>
{
let item = v.into_item();
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
-fn bad2<T: Iter>(v: T) -> Box<X+'static>
+fn bad2<T: Iter>(v: T) -> Box<dyn X + 'static>
where Box<T::Item> : X
{
let item: Box<_> = box v.into_item();
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
-fn bad3<'a, T: Iter>(v: T) -> Box<X+'a>
+fn bad3<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
{
let item = v.into_item();
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
-fn bad4<'a, T: Iter>(v: T) -> Box<X+'a>
+fn bad4<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
where Box<T::Item> : X
{
let item: Box<_> = box v.into_item();
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
-fn ok1<'a, T: Iter>(v: T) -> Box<X+'a>
+fn ok1<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
where T::Item : 'a
{
let item = v.into_item();
Box::new(item) // OK, T::Item : 'a is declared
}
-fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<X+'a>
+fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<dyn X + 'a>
where T::Item : Clone
{
let item = Clone::clone(w);
Box::new(item) // OK, T::Item : 'a is implied
}
-fn ok3<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+fn ok3<'a, T: Iter>(v: &'a T) -> Box<dyn X + 'a>
where T::Item : Clone + 'a
{
let item = Clone::clone(v.as_item());
Box::new(item) // OK, T::Item : 'a was declared
}
-fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+fn meh1<'a, T: Iter>(v: &'a T) -> Box<dyn X + 'a>
where T::Item : Clone
{
// This case is kind of interesting. It's the same as `ok3` but
error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-2.rs:10:5
|
-LL | fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-2.rs:10:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^---^^^^^^^^^^^
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^---^^^^^^^^^^^^^^^
| | |
| | `*v` is borrowed here
| returns a value referencing data owned by the current function
#![feature(box_syntax)]
trait A<T> { }
-struct B<'a, T:'a>(&'a (A<T>+'a));
+struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
-fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
- box B(&*v) as Box<X> //~ ERROR cannot infer
+fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+ box B(&*v) as Box<dyn X> //~ ERROR cannot infer
}
fn main() { }
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/regions-close-object-into-object-2.rs:10:11
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
--> $DIR/regions-close-object-into-object-2.rs:9:6
|
-LL | fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| ^^
note: ...so that the type `(dyn A<T> + 'a)` is not borrowed for too long
--> $DIR/regions-close-object-into-object-2.rs:10:11
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:10:5
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `U: 'static`...
error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:10:5
|
-LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-4.rs:10:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^---^^^^^^^^^^^
+LL | box B(&*v) as Box<dyn X>
+ | ^^^^^^---^^^^^^^^^^^^^^^
| | |
| | `*v` is borrowed here
| returns a value referencing data owned by the current function
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:10:9
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^^^^
|
= help: consider adding an explicit lifetime bound `U: 'static`...
#![feature(box_syntax)]
trait A<T> { }
-struct B<'a, T:'a>(&'a (A<T>+'a));
+struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
-fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
- box B(&*v) as Box<X> //~ ERROR cannot infer
+fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ box B(&*v) as Box<dyn X> //~ ERROR cannot infer
}
fn main() {}
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/regions-close-object-into-object-4.rs:10:11
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6...
--> $DIR/regions-close-object-into-object-4.rs:9:6
|
-LL | fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| ^^
note: ...so that the type `(dyn A<U> + 'a)` is not borrowed for too long
--> $DIR/regions-close-object-into-object-4.rs:10:11
|
-LL | box B(&*v) as Box<X>
+LL | box B(&*v) as Box<dyn X>
| ^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
-LL | box v as Box<SomeTrait+'static>
+LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
|
= help: consider adding an explicit lifetime bound `A: 'static`...
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
-LL | box v as Box<SomeTrait+'b>
+LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
|
= help: consider adding an explicit lifetime bound `A: 'b`...
trait SomeTrait { fn get(&self) -> isize; }
-fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
- box v as Box<SomeTrait+'static>
+fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+ box v as Box<dyn SomeTrait + 'static>
//~^ ERROR the parameter type `A` may not live long enough
//~| ERROR the parameter type `A` may not live long enough
}
-fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
- box v as Box<SomeTrait+'a>
+fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'a> {
+ box v as Box<dyn SomeTrait + 'a>
}
-fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
- box v as Box<SomeTrait+'b>
+fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+ box v as Box<dyn SomeTrait + 'b>
//~^ ERROR the parameter type `A` may not live long enough
//~| ERROR the parameter type `A` may not live long enough
}
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
-LL | fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
+LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound `A: 'static`...
-LL | box v as Box<SomeTrait+'static>
+LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
-LL | box v as Box<SomeTrait+'static>
+LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
-LL | fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
+LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound `A: 'static`...
-LL | box v as Box<SomeTrait+'static>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'static>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that it can be closed over into an object
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
-LL | box v as Box<SomeTrait+'static>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'static>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
-LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
+LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound `A: 'b`...
-LL | box v as Box<SomeTrait+'b>
+LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
-LL | box v as Box<SomeTrait+'b>
+LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
-LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
+LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound `A: 'b`...
-LL | box v as Box<SomeTrait+'b>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'b>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that it can be closed over into an object
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
-LL | box v as Box<SomeTrait+'b>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'b>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
error: lifetime may not live long enough
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
| -- -- lifetime `'c` defined here
| |
| lifetime `'a` defined here
LL | // A outlives 'a AND 'b...but not 'c.
-LL | box v as Box<SomeTrait+'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
+LL | box v as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
error: aborting due to previous error
trait SomeTrait { fn get(&self) -> isize; }
-fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'a> {
+fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'a> {
// A outlives 'a AND 'b...
- box v as Box<SomeTrait+'a> // ...hence this type is safe.
+ box v as Box<dyn SomeTrait + 'a> // ...hence this type is safe.
}
-fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
+fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'b> {
// A outlives 'a AND 'b...
- box v as Box<SomeTrait+'b> // ...hence this type is safe.
+ box v as Box<dyn SomeTrait + 'b> // ...hence this type is safe.
}
-fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
// A outlives 'a AND 'b...but not 'c.
- box v as Box<SomeTrait+'a> //~ ERROR cannot infer an appropriate lifetime
+ box v as Box<dyn SomeTrait + 'a> //~ ERROR cannot infer an appropriate lifetime
}
fn main() {
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | box v as Box<SomeTrait+'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 18:20...
--> $DIR/regions-close-over-type-parameter-multiple.rs:18:20
|
-LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
| ^^
note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | box v as Box<SomeTrait+'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | box v as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'c as defined on the function body at 18:26...
--> $DIR/regions-close-over-type-parameter-multiple.rs:18:26
|
-LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
+LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
| ^^
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn SomeTrait + 'c)>
trait X { fn foo(&self) {} }
-fn p1<T>(v: T) -> Box<X+'static>
+fn p1<T>(v: T) -> Box<dyn X + 'static>
where T : X
{
Box::new(v) //~ ERROR parameter type `T` may not live long enough
}
-fn p2<T>(v: Box<T>) -> Box<X+'static>
+fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
where Box<T> : X
{
Box::new(v) //~ ERROR parameter type `T` may not live long enough
}
-fn p3<'a,T>(v: T) -> Box<X+'a>
+fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
where T : X
{
Box::new(v) //~ ERROR parameter type `T` may not live long enough
}
-fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
where Box<T> : X
{
Box::new(v) //~ ERROR parameter type `T` may not live long enough
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:6:5
|
-LL | fn p1<T>(v: T) -> Box<X+'static>
+LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
LL | Box::new(v)
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:12:5
|
-LL | fn p2<T>(v: Box<T>) -> Box<X+'static>
+LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
LL | Box::new(v)
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:18:5
|
-LL | fn p3<'a,T>(v: T) -> Box<X+'a>
+LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound `T: 'a`...
...
LL | Box::new(v)
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:24:5
|
-LL | fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
| - help: consider adding an explicit lifetime bound `T: 'a`...
...
LL | Box::new(v)
// this argument `t` is not automatically considered well-formed,
// since for it to be WF, we would need to know that `'y: 'x`, but we
// do not infer that.
-fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
//~^ ERROR reference has a longer lifetime than the data it references
{
}
error[E0491]: in type `&'x (dyn for<'z> Trait1<<T as Trait2<'y, 'z>>::Foo> + 'x)`, reference has a longer lifetime than the data it references
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
|
-LL | / fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
LL | |
LL | | {
LL | | }
note: the pointer is valid for the lifetime 'x as defined on the function body at 21:11
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11
|
-LL | fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ^^
note: but the referenced data is only valid for the lifetime 'y as defined on the function body at 21:15
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15
|
-LL | fn callee<'x, 'y, T>(t: &'x for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ^^
error: aborting due to previous error
struct Parameterized1<'a> {
- g: Box<FnMut() + 'a>
+ g: Box<dyn FnMut() + 'a>
}
struct NotParameterized1 {
- g: Box<FnMut() + 'static>
+ g: Box<dyn FnMut() + 'static>
}
struct NotParameterized2 {
- g: Box<FnMut() + 'static>
+ g: Box<dyn FnMut() + 'static>
}
fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p }
struct Invariant<'a> {
- f: Box<FnOnce(&mut &'a isize) + 'static>,
+ f: Box<dyn FnOnce(&mut &'a isize) + 'static>,
}
fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
struct Invariant<'a> {
- f: Box<FnOnce() -> *mut &'a isize + 'static>,
+ f: Box<dyn FnOnce() -> *mut &'a isize + 'static>,
}
fn to_same_lifetime<'r>(b_isize: Invariant<'r>) {
struct Indirect1 {
// Here the lifetime parameter of direct is bound by the fn()
- g: Box<FnOnce(Direct) + 'static>
+ g: Box<dyn FnOnce(Direct) + 'static>
}
struct Indirect2<'a> {
// But here it is set to 'a
- g: Box<FnOnce(Direct<'a>) + 'static>
+ g: Box<dyn FnOnce(Direct<'a>) + 'static>
}
fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } //~ ERROR mismatched types
// &'a CAN be declared on functions and used then:
fn g<'a>(a: &'a isize) { } // OK
- fn h(a: Box<for<'a> FnOnce(&'a isize)>) { } // OK
+ fn h(a: Box<dyn for<'a> FnOnce(&'a isize)>) { } // OK
}
// Test nesting of lifetimes in fn type declarations
fn fn_types(a: &'a isize, //~ ERROR undeclared lifetime
- b: Box<for<'a> FnOnce(&'a isize,
+ b: Box<dyn for<'a> FnOnce(&'a isize,
&'b isize, //~ ERROR undeclared lifetime
- Box<for<'b> FnOnce(&'a isize,
+ Box<dyn for<'b> FnOnce(&'a isize,
&'b isize)>,
&'b isize)>, //~ ERROR undeclared lifetime
c: &'a isize) //~ ERROR undeclared lifetime
LL | let mut ay = &y;
| ------ `ay` is declared here, outside of the closure body
LL |
-LL | ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
- | - `z` is a reference that is only valid in the closure body
+LL | ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ | - `z` is a reference that is only valid in the closure body
...
LL | ay = z;
| ^^^^^^ `z` escapes the closure body here
error[E0597]: `y` does not live long enough
--> $DIR/regions-nested-fns.rs:9:15
|
-LL | ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
- | --- value captured here
+LL | ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ | --- value captured here
LL | ay = x;
LL | ay = &y;
| ^ borrowed value does not live long enough
let y = 3;
let mut ay = &y; //~ ERROR E0495
- ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
ay = x;
ay = &y;
ay = z;
}));
- ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
if false { return x; } //~ ERROR E0312
if false { return ay; }
return z;
LL | let mut ay = &y;
| ^^
|
-note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 7:54...
- --> $DIR/regions-nested-fns.rs:7:54
+note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 7:58...
+ --> $DIR/regions-nested-fns.rs:7:58
|
-LL | ignore::<Box<for<'z> FnMut(&'z isize)>>(Box::new(|z| {
- | ______________________________________________________^
+LL | ignore::<Box<dyn for<'z> FnMut(&'z isize)>>(Box::new(|z| {
+ | __________________________________________________________^
LL | | ay = x;
LL | | ay = &y;
LL | | ay = z;
|
LL | ay = z;
| ^
-note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 13:68...
- --> $DIR/regions-nested-fns.rs:13:68
+note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the body at 13:72...
+ --> $DIR/regions-nested-fns.rs:13:72
|
-LL | ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
- | ____________________________________________________________________^
+LL | ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ | ________________________________________________________________________^
LL | | if false { return x; }
LL | | if false { return ay; }
LL | | return z;
LL | if false { return x; }
| ^
|
-note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 13:68...
- --> $DIR/regions-nested-fns.rs:13:68
+note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 13:72...
+ --> $DIR/regions-nested-fns.rs:13:72
|
-LL | ignore::< Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
- | ____________________________________________________________________^
+LL | ignore::< Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
+ | ________________________________________________________________________^
LL | | if false { return x; }
LL | | if false { return ay; }
LL | | return z;
-fn borrowed_proc<'a>(x: &'a isize) -> Box<FnMut()->(isize) + 'a> {
+fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
// This is legal, because the region bound on `proc`
// states that it captures `x`.
Box::new(move|| { *x })
}
-fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
+fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
}
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/regions-proc-bound-capture.rs:9:5
|
-LL | fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
| ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
LL | // This is illegal, because the region bound on `proc` is 'static.
LL | Box::new(move|| { *x })
#![feature(fn_traits)]
struct ClosureBox<'a> {
- cl: Box<FnMut() + 'a>,
+ cl: Box<dyn FnMut() + 'a>,
}
-fn box_it<'r>(x: Box<FnMut() + 'r>) -> ClosureBox<'r> {
+fn box_it<'r>(x: Box<dyn FnMut() + 'r>) -> ClosureBox<'r> {
ClosureBox {cl: x}
}
}
-fn get_v(gc: Box<GetCtxt>) -> usize {
+fn get_v(gc: Box<dyn GetCtxt>) -> usize {
gc.get_ctxt().v
}
fn main() {
let ctxt = Ctxt { v: 22 };
let hc = HasCtxt { c: &ctxt };
- assert_eq!(get_v(box hc as Box<GetCtxt>), 22);
+ assert_eq!(get_v(box hc as Box<dyn GetCtxt>), 22);
}
error: lifetime may not live long enough
--> $DIR/regions-trait-object-subtyping.rs:15:5
|
-LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
error: lifetime may not live long enough
--> $DIR/regions-trait-object-subtyping.rs:22:5
|
-LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
trait Dummy { fn dummy(&self); }
-fn foo1<'a:'b,'b>(x: &'a mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+fn foo1<'a:'b,'b>(x: &'a mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) {
// Here, we are able to coerce
x
}
-fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+fn foo2<'a:'b,'b>(x: &'b mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) {
// Here, we are able to coerce
x
}
-fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
// Without knowing 'a:'b, we can't coerce
x //~ ERROR lifetime bound not satisfied
//~^ ERROR cannot infer an appropriate lifetime
}
struct Wrapper<T>(T);
-fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
// We can't coerce because it is packed in `Wrapper`
x //~ ERROR mismatched types
}
note: lifetime parameter instantiated with the lifetime 'a as defined on the function body at 13:9
--> $DIR/regions-trait-object-subtyping.rs:13:9
|
-LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
note: but lifetime parameter must outlive the lifetime 'b as defined on the function body at 13:12
--> $DIR/regions-trait-object-subtyping.rs:13:12
|
-LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:9...
--> $DIR/regions-trait-object-subtyping.rs:13:9
|
-LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/regions-trait-object-subtyping.rs:15:5
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 13:12...
--> $DIR/regions-trait-object-subtyping.rs:13:12
|
-LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
| ^^
= note: ...so that the expression is assignable:
expected &'b mut (dyn Dummy + 'b)
note: the lifetime 'b as defined on the function body at 20:15...
--> $DIR/regions-trait-object-subtyping.rs:20:15
|
-LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
| ^^
note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 20:9
--> $DIR/regions-trait-object-subtyping.rs:20:9
|
-LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> {
| ^^
error: aborting due to 3 previous errors
}
struct A<'r> {
- p: &'r (X+'r)
+ p: &'r (dyn X + 'r)
}
-fn make_a(p:&X) -> A {
+fn make_a(p: &dyn X) -> A {
A{p:p}
}
trait TheTrait<'t>: 't { }
struct Foo<'a,'b> {
- x: Box<TheTrait<'a>+'b> //~ ERROR E0478
+ x: Box<dyn TheTrait<'a>+'b> //~ ERROR E0478
}
fn main() { }
error[E0478]: lifetime bound not satisfied
--> $DIR/regions-wf-trait-object.rs:7:5
|
-LL | x: Box<TheTrait<'a>+'b>
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | x: Box<dyn TheTrait<'a>+'b>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 6:15
--> $DIR/regions-wf-trait-object.rs:6:15
fn new(val: T) -> Self;
}
-impl ToNbt<Self> {}
+impl dyn ToNbt<Self> {}
//~^ ERROR cycle detected
fn main() {}
-error[E0391]: cycle detected when processing `<impl at $DIR/issue-23305.rs:5:1: 5:20>`
- --> $DIR/issue-23305.rs:5:12
+error[E0391]: cycle detected when processing `<impl at $DIR/issue-23305.rs:5:1: 5:24>`
+ --> $DIR/issue-23305.rs:5:16
|
-LL | impl ToNbt<Self> {}
- | ^^^^
+LL | impl dyn ToNbt<Self> {}
+ | ^^^^
|
- = note: ...which again requires processing `<impl at $DIR/issue-23305.rs:5:1: 5:20>`, completing the cycle
+ = note: ...which again requires processing `<impl at $DIR/issue-23305.rs:5:1: 5:24>`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/issue-23305.rs:1:1
|
impl Bar for Foo {}
fn main() {
- let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
+ let any: &dyn Any = &Bar; //~ ERROR expected value, found trait `Bar`
if any.is::<u32>() { println!("u32"); }
}
error[E0423]: expected value, found trait `Bar`
- --> $DIR/issue-33876.rs:10:22
+ --> $DIR/issue-33876.rs:10:26
|
-LL | let any: &Any = &Bar;
- | ^^^ not a value
+LL | let any: &dyn Any = &Bar;
+ | ^^^ not a value
error: aborting due to previous error
extern crate issue_3907;
-type Foo = issue_3907::Foo+'static;
+type Foo = dyn issue_3907::Foo + 'static;
struct S {
name: isize
extern crate issue_3907;
-type Foo = issue_3907::Foo;
+type Foo = dyn issue_3907::Foo;
struct S {
name: isize
trait I {}
-type K = I+'static;
+type K = dyn I + 'static;
fn foo(_x: K) {}
//~^ ERROR the size for values of type
trait I {}
-type K = I;
+type K = dyn I;
impl K for isize {} //~ ERROR expected trait, found type alias `K`
use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
#[rustc_outlives]
struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
- field1: Bar<'a, 'b, T>
+ field1: dyn Bar<'a, 'b, T>
}
trait Bar<'x, 's, U>
--> $DIR/self-structs.rs:4:1
|
LL | / struct Foo<'a, 'b, T> {
-LL | | field1: Bar<'a, 'b, T>
+LL | | field1: dyn Bar<'a, 'b, T>
LL | | }
| |_^
|
type Assoc where Self: Sized;
type Assoc2<T> where T: Display;
type Assoc3<T>;
- type WithDefault<T> where T: Debug = Iterator<Item=T>;
+ type WithDefault<T> where T: Debug = dyn Iterator<Item=T>;
type NoGenerics;
}
type Assoc = usize;
type Assoc2<T> = Vec<T>;
type Assoc3<T> where T: Iterator = Vec<T>;
- type WithDefault<'a, T> = &'a Iterator<T>;
+ type WithDefault<'a, T> = &'a dyn Iterator<T>;
type NoGenerics = ::std::cell::Cell<i32>;
}
struct SomeStruct<'x, 'y, 'z: 'x> {
foo: &'x Foo<'z>,
bar: &'x Bar<'z>,
- f: &'y for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
+ f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
}
fn id<T>(t: T) -> T {
pub fn f() {
trait Trait {}
- impl Trait {
+ impl dyn Trait {
const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus`
}
}
}
fn make_foo() {
- let x = Rc::new(5usize) as Rc<Foo>;
+ let x = Rc::new(5usize) as Rc<dyn Foo>;
//~^ ERROR E0038
//~| ERROR E0038
}
fn make_bar() {
- let x = Rc::new(5usize) as Rc<Bar>;
+ let x = Rc::new(5usize) as Rc<dyn Bar>;
x.bar();
}
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
|
-LL | let x = Rc::new(5usize) as Rc<Foo>;
- | ^^^^^^^ the trait `Foo` cannot be made into an object
+LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
+ | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo`'s receiver cannot be dispatched on
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
|
-LL | let x = Rc::new(5usize) as Rc<Foo>;
+LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo`'s receiver cannot be dispatched on
}
fn main() {
- let null_i32 = ptr::null::<i32>() as *const Foo;
- let null_u32 = ptr::null::<u32>() as *const Foo;
+ let null_i32 = ptr::null::<i32>() as *const dyn Foo;
+ let null_u32 = ptr::null::<u32>() as *const dyn Foo;
assert_eq!("I'm an i32!", null_i32.foo());
assert_eq!("I'm a u32!", null_u32.foo());
assert_eq!("I'm an i32!", valid_i32_thin.foo());
assert_eq!(5, unsafe { valid_i32_thin.bar() });
assert_eq!(5, unsafe { (&valid_i32_thin as *const *const i32).complicated() });
- let valid_i32_fat = valid_i32_thin as *const Foo;
+ let valid_i32_fat = valid_i32_thin as *const dyn Foo;
assert_eq!("I'm an i32!", valid_i32_fat.foo());
assert_eq!(5, unsafe { valid_i32_fat.bar() });
assert_eq!("I'm a u32!", valid_u32_thin.foo());
assert_eq!(18, unsafe { valid_u32_thin.bar() });
assert_eq!(18, unsafe { (&valid_u32_thin as *const *const u32).complicated() });
- let valid_u32_fat = valid_u32_thin as *const Foo;
+ let valid_u32_fat = valid_u32_thin as *const dyn Foo;
assert_eq!("I'm a u32!", valid_u32_fat.foo());
assert_eq!(18, unsafe { valid_u32_fat.bar() });
pub fn main() {
let x = box S { x: 3 };
- let y = x as Box<Foo>;
+ let y = x as Box<dyn Foo>;
y.f();
}
c.get()
}
-fn tick2(c: &mut Counter) {
+fn tick2(c: &mut dyn Counter) {
tick3(c);
}
c.with(|i| ());
}
-fn tick2(c: &mut Counter) {
+fn tick2(c: &mut dyn Counter) {
tick3(c);
}
c
}
-fn tick(c: &mut Counter) {
+fn tick(c: &mut dyn Counter) {
tick_generic(c);
}
// Ensure that invoking a closure counts as a unique immutable borrow
-type Fn<'a> = Box<FnMut() + 'a>;
+type Fn<'a> = Box<dyn FnMut() + 'a>;
struct Test<'a> {
- f: Box<FnMut() + 'a>
+ f: Box<dyn FnMut() + 'a>
}
fn call<F>(mut f: F) where F: FnMut(Fn) {
}
fn test7() {
- fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
+ fn foo<F>(_: F) where F: FnMut(Box<dyn FnMut(isize)>, isize) {}
let s = String::new(); // Capture to make f !Copy
- let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+ let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
let _ = s.len();
};
f(Box::new(|a| {
error[E0507]: cannot move out of captured variable in an `FnMut` closure
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
|
-LL | let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
| ----- captured outer variable
...
LL | foo(f);
fn borrowed_mut(&mut self);
}
-fn borrowed_receiver(x: &Foo) {
+fn borrowed_receiver(x: &dyn Foo) {
x.borrowed();
x.borrowed_mut(); //~ ERROR cannot borrow
}
-fn borrowed_mut_receiver(x: &mut Foo) {
+fn borrowed_mut_receiver(x: &mut dyn Foo) {
x.borrowed();
x.borrowed_mut();
}
-fn owned_receiver(x: Box<Foo>) {
+fn owned_receiver(x: Box<dyn Foo>) {
x.borrowed();
x.borrowed_mut(); //~ ERROR cannot borrow
}
-fn mut_owned_receiver(mut x: Box<Foo>) {
+fn mut_owned_receiver(mut x: Box<dyn Foo>) {
x.borrowed();
x.borrowed_mut();
}
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
--> $DIR/borrowck-object-mutability.rs:8:5
|
-LL | fn borrowed_receiver(x: &Foo) {
- | ---- help: consider changing this to be a mutable reference: `&mut dyn Foo`
+LL | fn borrowed_receiver(x: &dyn Foo) {
+ | -------- help: consider changing this to be a mutable reference: `&mut dyn Foo`
LL | x.borrowed();
LL | x.borrowed_mut();
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
--> $DIR/borrowck-object-mutability.rs:18:5
|
-LL | fn owned_receiver(x: Box<Foo>) {
+LL | fn owned_receiver(x: Box<dyn Foo>) {
| - help: consider changing this to be mutable: `mut x`
LL | x.borrowed();
LL | x.borrowed_mut();
fn short<'b>(&'b self) -> isize;
}
-fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) { loop { } }
+fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) { loop { } }
trait MakerTrait {
fn mk() -> Self;
MakerTrait::mk()
}
-impl<'t> MakerTrait for Box<Trait<'t>+'static> {
- fn mk() -> Box<Trait<'t>+'static> { loop { } }
+impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> {
+ fn mk() -> Box<dyn Trait<'t>+'static> { loop { } }
}
pub fn main() {
- let m : Box<Trait+'static> = make_val();
+ let m : Box<dyn Trait+'static> = make_val();
assert_eq!(object_invoke1(&*m), (4,5));
//~^ ERROR `*m` does not live long enough
struct Container<'a> {
v: VecHolder,
- d: RefCell<Vec<Box<Obj+'a>>>,
+ d: RefCell<Vec<Box<dyn Obj+'a>>>,
}
impl<'a> Container<'a> {
// Still unsound Zook
trait Button { fn push(&self); }
-struct Zook<B> { button: B, trigger: Box<Trigger<B>+'static> }
+struct Zook<B> { button: B, trigger: Box<dyn Trigger<B>+'static> }
impl<B> Drop for Zook<B> {
fn drop(&mut self) {
{
let ss: &isize = &id(1);
//~^ ERROR temporary value dropped while borrowed
- blah = box ss as Box<Foo>;
+ blah = box ss as Box<dyn Foo>;
}
}
fn get(&self) { }
}
-fn repeater3<'a,A:'a>(v: A) -> Box<Foo+'a> {
- box v as Box<Foo+'a>
+fn repeater3<'a,A:'a>(v: A) -> Box<dyn Foo + 'a> {
+ box v as Box<dyn Foo+'a>
}
fn main() {
struct Guard<'a> {
- f: Box<Fn() + Send + 'a>,
+ f: Box<dyn Fn() + Send + 'a>,
}
fn scoped<'a, F: Fn() + Send + 'a>(f: F) -> Guard<'a> {
--- /dev/null
+struct Bravery {
+ guts: String,
+ brains: String,
+}
+
+fn main() {
+ let guts = "mettle";
+ let _ = Bravery {
+ guts, //~ ERROR mismatched types
+ brains: guts.clone(), //~ ERROR mismatched types
+ };
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-52820.rs:9:9
+ |
+LL | guts,
+ | ^^^^
+ | |
+ | expected struct `std::string::String`, found &str
+ | help: try using a conversion method: `guts: guts.to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `&str`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-52820.rs:10:17
+ |
+LL | brains: guts.clone(),
+ | ^^^^^^^^^^^^
+ | |
+ | expected struct `std::string::String`, found &str
+ | help: try using a conversion method: `guts.to_string()`
+ |
+ = note: expected type `std::string::String`
+ found type `&str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
type C;
}
pub struct Foo {
- i: Box<T<usize, usize, usize, usize, B=usize>>,
+ i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
//~^ ERROR must be specified
//~| ERROR wrong number of type arguments
}
error[E0107]: wrong number of type arguments: expected 2, found 4
- --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:28
+ --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:32
|
-LL | i: Box<T<usize, usize, usize, usize, B=usize>>,
- | ^^^^^ ^^^^^ unexpected type argument
- | |
- | unexpected type argument
+LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
+ | ^^^^^ ^^^^^ unexpected type argument
+ | |
+ | unexpected type argument
error[E0191]: the value of the associated types `A` (from the trait `T`), `C` (from the trait `T`) must be specified
--> $DIR/use-type-argument-instead-of-assoc-type.rs:7:12
LL | type C;
| ------- `C` defined here
...
-LL | i: Box<T<usize, usize, usize, usize, B=usize>>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| associated type `A` must be specified
| associated type `C` must be specified
help: if you meant to specify the associated types, write
|
-LL | i: Box<T<usize, usize, A = usize, C = usize, B=usize>>,
- | ^^^^^^^^^ ^^^^^^^^^
+LL | i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
+ | ^^^^^^^^^ ^^^^^^^^^
error: aborting due to 2 previous errors
--- /dev/null
+#![feature(rustc_attrs)]
+
+// This test is the same code as in ui/issue-53912.rs but this test checks that the symbol mangling
+// fix produces the correct result, whereas that test just checks that the reproduction compiles
+// successfully and doesn't segfault
+
+fn dummy() {}
+
+mod llvm {
+ pub(crate) struct Foo;
+}
+mod foo {
+ pub(crate) struct Foo<T>(T);
+
+ impl Foo<::llvm::Foo> {
+ #[rustc_symbol_name]
+//~^ ERROR _ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE
+ pub(crate) fn foo() {
+ for _ in 0..0 {
+ for _ in &[::dummy()] {
+ ::dummy();
+ ::dummy();
+ ::dummy();
+ }
+ }
+ }
+ }
+
+ pub(crate) fn foo() {
+ Foo::foo();
+ Foo::foo();
+ }
+}
+
+pub fn foo() {
+ foo::foo();
+}
+
+fn main() {}
--- /dev/null
+error: symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE)
+ --> $DIR/issue-60925.rs:16:9
+ |
+LL | #[rustc_symbol_name]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
#[allow(dead_code)]
struct Bar<T>(PhantomData<T>) where T: SendSyncAlias;
-impl EmptyAlias {}
+impl dyn EmptyAlias {}
impl<T: SendSyncAlias> Empty for T {}
trait ObjL<'l> {}
trait _9 = for<'a> ObjL<'a>;
trait _10 = for<'b> ObjL<'b>;
-type _T50 = _9 + _10;
+type _T50 = dyn _9 + _10;
//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
trait ObjT<T> {}
trait _11 = ObjT<for<'a> fn(&'a u8)>;
trait _12 = ObjT<for<'b> fn(&'b u8)>;
-type _T60 = _11 + _12;
+type _T60 = dyn _11 + _12;
//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225]
fn main() {}
| trait alias used in trait object type (first use)
error[E0225]: only auto traits can be used as additional traits in a trait object
- --> $DIR/trait-alias-no-duplicates.rs:117:18
+ --> $DIR/trait-alias-no-duplicates.rs:117:22
|
LL | trait _9 = for<'a> ObjL<'a>;
| ---------------- first non-auto trait
LL | trait _10 = for<'b> ObjL<'b>;
| ---------------- additional non-auto trait
-LL | type _T50 = _9 + _10;
- | -- ^^^ trait alias used in trait object type (additional use)
- | |
- | trait alias used in trait object type (first use)
+LL | type _T50 = dyn _9 + _10;
+ | -- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
error[E0225]: only auto traits can be used as additional traits in a trait object
- --> $DIR/trait-alias-no-duplicates.rs:123:19
+ --> $DIR/trait-alias-no-duplicates.rs:123:23
|
LL | trait _11 = ObjT<for<'a> fn(&'a u8)>;
| ------------------------ first non-auto trait
LL | trait _12 = ObjT<for<'b> fn(&'b u8)>;
| ------------------------ additional non-auto trait
-LL | type _T60 = _11 + _12;
- | --- ^^^ trait alias used in trait object type (additional use)
- | |
- | trait alias used in trait object type (first use)
+LL | type _T60 = dyn _11 + _12;
+ | --- ^^^ trait alias used in trait object type (additional use)
+ | |
+ | trait alias used in trait object type (first use)
error: aborting due to 27 previous errors
fn foo(_x: Foo + Send) {
//~^ ERROR the size for values of type
+ //~| WARN trait objects without an explicit `dyn` are deprecated
}
fn main() { }
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/trait-bounds-not-on-bare-trait.rs:7:12
+ |
+LL | fn foo(_x: Foo + Send) {
+ | ^^^^^^^^^^ help: use `dyn`: `dyn Foo + Send`
+ |
+ = note: #[warn(bare_trait_objects)] on by default
+
error[E0277]: the size for values of type `(dyn Foo + std::marker::Send + 'static)` cannot be known at compilation time
--> $DIR/trait-bounds-not-on-bare-trait.rs:7:8
|
trait Foo {}
-fn a(_x: Box<Foo+Send>) {
+fn a(_x: Box<dyn Foo + Send>) {
}
-fn b(_x: &'static (Foo+'static)) {
+fn b(_x: &'static (dyn Foo + 'static)) {
}
-fn c(x: Box<Foo+Sync>) {
+fn c(x: Box<dyn Foo + Sync>) {
a(x); //~ ERROR mismatched types
}
-fn d(x: &'static (Foo+Sync)) {
+fn d(x: &'static (dyn Foo + Sync)) {
b(x);
}
}
fn main() {
- let s: Box<Trait<isize>> = Box::new(Struct { person: "Fred" });
+ let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
//~^ ERROR `Struct: Trait<isize>` is not satisfied
s.f(1);
}
error[E0277]: the trait bound `Struct: Trait<isize>` is not satisfied
- --> $DIR/trait-coercion-generic-bad.rs:16:32
+ --> $DIR/trait-coercion-generic-bad.rs:16:36
|
-LL | let s: Box<Trait<isize>> = Box::new(Struct { person: "Fred" });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
+LL | let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
|
= help: the following implementations were found:
<Struct as Trait<&'static str>>
fn main() {
let person = "Fred".to_string();
let person: &str = &person; //~ ERROR `person` does not live long enough
- let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
+ let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
}
| |
| borrowed value does not live long enough
| assignment requires that `person` is borrowed for `'static`
-LL | let s: Box<Trait<&'static str>> = Box::new(Struct { person: person });
+LL | let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
LL | }
| - `person` dropped here while still borrowed
trait T {}
-impl<'a> T+'a {
+impl<'a> dyn T + 'a {
fn foo(&self) {}
}
S.b(); //~ ERROR no method named `b` found for type `S` in the current scope
S.c(); // OK
// a, b, c are resolved as inherent items, their traits don't need to be in scope
- let c = &S as &C;
+ let c = &S as &dyn C;
c.a(); //~ ERROR method `a` is private
c.b(); // OK
c.c(); // OK
let _: T::C; // OK
// Associated types, bindings
- let _: assoc_ty::B<
+ let _: dyn assoc_ty::B<
B = u8, // OK
>;
- let _: C<
+ let _: dyn C<
A = u8, //~ ERROR associated type `A` is private
B = u8, // OK
C = u8, // OK
impl Trait for Struct {}
trait Trait {}
-type Send1 = Trait + Send;
-type Send2 = Trait + Send + Send;
+type Send1 = dyn Trait + Send;
+type Send2 = dyn Trait + Send + Send;
fn main () {}
-impl Trait + Send {
+impl dyn Trait + Send {
fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
}
-impl Trait + Send + Send {
+impl dyn Trait + Send + Send {
fn test(&self) { println!("two"); }
}
}
fn main() {
- m!(Copy + Send + 'static); //~ ERROR the trait `std::marker::Copy` cannot be made into an object
- m!('static + Send);
- m!('static +); //~ ERROR at least one non-builtin trait is required for an object type
+ m!(dyn Copy + Send + 'static);
+ //~^ ERROR the trait `std::marker::Copy` cannot be made into an object
+ m!(dyn 'static + Send);
+ m!(dyn 'static +); //~ ERROR at least one non-builtin trait is required for an object type
}
error[E0224]: at least one non-builtin trait is required for an object type
- --> $DIR/trait-object-macro-matcher.rs:10:8
+ --> $DIR/trait-object-macro-matcher.rs:11:8
|
-LL | m!('static +);
- | ^^^^^^^^^
+LL | m!(dyn 'static +);
+ | ^^^^^^^^^^^^^
error[E0038]: the trait `std::marker::Copy` cannot be made into an object
--> $DIR/trait-object-macro-matcher.rs:8:8
|
-LL | m!(Copy + Send + 'static);
- | ^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
+LL | m!(dyn Copy + Send + 'static);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
}
fn main() {
- let _: &Tr = &St; //~ ERROR E0038
+ let _: &dyn Tr = &St; //~ ERROR E0038
//~^ ERROR E0038
}
error[E0038]: the trait `Tr` cannot be made into an object
- --> $DIR/trait-object-safety.rs:15:18
+ --> $DIR/trait-object-safety.rs:15:22
|
-LL | let _: &Tr = &St;
- | ^^^ the trait `Tr` cannot be made into an object
+LL | let _: &dyn Tr = &St;
+ | ^^^ the trait `Tr` cannot be made into an object
|
= note: method `foo` has no receiver
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
error[E0038]: the trait `Tr` cannot be made into an object
--> $DIR/trait-object-safety.rs:15:12
|
-LL | let _: &Tr = &St;
- | ^^^ the trait `Tr` cannot be made into an object
+LL | let _: &dyn Tr = &St;
+ | ^^^^^^^ the trait `Tr` cannot be made into an object
|
= note: method `foo` has no receiver
// `'static` is a lifetime, `'static +` is a type, `'a` is a type
fn g() where
'static: 'static,
- 'static +: 'static + Copy,
+ dyn 'static +: 'static + Copy,
//~^ ERROR at least one non-builtin trait is required for an object type
{}
error[E0224]: at least one non-builtin trait is required for an object type
--> $DIR/trait-object-vs-lifetime-2.rs:9:5
|
-LL | 'static +: 'static + Copy,
- | ^^^^^^^^^
+LL | dyn 'static +: 'static + Copy,
+ | ^^^^^^^^^^^^^
error: aborting due to previous error
fn main() {
// `'static` is a lifetime argument, `'static +` is a type argument
let _: S<'static, u8>;
- let _: S<'static, 'static +>;
+ let _: S<'static, dyn 'static +>;
//~^ at least one non-builtin trait is required for an object type
let _: S<'static, 'static>;
//~^ ERROR wrong number of lifetime arguments: expected 1, found 2
//~| ERROR wrong number of type arguments: expected 1, found 0
- let _: S<'static +, 'static>;
+ let _: S<dyn 'static +, 'static>;
//~^ ERROR lifetime arguments must be declared prior to type arguments
//~| ERROR at least one non-builtin trait is required for an object type
}
error: lifetime arguments must be declared prior to type arguments
- --> $DIR/trait-object-vs-lifetime.rs:14:25
+ --> $DIR/trait-object-vs-lifetime.rs:14:29
|
-LL | let _: S<'static +, 'static>;
- | ^^^^^^^
+LL | let _: S<dyn 'static +, 'static>;
+ | ^^^^^^^
error[E0224]: at least one non-builtin trait is required for an object type
--> $DIR/trait-object-vs-lifetime.rs:9:23
|
-LL | let _: S<'static, 'static +>;
- | ^^^^^^^^^
+LL | let _: S<'static, dyn 'static +>;
+ | ^^^^^^^^^^^^^
error[E0107]: wrong number of lifetime arguments: expected 1, found 2
--> $DIR/trait-object-vs-lifetime.rs:11:23
error[E0224]: at least one non-builtin trait is required for an object type
--> $DIR/trait-object-vs-lifetime.rs:14:14
|
-LL | let _: S<'static +, 'static>;
- | ^^^^^^^^^
+LL | let _: S<dyn 'static +, 'static>;
+ | ^^^^^^^^^^^^^
error: aborting due to 5 previous errors
fn main() {
10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
- (box 10 as Box<bar>).dup();
+ (box 10 as Box<dyn bar>).dup();
//~^ ERROR E0038
//~| ERROR E0038
}
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:16
|
-LL | (box 10 as Box<bar>).dup();
- | ^^^^^^^^ the trait `bar` cannot be made into an object
+LL | (box 10 as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^ the trait `bar` cannot be made into an object
|
= note: method `dup` references the `Self` type in its arguments or return type
= note: method `blah` has generic type parameters
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:6
|
-LL | (box 10 as Box<bar>).dup();
+LL | (box 10 as Box<dyn bar>).dup();
| ^^^^^^ the trait `bar` cannot be made into an object
|
= note: method `dup` references the `Self` type in its arguments or return type
impl CompareToInts for i64 { }
-fn with_obj(c: &CompareToInts) -> bool {
+fn with_obj(c: &dyn CompareToInts) -> bool {
c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
}
struct S(str, str) where str: Sized;
-fn unsized_local() where for<'a> T<A + 'a>: Sized {
- let x: T<A> = *(Box::new(T { x: 1 }) as Box<T<A>>);
+fn unsized_local() where for<'a> T<dyn A + 'a>: Sized {
+ let x: T<dyn A> = *(Box::new(T { x: 1 }) as Box<T<dyn A>>);
}
fn return_str() -> str where str: Sized {
= note: #[warn(trivial_bounds)] on by default
warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
- --> $DIR/trivial-bounds-inconsistent-sized.rs:16:45
+ --> $DIR/trivial-bounds-inconsistent-sized.rs:16:49
|
-LL | fn unsized_local() where for<'a> T<A + 'a>: Sized {
- | ^^^^^
+LL | fn unsized_local() where for<'a> T<dyn A + 'a>: Sized {
+ | ^^^^^
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:20:35
struct TwoStrs(str, str) where str: Sized;
-fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
- let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+fn unsized_local() where for<'a> Dst<dyn A + 'a>: Sized {
+ let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
}
fn return_str() -> str where str: Sized {
| ^^^^^
warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
- --> $DIR/trivial-bounds-inconsistent.rs:55:47
+ --> $DIR/trivial-bounds-inconsistent.rs:55:51
|
-LL | fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
- | ^^^^^
+LL | fn unsized_local() where for<'a> Dst<dyn A + 'a>: Sized {
+ | ^^^^^
warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:59:35
// unsize trait
let x: &Bar = &Bar;
- let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo`
- let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo`
- let _: &Foo = x;
- let _: *const Foo = x;
+ let _ = x as &dyn Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo`
+ let _ = x as *const dyn Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo`
+ let _: &dyn Foo = x;
+ let _: *const dyn Foo = x;
let x: &mut Bar = &mut Bar;
- let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo`
- let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo`
- let _: &mut Foo = x;
- let _: *mut Foo = x;
+ let _ = x as &mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo`
+ let _ = x as *mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo`
+ let _: &mut dyn Foo = x;
+ let _: *mut dyn Foo = x;
let x: Box<Bar> = Box::new(Bar);
- let _ = x as Box<Foo>; //~ERROR `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
+ let _ = x as Box<dyn Foo>; //~ERROR `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
let x: Box<Bar> = Box::new(Bar);
- let _: Box<Foo> = x;
+ let _: Box<dyn Foo> = x;
// functions
fn baz(_x: i32) {}
- let _ = &baz as &Fn(i32); //~ERROR `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
- let _: &Fn(i32) = &baz;
+ let _ = &baz as &dyn Fn(i32); //~ERROR `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
+ let _: &dyn Fn(i32) = &baz;
let x = |_x: i32| {};
- let _ = &x as &Fn(i32); //~ERROR trivial cast
- let _: &Fn(i32) = &x;
+ let _ = &x as &dyn Fn(i32); //~ERROR trivial cast
+ let _: &dyn Fn(i32) = &x;
}
// subtyping
error: trivial cast: `&Bar` as `&dyn Foo`
--> $DIR/trivial_casts.rs:52:13
|
-LL | let _ = x as &Foo;
- | ^^^^^^^^^
+LL | let _ = x as &dyn Foo;
+ | ^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&Bar` as `*const dyn Foo`
--> $DIR/trivial_casts.rs:53:13
|
-LL | let _ = x as *const Foo;
- | ^^^^^^^^^^^^^^^
+LL | let _ = x as *const dyn Foo;
+ | ^^^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&mut Bar` as `&mut dyn Foo`
--> $DIR/trivial_casts.rs:58:13
|
-LL | let _ = x as &mut Foo;
- | ^^^^^^^^^^^^^
+LL | let _ = x as &mut dyn Foo;
+ | ^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&mut Bar` as `*mut dyn Foo`
--> $DIR/trivial_casts.rs:59:13
|
-LL | let _ = x as *mut Foo;
- | ^^^^^^^^^^^^^
+LL | let _ = x as *mut dyn Foo;
+ | ^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
--> $DIR/trivial_casts.rs:64:13
|
-LL | let _ = x as Box<Foo>;
- | ^^^^^^^^^^^^^
+LL | let _ = x as Box<dyn Foo>;
+ | ^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
--> $DIR/trivial_casts.rs:70:13
|
-LL | let _ = &baz as &Fn(i32);
- | ^^^^^^^^^^^^^^^^
+LL | let _ = &baz as &dyn Fn(i32);
+ | ^^^^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:25]` as `&dyn std::ops::Fn(i32)`
--> $DIR/trivial_casts.rs:73:13
|
-LL | let _ = &x as &Fn(i32);
- | ^^^^^^^^^^^^^^
+LL | let _ = &x as &dyn Fn(i32);
+ | ^^^^^^^^^^^^^^^^^^
|
= help: cast can be replaced by coercion; this might require a temporary variable
//~^ ERROR mismatched types
//~| expected type `(isize, f64)`
//~| found type `(isize,)`
- //~| expected a tuple with 2 elements, found one with 1 elements
+ //~| expected a tuple with 2 elements, found one with 1 element
}
--> $DIR/tuple-arity-mismatch.rs:12:20
|
LL | let y = first ((1,));
- | ^^^^ expected a tuple with 2 elements, found one with 1 elements
+ | ^^^^ expected a tuple with 2 elements, found one with 1 element
|
= note: expected type `(isize, f64)`
found type `(isize,)`
// error-pattern:can't use generic parameters from outer function
fn foo<T>(x: T) {
- fn bar(f: Box<FnMut(T) -> T>) { }
+ fn bar(f: Box<dyn FnMut(T) -> T>) { }
}
fn main() { foo(1); }
error[E0401]: can't use generic parameters from outer function
- --> $DIR/type-arg-out-of-scope.rs:3:25
+ --> $DIR/type-arg-out-of-scope.rs:3:29
|
LL | fn foo<T>(x: T) {
| - type parameter from outer function
-LL | fn bar(f: Box<FnMut(T) -> T>) { }
- | --- ^ use of generic parameter from outer function
+LL | fn bar(f: Box<dyn FnMut(T) -> T>) { }
+ | --- ^ use of generic parameter from outer function
| |
| help: try using a local generic parameter instead: `bar<T>`
error[E0401]: can't use generic parameters from outer function
- --> $DIR/type-arg-out-of-scope.rs:3:31
+ --> $DIR/type-arg-out-of-scope.rs:3:35
|
LL | fn foo<T>(x: T) {
| - type parameter from outer function
-LL | fn bar(f: Box<FnMut(T) -> T>) { }
- | --- ^ use of generic parameter from outer function
+LL | fn bar(f: Box<dyn FnMut(T) -> T>) { }
+ | --- ^ use of generic parameter from outer function
| |
| help: try using a local generic parameter instead: `bar<T>`
const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
let s: [u32; l] = v.into_iter().collect();
//~^ ERROR evaluation of constant value failed
+ //~^^ ERROR a collection of type
}
LL | let s: [u32; l] = v.into_iter().collect();
| ^ referenced constant has errors
-error: aborting due to 2 previous errors
+error[E0277]: a collection of type `[u32; _]` cannot be built from an iterator over elements of type `{integer}`
+ --> $DIR/type-dependent-def-issue-49241.rs:4:37
+ |
+LL | let s: [u32; l] = v.into_iter().collect();
+ | ^^^^^^^ a collection of type `[u32; _]` cannot be built from `std::iter::Iterator<Item={integer}>`
+ |
+ = help: the trait `std::iter::FromIterator<{integer}>` is not implemented for `[u32; _]`
+
+error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0080, E0435.
+Some errors have detailed explanations: E0080, E0277, E0435.
For more information about an error, try `rustc --explain E0080`.
fn main() {
let x: i32 = 5;
- let y = x as MyAdd<i32>;
+ let y = x as dyn MyAdd<i32>;
//~^ ERROR E0038
//~| ERROR cast to unsized type: `i32` as `dyn MyAdd<i32>`
}
error[E0620]: cast to unsized type: `i32` as `dyn MyAdd<i32>`
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
|
-LL | let y = x as MyAdd<i32>;
- | ^^^^^^^^^^^^^^^
+LL | let y = x as dyn MyAdd<i32>;
+ | ^^^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13
|
-LL | let y = x as MyAdd<i32>;
+LL | let y = x as dyn MyAdd<i32>;
| ^
error[E0038]: the trait `MyAdd` cannot be made into an object
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
|
-LL | let y = x as MyAdd<i32>;
- | ^^^^^^^^^^ the trait `MyAdd` cannot be made into an object
+LL | let y = x as dyn MyAdd<i32>;
+ | ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object
|
= note: method `add` references the `Self` type in its arguments or return type
fn method(&self);
}
-fn foo(x: &Foo) { }
+fn foo(x: &dyn Foo) { }
//~^ ERROR the type parameter `T` must be explicitly specified
fn main() { }
error[E0393]: the type parameter `T` must be explicitly specified
- --> $DIR/type-parameter-defaults-referencing-Self.rs:10:12
+ --> $DIR/type-parameter-defaults-referencing-Self.rs:10:16
|
-LL | fn foo(x: &Foo) { }
- | ^^^ missing reference to `T`
+LL | fn foo(x: &dyn Foo) { }
+ | ^^^ missing reference to `T`
|
= note: because of the default `Self` reference, type parameters must be specified on object types
error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
- --> $SRC_DIR/libcore/mem.rs:LL:COL
+ --> $SRC_DIR/libcore/mem/mod.rs:LL:COL
|
LL | pub fn drop<T>(_x: T) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
fn foo1<T:Copy<U>, U>(x: T) {}
//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
-trait Trait: Copy<Send> {}
+trait Trait: Copy<dyn Send> {}
//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
struct MyStruct1<T: Copy<T>>;
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/typeck-builtin-bound-type-parameters.rs:4:19
|
-LL | trait Trait: Copy<Send> {}
- | ^^^^ unexpected type argument
+LL | trait Trait: Copy<dyn Send> {}
+ | ^^^^^^^^ unexpected type argument
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/typeck-builtin-bound-type-parameters.rs:7:26
}
fn main() {
- let x: Box<Foo(isize)>;
+ let x: Box<dyn Foo(isize)>;
//~^ ERROR parenthetical notation is only stable when used with `Fn`-family
// No errors with these:
- let x: Box<Fn(isize)>;
- let x: Box<FnMut(isize)>;
- let x: Box<FnOnce(isize)>;
+ let x: Box<dyn Fn(isize)>;
+ let x: Box<dyn FnMut(isize)>;
+ let x: Box<dyn FnOnce(isize)>;
}
error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits
- --> $DIR/unboxed-closure-feature-gate.rs:13:16
+ --> $DIR/unboxed-closure-feature-gate.rs:13:20
|
-LL | let x: Box<Foo(isize)>;
- | ^^^^^^^^^^
+LL | let x: Box<dyn Foo(isize)>;
+ | ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29625
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
fn test<'a,'b>() {
// Parens are equivalent to omitting default in angle.
- eq::< Foo<(isize,),Output=()>, Foo(isize) >();
+ eq::<dyn Foo<(isize,), Output=()>, dyn Foo(isize)>();
// In angle version, we supply something other than the default
- eq::< Foo<(isize,),isize,Output=()>, Foo(isize) >();
+ eq::<dyn Foo<(isize,), isize, Output=()>, dyn Foo(isize)>();
//~^ ERROR E0277
// Supply default explicitly.
- eq::< Foo<(isize,),(isize,),Output=()>, Foo(isize) >();
+ eq::<dyn Foo<(isize,), (isize,), Output=()>, dyn Foo(isize)>();
}
fn main() { }
error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq<dyn Foo<(isize,), Output = ()>>` is not satisfied
--> $DIR/unboxed-closure-sugar-default.rs:21:5
|
-LL | eq::< Foo<(isize,),isize,Output=()>, Foo(isize) >();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
+LL | eq::<dyn Foo<(isize,), isize, Output=()>, dyn Foo(isize)>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<dyn Foo<(isize,), Output = ()>>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>`
|
note: required by `eq`
--> $DIR/unboxed-closure-sugar-default.rs:14:1
fn test<'a,'b>() {
// No errors expected:
- eq::< Foo<(),Output=()>, Foo() >();
- eq::< Foo<(isize,),Output=()>, Foo(isize) >();
- eq::< Foo<(isize,usize),Output=()>, Foo(isize,usize) >();
- eq::< Foo<(isize,usize),Output=usize>, Foo(isize,usize) -> usize >();
- eq::< Foo<(&'a isize,&'b usize),Output=usize>, Foo(&'a isize,&'b usize) -> usize >();
+ eq::< dyn Foo<(),Output=()>, dyn Foo() >();
+ eq::< dyn Foo<(isize,),Output=()>, dyn Foo(isize) >();
+ eq::< dyn Foo<(isize,usize),Output=()>, dyn Foo(isize,usize) >();
+ eq::< dyn Foo<(isize,usize),Output=usize>, dyn Foo(isize,usize) -> usize >();
+ eq::< dyn Foo<(&'a isize,&'b usize),Output=usize>, dyn Foo(&'a isize,&'b usize) -> usize >();
// Test that anonymous regions in `()` form are equivalent
// to fresh bound regions, and that we can intermingle
// named and anonymous as we choose:
- eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
- for<'x,'y> Foo(&'x isize,&'y usize) -> usize >();
- eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
- for<'x> Foo(&'x isize,&usize) -> usize >();
- eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
- for<'y> Foo(&isize,&'y usize) -> usize >();
- eq::< for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
- Foo(&isize,&usize) -> usize >();
+ eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+ dyn for<'x,'y> Foo(&'x isize,&'y usize) -> usize >();
+ eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+ dyn for<'x> Foo(&'x isize,&usize) -> usize >();
+ eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+ dyn for<'y> Foo(&isize,&'y usize) -> usize >();
+ eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>,
+ dyn Foo(&isize,&usize) -> usize >();
// lifetime elision
- eq::< for<'x> Foo<(&'x isize,), Output=&'x isize>,
- Foo(&isize) -> &isize >();
+ eq::< dyn for<'x> Foo<(&'x isize,), Output=&'x isize>,
+ dyn Foo(&isize) -> &isize >();
// Errors expected:
- eq::< Foo<(),Output=()>,
- Foo(char) >();
+ eq::< dyn Foo<(),Output=()>,
+ dyn Foo(char) >();
//~^^ ERROR E0277
}
error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq<dyn Foo<(), Output = ()>>` is not satisfied
--> $DIR/unboxed-closure-sugar-equiv.rs:43:5
|
-LL | / eq::< Foo<(),Output=()>,
-LL | | Foo(char) >();
- | |___________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
+LL | / eq::< dyn Foo<(),Output=()>,
+LL | | dyn Foo(char) >();
+ | |_______________________________________________________________________^ the trait `Eq<dyn Foo<(), Output = ()>>` is not implemented for `dyn Foo<(char,), Output = ()>`
|
note: required by `eq`
--> $DIR/unboxed-closure-sugar-equiv.rs:16:1
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
fn main() {
- eq::< for<'a> Foo<(&'a isize,), Output=&'a isize>,
- Foo(&isize) -> &isize >();
- eq::< for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
- Foo(&isize) -> (&isize, &isize) >();
+ eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>,
+ dyn Foo(&isize) -> &isize >();
+ eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>,
+ dyn Foo(&isize) -> (&isize, &isize) >();
- let _: Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier
+ let _: dyn Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier
}
error[E0106]: missing lifetime specifier
- --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:35
+ --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39
|
-LL | let _: Foo(&isize, &usize) -> &usize;
- | ^ expected lifetime parameter
+LL | let _: dyn Foo(&isize, &usize) -> &usize;
+ | ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2
// Test that the `Fn` traits require `()` form without a feature gate.
-fn bar1(x: &Fn<(), Output=()>) {
+fn bar1(x: &dyn Fn<(), Output=()>) {
//~^ ERROR of `Fn`-family traits' type parameters is subject to change
}
error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead
- --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:13
+ --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:17
|
-LL | fn bar1(x: &Fn<(), Output=()>) {
- | ^^^^^^^^^^^^^^^^^
+LL | fn bar1(x: &dyn Fn<(), Output=()>) {
+ | ^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29625
= help: add #![feature(unboxed_closures)] to the crate attributes to enable
fn test<'a,'b>() {
// Parens are equivalent to omitting default in angle.
- eq::< Foo<(isize,),Output=()>, Foo(isize) >();
+ eq::< dyn Foo<(isize,),Output=()>, dyn Foo(isize) >();
// Here we specify 'static explicitly in angle-bracket version.
// Parenthesized winds up getting inferred.
- eq::< Foo<'static, (isize,),Output=()>, Foo(isize) >();
+ eq::< dyn Foo<'static, (isize,),Output=()>, dyn Foo(isize) >();
}
-fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
+fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
// Here, the omitted lifetimes are expanded to distinct things.
same_type(x, y)
error[E0107]: wrong number of lifetime arguments: expected 1, found 0
- --> $DIR/unboxed-closure-sugar-region.rs:30:43
+ --> $DIR/unboxed-closure-sugar-region.rs:30:51
|
-LL | fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
- | ^^^^^^^^^^ expected 1 lifetime argument
+LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
+ | ^^^^^^^^^^ expected 1 lifetime argument
error: aborting due to previous error
trait One<A> { fn foo(&self) -> A; }
-fn foo(_: &One()) //~ ERROR associated type `Output` not found for `One<()>`
+fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One<()>`
{}
fn main() { }
error[E0220]: associated type `Output` not found for `One<()>`
- --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:15
+ --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:19
|
-LL | fn foo(_: &One())
- | ^^ associated type `Output` not found
+LL | fn foo(_: &dyn One())
+ | ^^ associated type `Output` not found
error: aborting due to previous error
trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
-fn foo(_: &Three())
+fn foo(_: &dyn Three())
//~^ ERROR wrong number of type arguments
//~| ERROR associated type `Output` not found
{}
error[E0107]: wrong number of type arguments: expected 3, found 1
- --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:12
+ --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
|
-LL | fn foo(_: &Three())
- | ^^^^^^^ expected 3 type arguments
+LL | fn foo(_: &dyn Three())
+ | ^^^^^^^ expected 3 type arguments
error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>`
- --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:17
+ --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:21
|
-LL | fn foo(_: &Three())
- | ^^ associated type `Output` not found
+LL | fn foo(_: &dyn Three())
+ | ^^ associated type `Output` not found
error: aborting due to 2 previous errors
trait Zero { fn dummy(&self); }
-fn foo(_: Zero())
+fn foo(_: dyn Zero())
//~^ ERROR wrong number of type arguments
//~| ERROR associated type `Output` not found for `Zero`
{}
error[E0107]: wrong number of type arguments: expected 0, found 1
- --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+ --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:19
|
-LL | fn foo(_: Zero())
- | ^^ unexpected type argument
+LL | fn foo(_: dyn Zero())
+ | ^^ unexpected type argument
error[E0220]: associated type `Output` not found for `Zero`
- --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:15
+ --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:19
|
-LL | fn foo(_: Zero())
- | ^^ associated type `Output` not found
+LL | fn foo(_: dyn Zero())
+ | ^^ associated type `Output` not found
error: aborting due to 2 previous errors
// iteration, but it still doesn't work. The weird structure with
// the `Option` is to avoid giving any useful hints about the `Fn`
// kind via the expected type.
- let mut factorial: Option<Box<Fn(u32) -> u32>> = None;
+ let mut factorial: Option<Box<dyn Fn(u32) -> u32>> = None;
let f = |x: u32| -> u32 {
let g = factorial.as_ref().unwrap();
}
fn b() {
- let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
+ let mut factorial: Option<Box<dyn Fn(u32) -> u32 + 'static>> = None;
let f = |x: u32| -> u32 {
let g = factorial.as_ref().unwrap();
error[E0597]: `factorial` does not live long enough
--> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17
|
-LL | let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
- | ------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+LL | let mut factorial: Option<Box<dyn Fn(u32) -> u32 + 'static>> = None;
+ | ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
LL |
LL | let f = |x: u32| -> u32 {
| --------------- value captured here
error[E0506]: cannot assign to `factorial` because it is borrowed
--> $DIR/unboxed-closures-failed-recursive-fn-1.rs:33:5
|
-LL | let mut factorial: Option<Box<Fn(u32) -> u32 + 'static>> = None;
- | ------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
+LL | let mut factorial: Option<Box<dyn Fn(u32) -> u32 + 'static>> = None;
+ | ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
LL |
LL | let f = |x: u32| -> u32 {
| --------------- borrow of `factorial` occurs here
}
}
-impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
+impl<A,R,F : FnMut(&mut dyn FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R {
(self.func)(self, arg)
//~^ ERROR cannot borrow `*self` as mutable more than once at a time
}
}
-impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+impl<A,R,F : FnMut(&mut dyn FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
type Output = R;
extern "rust-call" fn call_once(mut self, args: (A,)) -> R {
self.call_mut(args)
fn main() {
let mut counter = 0;
- let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 {
+ let factorial = |recur: &mut dyn FnMut(u32) -> u32, arg: u32| -> u32 {
counter += 1;
if arg == 0 {1} else {arg * recur(arg-1)}
};
trait Meh<'a> {}
impl<'a> Meh<'a> for u8 {}
-fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR cannot be used here
+fn meh() -> Box<dyn for<'_> Meh<'_>> //~ ERROR cannot be used here
//~^ ERROR missing lifetime specifier
{
Box::new(5u8)
| ^^ `'_` is a reserved lifetime name
error[E0637]: `'_` cannot be used here
- --> $DIR/underscore-lifetime-binders.rs:10:21
+ --> $DIR/underscore-lifetime-binders.rs:10:25
|
-LL | fn meh() -> Box<for<'_> Meh<'_>>
- | ^^ `'_` is a reserved lifetime name
+LL | fn meh() -> Box<dyn for<'_> Meh<'_>>
+ | ^^ `'_` is a reserved lifetime name
error[E0106]: missing lifetime specifier
--> $DIR/underscore-lifetime-binders.rs:2:17
| ^^ expected lifetime parameter
error[E0106]: missing lifetime specifier
- --> $DIR/underscore-lifetime-binders.rs:10:29
+ --> $DIR/underscore-lifetime-binders.rs:10:33
|
-LL | fn meh() -> Box<for<'_> Meh<'_>>
- | ^^ help: consider giving it a 'static lifetime: `'static`
+LL | fn meh() -> Box<dyn for<'_> Meh<'_>>
+ | ^^ help: consider giving it a 'static lifetime: `'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
fn main() {
let x = box Bar { x: 10 };
- let y: Box<Foo> = x as Box<Foo>;
+ let y: Box<dyn Foo> = x as Box<dyn Foo>;
let _z = y.clone(); //~ ERROR no method named `clone` found
}
trait PathHelper3 {}
trait PathHelper4 {}
-struct Path1(PathHelper1);
-struct Path2(PathHelper2);
-struct Path3(PathHelper3);
-struct Path4(PathHelper4);
+struct Path1(dyn PathHelper1);
+struct Path2(dyn PathHelper2);
+struct Path3(dyn PathHelper3);
+struct Path4(dyn PathHelper4);
enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
// parameter
//~^ ERROR the size for values of type
// plain trait
- VM(Foo),
+ VM(dyn Foo),
//~^ ERROR the size for values of type
- VN{x: Bar},
+ VN{x: dyn Bar},
//~^ ERROR the size for values of type
- VO(isize, FooBar),
+ VO(isize, dyn FooBar),
//~^ ERROR the size for values of type
- VP{u: isize, x: BarFoo},
+ VP{u: isize, x: dyn BarFoo},
//~^ ERROR the size for values of type
// projected
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:53:8
|
-LL | VM(Foo),
- | ^^^ doesn't have a size known at compile-time
+LL | VM(dyn Foo),
+ | ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error[E0277]: the size for values of type `(dyn Bar + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:55:8
|
-LL | VN{x: Bar},
- | ^^^^^^ doesn't have a size known at compile-time
+LL | VN{x: dyn Bar},
+ | ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn Bar + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error[E0277]: the size for values of type `(dyn FooBar + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:57:15
|
-LL | VO(isize, FooBar),
- | ^^^^^^ doesn't have a size known at compile-time
+LL | VO(isize, dyn FooBar),
+ | ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn FooBar + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
error[E0277]: the size for values of type `(dyn BarFoo + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:59:18
|
-LL | VP{u: isize, x: BarFoo},
- | ^^^^^^^^^ doesn't have a size known at compile-time
+LL | VP{u: isize, x: dyn BarFoo},
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn BarFoo + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
}
struct List {
- list: Vec<Box<ToString+'static>> }
+ list: Vec<Box<dyn ToString + 'static>> }
impl List {
- fn push(&mut self, n: Box<ToString+'static>) {
+ fn push(&mut self, n: Box<dyn ToString + 'static>) {
self.list.push(n);
}
}
error: lifetime may not live long enough
--> $DIR/variance-contravariant-arg-object.rs:14:5
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
error: lifetime may not live long enough
--> $DIR/variance-contravariant-arg-object.rs:22:5
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
fn get(&self, t: T);
}
-fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
- -> Box<Get<&'min i32>>
+fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
+ -> Box<dyn Get<&'min i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
-fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
- -> Box<Get<&'max i32>>
+fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
+ -> Box<dyn Get<&'max i32>>
where 'max : 'min
{
// Previously OK:
note: the lifetime 'min as defined on the function body at 10:21...
--> $DIR/variance-contravariant-arg-object.rs:10:21
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
--> $DIR/variance-contravariant-arg-object.rs:10:27
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
error[E0308]: mismatched types
note: the lifetime 'min as defined on the function body at 17:21...
--> $DIR/variance-contravariant-arg-object.rs:17:21
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27
--> $DIR/variance-contravariant-arg-object.rs:17:27
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
error: aborting due to 2 previous errors
error: lifetime may not live long enough
--> $DIR/variance-covariant-arg-object.rs:15:5
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
error: lifetime may not live long enough
--> $DIR/variance-covariant-arg-object.rs:22:5
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
fn get(&self) -> T;
}
-fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
- -> Box<Get<&'min i32>>
+fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
+ -> Box<dyn Get<&'min i32>>
where 'max : 'min
{
// Previously OK, now an error as traits are invariant.
v //~ ERROR mismatched types
}
-fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
- -> Box<Get<&'max i32>>
+fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
+ -> Box<dyn Get<&'max i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
note: the lifetime 'min as defined on the function body at 10:21...
--> $DIR/variance-covariant-arg-object.rs:10:21
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27
--> $DIR/variance-covariant-arg-object.rs:10:27
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
error[E0308]: mismatched types
note: the lifetime 'min as defined on the function body at 18:21...
--> $DIR/variance-covariant-arg-object.rs:18:21
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 18:27
--> $DIR/variance-covariant-arg-object.rs:18:27
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
error: aborting due to 2 previous errors
error: lifetime may not live long enough
--> $DIR/variance-invariant-arg-object.rs:11:5
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
error: lifetime may not live long enough
--> $DIR/variance-invariant-arg-object.rs:18:5
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ---- ---- lifetime `'max` defined here
| |
| lifetime `'min` defined here
fn get(&self, t: T) -> T;
}
-fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
- -> Box<Get<&'min i32>>
+fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
+ -> Box<dyn Get<&'min i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
-fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
- -> Box<Get<&'max i32>>
+fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
+ -> Box<dyn Get<&'max i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
note: the lifetime 'min as defined on the function body at 7:21...
--> $DIR/variance-invariant-arg-object.rs:7:21
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27
--> $DIR/variance-invariant-arg-object.rs:7:27
|
-LL | fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+LL | fn get_min_from_max<'min, 'max>(v: Box<dyn Get<&'max i32>>)
| ^^^^
error[E0308]: mismatched types
note: the lifetime 'min as defined on the function body at 14:21...
--> $DIR/variance-invariant-arg-object.rs:14:21
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 14:27
--> $DIR/variance-invariant-arg-object.rs:14:27
|
-LL | fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+LL | fn get_max_from_min<'min, 'max, G>(v: Box<dyn Get<&'min i32>>)
| ^^^^
error: aborting due to 2 previous errors
// get an invariant result for `'a`.
#[rustc_variance]
struct Foo<'a> { //~ ERROR [o]
- x: Box<Fn(i32) -> &'a i32 + 'static>
+ x: Box<dyn Fn(i32) -> &'a i32 + 'static>
}
fn main() {
--> $DIR/variance-object-types.rs:11:1
|
LL | / struct Foo<'a> {
-LL | | x: Box<Fn(i32) -> &'a i32 + 'static>
+LL | | x: Box<dyn Fn(i32) -> &'a i32 + 'static>
LL | | }
| |_^
#[rustc_variance]
struct TOption<'a> { //~ ERROR [-]
- v: Option<Box<T + 'a>>,
+ v: Option<Box<dyn T + 'a>>,
}
fn main() { }
--> $DIR/variance-trait-object-bound.rs:14:1
|
LL | / struct TOption<'a> {
-LL | | v: Option<Box<T + 'a>>,
+LL | | v: Option<Box<dyn T + 'a>>,
LL | | }
| |_^
#[rustc_variance]
struct TestObject<A, R> { //~ ERROR [o, o]
- n: Box<Setter<A>+Send>,
- m: Box<Getter<R>+Send>,
+ n: Box<dyn Setter<A>+Send>,
+ m: Box<dyn Getter<R>+Send>,
}
fn main() {}
--> $DIR/variance-types-bounds.rs:38:1
|
LL | / struct TestObject<A, R> {
-LL | | n: Box<Setter<A>+Send>,
-LL | | m: Box<Getter<R>+Send>,
+LL | | n: Box<dyn Setter<A>+Send>,
+LL | | m: Box<dyn Getter<R>+Send>,
LL | | }
| |_^
struct Foo<T> {
// needs T: 'static
- x: Object<&'static T> //~ ERROR E0310
+ x: dyn Object<&'static T> //~ ERROR E0310
}
LL | struct Foo<T> {
| - help: consider adding an explicit lifetime bound `T: 'static`...
LL | // needs T: 'static
-LL | x: Object<&'static T>
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | x: dyn Object<&'static T>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that the reference type `&'static T` does not outlive the data it points at
--> $DIR/wf-in-obj-type-static.rs:14:5
|
-LL | x: Object<&'static T>
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | x: dyn Object<&'static T>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
struct Bar<T> {
// needs T: Copy
- x: Object<MustBeCopy<T>> //~ ERROR E0277
+ x: dyn Object<MustBeCopy<T>> //~ ERROR E0277
}
fn main() { }
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/wf-in-obj-type-trait.rs:11:5
|
-LL | x: Object<MustBeCopy<T>>
- | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+LL | x: dyn Object<MustBeCopy<T>>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
note: required by `MustBeCopy`
}
fn main() {
- let _x: &A; //~ ERROR E0038
+ let _x: &dyn A; //~ ERROR E0038
}
error[E0038]: the trait `A` cannot be made into an object
--> $DIR/wf-object-safe.rs:9:13
|
-LL | let _x: &A;
- | ^^ the trait `A` cannot be made into an object
+LL | let _x: &dyn A;
+ | ^^^^^^ the trait `A` cannot be made into an object
|
= note: method `foo` references the `Self` type in its arguments or return type
trait Baz<T> { }
impl<'a, T> Trait<'a, T> for u32 {
- type Out = &'a Baz<T>; //~ ERROR `T` may not live long enough
+ type Out = &'a dyn Baz<T>; //~ ERROR `T` may not live long enough
}
fn main() { }
|
LL | impl<'a, T> Trait<'a, T> for u32 {
| - help: consider adding an explicit lifetime bound `T: 'a`...
-LL | type Out = &'a Baz<T>;
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | type Out = &'a dyn Baz<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
--> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
|
-LL | type Out = &'a Baz<T>;
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | type Out = &'a dyn Baz<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
trait Trait2<'a, 'b> {}
fn f() where
- for<'a> Trait1<'a>: Trait1<'a>, // OK
- (for<'a> Trait1<'a>): Trait1<'a>,
+ for<'a> dyn Trait1<'a>: Trait1<'a>, // OK
+ (dyn for<'a> Trait1<'a>): Trait1<'a>,
//~^ ERROR use of undeclared lifetime name `'a`
- for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+ for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
//~^ ERROR use of undeclared lifetime name `'b`
//~| ERROR nested quantification of lifetimes
{}
error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/where-lifetime-resolution.rs:6:34
+ --> $DIR/where-lifetime-resolution.rs:6:38
|
-LL | (for<'a> Trait1<'a>): Trait1<'a>,
- | ^^ undeclared lifetime
+LL | (dyn for<'a> Trait1<'a>): Trait1<'a>,
+ | ^^ undeclared lifetime
error[E0316]: nested quantification of lifetimes
- --> $DIR/where-lifetime-resolution.rs:8:13
+ --> $DIR/where-lifetime-resolution.rs:8:17
|
-LL | for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0261]: use of undeclared lifetime name `'b`
- --> $DIR/where-lifetime-resolution.rs:8:48
+ --> $DIR/where-lifetime-resolution.rs:8:52
|
-LL | for<'a> for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
- | ^^ undeclared lifetime
+LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+ | ^^ undeclared lifetime
error: aborting due to 3 previous errors
-Subproject commit 46e64911ad43c519c61d22afef7f82625dd9c4a8
+Subproject commit fb33fad08e8f08c032b443bab0df299ce22fe61b