Merge branch 'master' into rusty-hermit
This commit is contained in:
commit
b6801b7dcd
1077 changed files with 17752 additions and 10318 deletions
|
|
@ -1,40 +1,3 @@
|
|||
# The Rust Code of Conduct
|
||||
|
||||
A version of this document [can be found online](https://www.rust-lang.org/conduct.html).
|
||||
|
||||
## Conduct
|
||||
|
||||
**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org)
|
||||
|
||||
* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic.
|
||||
* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all.
|
||||
* Please be kind and courteous. There's no need to be mean or rude.
|
||||
* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
|
||||
* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
|
||||
* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
|
||||
* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
|
||||
* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.
|
||||
|
||||
## Moderation
|
||||
|
||||
|
||||
These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team].
|
||||
|
||||
1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.)
|
||||
2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed.
|
||||
3. Moderators will first respond to such remarks with a warning.
|
||||
4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off.
|
||||
5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded.
|
||||
6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology.
|
||||
7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed.
|
||||
8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others.
|
||||
|
||||
In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.
|
||||
|
||||
And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.
|
||||
|
||||
The enforcement policies listed above apply to all official Rust venues; including all communication channels (Rust Discord server, Rust Zulip server); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
|
||||
|
||||
*Adapted from the [Node.js Policy on Trolling](https://blog.izs.me/2012/08/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
|
||||
|
||||
[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
|
||||
The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html).
|
||||
|
|
|
|||
209
Cargo.lock
209
Cargo.lock
|
|
@ -107,6 +107,12 @@ dependencies = [
|
|||
"winapi 0.3.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.37"
|
||||
|
|
@ -550,9 +556,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "compiletest_rs"
|
||||
version = "0.3.23"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb783fe7afb90ec3d3e49ccaf9196d29ab63c6ed61d4b0695839daa580ae3a3d"
|
||||
checksum = "676a74b493d50ac33cacd83fd536597e6b52c0b46b9856f7b9c809d82fef4ac0"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"filetime",
|
||||
|
|
@ -659,6 +665,16 @@ dependencies = [
|
|||
"crossbeam-utils 0.6.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.7.2",
|
||||
"crossbeam-utils 0.6.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.3.1"
|
||||
|
|
@ -993,7 +1009,7 @@ dependencies = [
|
|||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.12",
|
||||
"syn 0.15.35",
|
||||
"synstructure",
|
||||
"synstructure 0.10.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1259,7 +1275,7 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"hashbrown 0.5.0",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"pest",
|
||||
|
|
@ -1276,10 +1292,19 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1316,9 +1341,9 @@ checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
|
|||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3"
|
||||
checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8"
|
||||
dependencies = [
|
||||
"scopeguard 1.0.0",
|
||||
"winapi 0.3.6",
|
||||
|
|
@ -2643,9 +2668,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "racer"
|
||||
version = "2.1.27"
|
||||
version = "2.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae"
|
||||
checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap",
|
||||
|
|
@ -2802,22 +2827,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
|
||||
checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.6.3",
|
||||
"crossbeam-deque 0.7.1",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
|
||||
checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.6.3",
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils 0.6.5",
|
||||
"lazy_static 1.3.0",
|
||||
|
|
@ -3085,8 +3110,8 @@ dependencies = [
|
|||
"num_cpus",
|
||||
"parking_lot 0.9.0",
|
||||
"polonius-engine",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc-rayon 0.3.0",
|
||||
"rustc-rayon-core 0.3.0",
|
||||
"rustc_apfloat",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3098,14 +3123,15 @@ dependencies = [
|
|||
"serialize",
|
||||
"smallvec",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-arena"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5"
|
||||
checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009"
|
||||
dependencies = [
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"smallvec",
|
||||
|
|
@ -3113,15 +3139,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-graphviz"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142"
|
||||
checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_data_structures"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36"
|
||||
checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils 0.6.5",
|
||||
|
|
@ -3130,21 +3156,22 @@ dependencies = [
|
|||
"jobserver",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"parking_lot 0.7.1",
|
||||
"parking_lot 0.9.0",
|
||||
"rustc-ap-graphviz",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-serialize",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc-rayon 0.2.0",
|
||||
"rustc-rayon-core 0.2.0",
|
||||
"smallvec",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_errors"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333"
|
||||
checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"atty",
|
||||
|
|
@ -3158,45 +3185,56 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_lexer"
|
||||
version = "583.0.0"
|
||||
name = "rustc-ap-rustc_index"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305"
|
||||
checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea"
|
||||
dependencies = [
|
||||
"rustc-ap-serialize",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_lexer"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_macros"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f"
|
||||
checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0"
|
||||
dependencies = [
|
||||
"itertools 0.8.0",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.12",
|
||||
"syn 0.15.35",
|
||||
"synstructure",
|
||||
"synstructure 0.10.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_target"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2"
|
||||
checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-serialize",
|
||||
"rustc-ap-syntax_pos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-serialize"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6"
|
||||
checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"smallvec",
|
||||
|
|
@ -3204,17 +3242,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-syntax"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9"
|
||||
checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_errors",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-rustc_lexer",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_target",
|
||||
"rustc-ap-serialize",
|
||||
"rustc-ap-syntax_pos",
|
||||
|
|
@ -3224,13 +3262,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-syntax_pos"
|
||||
version = "583.0.0"
|
||||
version = "606.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213"
|
||||
checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"rustc-ap-arena",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-serialize",
|
||||
"scoped-tls",
|
||||
|
|
@ -3274,7 +3313,18 @@ checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363"
|
|||
dependencies = [
|
||||
"crossbeam-deque 0.2.0",
|
||||
"either",
|
||||
"rustc-rayon-core",
|
||||
"rustc-rayon-core 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"either",
|
||||
"rustc-rayon-core 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3289,6 +3339,19 @@ dependencies = [
|
|||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-rayon-core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils 0.6.5",
|
||||
"lazy_static 1.3.0",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
|
|
@ -3376,6 +3439,7 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"serialize",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
"tempfile",
|
||||
]
|
||||
|
|
@ -3409,8 +3473,8 @@ dependencies = [
|
|||
"log",
|
||||
"parking_lot 0.9.0",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
"rustc-rayon 0.3.0",
|
||||
"rustc-rayon-core 0.3.0",
|
||||
"rustc_index",
|
||||
"serialize",
|
||||
"smallvec",
|
||||
|
|
@ -3490,7 +3554,7 @@ dependencies = [
|
|||
"log",
|
||||
"once_cell",
|
||||
"rustc",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon 0.3.0",
|
||||
"rustc_codegen_ssa",
|
||||
"rustc_codegen_utils",
|
||||
"rustc_data_structures",
|
||||
|
|
@ -3508,6 +3572,7 @@ dependencies = [
|
|||
"serialize",
|
||||
"smallvec",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_ext",
|
||||
"syntax_pos",
|
||||
"tempfile",
|
||||
|
|
@ -3557,10 +3622,10 @@ name = "rustc_macros"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools 0.8.0",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.12",
|
||||
"syn 0.15.35",
|
||||
"synstructure",
|
||||
"proc-macro2 1.0.3",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.5",
|
||||
"synstructure 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3579,6 +3644,7 @@ dependencies = [
|
|||
"smallvec",
|
||||
"stable_deref_trait",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
|
|
@ -3624,7 +3690,10 @@ dependencies = [
|
|||
"rustc",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_index",
|
||||
"rustc_target",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
|
|
@ -3642,6 +3711,7 @@ dependencies = [
|
|||
"rustc",
|
||||
"rustc_metadata",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
|
|
@ -3670,6 +3740,7 @@ dependencies = [
|
|||
"rustc_metadata",
|
||||
"smallvec",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
|
|
@ -3767,7 +3838,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"minifier",
|
||||
"pulldown-cmark 0.5.3",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon 0.3.0",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
|
|
@ -3806,7 +3877,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.4.8"
|
||||
version = "1.4.9"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"bytecount",
|
||||
|
|
@ -4254,6 +4325,18 @@ dependencies = [
|
|||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.3",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.5",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntax"
|
||||
version = "0.0.0"
|
||||
|
|
@ -4272,6 +4355,25 @@ dependencies = [
|
|||
"syntax_pos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntax_expand"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static 1.3.0",
|
||||
"log",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_index",
|
||||
"rustc_lexer",
|
||||
"rustc_target",
|
||||
"scoped-tls",
|
||||
"serialize",
|
||||
"smallvec",
|
||||
"syntax",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntax_ext"
|
||||
version = "0.0.0"
|
||||
|
|
@ -4283,6 +4385,7 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"smallvec",
|
||||
"syntax",
|
||||
"syntax_expand",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -817,12 +817,22 @@ impl<'a> Builder<'a> {
|
|||
|
||||
let mut rustflags = Rustflags::new(&target);
|
||||
if stage != 0 {
|
||||
if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") {
|
||||
cargo.args(s.split_whitespace());
|
||||
}
|
||||
rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP");
|
||||
} else {
|
||||
if let Ok(s) = env::var("CARGOFLAGS_BOOTSTRAP") {
|
||||
cargo.args(s.split_whitespace());
|
||||
}
|
||||
rustflags.env("RUSTFLAGS_BOOTSTRAP");
|
||||
rustflags.arg("--cfg=bootstrap");
|
||||
}
|
||||
|
||||
if let Ok(s) = env::var("CARGOFLAGS") {
|
||||
cargo.args(s.split_whitespace());
|
||||
}
|
||||
|
||||
match mode {
|
||||
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {},
|
||||
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
|
||||
|
|
|
|||
|
|
@ -1126,7 +1126,7 @@ impl Build {
|
|||
}
|
||||
|
||||
let mut paths = Vec::new();
|
||||
let contents = t!(fs::read(stamp));
|
||||
let contents = t!(fs::read(stamp), &stamp);
|
||||
// This is the method we use for extracting paths from the stamp file passed to us. See
|
||||
// run_cargo for more information (in compile.rs).
|
||||
for part in contents.split(|b| *b == 0) {
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ impl Step for Llvm {
|
|||
.define("WITH_POLLY", "OFF")
|
||||
.define("LLVM_ENABLE_TERMINFO", "OFF")
|
||||
.define("LLVM_ENABLE_LIBEDIT", "OFF")
|
||||
.define("LLVM_ENABLE_BINDINGS", "OFF")
|
||||
.define("LLVM_ENABLE_Z3_SOLVER", "OFF")
|
||||
.define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
|
||||
.define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
|
||||
|
|
@ -169,15 +170,6 @@ impl Step for Llvm {
|
|||
}
|
||||
}
|
||||
|
||||
// By default, LLVM will automatically find OCaml and, if it finds it,
|
||||
// install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults
|
||||
// to /usr/bin/ocaml.
|
||||
// This causes problem for non-root builds of Rust. Side-step the issue
|
||||
// by setting LLVM_OCAML_INSTALL_PATH to a relative path, so it installs
|
||||
// in the prefix.
|
||||
cfg.define("LLVM_OCAML_INSTALL_PATH",
|
||||
env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into()));
|
||||
|
||||
let want_lldb = builder.config.lldb_enabled && !self.emscripten;
|
||||
|
||||
// This setting makes the LLVM tools link to the dynamic LLVM library,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@ macro_rules! t {
|
|||
Err(e) => panic!("{} failed with {}", stringify!($e), e),
|
||||
}
|
||||
};
|
||||
// it can show extra info in the second parameter
|
||||
($e:expr, $extra:expr) => {
|
||||
match $e {
|
||||
Ok(e) => e,
|
||||
Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
|
||||
|
|
|
|||
|
|
@ -124,14 +124,14 @@ jobs:
|
|||
IMAGE: dist-x86_64-netbsd
|
||||
DEPLOY: 1
|
||||
|
||||
asmjs:
|
||||
IMAGE: asmjs
|
||||
i686-gnu:
|
||||
IMAGE: i686-gnu
|
||||
i686-gnu-nopt:
|
||||
IMAGE: i686-gnu-nopt
|
||||
test-various:
|
||||
IMAGE: test-various
|
||||
wasm32:
|
||||
IMAGE: wasm32
|
||||
x86_64-gnu:
|
||||
IMAGE: x86_64-gnu
|
||||
x86_64-gnu-full-bootstrap:
|
||||
|
|
|
|||
|
|
@ -165,8 +165,7 @@ For targets: `arm-unknown-linux-gnueabihf`
|
|||
For targets: `armv7-unknown-linux-gnueabihf`
|
||||
|
||||
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
|
||||
- Path and misc options > Patches origin = Bundled, then local
|
||||
- Path and misc options > Local patch directory = /tmp/patches
|
||||
- Path and misc options > Patches origin = Bundled only
|
||||
- Target options > Target Architecture = arm
|
||||
- Target options > Suffix to the arch-part = v7
|
||||
- Target options > Architecture level = armv7-a -- (+)
|
||||
|
|
@ -174,9 +173,9 @@ For targets: `armv7-unknown-linux-gnueabihf`
|
|||
- Target options > Floating point = hardware (FPU) -- (\*)
|
||||
- Target options > Default instruction set mode = thumb -- (\*)
|
||||
- Operating System > Target OS = linux
|
||||
- Operating System > Linux kernel version = 3.2.72 -- Precise kernel
|
||||
- C-library > glibc version = 2.16.0
|
||||
- C compiler > gcc version = 5.2.0
|
||||
- Operating System > Linux kernel version = 3.2.101
|
||||
- C-library > glibc version = 2.17.0
|
||||
- C compiler > gcc version = 8.3.0
|
||||
- C compiler > C++ = ENABLE -- to cross compile LLVM
|
||||
|
||||
(\*) These options have been selected to match the configuration of the arm
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ ENV PATH=$PATH:/emsdk-portable
|
|||
ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/upstream/
|
||||
ENV EM_CONFIG=/emsdk-portable/.emscripten
|
||||
|
||||
ENV TARGETS=asmjs-unknown-emscripten
|
||||
|
||||
# Use -O1 optimizations in the link step to reduce time spent optimizing JS.
|
||||
ENV EMCC_CFLAGS=-O1
|
||||
|
||||
# Emscripten installation is user-specific
|
||||
ENV NO_CHANGE_USER=1
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
||||
# This is almost identical to the wasm32-unknown-emscripten target, so
|
||||
|
|
@ -3,12 +3,7 @@ FROM ubuntu:16.04
|
|||
COPY scripts/cross-apt-packages.sh /scripts/
|
||||
RUN sh /scripts/cross-apt-packages.sh
|
||||
|
||||
# Ubuntu 16.04 (this container) ships with make 4, but something in the
|
||||
# toolchains we build below chokes on that, so go back to make 3
|
||||
COPY scripts/make3.sh /scripts/
|
||||
RUN sh /scripts/make3.sh
|
||||
|
||||
COPY scripts/crosstool-ng.sh /scripts/
|
||||
COPY dist-armv7-linux/crosstool-ng.sh /scripts/
|
||||
RUN sh /scripts/crosstool-ng.sh
|
||||
|
||||
COPY scripts/rustbuild-setup.sh /scripts/
|
||||
|
|
@ -16,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh
|
|||
USER rustbuild
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY dist-armv7-linux/patches/ /tmp/patches/
|
||||
COPY dist-armv7-linux/build-toolchains.sh dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/
|
||||
RUN ./build-toolchains.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,32 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Crosstool-NG Configuration
|
||||
# crosstool-NG Configuration
|
||||
#
|
||||
CT_CONFIGURE_has_make381=y
|
||||
CT_CONFIGURE_has_xz=y
|
||||
CT_CONFIGURE_has_static_link=y
|
||||
CT_CONFIGURE_has_cxx11=y
|
||||
CT_CONFIGURE_has_wget=y
|
||||
CT_CONFIGURE_has_curl=y
|
||||
CT_CONFIGURE_has_make_3_81_or_newer=y
|
||||
CT_CONFIGURE_has_make_4_0_or_newer=y
|
||||
CT_CONFIGURE_has_libtool_2_4_or_newer=y
|
||||
CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
|
||||
CT_CONFIGURE_has_autoconf_2_65_or_newer=y
|
||||
CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
|
||||
CT_CONFIGURE_has_automake_1_15_or_newer=y
|
||||
CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
|
||||
CT_CONFIGURE_has_python_3_4_or_newer=y
|
||||
CT_CONFIGURE_has_bison_2_7_or_newer=y
|
||||
CT_CONFIGURE_has_python=y
|
||||
CT_CONFIGURE_has_dtc=y
|
||||
CT_CONFIGURE_has_svn=y
|
||||
CT_CONFIGURE_has_git=y
|
||||
CT_CONFIGURE_has_md5sum=y
|
||||
CT_CONFIGURE_has_sha1sum=y
|
||||
CT_CONFIGURE_has_sha256sum=y
|
||||
CT_CONFIGURE_has_sha512sum=y
|
||||
CT_CONFIGURE_has_install_with_strip_program=y
|
||||
CT_CONFIG_VERSION_CURRENT="3"
|
||||
CT_CONFIG_VERSION="3"
|
||||
CT_MODULES=y
|
||||
|
||||
#
|
||||
|
|
@ -21,40 +44,46 @@ CT_MODULES=y
|
|||
# Paths
|
||||
#
|
||||
CT_LOCAL_TARBALLS_DIR=""
|
||||
# CT_TARBALLS_BUILDROOT_LAYOUT is not set
|
||||
CT_WORK_DIR="${CT_TOP_DIR}/.build"
|
||||
CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
|
||||
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
|
||||
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
|
||||
CT_RM_RF_PREFIX_DIR=y
|
||||
CT_REMOVE_DOCS=y
|
||||
CT_INSTALL_DIR_RO=y
|
||||
CT_INSTALL_LICENSES=y
|
||||
CT_PREFIX_DIR_RO=y
|
||||
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
|
||||
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
|
||||
|
||||
#
|
||||
# Downloading
|
||||
#
|
||||
CT_DOWNLOAD_AGENT_WGET=y
|
||||
# CT_DOWNLOAD_AGENT_CURL is not set
|
||||
# CT_DOWNLOAD_AGENT_NONE is not set
|
||||
# CT_FORBID_DOWNLOAD is not set
|
||||
# CT_FORCE_DOWNLOAD is not set
|
||||
CT_CONNECT_TIMEOUT=10
|
||||
CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
|
||||
# CT_ONLY_DOWNLOAD is not set
|
||||
# CT_USE_MIRROR is not set
|
||||
CT_VERIFY_DOWNLOAD_DIGEST=y
|
||||
CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
|
||||
# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
|
||||
# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
|
||||
# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
|
||||
CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
|
||||
# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
|
||||
|
||||
#
|
||||
# Extracting
|
||||
#
|
||||
# CT_FORCE_EXTRACT is not set
|
||||
CT_OVERIDE_CONFIG_GUESS_SUB=y
|
||||
CT_OVERRIDE_CONFIG_GUESS_SUB=y
|
||||
# CT_ONLY_EXTRACT is not set
|
||||
# CT_PATCH_BUNDLED is not set
|
||||
# CT_PATCH_LOCAL is not set
|
||||
CT_PATCH_BUNDLED_LOCAL=y
|
||||
# CT_PATCH_LOCAL_BUNDLED is not set
|
||||
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
|
||||
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
|
||||
# CT_PATCH_NONE is not set
|
||||
CT_PATCH_ORDER="bundled,local"
|
||||
CT_PATCH_USE_LOCAL=y
|
||||
CT_LOCAL_PATCH_DIR="/tmp/patches"
|
||||
CT_PATCH_BUNDLED=y
|
||||
# CT_PATCH_BUNDLED_LOCAL is not set
|
||||
CT_PATCH_ORDER="bundled"
|
||||
|
||||
#
|
||||
# Build behavior
|
||||
|
|
@ -90,78 +119,29 @@ CT_LOG_FILE_COMPRESS=y
|
|||
#
|
||||
# Target options
|
||||
#
|
||||
# CT_ARCH_ALPHA is not set
|
||||
# CT_ARCH_ARC is not set
|
||||
CT_ARCH_ARM=y
|
||||
# CT_ARCH_AVR is not set
|
||||
# CT_ARCH_M68K is not set
|
||||
# CT_ARCH_MIPS is not set
|
||||
# CT_ARCH_NIOS2 is not set
|
||||
# CT_ARCH_POWERPC is not set
|
||||
# CT_ARCH_S390 is not set
|
||||
# CT_ARCH_SH is not set
|
||||
# CT_ARCH_SPARC is not set
|
||||
# CT_ARCH_X86 is not set
|
||||
# CT_ARCH_XTENSA is not set
|
||||
CT_ARCH="arm"
|
||||
CT_ARCH_SUPPORTS_BOTH_MMU=y
|
||||
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
|
||||
CT_ARCH_SUPPORTS_32=y
|
||||
CT_ARCH_SUPPORTS_64=y
|
||||
CT_ARCH_SUPPORTS_WITH_ARCH=y
|
||||
CT_ARCH_SUPPORTS_WITH_CPU=y
|
||||
CT_ARCH_SUPPORTS_WITH_TUNE=y
|
||||
CT_ARCH_SUPPORTS_WITH_FLOAT=y
|
||||
CT_ARCH_SUPPORTS_WITH_FPU=y
|
||||
CT_ARCH_SUPPORTS_SOFTFP=y
|
||||
CT_ARCH_DEFAULT_HAS_MMU=y
|
||||
CT_ARCH_DEFAULT_LE=y
|
||||
CT_ARCH_DEFAULT_32=y
|
||||
CT_ARCH_ARCH="armv7-a"
|
||||
CT_ARCH_CHOICE_KSYM="ARM"
|
||||
CT_ARCH_CPU=""
|
||||
CT_ARCH_TUNE=""
|
||||
CT_ARCH_FPU="vfpv3-d16"
|
||||
# CT_ARCH_BE is not set
|
||||
CT_ARCH_LE=y
|
||||
CT_ARCH_32=y
|
||||
# CT_ARCH_64 is not set
|
||||
CT_ARCH_BITNESS=32
|
||||
CT_ARCH_FLOAT_HW=y
|
||||
# CT_ARCH_FLOAT_SW is not set
|
||||
CT_TARGET_CFLAGS=""
|
||||
CT_TARGET_LDFLAGS=""
|
||||
# CT_ARCH_alpha is not set
|
||||
CT_ARCH_arm=y
|
||||
# CT_ARCH_avr is not set
|
||||
# CT_ARCH_m68k is not set
|
||||
# CT_ARCH_mips is not set
|
||||
# CT_ARCH_nios2 is not set
|
||||
# CT_ARCH_powerpc is not set
|
||||
# CT_ARCH_s390 is not set
|
||||
# CT_ARCH_sh is not set
|
||||
# CT_ARCH_sparc is not set
|
||||
# CT_ARCH_x86 is not set
|
||||
# CT_ARCH_xtensa is not set
|
||||
CT_ARCH_alpha_AVAILABLE=y
|
||||
CT_ARCH_arm_AVAILABLE=y
|
||||
CT_ARCH_avr_AVAILABLE=y
|
||||
CT_ARCH_m68k_AVAILABLE=y
|
||||
CT_ARCH_microblaze_AVAILABLE=y
|
||||
CT_ARCH_mips_AVAILABLE=y
|
||||
CT_ARCH_nios2_AVAILABLE=y
|
||||
CT_ARCH_powerpc_AVAILABLE=y
|
||||
CT_ARCH_s390_AVAILABLE=y
|
||||
CT_ARCH_sh_AVAILABLE=y
|
||||
CT_ARCH_sparc_AVAILABLE=y
|
||||
CT_ARCH_x86_AVAILABLE=y
|
||||
CT_ARCH_xtensa_AVAILABLE=y
|
||||
CT_ARCH_SUFFIX="v7"
|
||||
CT_ARCH_ARM_SHOW=y
|
||||
|
||||
#
|
||||
# Generic target options
|
||||
#
|
||||
# CT_MULTILIB is not set
|
||||
CT_ARCH_USE_MMU=y
|
||||
CT_ARCH_ENDIAN="little"
|
||||
|
||||
#
|
||||
# Target optimisations
|
||||
#
|
||||
CT_ARCH_EXCLUSIVE_WITH_CPU=y
|
||||
# CT_ARCH_FLOAT_AUTO is not set
|
||||
# CT_ARCH_FLOAT_SOFTFP is not set
|
||||
CT_ARCH_FLOAT="hard"
|
||||
|
||||
#
|
||||
# arm other options
|
||||
# Options for arm
|
||||
#
|
||||
CT_ARCH_ARM_PKG_KSYM=""
|
||||
CT_ARCH_ARM_MODE="thumb"
|
||||
# CT_ARCH_ARM_MODE_ARM is not set
|
||||
CT_ARCH_ARM_MODE_THUMB=y
|
||||
|
|
@ -169,6 +149,50 @@ CT_ARCH_ARM_MODE_THUMB=y
|
|||
CT_ARCH_ARM_EABI_FORCE=y
|
||||
CT_ARCH_ARM_EABI=y
|
||||
CT_ARCH_ARM_TUPLE_USE_EABIHF=y
|
||||
CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
|
||||
CT_ARCH_SUFFIX="v7"
|
||||
# CT_OMIT_TARGET_VENDOR is not set
|
||||
|
||||
#
|
||||
# Generic target options
|
||||
#
|
||||
# CT_MULTILIB is not set
|
||||
CT_DEMULTILIB=y
|
||||
CT_ARCH_SUPPORTS_BOTH_MMU=y
|
||||
CT_ARCH_DEFAULT_HAS_MMU=y
|
||||
CT_ARCH_USE_MMU=y
|
||||
CT_ARCH_SUPPORTS_FLAT_FORMAT=y
|
||||
CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
|
||||
CT_ARCH_DEFAULT_LE=y
|
||||
# CT_ARCH_BE is not set
|
||||
CT_ARCH_LE=y
|
||||
CT_ARCH_ENDIAN="little"
|
||||
CT_ARCH_SUPPORTS_32=y
|
||||
CT_ARCH_SUPPORTS_64=y
|
||||
CT_ARCH_DEFAULT_32=y
|
||||
CT_ARCH_BITNESS=32
|
||||
CT_ARCH_32=y
|
||||
# CT_ARCH_64 is not set
|
||||
|
||||
#
|
||||
# Target optimisations
|
||||
#
|
||||
CT_ARCH_SUPPORTS_WITH_ARCH=y
|
||||
CT_ARCH_SUPPORTS_WITH_CPU=y
|
||||
CT_ARCH_SUPPORTS_WITH_TUNE=y
|
||||
CT_ARCH_SUPPORTS_WITH_FLOAT=y
|
||||
CT_ARCH_SUPPORTS_WITH_FPU=y
|
||||
CT_ARCH_SUPPORTS_SOFTFP=y
|
||||
CT_ARCH_EXCLUSIVE_WITH_CPU=y
|
||||
CT_ARCH_ARCH="armv7-a"
|
||||
CT_ARCH_FPU="vfpv3-d16"
|
||||
# CT_ARCH_FLOAT_AUTO is not set
|
||||
CT_ARCH_FLOAT_HW=y
|
||||
# CT_ARCH_FLOAT_SOFTFP is not set
|
||||
# CT_ARCH_FLOAT_SW is not set
|
||||
CT_TARGET_CFLAGS=""
|
||||
CT_TARGET_LDFLAGS=""
|
||||
CT_ARCH_FLOAT="hard"
|
||||
|
||||
#
|
||||
# Toolchain options
|
||||
|
|
@ -182,7 +206,9 @@ CT_USE_SYSROOT=y
|
|||
CT_SYSROOT_NAME="sysroot"
|
||||
CT_SYSROOT_DIR_PREFIX=""
|
||||
CT_WANTS_STATIC_LINK=y
|
||||
CT_WANTS_STATIC_LINK_CXX=y
|
||||
# CT_STATIC_TOOLCHAIN is not set
|
||||
CT_SHOW_CT_VERSION=y
|
||||
CT_TOOLCHAIN_PKGVERSION=""
|
||||
CT_TOOLCHAIN_BUGURL=""
|
||||
|
||||
|
|
@ -216,126 +242,207 @@ CT_BUILD_SUFFIX=""
|
|||
# Operating System
|
||||
#
|
||||
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
|
||||
# CT_KERNEL_BARE_METAL is not set
|
||||
CT_KERNEL_LINUX=y
|
||||
CT_KERNEL="linux"
|
||||
CT_KERNEL_VERSION="3.2.72"
|
||||
# CT_KERNEL_bare_metal is not set
|
||||
CT_KERNEL_linux=y
|
||||
CT_KERNEL_bare_metal_AVAILABLE=y
|
||||
CT_KERNEL_linux_AVAILABLE=y
|
||||
# CT_KERNEL_V_4_3 is not set
|
||||
# CT_KERNEL_V_4_2 is not set
|
||||
# CT_KERNEL_V_4_1 is not set
|
||||
# CT_KERNEL_V_3_18 is not set
|
||||
# CT_KERNEL_V_3_14 is not set
|
||||
# CT_KERNEL_V_3_12 is not set
|
||||
# CT_KERNEL_V_3_10 is not set
|
||||
# CT_KERNEL_V_3_4 is not set
|
||||
CT_KERNEL_V_3_2=y
|
||||
# CT_KERNEL_V_2_6_32 is not set
|
||||
# CT_KERNEL_LINUX_CUSTOM is not set
|
||||
CT_KERNEL_windows_AVAILABLE=y
|
||||
CT_KERNEL_CHOICE_KSYM="LINUX"
|
||||
CT_KERNEL_LINUX_SHOW=y
|
||||
|
||||
#
|
||||
# Options for linux
|
||||
#
|
||||
CT_KERNEL_LINUX_PKG_KSYM="LINUX"
|
||||
CT_LINUX_DIR_NAME="linux"
|
||||
CT_LINUX_PKG_NAME="linux"
|
||||
CT_LINUX_SRC_RELEASE=y
|
||||
CT_LINUX_PATCH_ORDER="global"
|
||||
# CT_LINUX_V_4_20 is not set
|
||||
# CT_LINUX_V_4_19 is not set
|
||||
# CT_LINUX_V_4_18 is not set
|
||||
# CT_LINUX_V_4_17 is not set
|
||||
# CT_LINUX_V_4_16 is not set
|
||||
# CT_LINUX_V_4_15 is not set
|
||||
# CT_LINUX_V_4_14 is not set
|
||||
# CT_LINUX_V_4_13 is not set
|
||||
# CT_LINUX_V_4_12 is not set
|
||||
# CT_LINUX_V_4_11 is not set
|
||||
# CT_LINUX_V_4_10 is not set
|
||||
# CT_LINUX_V_4_9 is not set
|
||||
# CT_LINUX_V_4_4 is not set
|
||||
# CT_LINUX_V_4_1 is not set
|
||||
# CT_LINUX_V_3_16 is not set
|
||||
# CT_LINUX_V_3_13 is not set
|
||||
# CT_LINUX_V_3_12 is not set
|
||||
# CT_LINUX_V_3_10 is not set
|
||||
# CT_LINUX_V_3_4 is not set
|
||||
CT_LINUX_V_3_2=y
|
||||
# CT_LINUX_V_2_6_32 is not set
|
||||
# CT_LINUX_NO_VERSIONS is not set
|
||||
CT_LINUX_VERSION="3.2.101"
|
||||
CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
|
||||
CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
|
||||
CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
|
||||
CT_LINUX_4_8_or_older=y
|
||||
CT_LINUX_older_than_4_8=y
|
||||
CT_LINUX_3_7_or_older=y
|
||||
CT_LINUX_older_than_3_7=y
|
||||
CT_LINUX_later_than_3_2=y
|
||||
CT_LINUX_3_2_or_later=y
|
||||
CT_KERNEL_LINUX_VERBOSITY_0=y
|
||||
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
|
||||
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
|
||||
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
|
||||
CT_KERNEL_LINUX_INSTALL_CHECK=y
|
||||
CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
|
||||
|
||||
#
|
||||
# Common kernel options
|
||||
#
|
||||
CT_SHARED_LIBS=y
|
||||
|
||||
#
|
||||
# linux other options
|
||||
#
|
||||
CT_KERNEL_LINUX_VERBOSITY_0=y
|
||||
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
|
||||
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
|
||||
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
|
||||
CT_KERNEL_LINUX_INSTALL_CHECK=y
|
||||
|
||||
#
|
||||
# Binary utilities
|
||||
#
|
||||
CT_ARCH_BINFMT_ELF=y
|
||||
CT_BINUTILS_BINUTILS=y
|
||||
CT_BINUTILS="binutils"
|
||||
CT_BINUTILS_binutils=y
|
||||
CT_BINUTILS_CHOICE_KSYM="BINUTILS"
|
||||
CT_BINUTILS_BINUTILS_SHOW=y
|
||||
|
||||
#
|
||||
# Options for binutils
|
||||
#
|
||||
CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
|
||||
CT_BINUTILS_DIR_NAME="binutils"
|
||||
CT_BINUTILS_USE_GNU=y
|
||||
CT_BINUTILS_USE="BINUTILS"
|
||||
CT_BINUTILS_PKG_NAME="binutils"
|
||||
CT_BINUTILS_SRC_RELEASE=y
|
||||
CT_BINUTILS_PATCH_ORDER="global"
|
||||
CT_BINUTILS_V_2_32=y
|
||||
# CT_BINUTILS_V_2_31 is not set
|
||||
# CT_BINUTILS_V_2_30 is not set
|
||||
# CT_BINUTILS_V_2_29 is not set
|
||||
# CT_BINUTILS_V_2_28 is not set
|
||||
# CT_BINUTILS_V_2_27 is not set
|
||||
# CT_BINUTILS_V_2_26 is not set
|
||||
# CT_BINUTILS_NO_VERSIONS is not set
|
||||
CT_BINUTILS_VERSION="2.32"
|
||||
CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
|
||||
CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_BINUTILS_later_than_2_30=y
|
||||
CT_BINUTILS_2_30_or_later=y
|
||||
CT_BINUTILS_later_than_2_27=y
|
||||
CT_BINUTILS_2_27_or_later=y
|
||||
CT_BINUTILS_later_than_2_25=y
|
||||
CT_BINUTILS_2_25_or_later=y
|
||||
CT_BINUTILS_later_than_2_23=y
|
||||
CT_BINUTILS_2_23_or_later=y
|
||||
|
||||
#
|
||||
# GNU binutils
|
||||
#
|
||||
# CT_CC_BINUTILS_SHOW_LINARO is not set
|
||||
CT_BINUTILS_V_2_25_1=y
|
||||
# CT_BINUTILS_V_2_25 is not set
|
||||
# CT_BINUTILS_V_2_24 is not set
|
||||
# CT_BINUTILS_V_2_23_2 is not set
|
||||
# CT_BINUTILS_V_2_23_1 is not set
|
||||
# CT_BINUTILS_V_2_22 is not set
|
||||
# CT_BINUTILS_V_2_21_53 is not set
|
||||
# CT_BINUTILS_V_2_21_1a is not set
|
||||
# CT_BINUTILS_V_2_20_1a is not set
|
||||
# CT_BINUTILS_V_2_19_1a is not set
|
||||
# CT_BINUTILS_V_2_18a is not set
|
||||
CT_BINUTILS_VERSION="2.25.1"
|
||||
CT_BINUTILS_2_25_1_or_later=y
|
||||
CT_BINUTILS_2_25_or_later=y
|
||||
CT_BINUTILS_2_24_or_later=y
|
||||
CT_BINUTILS_2_23_or_later=y
|
||||
CT_BINUTILS_2_22_or_later=y
|
||||
CT_BINUTILS_2_21_or_later=y
|
||||
CT_BINUTILS_2_20_or_later=y
|
||||
CT_BINUTILS_2_19_or_later=y
|
||||
CT_BINUTILS_2_18_or_later=y
|
||||
CT_BINUTILS_HAS_HASH_STYLE=y
|
||||
CT_BINUTILS_HAS_GOLD=y
|
||||
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
|
||||
CT_BINUTILS_GOLD_SUPPORT=y
|
||||
CT_BINUTILS_HAS_PLUGINS=y
|
||||
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
|
||||
CT_BINUTILS_FORCE_LD_BFD=y
|
||||
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
|
||||
CT_BINUTILS_GOLD_SUPPORT=y
|
||||
CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
|
||||
CT_BINUTILS_LINKER_LD=y
|
||||
# CT_BINUTILS_LINKER_LD_GOLD is not set
|
||||
# CT_BINUTILS_LINKER_GOLD_LD is not set
|
||||
CT_BINUTILS_LINKERS_LIST="ld"
|
||||
CT_BINUTILS_LINKER_DEFAULT="bfd"
|
||||
# CT_BINUTILS_PLUGINS is not set
|
||||
CT_BINUTILS_RELRO=m
|
||||
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
|
||||
# CT_BINUTILS_FOR_TARGET is not set
|
||||
|
||||
#
|
||||
# binutils other options
|
||||
#
|
||||
CT_ALL_BINUTILS_CHOICES="BINUTILS"
|
||||
|
||||
#
|
||||
# C-library
|
||||
#
|
||||
CT_LIBC_GLIBC=y
|
||||
# CT_LIBC_UCLIBC is not set
|
||||
CT_LIBC="glibc"
|
||||
CT_LIBC_VERSION="2.16.0"
|
||||
CT_LIBC_glibc=y
|
||||
# CT_LIBC_musl is not set
|
||||
# CT_LIBC_uClibc is not set
|
||||
CT_LIBC_avr_libc_AVAILABLE=y
|
||||
CT_LIBC_glibc_AVAILABLE=y
|
||||
CT_LIBC_CHOICE_KSYM="GLIBC"
|
||||
CT_THREADS="nptl"
|
||||
# CT_CC_GLIBC_SHOW_LINARO is not set
|
||||
# CT_LIBC_GLIBC_V_2_22 is not set
|
||||
# CT_LIBC_GLIBC_V_2_21 is not set
|
||||
# CT_LIBC_GLIBC_V_2_20 is not set
|
||||
# CT_LIBC_GLIBC_V_2_19 is not set
|
||||
# CT_LIBC_GLIBC_V_2_18 is not set
|
||||
# CT_LIBC_GLIBC_V_2_17 is not set
|
||||
CT_LIBC_GLIBC_V_2_16_0=y
|
||||
# CT_LIBC_GLIBC_V_2_15 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_14 is not set
|
||||
# CT_LIBC_GLIBC_V_2_13 is not set
|
||||
# CT_LIBC_GLIBC_V_2_12_2 is not set
|
||||
# CT_LIBC_GLIBC_V_2_12_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_11 is not set
|
||||
# CT_LIBC_GLIBC_V_2_10_1 is not set
|
||||
# CT_LIBC_GLIBC_V_2_9 is not set
|
||||
# CT_LIBC_GLIBC_V_2_8 is not set
|
||||
CT_LIBC_mingw_AVAILABLE=y
|
||||
CT_LIBC_musl_AVAILABLE=y
|
||||
CT_LIBC_newlib_AVAILABLE=y
|
||||
CT_LIBC_none_AVAILABLE=y
|
||||
CT_LIBC_uClibc_AVAILABLE=y
|
||||
CT_LIBC_GLIBC_SHOW=y
|
||||
|
||||
#
|
||||
# Options for glibc
|
||||
#
|
||||
CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
|
||||
CT_GLIBC_DIR_NAME="glibc"
|
||||
CT_GLIBC_USE_GNU=y
|
||||
CT_GLIBC_USE="GLIBC"
|
||||
CT_GLIBC_PKG_NAME="glibc"
|
||||
CT_GLIBC_SRC_RELEASE=y
|
||||
CT_GLIBC_PATCH_ORDER="global"
|
||||
# CT_GLIBC_V_2_29 is not set
|
||||
# CT_GLIBC_V_2_28 is not set
|
||||
# CT_GLIBC_V_2_27 is not set
|
||||
# CT_GLIBC_V_2_26 is not set
|
||||
# CT_GLIBC_V_2_25 is not set
|
||||
# CT_GLIBC_V_2_24 is not set
|
||||
# CT_GLIBC_V_2_23 is not set
|
||||
# CT_GLIBC_V_2_19 is not set
|
||||
CT_GLIBC_V_2_17=y
|
||||
# CT_GLIBC_V_2_12_1 is not set
|
||||
# CT_GLIBC_NO_VERSIONS is not set
|
||||
CT_GLIBC_VERSION="2.17"
|
||||
CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
|
||||
CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_GLIBC_2_29_or_older=y
|
||||
CT_GLIBC_older_than_2_29=y
|
||||
CT_GLIBC_2_27_or_older=y
|
||||
CT_GLIBC_older_than_2_27=y
|
||||
CT_GLIBC_2_26_or_older=y
|
||||
CT_GLIBC_older_than_2_26=y
|
||||
CT_GLIBC_2_25_or_older=y
|
||||
CT_GLIBC_older_than_2_25=y
|
||||
CT_GLIBC_2_24_or_older=y
|
||||
CT_GLIBC_older_than_2_24=y
|
||||
CT_GLIBC_2_23_or_older=y
|
||||
CT_GLIBC_older_than_2_23=y
|
||||
CT_GLIBC_2_20_or_older=y
|
||||
CT_GLIBC_older_than_2_20=y
|
||||
CT_GLIBC_2_17_or_later=y
|
||||
CT_GLIBC_2_17_or_older=y
|
||||
CT_GLIBC_later_than_2_14=y
|
||||
CT_GLIBC_2_14_or_later=y
|
||||
CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
|
||||
CT_GLIBC_DEP_BINUTILS=y
|
||||
CT_GLIBC_DEP_GCC=y
|
||||
CT_GLIBC_DEP_PYTHON=y
|
||||
CT_GLIBC_HAS_NPTL_ADDON=y
|
||||
CT_GLIBC_HAS_PORTS_ADDON=y
|
||||
CT_GLIBC_HAS_LIBIDN_ADDON=y
|
||||
CT_GLIBC_USE_PORTS_ADDON=y
|
||||
CT_GLIBC_USE_NPTL_ADDON=y
|
||||
# CT_GLIBC_USE_LIBIDN_ADDON is not set
|
||||
CT_GLIBC_HAS_OBSOLETE_RPC=y
|
||||
CT_GLIBC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_GLIBC_CONFIGPARMS=""
|
||||
CT_GLIBC_EXTRA_CFLAGS=""
|
||||
CT_GLIBC_ENABLE_OBSOLETE_RPC=y
|
||||
# CT_GLIBC_DISABLE_VERSIONING is not set
|
||||
CT_GLIBC_OLDEST_ABI=""
|
||||
CT_GLIBC_FORCE_UNWIND=y
|
||||
# CT_GLIBC_LOCALES is not set
|
||||
# CT_GLIBC_KERNEL_VERSION_NONE is not set
|
||||
CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_GLIBC_MIN_KERNEL="3.2.101"
|
||||
CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
|
||||
CT_LIBC_SUPPORT_THREADS_ANY=y
|
||||
CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
||||
|
||||
|
|
@ -343,100 +450,71 @@ CT_LIBC_SUPPORT_THREADS_NATIVE=y
|
|||
# Common C library options
|
||||
#
|
||||
CT_THREADS_NATIVE=y
|
||||
# CT_CREATE_LDSO_CONF is not set
|
||||
CT_LIBC_XLDD=y
|
||||
|
||||
#
|
||||
# glibc other options
|
||||
#
|
||||
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
|
||||
CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
|
||||
CT_LIBC_glibc_familly=y
|
||||
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_LIBC_GLIBC_CONFIGPARMS=""
|
||||
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
|
||||
CT_LIBC_EXTRA_CC_ARGS=""
|
||||
# CT_LIBC_DISABLE_VERSIONING is not set
|
||||
CT_LIBC_OLDEST_ABI=""
|
||||
CT_LIBC_GLIBC_FORCE_UNWIND=y
|
||||
CT_LIBC_GLIBC_USE_PORTS=y
|
||||
CT_LIBC_ADDONS_LIST=""
|
||||
|
||||
#
|
||||
# WARNING !!!
|
||||
#
|
||||
|
||||
#
|
||||
# For glibc >= 2.8, it can happen that the tarballs
|
||||
#
|
||||
|
||||
#
|
||||
# for the addons are not available for download.
|
||||
#
|
||||
|
||||
#
|
||||
# If that happens, bad luck... Try a previous version
|
||||
#
|
||||
|
||||
#
|
||||
# or try again later... :-(
|
||||
#
|
||||
# CT_LIBC_LOCALES is not set
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
|
||||
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
|
||||
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
|
||||
CT_LIBC_GLIBC_MIN_KERNEL="3.2.72"
|
||||
|
||||
#
|
||||
# C compiler
|
||||
#
|
||||
CT_CC="gcc"
|
||||
CT_CC_CORE_PASSES_NEEDED=y
|
||||
CT_CC_CORE_PASS_1_NEEDED=y
|
||||
CT_CC_CORE_PASS_2_NEEDED=y
|
||||
CT_CC_gcc=y
|
||||
# CT_CC_GCC_SHOW_LINARO is not set
|
||||
CT_CC_GCC_V_5_2_0=y
|
||||
# CT_CC_GCC_V_4_9_3 is not set
|
||||
# CT_CC_GCC_V_4_8_5 is not set
|
||||
# CT_CC_GCC_V_4_7_4 is not set
|
||||
# CT_CC_GCC_V_4_6_4 is not set
|
||||
# CT_CC_GCC_V_4_5_4 is not set
|
||||
# CT_CC_GCC_V_4_4_7 is not set
|
||||
# CT_CC_GCC_V_4_3_6 is not set
|
||||
# CT_CC_GCC_V_4_2_4 is not set
|
||||
CT_CC_GCC_4_2_or_later=y
|
||||
CT_CC_GCC_4_3_or_later=y
|
||||
CT_CC_GCC_4_4_or_later=y
|
||||
CT_CC_GCC_4_5_or_later=y
|
||||
CT_CC_GCC_4_6_or_later=y
|
||||
CT_CC_GCC_4_7_or_later=y
|
||||
CT_CC_GCC_4_8_or_later=y
|
||||
CT_CC_GCC_4_9_or_later=y
|
||||
CT_CC_GCC_5=y
|
||||
CT_CC_GCC_5_or_later=y
|
||||
CT_CC_GCC_HAS_GRAPHITE=y
|
||||
CT_CC_GCC_USE_GRAPHITE=y
|
||||
CT_CC_GCC_HAS_LTO=y
|
||||
CT_CC_GCC_USE_LTO=y
|
||||
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
|
||||
CT_CC_GCC_HAS_BUILD_ID=y
|
||||
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
|
||||
CT_CC_GCC_USE_GMP_MPFR=y
|
||||
CT_CC_GCC_USE_MPC=y
|
||||
CT_CC_GCC_HAS_LIBQUADMATH=y
|
||||
CT_CC_GCC_HAS_LIBSANITIZER=y
|
||||
CT_CC_GCC_VERSION="5.2.0"
|
||||
# CT_CC_LANG_FORTRAN is not set
|
||||
CT_CC_SUPPORT_CXX=y
|
||||
CT_CC_SUPPORT_FORTRAN=y
|
||||
CT_CC_SUPPORT_ADA=y
|
||||
CT_CC_SUPPORT_OBJC=y
|
||||
CT_CC_SUPPORT_OBJCXX=y
|
||||
CT_CC_SUPPORT_GOLANG=y
|
||||
CT_CC_GCC=y
|
||||
CT_CC="gcc"
|
||||
CT_CC_CHOICE_KSYM="GCC"
|
||||
CT_CC_GCC_SHOW=y
|
||||
|
||||
#
|
||||
# Options for gcc
|
||||
#
|
||||
CT_CC_GCC_PKG_KSYM="GCC"
|
||||
CT_GCC_DIR_NAME="gcc"
|
||||
CT_GCC_USE_GNU=y
|
||||
CT_GCC_USE="GCC"
|
||||
CT_GCC_PKG_NAME="gcc"
|
||||
CT_GCC_SRC_RELEASE=y
|
||||
CT_GCC_PATCH_ORDER="global"
|
||||
CT_GCC_V_8=y
|
||||
# CT_GCC_V_7 is not set
|
||||
# CT_GCC_V_6 is not set
|
||||
# CT_GCC_V_5 is not set
|
||||
# CT_GCC_V_4_9 is not set
|
||||
# CT_GCC_NO_VERSIONS is not set
|
||||
CT_GCC_VERSION="8.3.0"
|
||||
CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
|
||||
CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
|
||||
CT_GCC_SIGNATURE_FORMAT=""
|
||||
CT_GCC_later_than_7=y
|
||||
CT_GCC_7_or_later=y
|
||||
CT_GCC_later_than_6=y
|
||||
CT_GCC_6_or_later=y
|
||||
CT_GCC_later_than_5=y
|
||||
CT_GCC_5_or_later=y
|
||||
CT_GCC_later_than_4_9=y
|
||||
CT_GCC_4_9_or_later=y
|
||||
CT_GCC_later_than_4_8=y
|
||||
CT_GCC_4_8_or_later=y
|
||||
CT_CC_GCC_HAS_LIBMPX=y
|
||||
CT_CC_GCC_ENABLE_CXX_FLAGS=""
|
||||
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
|
||||
CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
|
||||
CT_CC_GCC_EXTRA_ENV_ARRAY=""
|
||||
CT_CC_GCC_STATIC_LIBSTDCXX=y
|
||||
# CT_CC_GCC_SYSTEM_ZLIB is not set
|
||||
CT_CC_GCC_CONFIG_TLS=m
|
||||
|
||||
#
|
||||
# Optimisation features
|
||||
#
|
||||
CT_CC_GCC_USE_GRAPHITE=y
|
||||
CT_CC_GCC_USE_LTO=y
|
||||
|
||||
#
|
||||
# Settings for libraries running on target
|
||||
|
|
@ -465,97 +543,206 @@ CT_CC_GCC_DEC_FLOAT_AUTO=y
|
|||
# CT_CC_GCC_DEC_FLOAT_BID is not set
|
||||
# CT_CC_GCC_DEC_FLOAT_DPD is not set
|
||||
# CT_CC_GCC_DEC_FLOATS_NO is not set
|
||||
CT_CC_SUPPORT_CXX=y
|
||||
CT_CC_SUPPORT_FORTRAN=y
|
||||
CT_CC_SUPPORT_JAVA=y
|
||||
CT_CC_SUPPORT_ADA=y
|
||||
CT_CC_SUPPORT_OBJC=y
|
||||
CT_CC_SUPPORT_OBJCXX=y
|
||||
CT_CC_SUPPORT_GOLANG=y
|
||||
CT_ALL_CC_CHOICES="GCC"
|
||||
|
||||
#
|
||||
# Additional supported languages:
|
||||
#
|
||||
CT_CC_LANG_CXX=y
|
||||
# CT_CC_LANG_JAVA is not set
|
||||
# CT_CC_LANG_FORTRAN is not set
|
||||
|
||||
#
|
||||
# Debug facilities
|
||||
#
|
||||
# CT_DEBUG_dmalloc is not set
|
||||
# CT_DEBUG_duma is not set
|
||||
# CT_DEBUG_gdb is not set
|
||||
# CT_DEBUG_ltrace is not set
|
||||
# CT_DEBUG_strace is not set
|
||||
# CT_DEBUG_DUMA is not set
|
||||
# CT_DEBUG_GDB is not set
|
||||
# CT_DEBUG_LTRACE is not set
|
||||
# CT_DEBUG_STRACE is not set
|
||||
CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
|
||||
|
||||
#
|
||||
# Companion libraries
|
||||
#
|
||||
CT_COMPLIBS_NEEDED=y
|
||||
# CT_COMPLIBS_CHECK is not set
|
||||
# CT_COMP_LIBS_CLOOG is not set
|
||||
# CT_COMP_LIBS_EXPAT is not set
|
||||
CT_COMP_LIBS_GETTEXT=y
|
||||
CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
|
||||
CT_GETTEXT_DIR_NAME="gettext"
|
||||
CT_GETTEXT_PKG_NAME="gettext"
|
||||
CT_GETTEXT_SRC_RELEASE=y
|
||||
CT_GETTEXT_PATCH_ORDER="global"
|
||||
CT_GETTEXT_V_0_19_8_1=y
|
||||
# CT_GETTEXT_NO_VERSIONS is not set
|
||||
CT_GETTEXT_VERSION="0.19.8.1"
|
||||
CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
|
||||
CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
|
||||
CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_COMP_LIBS_GMP=y
|
||||
CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
|
||||
CT_GMP_DIR_NAME="gmp"
|
||||
CT_GMP_PKG_NAME="gmp"
|
||||
CT_GMP_SRC_RELEASE=y
|
||||
CT_GMP_PATCH_ORDER="global"
|
||||
CT_GMP_V_6_1=y
|
||||
# CT_GMP_NO_VERSIONS is not set
|
||||
CT_GMP_VERSION="6.1.2"
|
||||
CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
|
||||
CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
|
||||
CT_GMP_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_GMP_later_than_5_1_0=y
|
||||
CT_GMP_5_1_0_or_later=y
|
||||
CT_GMP_later_than_5_0_0=y
|
||||
CT_GMP_5_0_0_or_later=y
|
||||
CT_COMP_LIBS_ISL=y
|
||||
CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
|
||||
CT_ISL_DIR_NAME="isl"
|
||||
CT_ISL_PKG_NAME="isl"
|
||||
CT_ISL_SRC_RELEASE=y
|
||||
CT_ISL_PATCH_ORDER="global"
|
||||
CT_ISL_V_0_20=y
|
||||
# CT_ISL_V_0_19 is not set
|
||||
# CT_ISL_V_0_18 is not set
|
||||
# CT_ISL_V_0_17 is not set
|
||||
# CT_ISL_V_0_16 is not set
|
||||
# CT_ISL_V_0_15 is not set
|
||||
# CT_ISL_NO_VERSIONS is not set
|
||||
CT_ISL_VERSION="0.20"
|
||||
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
|
||||
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
|
||||
CT_ISL_SIGNATURE_FORMAT=""
|
||||
CT_ISL_later_than_0_18=y
|
||||
CT_ISL_0_18_or_later=y
|
||||
CT_ISL_later_than_0_15=y
|
||||
CT_ISL_0_15_or_later=y
|
||||
CT_ISL_REQUIRE_0_15_or_later=y
|
||||
CT_ISL_later_than_0_14=y
|
||||
CT_ISL_0_14_or_later=y
|
||||
CT_ISL_REQUIRE_0_14_or_later=y
|
||||
CT_ISL_later_than_0_13=y
|
||||
CT_ISL_0_13_or_later=y
|
||||
CT_ISL_later_than_0_12=y
|
||||
CT_ISL_0_12_or_later=y
|
||||
CT_ISL_REQUIRE_0_12_or_later=y
|
||||
# CT_COMP_LIBS_LIBELF is not set
|
||||
CT_COMP_LIBS_LIBICONV=y
|
||||
CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
|
||||
CT_LIBICONV_DIR_NAME="libiconv"
|
||||
CT_LIBICONV_PKG_NAME="libiconv"
|
||||
CT_LIBICONV_SRC_RELEASE=y
|
||||
CT_LIBICONV_PATCH_ORDER="global"
|
||||
CT_LIBICONV_V_1_15=y
|
||||
# CT_LIBICONV_NO_VERSIONS is not set
|
||||
CT_LIBICONV_VERSION="1.15"
|
||||
CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
|
||||
CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
|
||||
CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_COMP_LIBS_MPC=y
|
||||
CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
|
||||
CT_MPC_DIR_NAME="mpc"
|
||||
CT_MPC_PKG_NAME="mpc"
|
||||
CT_MPC_SRC_RELEASE=y
|
||||
CT_MPC_PATCH_ORDER="global"
|
||||
# CT_MPC_V_1_1 is not set
|
||||
CT_MPC_V_1_0=y
|
||||
# CT_MPC_NO_VERSIONS is not set
|
||||
CT_MPC_VERSION="1.0.3"
|
||||
CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
|
||||
CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_MPC_ARCHIVE_FORMATS=".tar.gz"
|
||||
CT_MPC_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_MPC_1_1_0_or_older=y
|
||||
CT_MPC_older_than_1_1_0=y
|
||||
CT_COMP_LIBS_MPFR=y
|
||||
CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
|
||||
CT_MPFR_DIR_NAME="mpfr"
|
||||
CT_MPFR_PKG_NAME="mpfr"
|
||||
CT_MPFR_SRC_RELEASE=y
|
||||
CT_MPFR_PATCH_ORDER="global"
|
||||
CT_MPFR_V_3_1=y
|
||||
# CT_MPFR_NO_VERSIONS is not set
|
||||
CT_MPFR_VERSION="3.1.6"
|
||||
CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
|
||||
CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
|
||||
CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
|
||||
CT_MPFR_4_0_0_or_older=y
|
||||
CT_MPFR_older_than_4_0_0=y
|
||||
CT_MPFR_REQUIRE_older_than_4_0_0=y
|
||||
CT_MPFR_later_than_3_0_0=y
|
||||
CT_MPFR_3_0_0_or_later=y
|
||||
CT_COMP_LIBS_NCURSES=y
|
||||
CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
|
||||
CT_NCURSES_DIR_NAME="ncurses"
|
||||
CT_NCURSES_PKG_NAME="ncurses"
|
||||
CT_NCURSES_SRC_RELEASE=y
|
||||
CT_NCURSES_PATCH_ORDER="global"
|
||||
CT_NCURSES_V_6_1=y
|
||||
# CT_NCURSES_V_6_0 is not set
|
||||
# CT_NCURSES_NO_VERSIONS is not set
|
||||
CT_NCURSES_VERSION="6.1"
|
||||
CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
|
||||
CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
|
||||
CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
|
||||
CT_NCURSES_HOST_CONFIG_ARGS=""
|
||||
CT_NCURSES_HOST_DISABLE_DB=y
|
||||
CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
|
||||
CT_NCURSES_TARGET_CONFIG_ARGS=""
|
||||
# CT_NCURSES_TARGET_DISABLE_DB is not set
|
||||
CT_NCURSES_TARGET_FALLBACKS=""
|
||||
CT_COMP_LIBS_ZLIB=y
|
||||
CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
|
||||
CT_ZLIB_DIR_NAME="zlib"
|
||||
CT_ZLIB_PKG_NAME="zlib"
|
||||
CT_ZLIB_SRC_RELEASE=y
|
||||
CT_ZLIB_PATCH_ORDER="global"
|
||||
CT_ZLIB_V_1_2_11=y
|
||||
# CT_ZLIB_NO_VERSIONS is not set
|
||||
CT_ZLIB_VERSION="1.2.11"
|
||||
CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
|
||||
CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
|
||||
CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
|
||||
CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
|
||||
CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
|
||||
CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
|
||||
CT_LIBICONV_NEEDED=y
|
||||
CT_GETTEXT_NEEDED=y
|
||||
CT_GMP_NEEDED=y
|
||||
CT_MPFR_NEEDED=y
|
||||
CT_ISL_NEEDED=y
|
||||
CT_MPC_NEEDED=y
|
||||
CT_COMPLIBS=y
|
||||
CT_NCURSES_NEEDED=y
|
||||
CT_ZLIB_NEEDED=y
|
||||
CT_LIBICONV=y
|
||||
CT_GETTEXT=y
|
||||
CT_GMP=y
|
||||
CT_MPFR=y
|
||||
CT_ISL=y
|
||||
CT_MPC=y
|
||||
CT_LIBICONV_V_1_14=y
|
||||
CT_LIBICONV_VERSION="1.14"
|
||||
CT_GETTEXT_V_0_19_6=y
|
||||
CT_GETTEXT_VERSION="0.19.6"
|
||||
CT_GMP_V_6_0_0=y
|
||||
# CT_GMP_V_5_1_3 is not set
|
||||
# CT_GMP_V_5_1_1 is not set
|
||||
# CT_GMP_V_5_0_2 is not set
|
||||
# CT_GMP_V_5_0_1 is not set
|
||||
# CT_GMP_V_4_3_2 is not set
|
||||
# CT_GMP_V_4_3_1 is not set
|
||||
# CT_GMP_V_4_3_0 is not set
|
||||
CT_GMP_5_0_2_or_later=y
|
||||
CT_GMP_VERSION="6.0.0a"
|
||||
CT_MPFR_V_3_1_3=y
|
||||
# CT_MPFR_V_3_1_2 is not set
|
||||
# CT_MPFR_V_3_1_0 is not set
|
||||
# CT_MPFR_V_3_0_1 is not set
|
||||
# CT_MPFR_V_3_0_0 is not set
|
||||
# CT_MPFR_V_2_4_2 is not set
|
||||
# CT_MPFR_V_2_4_1 is not set
|
||||
# CT_MPFR_V_2_4_0 is not set
|
||||
CT_MPFR_VERSION="3.1.3"
|
||||
CT_ISL_V_0_14=y
|
||||
# CT_ISL_V_0_12_2 is not set
|
||||
CT_ISL_V_0_14_or_later=y
|
||||
CT_ISL_V_0_12_or_later=y
|
||||
CT_ISL_VERSION="0.14"
|
||||
# CT_CLOOG_V_0_18_4 is not set
|
||||
# CT_CLOOG_V_0_18_1 is not set
|
||||
# CT_CLOOG_V_0_18_0 is not set
|
||||
CT_MPC_V_1_0_3=y
|
||||
# CT_MPC_V_1_0_2 is not set
|
||||
# CT_MPC_V_1_0_1 is not set
|
||||
# CT_MPC_V_1_0 is not set
|
||||
# CT_MPC_V_0_9 is not set
|
||||
# CT_MPC_V_0_8_2 is not set
|
||||
# CT_MPC_V_0_8_1 is not set
|
||||
# CT_MPC_V_0_7 is not set
|
||||
CT_MPC_VERSION="1.0.3"
|
||||
|
||||
#
|
||||
# Companion libraries common options
|
||||
#
|
||||
# CT_COMPLIBS_CHECK is not set
|
||||
CT_NCURSES=y
|
||||
CT_ZLIB=y
|
||||
|
||||
#
|
||||
# Companion tools
|
||||
#
|
||||
|
||||
#
|
||||
# READ HELP before you say 'Y' below !!!
|
||||
#
|
||||
# CT_COMP_TOOLS is not set
|
||||
# CT_COMP_TOOLS_FOR_HOST is not set
|
||||
# CT_COMP_TOOLS_AUTOCONF is not set
|
||||
# CT_COMP_TOOLS_AUTOMAKE is not set
|
||||
# CT_COMP_TOOLS_BISON is not set
|
||||
# CT_COMP_TOOLS_DTC is not set
|
||||
# CT_COMP_TOOLS_LIBTOOL is not set
|
||||
# CT_COMP_TOOLS_M4 is not set
|
||||
# CT_COMP_TOOLS_MAKE is not set
|
||||
CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
|
||||
|
|
|
|||
12
src/ci/docker/dist-armv7-linux/crosstool-ng.sh
Normal file
12
src/ci/docker/dist-armv7-linux/crosstool-ng.sh
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
set -ex
|
||||
|
||||
# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
|
||||
url="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/crosstool-ng-1.24.0.tar.gz"
|
||||
curl -Lf $url | tar xzf -
|
||||
cd crosstool-ng-crosstool-ng-1.24.0
|
||||
./bootstrap
|
||||
./configure --prefix=/usr/local
|
||||
make -j$(nproc)
|
||||
make install
|
||||
cd ..
|
||||
rm -rf crosstool-ng-crosstool-ng-1.24.0
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
commit bdb24c2851fd5f0ad9b82d7ea1db911d334b02d2
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Tue May 20 21:27:13 2014 +0000
|
||||
|
||||
Fix ARM build with GCC trunk.
|
||||
|
||||
sysdeps/unix/sysv/linux/arm/unwind-resume.c and
|
||||
sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c have static
|
||||
variables that are written in C code but only read from toplevel asms.
|
||||
Current GCC trunk now optimizes away such apparently write-only static
|
||||
variables, so causing a build failure. This patch marks those
|
||||
variables with __attribute_used__ to avoid that optimization.
|
||||
|
||||
Tested that this fixes the build for ARM.
|
||||
|
||||
* sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c
|
||||
(libgcc_s_resume): Use __attribute_used__.
|
||||
* sysdeps/unix/sysv/linux/arm/unwind-resume.c (libgcc_s_resume):
|
||||
Likewise.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
|
||||
index 29e2c2b00b04..e848bfeffdcb 100644
|
||||
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
|
||||
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
|
||||
@@ -22,7 +22,8 @@
|
||||
#include <pthreadP.h>
|
||||
|
||||
static void *libgcc_s_handle;
|
||||
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
|
||||
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
|
||||
+ __attribute_used__;
|
||||
static _Unwind_Reason_Code (*libgcc_s_personality)
|
||||
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
|
||||
static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
|
||||
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
|
||||
index 285b99b5ed0d..48d00fc83641 100644
|
||||
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
|
||||
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
|
||||
@@ -20,7 +20,8 @@
|
||||
#include <stdio.h>
|
||||
#include <unwind.h>
|
||||
|
||||
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
|
||||
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
|
||||
+ __attribute_used__;
|
||||
static _Unwind_Reason_Code (*libgcc_s_personality)
|
||||
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
|
||||
|
||||
|
|
@ -22,5 +22,6 @@ apt-get update && apt-get install -y --no-install-recommends \
|
|||
python2.7 \
|
||||
sudo \
|
||||
texinfo \
|
||||
unzip \
|
||||
wget \
|
||||
xz-utils
|
||||
|
|
|
|||
|
|
@ -21,13 +21,3 @@ git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
|
|||
cd /emsdk-portable
|
||||
hide_output ./emsdk install 1.38.46-upstream
|
||||
./emsdk activate 1.38.46-upstream
|
||||
|
||||
# Compile and cache libc
|
||||
source ./emsdk_env.sh
|
||||
echo "main(){}" > a.c
|
||||
HOME=/emsdk-portable/ emcc a.c
|
||||
rm -f a.*
|
||||
|
||||
# Make emsdk usable by any user
|
||||
cp /root/.emscripten /emsdk-portable
|
||||
chmod a+rxw -R /emsdk-portable
|
||||
|
|
|
|||
|
|
@ -24,11 +24,17 @@ ENV PATH=$PATH:/emsdk-portable
|
|||
ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/upstream/
|
||||
ENV EM_CONFIG=/emsdk-portable/.emscripten
|
||||
|
||||
ENV TARGETS=wasm32-unknown-emscripten
|
||||
|
||||
# FIXME: Re-enable these tests once Cargo stops trying to execute wasms
|
||||
# Use -O1 optimizations in the link step to reduce time spent optimizing.
|
||||
ENV EMCC_CFLAGS=-O1
|
||||
|
||||
# Emscripten installation is user-specific
|
||||
ENV NO_CHANGE_USER=1
|
||||
|
||||
# FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476
|
||||
# is picked up by CI
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
|
||||
--exclude src/libcore \
|
||||
--exclude src/liballoc \
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 04806c80be0f54b1290287e3f85e84bdfc0b6ec7
|
||||
Subproject commit 9bb8b161963fcebc9d9ccd732ba26f42108016d5
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4374786f0b4bf0606b35d5c30a9681f342e5707b
|
||||
Subproject commit 5004ad30d69f93553ceef74439fea2159d1f769e
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 320d232b206edecb67489316f71a14e31dbc6c08
|
||||
Subproject commit 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit a6288e7407a6c4c19ea29de6d43f40c803883f21
|
||||
Subproject commit 0b111eaae36cc4b4997684be853882a59e2c7ca7
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
- [Warn-by-default lints](lints/listing/warn-by-default.md)
|
||||
- [Deny-by-default lints](lints/listing/deny-by-default.md)
|
||||
- [Codegen options](codegen-options/index.md)
|
||||
- [JSON Output](json.md)
|
||||
- [Targets](targets/index.md)
|
||||
- [Built-in Targets](targets/built-in.md)
|
||||
- [Custom Targets](targets/custom.md)
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ information about editions may be found in the [edition guide].
|
|||
[edition guide]: ../edition-guide/introduction.html
|
||||
|
||||
## `--emit`: specifies the types of output files to generate
|
||||
<a id="option-emit"></a>
|
||||
|
||||
This flag controls the types of output files generated by the compiler. It
|
||||
accepts a comma-separated list of values, and may be specified multiple times.
|
||||
|
|
@ -241,12 +242,13 @@ The "sysroot" is where `rustc` looks for the crates that come with the Rust
|
|||
distribution; this flag allows that to be overridden.
|
||||
|
||||
## `--error-format`: control how errors are produced
|
||||
<a id="option-error-format"></a>
|
||||
|
||||
This flag lets you control the format of messages. Messages are printed to
|
||||
stderr. The valid options are:
|
||||
|
||||
- `human` — Human-readable output. This is the default.
|
||||
- `json` — Structured JSON output.
|
||||
- `json` — Structured JSON output. See [the JSON chapter] for more detail.
|
||||
- `short` — Short, one-line messages.
|
||||
|
||||
## `--color`: configure coloring of output
|
||||
|
|
@ -273,6 +275,7 @@ pathname syntax. For example `--remap-path-prefix foo=bar` will match
|
|||
`foo/lib.rs` but not `./foo/lib.rs`.
|
||||
|
||||
## `--json`: configure json messages printed by the compiler
|
||||
<a id="option-json"></a>
|
||||
|
||||
When the `--error-format=json` option is passed to rustc then all of the
|
||||
compiler's diagnostic output will be emitted in the form of JSON blobs. The
|
||||
|
|
@ -305,9 +308,13 @@ to customize the output:
|
|||
Note that it is invalid to combine the `--json` argument with the `--color`
|
||||
argument, and it is required to combine `--json` with `--error-format=json`.
|
||||
|
||||
See [the JSON chapter] for more detail.
|
||||
|
||||
## `@path`: load command-line flags from a path
|
||||
|
||||
If you specify `@path` on the command-line, then it will open `path` and read
|
||||
command line options from it. These options are one per line; a blank line indicates
|
||||
an empty option. The file can use Unix or Windows style line endings, and must be
|
||||
encoded as UTF-8.
|
||||
|
||||
[the JSON chapter]: json.md
|
||||
|
|
|
|||
231
src/doc/rustc/src/json.md
Normal file
231
src/doc/rustc/src/json.md
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
# JSON Output
|
||||
|
||||
This chapter documents the JSON structures emitted by `rustc`. JSON may be
|
||||
enabled with the [`--error-format=json` flag][option-error-format]. Additional
|
||||
options may be specified with the [`--json` flag][option-json] which can
|
||||
change which messages are generated, and the format of the messages.
|
||||
|
||||
JSON messages are emitted one per line to stderr.
|
||||
|
||||
If parsing the output with Rust, the
|
||||
[`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides
|
||||
some support for parsing the messages.
|
||||
|
||||
When parsing, care should be taken to be forwards-compatible with future changes
|
||||
to the format. Optional values may be `null`. New fields may be added. Enumerated
|
||||
fields like "level" or "suggestion_applicability" may add new values.
|
||||
|
||||
## Diagnostics
|
||||
|
||||
Diagnostic messages provide errors or possible concerns generated during
|
||||
compilation. `rustc` provides detailed information about where the diagnostic
|
||||
originates, along with hints and suggestions.
|
||||
|
||||
Diagnostics are arranged in a parent/child relationship where the parent
|
||||
diagnostic value is the core of the diagnostic, and the attached children
|
||||
provide additional context, help, and information.
|
||||
|
||||
Diagnostics have the following format:
|
||||
|
||||
```javascript
|
||||
{
|
||||
/* The primary message. */
|
||||
"message": "unused variable: `x`",
|
||||
/* The diagnostic code.
|
||||
Some messages may set this value to null.
|
||||
*/
|
||||
"code": {
|
||||
/* A unique string identifying which diagnostic triggered. */
|
||||
"code": "unused_variables",
|
||||
/* An optional string explaining more detail about the diagnostic code. */
|
||||
"explanation": null
|
||||
},
|
||||
/* The severity of the diagnostic.
|
||||
Values may be:
|
||||
- "error": A fatal error that prevents compilation.
|
||||
- "warning": A possible error or concern.
|
||||
- "note": Additional information or context about the diagnostic.
|
||||
- "help": A suggestion on how to resolve the diagnostic.
|
||||
- "failure-note": A note attached to the message for further information.
|
||||
- "error: internal compiler error": Indicates a bug within the compiler.
|
||||
*/
|
||||
"level": "warning",
|
||||
/* An array of source code locations to point out specific details about
|
||||
where the diagnostic originates from. This may be empty, for example
|
||||
for some global messages, or child messages attached to a parent.
|
||||
|
||||
Character offsets are offsets of Unicode Scalar Values.
|
||||
*/
|
||||
"spans": [
|
||||
{
|
||||
/* The file where the span is located.
|
||||
For spans located within a macro expansion, this will be the
|
||||
name of the expanded macro in the format "<MACRONAME macros>".
|
||||
*/
|
||||
"file_name": "lib.rs",
|
||||
/* The byte offset where the span starts (0-based, inclusive). */
|
||||
"byte_start": 21,
|
||||
/* The byte offset where the span ends (0-based, exclusive). */
|
||||
"byte_end": 22,
|
||||
/* The first line number of the span (1-based, inclusive). */
|
||||
"line_start": 2,
|
||||
/* The last line number of the span (1-based, inclusive). */
|
||||
"line_end": 2,
|
||||
/* The first character offset of the line_start (1-based, inclusive). */
|
||||
"column_start": 9,
|
||||
/* The last character offset of the line_end (1-based, exclusive). */
|
||||
"column_end": 10,
|
||||
/* Whether or not this is the "primary" span.
|
||||
|
||||
This indicates that this span is the focal point of the
|
||||
diagnostic.
|
||||
|
||||
There are rare cases where multiple spans may be marked as
|
||||
primary. For example, "immutable borrow occurs here" and
|
||||
"mutable borrow ends here" can be two separate primary spans.
|
||||
|
||||
The top (parent) message should always have at least one
|
||||
primary span, unless it has zero spans. Child messages may have
|
||||
zero or more primary spans.
|
||||
*/
|
||||
"is_primary": true,
|
||||
/* An array of objects showing the original source code for this
|
||||
span. This shows the entire lines of text where the span is
|
||||
located. A span across multiple lines will have a separate
|
||||
value for each line.
|
||||
*/
|
||||
"text": [
|
||||
{
|
||||
/* The entire line of the original source code. */
|
||||
"text": " let x = 123;",
|
||||
/* The first character offset of the line of
|
||||
where the span covers this line (1-based, inclusive). */
|
||||
"highlight_start": 9,
|
||||
/* The last character offset of the line of
|
||||
where the span covers this line (1-based, exclusive). */
|
||||
"highlight_end": 10
|
||||
}
|
||||
],
|
||||
/* An optional message to display at this span location.
|
||||
This is typically null for primary spans.
|
||||
*/
|
||||
"label": null,
|
||||
/* An optional string of a suggested replacement for this span to
|
||||
solve the issue. Tools may try to replace the contents of the
|
||||
span with this text.
|
||||
*/
|
||||
"suggested_replacement": null,
|
||||
/* An optional string that indicates the confidence of the
|
||||
"suggested_replacement". Tools may use this value to determine
|
||||
whether or not suggestions should be automatically applied.
|
||||
|
||||
Possible values may be:
|
||||
- "MachineApplicable": The suggestion is definitely what the
|
||||
user intended. This suggestion should be automatically
|
||||
applied.
|
||||
- "MaybeIncorrect": The suggestion may be what the user
|
||||
intended, but it is uncertain. The suggestion should result
|
||||
in valid Rust code if it is applied.
|
||||
- "HasPlaceholders": The suggestion contains placeholders like
|
||||
`(...)`. The suggestion cannot be applied automatically
|
||||
because it will not result in valid Rust code. The user will
|
||||
need to fill in the placeholders.
|
||||
- "Unspecified": The applicability of the suggestion is unknown.
|
||||
*/
|
||||
"suggestion_applicability": null,
|
||||
/* An optional object indicating the expansion of a macro within
|
||||
this span.
|
||||
|
||||
If a message occurs within a macro invocation, this object will
|
||||
provide details of where within the macro expansion the message
|
||||
is located.
|
||||
*/
|
||||
"expansion": {
|
||||
/* The span of the macro invocation.
|
||||
Uses the same span definition as the "spans" array.
|
||||
*/
|
||||
"span": {/*...*/}
|
||||
/* Name of the macro, such as "foo!" or "#[derive(Eq)]". */
|
||||
"macro_decl_name": "some_macro!",
|
||||
/* Optional span where the relevant part of the macro is
|
||||
defined. */
|
||||
"def_site_span": {/*...*/},
|
||||
}
|
||||
}
|
||||
],
|
||||
/* Array of attached diagnostic messages.
|
||||
This is an array of objects using the same format as the parent
|
||||
message. Children are not nested (children do not themselves
|
||||
contain "children" definitions).
|
||||
*/
|
||||
"children": [
|
||||
{
|
||||
"message": "`#[warn(unused_variables)]` on by default",
|
||||
"code": null,
|
||||
"level": "note",
|
||||
"spans": [],
|
||||
"children": [],
|
||||
"rendered": null
|
||||
},
|
||||
{
|
||||
"message": "consider prefixing with an underscore",
|
||||
"code": null,
|
||||
"level": "help",
|
||||
"spans": [
|
||||
{
|
||||
"file_name": "lib.rs",
|
||||
"byte_start": 21,
|
||||
"byte_end": 22,
|
||||
"line_start": 2,
|
||||
"line_end": 2,
|
||||
"column_start": 9,
|
||||
"column_end": 10,
|
||||
"is_primary": true,
|
||||
"text": [
|
||||
{
|
||||
"text": " let x = 123;",
|
||||
"highlight_start": 9,
|
||||
"highlight_end": 10
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": "_x",
|
||||
"suggestion_applicability": "MachineApplicable",
|
||||
"expansion": null
|
||||
}
|
||||
],
|
||||
"children": [],
|
||||
"rendered": null
|
||||
}
|
||||
],
|
||||
/* Optional string of the rendered version of the diagnostic as displayed
|
||||
by rustc. Note that this may be influenced by the `--json` flag.
|
||||
*/
|
||||
"rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n |\n2 | let x = 123;\n | ^ help: consider prefixing with an underscore: `_x`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n"
|
||||
}
|
||||
```
|
||||
|
||||
## Artifact notifications
|
||||
|
||||
Artifact notifications are emitted when the [`--json=artifacts`
|
||||
flag][option-json] is used. They indicate that a file artifact has been saved
|
||||
to disk. More information about emit kinds may be found in the [`--emit`
|
||||
flag][option-emit] documentation.
|
||||
|
||||
```javascript
|
||||
{
|
||||
/* The filename that was generated. */
|
||||
"artifact": "libfoo.rlib",
|
||||
/* The kind of artifact that was generated. Possible values:
|
||||
- "link": The generated crate as specified by the crate-type.
|
||||
- "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
|
||||
- "metadata": The Rust `.rmeta` file containing metadata about the crate.
|
||||
- "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature.
|
||||
*/
|
||||
"emit": "link"
|
||||
}
|
||||
```
|
||||
|
||||
[option-emit]: command-line-arguments.md#option-emit
|
||||
[option-error-format]: command-line-arguments.md#option-error-format
|
||||
[option-json]: command-line-arguments.md#option-json
|
||||
|
|
@ -222,3 +222,28 @@ error: invalid `crate_type` value
|
|||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
```
|
||||
|
||||
## const-err
|
||||
|
||||
This lint detects expressions that will always panic at runtime and would be an
|
||||
error in a `const` context.
|
||||
|
||||
```rust,ignore
|
||||
let _ = [0; 4][4];
|
||||
```
|
||||
|
||||
This will produce:
|
||||
|
||||
```text
|
||||
error: index out of bounds: the len is 4 but the index is 4
|
||||
--> src/lib.rs:1:9
|
||||
|
|
||||
1 | let _ = [0; 4][4];
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
```
|
||||
|
||||
## order-dependent-trait-objects
|
||||
|
||||
This lint detects a trait coherency violation that would allow creating two
|
||||
trait impls for the same dynamic trait object involving marker traits.
|
||||
|
|
|
|||
|
|
@ -125,6 +125,17 @@ RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \
|
|||
cargo build --release --target=x86_64-unknown-linux-gnu
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- It is recommended to pass `-Cllvm-args=-pgo-warn-missing-function` during the
|
||||
`-Cprofile-use` phase. LLVM by default does not warn if it cannot find
|
||||
profiling data for a given function. Enabling this warning will make it
|
||||
easier to spot errors in your setup.
|
||||
|
||||
- There is a [known issue](https://github.com/rust-lang/cargo/issues/7416) in
|
||||
Cargo prior to version 1.39 that will prevent PGO from working correctly. Be
|
||||
sure to use Cargo 1.39 or newer when doing PGO.
|
||||
|
||||
## Further Reading
|
||||
|
||||
`rustc`'s PGO support relies entirely on LLVM's implementation of the feature
|
||||
|
|
|
|||
80
src/doc/unstable-book/src/compiler-flags/report-time.md
Normal file
80
src/doc/unstable-book/src/compiler-flags/report-time.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# `report-time`
|
||||
|
||||
The tracking issue for this feature is: [#64888]
|
||||
|
||||
[#64888]: https://github.com/rust-lang/rust/issues/64888
|
||||
|
||||
------------------------
|
||||
|
||||
The `report-time` feature adds a possibility to report execution time of the
|
||||
tests generated via `libtest`.
|
||||
|
||||
This is unstable feature, so you have to provide `-Zunstable-options` to get
|
||||
this feature working.
|
||||
|
||||
Sample usage command:
|
||||
|
||||
```sh
|
||||
./test_executable -Zunstable-options --report-time
|
||||
```
|
||||
|
||||
Available options:
|
||||
|
||||
```sh
|
||||
--report-time [plain|colored]
|
||||
Show execution time of each test. Awailable values:
|
||||
plain = do not colorize the execution time (default);
|
||||
colored = colorize output according to the `color`
|
||||
parameter value;
|
||||
Threshold values for colorized output can be
|
||||
configured via
|
||||
`RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
|
||||
and
|
||||
`RUST_TEST_TIME_DOCTEST` environment variables.
|
||||
Expected format of environment variable is
|
||||
`VARIABLE=WARN_TIME,CRITICAL_TIME`.
|
||||
Not available for --format=terse
|
||||
--ensure-time
|
||||
Treat excess of the test execution time limit as
|
||||
error.
|
||||
Threshold values for this option can be configured via
|
||||
`RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
|
||||
and
|
||||
`RUST_TEST_TIME_DOCTEST` environment variables.
|
||||
Expected format of environment variable is
|
||||
`VARIABLE=WARN_TIME,CRITICAL_TIME`.
|
||||
`CRITICAL_TIME` here means the limit that should not be
|
||||
exceeded by test.
|
||||
```
|
||||
|
||||
Example of the environment variable format:
|
||||
|
||||
```sh
|
||||
RUST_TEST_TIME_UNIT=100,200
|
||||
```
|
||||
|
||||
where 100 stands for warn time, and 200 stands for critical time.
|
||||
|
||||
## Examples
|
||||
|
||||
```sh
|
||||
cargo test --tests -- -Zunstable-options --report-time
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
|
||||
Running target/debug/deps/example-27fb188025bec02c
|
||||
|
||||
running 3 tests
|
||||
test tests::unit_test_quick ... ok <0.000s>
|
||||
test tests::unit_test_warn ... ok <0.055s>
|
||||
test tests::unit_test_critical ... ok <0.110s>
|
||||
|
||||
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
||||
Running target/debug/deps/tests-cedb06f6526d15d9
|
||||
|
||||
running 3 tests
|
||||
test unit_test_quick ... ok <0.000s>
|
||||
test unit_test_warn ... ok <0.550s>
|
||||
test unit_test_critical ... ok <1.100s>
|
||||
|
||||
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
```
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# `track_caller`
|
||||
|
||||
The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
|
||||
|
||||
------------------------
|
||||
|
|
@ -142,6 +142,9 @@ impl<T> Box<T> {
|
|||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
|
||||
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
|
||||
if layout.size() == 0 {
|
||||
return Box(NonNull::dangling().into())
|
||||
}
|
||||
let ptr = unsafe {
|
||||
Global.alloc(layout)
|
||||
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
|
||||
|
|
@ -182,9 +185,16 @@ impl<T> Box<[T]> {
|
|||
#[unstable(feature = "new_uninit", issue = "63291")]
|
||||
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
|
||||
let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
|
||||
let ptr = unsafe { alloc::alloc(layout) };
|
||||
let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
|
||||
let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) };
|
||||
let ptr = if layout.size() == 0 {
|
||||
NonNull::dangling()
|
||||
} else {
|
||||
unsafe {
|
||||
Global.alloc(layout)
|
||||
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
|
||||
.cast()
|
||||
}
|
||||
};
|
||||
let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) };
|
||||
Box(Unique::from(slice))
|
||||
}
|
||||
}
|
||||
|
|
@ -871,11 +881,33 @@ impl<I: Iterator + ?Sized> Iterator for Box<I> {
|
|||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
(**self).nth(n)
|
||||
}
|
||||
fn last(self) -> Option<I::Item> {
|
||||
BoxIter::last(self)
|
||||
}
|
||||
}
|
||||
|
||||
trait BoxIter {
|
||||
type Item;
|
||||
fn last(self) -> Option<Self::Item>;
|
||||
}
|
||||
|
||||
impl<I: Iterator + ?Sized> BoxIter for Box<I> {
|
||||
type Item = I::Item;
|
||||
default fn last(self) -> Option<I::Item> {
|
||||
#[inline]
|
||||
fn some<T>(_: Option<T>, x: T) -> Option<T> {
|
||||
Some(x)
|
||||
}
|
||||
|
||||
self.fold(None, some)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specialization for sized `I`s that uses `I`s implementation of `last()`
|
||||
/// instead of the default.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator + Sized> Iterator for Box<I> {
|
||||
fn last(self) -> Option<I::Item> where I: Sized {
|
||||
impl<I: Iterator> BoxIter for Box<I> {
|
||||
fn last(self) -> Option<I::Item> {
|
||||
(*self).last()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// to TreeMap
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use core::cmp::Ordering::{Less, Greater, Equal};
|
||||
use core::cmp::{max, min};
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::{Peekable, FromIterator, FusedIterator};
|
||||
|
|
@ -109,6 +109,77 @@ pub struct Range<'a, T: 'a> {
|
|||
iter: btree_map::Range<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// Core of SymmetricDifference and Union.
|
||||
/// More efficient than btree.map.MergeIter,
|
||||
/// and crucially for SymmetricDifference, nexts() reports on both sides.
|
||||
#[derive(Clone)]
|
||||
struct MergeIterInner<I>
|
||||
where I: Iterator,
|
||||
I::Item: Copy,
|
||||
{
|
||||
a: I,
|
||||
b: I,
|
||||
peeked: Option<MergeIterPeeked<I>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum MergeIterPeeked<I: Iterator> {
|
||||
A(I::Item),
|
||||
B(I::Item),
|
||||
}
|
||||
|
||||
impl<I> MergeIterInner<I>
|
||||
where I: ExactSizeIterator + FusedIterator,
|
||||
I::Item: Copy + Ord,
|
||||
{
|
||||
fn new(a: I, b: I) -> Self {
|
||||
MergeIterInner { a, b, peeked: None }
|
||||
}
|
||||
|
||||
fn nexts(&mut self) -> (Option<I::Item>, Option<I::Item>) {
|
||||
let mut a_next = match self.peeked {
|
||||
Some(MergeIterPeeked::A(next)) => Some(next),
|
||||
_ => self.a.next(),
|
||||
};
|
||||
let mut b_next = match self.peeked {
|
||||
Some(MergeIterPeeked::B(next)) => Some(next),
|
||||
_ => self.b.next(),
|
||||
};
|
||||
let ord = match (a_next, b_next) {
|
||||
(None, None) => Equal,
|
||||
(_, None) => Less,
|
||||
(None, _) => Greater,
|
||||
(Some(a1), Some(b1)) => a1.cmp(&b1),
|
||||
};
|
||||
self.peeked = match ord {
|
||||
Less => b_next.take().map(MergeIterPeeked::B),
|
||||
Equal => None,
|
||||
Greater => a_next.take().map(MergeIterPeeked::A),
|
||||
};
|
||||
(a_next, b_next)
|
||||
}
|
||||
|
||||
fn lens(&self) -> (usize, usize) {
|
||||
match self.peeked {
|
||||
Some(MergeIterPeeked::A(_)) => (1 + self.a.len(), self.b.len()),
|
||||
Some(MergeIterPeeked::B(_)) => (self.a.len(), 1 + self.b.len()),
|
||||
_ => (self.a.len(), self.b.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Debug for MergeIterInner<I>
|
||||
where I: Iterator + Debug,
|
||||
I::Item: Copy + Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MergeIterInner")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the difference of `BTreeSet`s.
|
||||
///
|
||||
/// This `struct` is created by the [`difference`] method on [`BTreeSet`].
|
||||
|
|
@ -120,6 +191,7 @@ pub struct Range<'a, T: 'a> {
|
|||
pub struct Difference<'a, T: 'a> {
|
||||
inner: DifferenceInner<'a, T>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum DifferenceInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
// iterate all of self and some of other, spotting matches along the way
|
||||
|
|
@ -137,21 +209,7 @@ enum DifferenceInner<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => f
|
||||
.debug_tuple("Difference")
|
||||
.field(&self_iter)
|
||||
.field(&other_iter)
|
||||
.finish(),
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set: _,
|
||||
} => f.debug_tuple("Difference").field(&self_iter).finish(),
|
||||
DifferenceInner::Iterate(iter) => f.debug_tuple("Difference").field(&iter).finish(),
|
||||
}
|
||||
f.debug_tuple("Difference").field(&self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,18 +221,12 @@ impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
|
|||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SymmetricDifference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("SymmetricDifference")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
f.debug_tuple("SymmetricDifference").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +241,7 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
|
|||
pub struct Intersection<'a, T: 'a> {
|
||||
inner: IntersectionInner<'a, T>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum IntersectionInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
// iterate similarly sized sets jointly, spotting matches along the way
|
||||
|
|
@ -206,23 +259,7 @@ enum IntersectionInner<'a, T: 'a> {
|
|||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
a,
|
||||
b,
|
||||
} => f
|
||||
.debug_tuple("Intersection")
|
||||
.field(&a)
|
||||
.field(&b)
|
||||
.finish(),
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set: _,
|
||||
} => f.debug_tuple("Intersection").field(&small_iter).finish(),
|
||||
IntersectionInner::Answer(answer) => {
|
||||
f.debug_tuple("Intersection").field(&answer).finish()
|
||||
}
|
||||
}
|
||||
f.debug_tuple("Intersection").field(&self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,18 +271,12 @@ impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
|
|||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`union`]: struct.BTreeSet.html#method.union
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Union<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
pub struct Union<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Union<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Union")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
f.debug_tuple("Union").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,19 +386,16 @@ impl<T: Ord> BTreeSet<T> {
|
|||
self_iter.next_back();
|
||||
DifferenceInner::Iterate(self_iter)
|
||||
}
|
||||
_ => {
|
||||
if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
}
|
||||
} else {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
other_iter: other.iter().peekable(),
|
||||
}
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
}
|
||||
}
|
||||
_ => DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
other_iter: other.iter().peekable(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -396,10 +424,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
pub fn symmetric_difference<'a>(&'a self,
|
||||
other: &'a BTreeSet<T>)
|
||||
-> SymmetricDifference<'a, T> {
|
||||
SymmetricDifference {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
}
|
||||
SymmetricDifference(MergeIterInner::new(self.iter(), other.iter()))
|
||||
}
|
||||
|
||||
/// Visits the values representing the intersection,
|
||||
|
|
@ -447,24 +472,22 @@ impl<T: Ord> BTreeSet<T> {
|
|||
(Greater, _) | (_, Less) => IntersectionInner::Answer(None),
|
||||
(Equal, _) => IntersectionInner::Answer(Some(self_min)),
|
||||
(_, Equal) => IntersectionInner::Answer(Some(self_max)),
|
||||
_ => {
|
||||
if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
IntersectionInner::Search {
|
||||
small_iter: self.iter(),
|
||||
large_set: other,
|
||||
}
|
||||
} else if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
IntersectionInner::Search {
|
||||
small_iter: other.iter(),
|
||||
large_set: self,
|
||||
}
|
||||
} else {
|
||||
IntersectionInner::Stitch {
|
||||
a: self.iter(),
|
||||
b: other.iter(),
|
||||
}
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: self.iter(),
|
||||
large_set: other,
|
||||
}
|
||||
}
|
||||
_ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: other.iter(),
|
||||
large_set: self,
|
||||
}
|
||||
}
|
||||
_ => IntersectionInner::Stitch {
|
||||
a: self.iter(),
|
||||
b: other.iter(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -489,10 +512,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
|
||||
Union {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
}
|
||||
Union(MergeIterInner::new(self.iter(), other.iter()))
|
||||
}
|
||||
|
||||
/// Clears the set, removing all values.
|
||||
|
|
@ -1166,15 +1186,6 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> {
|
|||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Range<'_, T> {}
|
||||
|
||||
/// Compares `x` and `y`, but return `short` if x is None and `long` if y is None
|
||||
fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering) -> Ordering {
|
||||
match (x, y) {
|
||||
(None, _) => short,
|
||||
(_, None) => long,
|
||||
(Some(x1), Some(y1)) => x1.cmp(y1),
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Difference<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
|
|
@ -1261,10 +1272,7 @@ impl<T: Ord> FusedIterator for Difference<'_, T> {}
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for SymmetricDifference<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
SymmetricDifference {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
SymmetricDifference(self.0.clone())
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -1273,19 +1281,19 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
|
|||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => {
|
||||
self.a.next();
|
||||
self.b.next();
|
||||
}
|
||||
Greater => return self.b.next(),
|
||||
let (a_next, b_next) = self.0.nexts();
|
||||
if a_next.and(b_next).is_none() {
|
||||
return a_next.or(b_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(self.a.len() + self.b.len()))
|
||||
let (a_len, b_len) = self.0.lens();
|
||||
// No checked_add, because even if a and b refer to the same set,
|
||||
// and T is an empty type, the storage overhead of sets limits
|
||||
// the number of elements to less than half the range of usize.
|
||||
(0, Some(a_len + b_len))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1311,7 +1319,7 @@ impl<T> Clone for Intersection<'_, T> {
|
|||
small_iter: small_iter.clone(),
|
||||
large_set,
|
||||
},
|
||||
IntersectionInner::Answer(answer) => IntersectionInner::Answer(answer.clone()),
|
||||
IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1365,10 +1373,7 @@ impl<T: Ord> FusedIterator for Intersection<'_, T> {}
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Union<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Union {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
Union(self.0.clone())
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -1376,19 +1381,13 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
|
|||
type Item = &'a T;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => self.a.next(),
|
||||
Equal => {
|
||||
self.b.next();
|
||||
self.a.next()
|
||||
}
|
||||
Greater => self.b.next(),
|
||||
}
|
||||
let (a_next, b_next) = self.0.nexts();
|
||||
a_next.or(b_next)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let a_len = self.a.len();
|
||||
let b_len = self.b.len();
|
||||
let (a_len, b_len) = self.0.lens();
|
||||
// No checked_add - see SymmetricDifference::size_hint.
|
||||
(max(a_len, b_len), Some(a_len + b_len))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
use core::array::LengthAtMost32;
|
||||
use core::cmp::{self, Ordering};
|
||||
use core::fmt;
|
||||
use core::iter::{repeat_with, FromIterator, FusedIterator};
|
||||
use core::mem;
|
||||
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
|
||||
use core::mem::{self, replace};
|
||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||
use core::ops::{Index, IndexMut, RangeBounds, Try};
|
||||
use core::ptr::{self, NonNull};
|
||||
|
|
@ -57,11 +57,88 @@ pub struct VecDeque<T> {
|
|||
buf: RawVec<T>,
|
||||
}
|
||||
|
||||
/// PairSlices pairs up equal length slice parts of two deques
|
||||
///
|
||||
/// For example, given deques "A" and "B" with the following division into slices:
|
||||
///
|
||||
/// A: [0 1 2] [3 4 5]
|
||||
/// B: [a b] [c d e]
|
||||
///
|
||||
/// It produces the following sequence of matching slices:
|
||||
///
|
||||
/// ([0 1], [a b])
|
||||
/// ([2], [c])
|
||||
/// ([3 4], [d e])
|
||||
///
|
||||
/// and the uneven remainder of either A or B is skipped.
|
||||
struct PairSlices<'a, 'b, T> {
|
||||
a0: &'a mut [T],
|
||||
a1: &'a mut [T],
|
||||
b0: &'b [T],
|
||||
b1: &'b [T],
|
||||
}
|
||||
|
||||
impl<'a, 'b, T> PairSlices<'a, 'b, T> {
|
||||
fn from(to: &'a mut VecDeque<T>, from: &'b VecDeque<T>) -> Self {
|
||||
let (a0, a1) = to.as_mut_slices();
|
||||
let (b0, b1) = from.as_slices();
|
||||
PairSlices { a0, a1, b0, b1 }
|
||||
}
|
||||
|
||||
fn has_remainder(&self) -> bool {
|
||||
!self.b0.is_empty()
|
||||
}
|
||||
|
||||
fn remainder(self) -> impl Iterator<Item=&'b [T]> {
|
||||
once(self.b0).chain(once(self.b1))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T>
|
||||
{
|
||||
type Item = (&'a mut [T], &'b [T]);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Get next part length
|
||||
let part = cmp::min(self.a0.len(), self.b0.len());
|
||||
if part == 0 {
|
||||
return None;
|
||||
}
|
||||
let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part);
|
||||
let (q0, q1) = self.b0.split_at(part);
|
||||
|
||||
// Move a1 into a0, if it's empty (and b1, b0 the same way).
|
||||
self.a0 = p1;
|
||||
self.b0 = q1;
|
||||
if self.a0.is_empty() {
|
||||
self.a0 = replace(&mut self.a1, &mut []);
|
||||
}
|
||||
if self.b0.is_empty() {
|
||||
self.b0 = replace(&mut self.b1, &[]);
|
||||
}
|
||||
Some((p0, q0))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Clone> Clone for VecDeque<T> {
|
||||
fn clone(&self) -> VecDeque<T> {
|
||||
self.iter().cloned().collect()
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, other: &Self) {
|
||||
self.truncate(other.len());
|
||||
|
||||
let mut iter = PairSlices::from(self, other);
|
||||
while let Some((dst, src)) = iter.next() {
|
||||
dst.clone_from_slice(&src);
|
||||
}
|
||||
|
||||
if iter.has_remainder() {
|
||||
for remainder in iter.remainder() {
|
||||
self.extend(remainder.iter().cloned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -2209,6 +2286,16 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
|||
final_res
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
if n >= count(self.tail, self.head, self.ring.len()) {
|
||||
self.tail = self.head;
|
||||
None
|
||||
} else {
|
||||
self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<&'a T> {
|
||||
self.next_back()
|
||||
|
|
@ -2327,6 +2414,16 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
|||
back.iter_mut().fold(accum, &mut f)
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
if n >= count(self.tail, self.head, self.ring.len()) {
|
||||
self.tail = self.head;
|
||||
None
|
||||
} else {
|
||||
self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<&'a mut T> {
|
||||
self.next_back()
|
||||
|
|
|
|||
|
|
@ -361,6 +361,29 @@ fn test_vec_from_vecdeque() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_from() {
|
||||
let m = vec![1; 8];
|
||||
let n = vec![2; 12];
|
||||
for pfv in 0..8 {
|
||||
for pfu in 0..8 {
|
||||
for longer in 0..2 {
|
||||
let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) };
|
||||
let mut v = VecDeque::from(vr.clone());
|
||||
for _ in 0..pfv {
|
||||
v.push_front(1);
|
||||
}
|
||||
let mut u = VecDeque::from(ur.clone());
|
||||
for _ in 0..pfu {
|
||||
u.push_front(2);
|
||||
}
|
||||
v.clone_from(&u);
|
||||
assert_eq!(&v, &u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_53529() {
|
||||
use crate::boxed::Box;
|
||||
|
|
|
|||
|
|
@ -80,24 +80,210 @@
|
|||
//! arguments which have names. Like with positional parameters, it is not
|
||||
//! valid to provide named parameters that are unused by the format string.
|
||||
//!
|
||||
//! ## Argument types
|
||||
//! # Formatting Parameters
|
||||
//!
|
||||
//! Each argument's type is dictated by the format string.
|
||||
//! There are various parameters which require a particular type, however.
|
||||
//! An example is the `{:.*}` syntax, which sets the number of decimal places
|
||||
//! in floating-point types:
|
||||
//! Each argument being formatted can be transformed by a number of formatting
|
||||
//! parameters (corresponding to `format_spec` in the syntax above). These
|
||||
//! parameters affect the string representation of what's being formatted.
|
||||
//!
|
||||
//! ## Width
|
||||
//!
|
||||
//! ```
|
||||
//! let formatted_number = format!("{:.*}", 2, 1.234567);
|
||||
//!
|
||||
//! assert_eq!("1.23", formatted_number)
|
||||
//! // All of these print "Hello x !"
|
||||
//! println!("Hello {:5}!", "x");
|
||||
//! println!("Hello {:1$}!", "x", 5);
|
||||
//! println!("Hello {1:0$}!", 5, "x");
|
||||
//! println!("Hello {:width$}!", "x", width = 5);
|
||||
//! ```
|
||||
//!
|
||||
//! If this syntax is used, then the number of characters to print precedes the
|
||||
//! actual object being formatted, and the number of characters must have the
|
||||
//! type [`usize`].
|
||||
//! This is a parameter for the "minimum width" that the format should take up.
|
||||
//! If the value's string does not fill up this many characters, then the
|
||||
//! padding specified by fill/alignment will be used to take up the required
|
||||
//! space (see below).
|
||||
//!
|
||||
//! ## Formatting traits
|
||||
//! The value for the width can also be provided as a [`usize`] in the list of
|
||||
//! parameters by adding a postfix `$`, indicating that the second argument is
|
||||
//! a [`usize`] specifying the width.
|
||||
//!
|
||||
//! Referring to an argument with the dollar syntax does not affect the "next
|
||||
//! argument" counter, so it's usually a good idea to refer to arguments by
|
||||
//! position, or use named arguments.
|
||||
//!
|
||||
//! ## Fill/Alignment
|
||||
//!
|
||||
//! ```
|
||||
//! assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !");
|
||||
//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!");
|
||||
//! assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !");
|
||||
//! assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!");
|
||||
//! ```
|
||||
//!
|
||||
//! The optional fill character and alignment is provided normally in conjunction with the
|
||||
//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`.
|
||||
//! This indicates that if the value being formatted is smaller than
|
||||
//! `width` some extra characters will be printed around it.
|
||||
//! Filling comes in the following variants for different alignments:
|
||||
//!
|
||||
//! * `[fill]<` - the argument is left-aligned in `width` columns
|
||||
//! * `[fill]^` - the argument is center-aligned in `width` columns
|
||||
//! * `[fill]>` - the argument is right-aligned in `width` columns
|
||||
//!
|
||||
//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
|
||||
//! left-aligned. The
|
||||
//! defaults for numeric formatters is also a space but with right-alignment. If
|
||||
//! the `0` flag (see below) is specified for numerics, then the implicit fill character is
|
||||
//! `0`.
|
||||
//!
|
||||
//! Note that alignment may not be implemented by some types. In particular, it
|
||||
//! is not generally implemented for the `Debug` trait. A good way to ensure
|
||||
//! padding is applied is to format your input, then pad this resulting string
|
||||
//! to obtain your output:
|
||||
//!
|
||||
//! ```
|
||||
//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello Some("hi") !"
|
||||
//! ```
|
||||
//!
|
||||
//! ## Sign/`#`/`0`
|
||||
//!
|
||||
//! ```
|
||||
//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!");
|
||||
//! assert_eq!(format!("{:#x}!", 27), "0x1b!");
|
||||
//! assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!");
|
||||
//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!");
|
||||
//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!");
|
||||
//! ```
|
||||
//!
|
||||
//! These are all flags altering the behavior of the formatter.
|
||||
//!
|
||||
//! * `+` - This is intended for numeric types and indicates that the sign
|
||||
//! should always be printed. Positive signs are never printed by
|
||||
//! default, and the negative sign is only printed by default for the
|
||||
//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`)
|
||||
//! should always be printed.
|
||||
//! * `-` - Currently not used
|
||||
//! * `#` - This flag is indicates that the "alternate" form of printing should
|
||||
//! be used. The alternate forms are:
|
||||
//! * `#?` - pretty-print the [`Debug`] formatting
|
||||
//! * `#x` - precedes the argument with a `0x`
|
||||
//! * `#X` - precedes the argument with a `0x`
|
||||
//! * `#b` - precedes the argument with a `0b`
|
||||
//! * `#o` - precedes the argument with a `0o`
|
||||
//! * `0` - This is used to indicate for integer formats that the padding to `width` should
|
||||
//! both be done with a `0` character as well as be sign-aware. A format
|
||||
//! like `{:08}` would yield `00000001` for the integer `1`, while the
|
||||
//! same format would yield `-0000001` for the integer `-1`. Notice that
|
||||
//! the negative version has one fewer zero than the positive version.
|
||||
//! Note that padding zeroes are always placed after the sign (if any)
|
||||
//! and before the digits. When used together with the `#` flag, a similar
|
||||
//! rule applies: padding zeroes are inserted after the prefix but before
|
||||
//! the digits. The prefix is included in the total width.
|
||||
//!
|
||||
//! ## Precision
|
||||
//!
|
||||
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
|
||||
//! longer than this width, then it is truncated down to this many characters and that truncated
|
||||
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
|
||||
//!
|
||||
//! For integral types, this is ignored.
|
||||
//!
|
||||
//! For floating-point types, this indicates how many digits after the decimal point should be
|
||||
//! printed.
|
||||
//!
|
||||
//! There are three possible ways to specify the desired `precision`:
|
||||
//!
|
||||
//! 1. An integer `.N`:
|
||||
//!
|
||||
//! the integer `N` itself is the precision.
|
||||
//!
|
||||
//! 2. An integer or name followed by dollar sign `.N$`:
|
||||
//!
|
||||
//! use format *argument* `N` (which must be a `usize`) as the precision.
|
||||
//!
|
||||
//! 3. An asterisk `.*`:
|
||||
//!
|
||||
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
|
||||
//! first input holds the `usize` precision, and the second holds the value to print. Note that
|
||||
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
|
||||
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
|
||||
//!
|
||||
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
|
||||
//!
|
||||
//! ```
|
||||
//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
|
||||
//! println!("Hello {0} is {1:.5}", "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
|
||||
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
|
||||
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
|
||||
//! // specified in first of next two args (5)}
|
||||
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
|
||||
//! // specified in its predecessor (5)}
|
||||
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
|
||||
//! // in arg "prec" (5)}
|
||||
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
||||
//! ```
|
||||
//!
|
||||
//! While these:
|
||||
//!
|
||||
//! ```
|
||||
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
|
||||
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
|
||||
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
|
||||
//! ```
|
||||
//!
|
||||
//! print two significantly different things:
|
||||
//!
|
||||
//! ```text
|
||||
//! Hello, `1234.560` has 3 fractional digits
|
||||
//! Hello, `123` has 3 characters
|
||||
//! Hello, ` 123` has 3 right-aligned characters
|
||||
//! ```
|
||||
//!
|
||||
//! # Escaping
|
||||
//!
|
||||
//! The literal characters `{` and `}` may be included in a string by preceding
|
||||
//! them with the same character. For example, the `{` character is escaped with
|
||||
//! `{{` and the `}` character is escaped with `}}`.
|
||||
//!
|
||||
//! ```
|
||||
//! assert_eq!(format!("Hello {{}}"), "Hello {}");
|
||||
//! assert_eq!(format!("{{ Hello"), "{ Hello");
|
||||
//! ```
|
||||
//!
|
||||
//! # Syntax
|
||||
//!
|
||||
//! To summarize, here you can find the full grammar of format strings.
|
||||
//! The syntax for the formatting language used is drawn from other languages,
|
||||
//! so it should not be too alien. Arguments are formatted with Python-like
|
||||
//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like
|
||||
//! `%`. The actual grammar for the formatting syntax is:
|
||||
//!
|
||||
//! ```text
|
||||
//! format_string := <text> [ maybe-format <text> ] *
|
||||
//! maybe-format := '{' '{' | '}' '}' | <format>
|
||||
//! format := '{' [ argument ] [ ':' format_spec ] '}'
|
||||
//! argument := integer | identifier
|
||||
//!
|
||||
//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
|
||||
//! fill := character
|
||||
//! align := '<' | '^' | '>'
|
||||
//! sign := '+' | '-'
|
||||
//! width := count
|
||||
//! precision := count | '*'
|
||||
//! type := identifier | '?' | ''
|
||||
//! count := parameter | integer
|
||||
//! parameter := argument '$'
|
||||
//! ```
|
||||
//!
|
||||
//! # Formatting traits
|
||||
//!
|
||||
//! When requesting that an argument be formatted with a particular type, you
|
||||
//! are actually requesting that an argument ascribes to a particular trait.
|
||||
|
|
@ -220,7 +406,7 @@
|
|||
//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\"");
|
||||
//! ```
|
||||
//!
|
||||
//! ## Related macros
|
||||
//! # Related macros
|
||||
//!
|
||||
//! There are a number of related macros in the [`format!`] family. The ones that
|
||||
//! are currently implemented are:
|
||||
|
|
@ -300,185 +486,6 @@
|
|||
//! it would internally pass around this structure until it has been determined
|
||||
//! where output should go to.
|
||||
//!
|
||||
//! # Syntax
|
||||
//!
|
||||
//! The syntax for the formatting language used is drawn from other languages,
|
||||
//! so it should not be too alien. Arguments are formatted with Python-like
|
||||
//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like
|
||||
//! `%`. The actual grammar for the formatting syntax is:
|
||||
//!
|
||||
//! ```text
|
||||
//! format_string := <text> [ maybe-format <text> ] *
|
||||
//! maybe-format := '{' '{' | '}' '}' | <format>
|
||||
//! format := '{' [ argument ] [ ':' format_spec ] '}'
|
||||
//! argument := integer | identifier
|
||||
//!
|
||||
//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
|
||||
//! fill := character
|
||||
//! align := '<' | '^' | '>'
|
||||
//! sign := '+' | '-'
|
||||
//! width := count
|
||||
//! precision := count | '*'
|
||||
//! type := identifier | '?' | ''
|
||||
//! count := parameter | integer
|
||||
//! parameter := argument '$'
|
||||
//! ```
|
||||
//!
|
||||
//! # Formatting Parameters
|
||||
//!
|
||||
//! Each argument being formatted can be transformed by a number of formatting
|
||||
//! parameters (corresponding to `format_spec` in the syntax above). These
|
||||
//! parameters affect the string representation of what's being formatted.
|
||||
//!
|
||||
//! ## Fill/Alignment
|
||||
//!
|
||||
//! The fill character is provided normally in conjunction with the
|
||||
//! [`width`](#width)
|
||||
//! parameter. This indicates that if the value being formatted is smaller than
|
||||
//! `width` some extra characters will be printed around it. The extra
|
||||
//! characters are specified by `fill`, and the alignment can be one of the
|
||||
//! following options:
|
||||
//!
|
||||
//! * `<` - the argument is left-aligned in `width` columns
|
||||
//! * `^` - the argument is center-aligned in `width` columns
|
||||
//! * `>` - the argument is right-aligned in `width` columns
|
||||
//!
|
||||
//! Note that alignment may not be implemented by some types. In particular, it
|
||||
//! is not generally implemented for the `Debug` trait. A good way to ensure
|
||||
//! padding is applied is to format your input, then use this resulting string
|
||||
//! to pad your output.
|
||||
//!
|
||||
//! ## Sign/`#`/`0`
|
||||
//!
|
||||
//! These can all be interpreted as flags for a particular formatter.
|
||||
//!
|
||||
//! * `+` - This is intended for numeric types and indicates that the sign
|
||||
//! should always be printed. Positive signs are never printed by
|
||||
//! default, and the negative sign is only printed by default for the
|
||||
//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`)
|
||||
//! should always be printed.
|
||||
//! * `-` - Currently not used
|
||||
//! * `#` - This flag is indicates that the "alternate" form of printing should
|
||||
//! be used. The alternate forms are:
|
||||
//! * `#?` - pretty-print the [`Debug`] formatting
|
||||
//! * `#x` - precedes the argument with a `0x`
|
||||
//! * `#X` - precedes the argument with a `0x`
|
||||
//! * `#b` - precedes the argument with a `0b`
|
||||
//! * `#o` - precedes the argument with a `0o`
|
||||
//! * `0` - This is used to indicate for integer formats that the padding should
|
||||
//! both be done with a `0` character as well as be sign-aware. A format
|
||||
//! like `{:08}` would yield `00000001` for the integer `1`, while the
|
||||
//! same format would yield `-0000001` for the integer `-1`. Notice that
|
||||
//! the negative version has one fewer zero than the positive version.
|
||||
//! Note that padding zeroes are always placed after the sign (if any)
|
||||
//! and before the digits. When used together with the `#` flag, a similar
|
||||
//! rule applies: padding zeroes are inserted after the prefix but before
|
||||
//! the digits.
|
||||
//!
|
||||
//! ## Width
|
||||
//!
|
||||
//! This is a parameter for the "minimum width" that the format should take up.
|
||||
//! If the value's string does not fill up this many characters, then the
|
||||
//! padding specified by fill/alignment will be used to take up the required
|
||||
//! space.
|
||||
//!
|
||||
//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
|
||||
//! left-aligned. The
|
||||
//! defaults for numeric formatters is also a space but with right-alignment. If
|
||||
//! the `0` flag is specified for numerics, then the implicit fill character is
|
||||
//! `0`.
|
||||
//!
|
||||
//! The value for the width can also be provided as a [`usize`] in the list of
|
||||
//! parameters by using the dollar syntax indicating that the second argument is
|
||||
//! a [`usize`] specifying the width, for example:
|
||||
//!
|
||||
//! ```
|
||||
//! // All of these print "Hello x !"
|
||||
//! println!("Hello {:5}!", "x");
|
||||
//! println!("Hello {:1$}!", "x", 5);
|
||||
//! println!("Hello {1:0$}!", 5, "x");
|
||||
//! println!("Hello {:width$}!", "x", width = 5);
|
||||
//! ```
|
||||
//!
|
||||
//! Referring to an argument with the dollar syntax does not affect the "next
|
||||
//! argument" counter, so it's usually a good idea to refer to arguments by
|
||||
//! position, or use named arguments.
|
||||
//!
|
||||
//! ## Precision
|
||||
//!
|
||||
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
|
||||
//! longer than this width, then it is truncated down to this many characters and that truncated
|
||||
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
|
||||
//!
|
||||
//! For integral types, this is ignored.
|
||||
//!
|
||||
//! For floating-point types, this indicates how many digits after the decimal point should be
|
||||
//! printed.
|
||||
//!
|
||||
//! There are three possible ways to specify the desired `precision`:
|
||||
//!
|
||||
//! 1. An integer `.N`:
|
||||
//!
|
||||
//! the integer `N` itself is the precision.
|
||||
//!
|
||||
//! 2. An integer or name followed by dollar sign `.N$`:
|
||||
//!
|
||||
//! use format *argument* `N` (which must be a `usize`) as the precision.
|
||||
//!
|
||||
//! 3. An asterisk `.*`:
|
||||
//!
|
||||
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
|
||||
//! first input holds the `usize` precision, and the second holds the value to print. Note that
|
||||
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
|
||||
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
|
||||
//!
|
||||
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
|
||||
//!
|
||||
//! ```
|
||||
//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
|
||||
//! println!("Hello {0} is {1:.5}", "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
|
||||
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
|
||||
//!
|
||||
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
|
||||
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
|
||||
//! // specified in first of next two args (5)}
|
||||
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
|
||||
//! // specified in its predecessor (5)}
|
||||
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
||||
//!
|
||||
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
|
||||
//! // in arg "prec" (5)}
|
||||
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
||||
//! ```
|
||||
//!
|
||||
//! While these:
|
||||
//!
|
||||
//! ```
|
||||
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
|
||||
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
|
||||
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
|
||||
//! ```
|
||||
//!
|
||||
//! print two significantly different things:
|
||||
//!
|
||||
//! ```text
|
||||
//! Hello, `1234.560` has 3 fractional digits
|
||||
//! Hello, `123` has 3 characters
|
||||
//! Hello, ` 123` has 3 right-aligned characters
|
||||
//! ```
|
||||
//!
|
||||
//! # Escaping
|
||||
//!
|
||||
//! The literal characters `{` and `}` may be included in a string by preceding
|
||||
//! them with the same character. For example, the `{` character is escaped with
|
||||
//! `{{` and the `}` character is escaped with `}}`.
|
||||
//!
|
||||
//! [`usize`]: ../../std/primitive.usize.html
|
||||
//! [`isize`]: ../../std/primitive.isize.html
|
||||
//! [`i8`]: ../../std/primitive.i8.html
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@
|
|||
#![feature(maybe_uninit_extra, maybe_uninit_slice)]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(associated_type_bounds)]
|
||||
|
||||
// Allow testing this library
|
||||
|
|
@ -154,7 +153,7 @@ mod boxed {
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod collections;
|
||||
#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub mod sync;
|
||||
pub mod rc;
|
||||
pub mod raw_vec;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
//!
|
||||
//! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`,
|
||||
//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new
|
||||
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a
|
||||
//! given value is destroyed, the pointed-to value is also destroyed.
|
||||
//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a
|
||||
//! given allocation is destroyed, the value stored in that allocation (often
|
||||
//! referred to as "inner value") is also dropped.
|
||||
//!
|
||||
//! Shared references in Rust disallow mutation by default, and [`Rc`]
|
||||
//! is no exception: you cannot generally obtain a mutable reference to
|
||||
|
|
@ -21,8 +22,10 @@
|
|||
//!
|
||||
//! The [`downgrade`][downgrade] method can be used to create a non-owning
|
||||
//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
|
||||
//! to an [`Rc`], but this will return [`None`] if the value has
|
||||
//! already been dropped.
|
||||
//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has
|
||||
//! already been dropped. In other words, `Weak` pointers do not keep the value
|
||||
//! inside the allocation alive; however, they *do* keep the allocation
|
||||
//! (the backing store for the inner value) alive.
|
||||
//!
|
||||
//! A cycle between [`Rc`] pointers will never be deallocated. For this reason,
|
||||
//! [`Weak`] is used to break cycles. For example, a tree could have strong
|
||||
|
|
@ -41,13 +44,13 @@
|
|||
//! Rc::downgrade(&my_rc);
|
||||
//! ```
|
||||
//!
|
||||
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the value may have
|
||||
//! already been destroyed.
|
||||
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the inner value may have
|
||||
//! already been dropped.
|
||||
//!
|
||||
//! # Cloning references
|
||||
//!
|
||||
//! Creating a new reference from an existing reference counted pointer is done using the
|
||||
//! `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
|
||||
//! Creating a new reference to the same allocation as an existing reference counted pointer
|
||||
//! is done using the `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
|
||||
//!
|
||||
//! ```
|
||||
//! use std::rc::Rc;
|
||||
|
|
@ -93,7 +96,7 @@
|
|||
//! );
|
||||
//!
|
||||
//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc<Owner>`
|
||||
//! // value gives us a new pointer to the same `Owner` value, incrementing
|
||||
//! // gives us a new pointer to the same `Owner` allocation, incrementing
|
||||
//! // the reference count in the process.
|
||||
//! let gadget1 = Gadget {
|
||||
//! id: 1,
|
||||
|
|
@ -110,8 +113,8 @@
|
|||
//! // Despite dropping `gadget_owner`, we're still able to print out the name
|
||||
//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a
|
||||
//! // single `Rc<Owner>`, not the `Owner` it points to. As long as there are
|
||||
//! // other `Rc<Owner>` values pointing at the same `Owner`, it will remain
|
||||
//! // allocated. The field projection `gadget1.owner.name` works because
|
||||
//! // other `Rc<Owner>` pointing at the same `Owner` allocation, it will remain
|
||||
//! // live. The field projection `gadget1.owner.name` works because
|
||||
//! // `Rc<Owner>` automatically dereferences to `Owner`.
|
||||
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
|
||||
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
|
||||
|
|
@ -124,9 +127,9 @@
|
|||
//!
|
||||
//! If our requirements change, and we also need to be able to traverse from
|
||||
//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner`
|
||||
//! to `Gadget` introduces a cycle between the values. This means that their
|
||||
//! reference counts can never reach 0, and the values will remain allocated
|
||||
//! forever: a memory leak. In order to get around this, we can use [`Weak`]
|
||||
//! to `Gadget` introduces a cycle. This means that their
|
||||
//! reference counts can never reach 0, and the allocation will never be destroyed:
|
||||
//! a memory leak. In order to get around this, we can use [`Weak`]
|
||||
//! pointers.
|
||||
//!
|
||||
//! Rust actually makes it somewhat difficult to produce this loop in the first
|
||||
|
|
@ -193,10 +196,10 @@
|
|||
//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
|
||||
//!
|
||||
//! // `gadget_weak` is a `Weak<Gadget>`. Since `Weak` pointers can't
|
||||
//! // guarantee the value is still allocated, we need to call
|
||||
//! // guarantee the allocation still exists, we need to call
|
||||
//! // `upgrade`, which returns an `Option<Rc<Gadget>>`.
|
||||
//! //
|
||||
//! // In this case we know the value still exists, so we simply
|
||||
//! // In this case we know the allocation still exists, so we simply
|
||||
//! // `unwrap` the `Option`. In a more complicated program, you might
|
||||
//! // need graceful error handling for a `None` result.
|
||||
//!
|
||||
|
|
@ -365,7 +368,7 @@ impl<T> Rc<T> {
|
|||
unsafe { Pin::new_unchecked(Rc::new(value)) }
|
||||
}
|
||||
|
||||
/// Returns the contained value, if the `Rc` has exactly one strong reference.
|
||||
/// Returns the inner value, if the `Rc` has exactly one strong reference.
|
||||
///
|
||||
/// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
|
||||
/// passed in.
|
||||
|
|
@ -446,7 +449,7 @@ impl<T> Rc<mem::MaybeUninit<T>> {
|
|||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
|
|
@ -485,7 +488,7 @@ impl<T> Rc<[mem::MaybeUninit<T>]> {
|
|||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
|
|
@ -604,7 +607,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) }
|
||||
}
|
||||
|
||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||
/// Creates a new [`Weak`][weak] pointer to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
|
|
@ -625,7 +628,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
Weak { ptr: this.ptr }
|
||||
}
|
||||
|
||||
/// Gets the number of [`Weak`][weak] pointers to this value.
|
||||
/// Gets the number of [`Weak`][weak] pointers to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
|
|
@ -645,7 +648,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
this.weak() - 1
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Rc`) pointers to this value.
|
||||
/// Gets the number of strong (`Rc`) pointers to this allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -664,7 +667,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
}
|
||||
|
||||
/// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to
|
||||
/// this inner value.
|
||||
/// this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
#[inline]
|
||||
|
|
@ -672,14 +675,14 @@ impl<T: ?Sized> Rc<T> {
|
|||
Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value, if there are
|
||||
/// no other `Rc` or [`Weak`][weak] pointers to the same value.
|
||||
/// Returns a mutable reference into the given `Rc`, if there are
|
||||
/// no other `Rc` or [`Weak`][weak] pointers to the same allocation.
|
||||
///
|
||||
/// Returns [`None`] otherwise, because it is not safe to
|
||||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when it's shared.
|
||||
/// the inner value when there are other pointers.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
|
|
@ -710,7 +713,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value,
|
||||
/// Returns a mutable reference into the given `Rc`,
|
||||
/// without any check.
|
||||
///
|
||||
/// See also [`get_mut`], which is safe and does appropriate checks.
|
||||
|
|
@ -719,7 +722,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced
|
||||
/// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced
|
||||
/// for the duration of the returned borrow.
|
||||
/// This is trivially the case if no such pointers exist,
|
||||
/// for example immediately after `Rc::new`.
|
||||
|
|
@ -745,8 +748,8 @@ impl<T: ?Sized> Rc<T> {
|
|||
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_eq", since = "1.17.0")]
|
||||
/// Returns `true` if the two `Rc`s point to the same value (not
|
||||
/// just values that compare as equal).
|
||||
/// Returns `true` if the two `Rc`s point to the same allocation
|
||||
/// (in a vein similar to [`ptr::eq`]).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -760,6 +763,8 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// assert!(Rc::ptr_eq(&five, &same_five));
|
||||
/// assert!(!Rc::ptr_eq(&five, &other_five));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.ptr.as_ptr() == other.ptr.as_ptr()
|
||||
}
|
||||
|
|
@ -768,12 +773,12 @@ impl<T: ?Sized> Rc<T> {
|
|||
impl<T: Clone> Rc<T> {
|
||||
/// Makes a mutable reference into the given `Rc`.
|
||||
///
|
||||
/// If there are other `Rc` pointers to the same value, then `make_mut` will
|
||||
/// [`clone`] the inner value to ensure unique ownership. This is also
|
||||
/// If there are other `Rc` pointers to the same allocation, then `make_mut` will
|
||||
/// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also
|
||||
/// referred to as clone-on-write.
|
||||
///
|
||||
/// If there are no other `Rc` pointers to this value, then [`Weak`]
|
||||
/// pointers to this value will be dissassociated.
|
||||
/// If there are no other `Rc` pointers to this allocation, then [`Weak`]
|
||||
/// pointers to this allocation will be disassociated.
|
||||
///
|
||||
/// See also [`get_mut`], which will fail rather than cloning.
|
||||
///
|
||||
|
|
@ -794,12 +799,12 @@ impl<T: Clone> Rc<T> {
|
|||
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
|
||||
/// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything
|
||||
///
|
||||
/// // Now `data` and `other_data` point to different values.
|
||||
/// // Now `data` and `other_data` point to different allocations.
|
||||
/// assert_eq!(*data, 8);
|
||||
/// assert_eq!(*other_data, 12);
|
||||
/// ```
|
||||
///
|
||||
/// [`Weak`] pointers will be dissassociated:
|
||||
/// [`Weak`] pointers will be disassociated:
|
||||
///
|
||||
/// ```
|
||||
/// use std::rc::Rc;
|
||||
|
|
@ -837,7 +842,7 @@ impl<T: Clone> Rc<T> {
|
|||
// returned is the *only* pointer that will ever be returned to T. Our
|
||||
// reference count is guaranteed to be 1 at this point, and we required
|
||||
// the `Rc<T>` itself to be `mut`, so we're returning the only possible
|
||||
// reference to the inner value.
|
||||
// reference to the allocation.
|
||||
unsafe {
|
||||
&mut this.ptr.as_mut().value
|
||||
}
|
||||
|
|
@ -878,7 +883,7 @@ impl Rc<dyn Any> {
|
|||
|
||||
impl<T: ?Sized> Rc<T> {
|
||||
/// Allocates an `RcBox<T>` with sufficient space for
|
||||
/// a possibly-unsized value where the value has the layout provided.
|
||||
/// a possibly-unsized inner value where the value has the layout provided.
|
||||
///
|
||||
/// The function `mem_to_rcbox` is called with the data pointer
|
||||
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
|
||||
|
|
@ -908,7 +913,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
inner
|
||||
}
|
||||
|
||||
/// Allocates an `RcBox<T>` with sufficient space for an unsized value
|
||||
/// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
|
||||
// Allocate for the `RcBox<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
|
|
@ -1111,7 +1116,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
|
|||
impl<T: ?Sized> Clone for Rc<T> {
|
||||
/// Makes a clone of the `Rc` pointer.
|
||||
///
|
||||
/// This creates another pointer to the same inner value, increasing the
|
||||
/// This creates another pointer to the same allocation, increasing the
|
||||
/// strong reference count.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -1172,6 +1177,8 @@ impl<T: ?Sized + PartialEq> RcEqIdent<T> for Rc<T> {
|
|||
/// store large values, that are slow to clone, but also heavy to check for equality, causing this
|
||||
/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to
|
||||
/// the same value, than two `&T`s.
|
||||
///
|
||||
/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> {
|
||||
#[inline]
|
||||
|
|
@ -1189,9 +1196,11 @@ impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> {
|
|||
impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
|
||||
/// Equality for two `Rc`s.
|
||||
///
|
||||
/// Two `Rc`s are equal if their inner values are equal.
|
||||
/// Two `Rc`s are equal if their inner values are equal, even if they are
|
||||
/// stored in different allocation.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Rc`s that point to the same allocation are
|
||||
/// always equal.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -1212,7 +1221,8 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
|
|||
///
|
||||
/// Two `Rc`s are unequal if their inner values are unequal.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Rc`s that point to the same allocation are
|
||||
/// never unequal.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -1541,17 +1551,18 @@ impl<'a, T: 'a + Clone> RcFromIter<&'a T, slice::Iter<'a, T>> for Rc<[T]> {
|
|||
}
|
||||
|
||||
/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
|
||||
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
|
||||
///
|
||||
/// Since a `Weak` reference does not count towards ownership, it will not
|
||||
/// prevent the inner value from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present and may return [`None`]
|
||||
/// when [`upgrade`]d.
|
||||
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present. Thus it may return [`None`]
|
||||
/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation
|
||||
/// itself (the backing store) from being deallocated.
|
||||
///
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the value
|
||||
/// within [`Rc`] without extending its lifetime. It is also used to prevent
|
||||
/// circular references between [`Rc`] pointers, since mutual owning references
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the allocation
|
||||
/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to
|
||||
/// prevent circular references between [`Rc`] pointers, since mutual owning references
|
||||
/// would never allow either [`Rc`] to be dropped. For example, a tree could
|
||||
/// have strong [`Rc`] pointers from parent nodes to children, and `Weak`
|
||||
/// pointers from children back to their parents.
|
||||
|
|
@ -1750,10 +1761,10 @@ pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
|
|||
}
|
||||
|
||||
impl<T: ?Sized> Weak<T> {
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending
|
||||
/// the lifetime of the value if successful.
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
|
||||
/// dropping of the inner value if successful.
|
||||
///
|
||||
/// Returns [`None`] if the value has since been dropped.
|
||||
/// Returns [`None`] if the inner value has since been dropped.
|
||||
///
|
||||
/// [`Rc`]: struct.Rc.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html
|
||||
|
|
@ -1787,7 +1798,7 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Rc`) pointers pointing to this value.
|
||||
/// Gets the number of strong (`Rc`) pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0.
|
||||
///
|
||||
|
|
@ -1801,11 +1812,11 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the number of `Weak` pointers pointing to this value.
|
||||
/// Gets the number of `Weak` pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return `None`. If
|
||||
/// not, the returned value is at least 1, since `self` still points to the
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// [`Weak::new`]: #method.new
|
||||
#[unstable(feature = "weak_counts", issue = "57977")]
|
||||
|
|
@ -1830,14 +1841,14 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same value (not just
|
||||
/// values that compare as equal), or if both don't point to any value
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
/// [`ptr::eq`]), or if both don't point to any allocation
|
||||
/// (because they were created with `Weak::new()`).
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Since this compares pointers it means that `Weak::new()` will equal each
|
||||
/// other, even though they don't point to any value.
|
||||
/// other, even though they don't point to any allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1869,6 +1880,8 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// let third = Rc::downgrade(&third_rc);
|
||||
/// assert!(!first.ptr_eq(&third));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
#[inline]
|
||||
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
|
||||
pub fn ptr_eq(&self, other: &Self) -> bool {
|
||||
|
|
@ -1918,7 +1931,7 @@ impl<T: ?Sized> Drop for Weak<T> {
|
|||
|
||||
#[stable(feature = "rc_weak", since = "1.4.0")]
|
||||
impl<T: ?Sized> Clone for Weak<T> {
|
||||
/// Makes a clone of the `Weak` pointer that points to the same value.
|
||||
/// Makes a clone of the `Weak` pointer that points to the same allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -411,20 +411,16 @@ impl<T> [T] {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(repeat_generic_slice)]
|
||||
/// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
|
||||
/// ```
|
||||
///
|
||||
/// A panic upon overflow:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(repeat_generic_slice)]
|
||||
/// // this will panic at runtime
|
||||
/// b"0123456789abcdef".repeat(usize::max_value());
|
||||
/// ```
|
||||
#[unstable(feature = "repeat_generic_slice",
|
||||
reason = "it's on str, why not on slice?",
|
||||
issue = "48784")]
|
||||
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
|
||||
pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
|
||||
if n == 0 {
|
||||
return Vec::new();
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
///
|
||||
/// The type `Arc<T>` provides shared ownership of a value of type `T`,
|
||||
/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
|
||||
/// a new `Arc` instance, which points to the same value on the heap as the
|
||||
/// a new `Arc` instance, which points to the same allocation on the heap as the
|
||||
/// source `Arc`, while increasing a reference count. When the last `Arc`
|
||||
/// pointer to a given value is destroyed, the pointed-to value is also
|
||||
/// destroyed.
|
||||
/// pointer to a given allocation is destroyed, the value stored in that allocation (often
|
||||
/// referred to as "inner value") is also dropped.
|
||||
///
|
||||
/// Shared references in Rust disallow mutation by default, and `Arc` is no
|
||||
/// exception: you cannot generally obtain a mutable reference to something
|
||||
|
|
@ -61,7 +61,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
|
||||
/// counting. This means that it is thread-safe. The disadvantage is that
|
||||
/// atomic operations are more expensive than ordinary memory accesses. If you
|
||||
/// are not sharing reference-counted values between threads, consider using
|
||||
/// are not sharing reference-counted allocations between threads, consider using
|
||||
/// [`Rc<T>`] for lower overhead. [`Rc<T>`] is a safe default, because the
|
||||
/// compiler will catch any attempt to send an [`Rc<T>`] between threads.
|
||||
/// However, a library might choose `Arc<T>` in order to give library consumers
|
||||
|
|
@ -85,8 +85,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
///
|
||||
/// The [`downgrade`][downgrade] method can be used to create a non-owning
|
||||
/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
|
||||
/// to an `Arc`, but this will return [`None`] if the value has already been
|
||||
/// dropped.
|
||||
/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has
|
||||
/// already been dropped. In other words, `Weak` pointers do not keep the value
|
||||
/// inside the allocation alive; however, they *do* keep the allocation
|
||||
/// (the backing store for the value) alive.
|
||||
///
|
||||
/// A cycle between `Arc` pointers will never be deallocated. For this reason,
|
||||
/// [`Weak`][weak] is used to break cycles. For example, a tree could have
|
||||
|
|
@ -121,8 +123,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
|||
/// Arc::downgrade(&my_arc);
|
||||
/// ```
|
||||
///
|
||||
/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the value may have
|
||||
/// already been destroyed.
|
||||
/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the inner value may have
|
||||
/// already been dropped.
|
||||
///
|
||||
/// [arc]: struct.Arc.html
|
||||
/// [weak]: struct.Weak.html
|
||||
|
|
@ -221,17 +223,18 @@ impl<T: ?Sized> Arc<T> {
|
|||
}
|
||||
|
||||
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
|
||||
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
|
||||
///
|
||||
/// Since a `Weak` reference does not count towards ownership, it will not
|
||||
/// prevent the inner value from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present and may return [`None`]
|
||||
/// when [`upgrade`]d.
|
||||
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present. Thus it may return [`None`]
|
||||
/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation
|
||||
/// itself (the backing store) from being deallocated.
|
||||
///
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the value
|
||||
/// within [`Arc`] without extending its lifetime. It is also used to prevent
|
||||
/// circular references between [`Arc`] pointers, since mutual owning references
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the allocation
|
||||
/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to
|
||||
/// prevent circular references between [`Arc`] pointers, since mutual owning references
|
||||
/// would never allow either [`Arc`] to be dropped. For example, a tree could
|
||||
/// have strong [`Arc`] pointers from parent nodes to children, and `Weak`
|
||||
/// pointers from children back to their parents.
|
||||
|
|
@ -345,7 +348,7 @@ impl<T> Arc<T> {
|
|||
unsafe { Pin::new_unchecked(Arc::new(data)) }
|
||||
}
|
||||
|
||||
/// Returns the contained value, if the `Arc` has exactly one strong reference.
|
||||
/// Returns the inner value, if the `Arc` has exactly one strong reference.
|
||||
///
|
||||
/// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
|
||||
/// passed in.
|
||||
|
|
@ -426,7 +429,7 @@ impl<T> Arc<mem::MaybeUninit<T>> {
|
|||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
|
|
@ -465,7 +468,7 @@ impl<T> Arc<[mem::MaybeUninit<T>]> {
|
|||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
|
|
@ -584,7 +587,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) }
|
||||
}
|
||||
|
||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||
/// Creates a new [`Weak`][weak] pointer to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
|
|
@ -628,7 +631,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the number of [`Weak`][weak] pointers to this value.
|
||||
/// Gets the number of [`Weak`][weak] pointers to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
|
|
@ -659,7 +662,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
if cnt == usize::MAX { 0 } else { cnt - 1 }
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Arc`) pointers to this value.
|
||||
/// Gets the number of strong (`Arc`) pointers to this allocation.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
|
@ -710,8 +713,8 @@ impl<T: ?Sized> Arc<T> {
|
|||
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_eq", since = "1.17.0")]
|
||||
/// Returns `true` if the two `Arc`s point to the same value (not
|
||||
/// just values that compare as equal).
|
||||
/// Returns `true` if the two `Arc`s point to the same allocation
|
||||
/// (in a vein similar to [`ptr::eq`]).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -725,6 +728,8 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// assert!(Arc::ptr_eq(&five, &same_five));
|
||||
/// assert!(!Arc::ptr_eq(&five, &other_five));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.ptr.as_ptr() == other.ptr.as_ptr()
|
||||
}
|
||||
|
|
@ -732,7 +737,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for
|
||||
/// a possibly-unsized value where the value has the layout provided.
|
||||
/// a possibly-unsized inner value where the value has the layout provided.
|
||||
///
|
||||
/// The function `mem_to_arcinner` is called with the data pointer
|
||||
/// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
|
||||
|
|
@ -761,7 +766,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
inner
|
||||
}
|
||||
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for an unsized value.
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
|
||||
// Allocate for the `ArcInner<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
|
|
@ -903,7 +908,7 @@ impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
|
|||
impl<T: ?Sized> Clone for Arc<T> {
|
||||
/// Makes a clone of the `Arc` pointer.
|
||||
///
|
||||
/// This creates another pointer to the same inner value, increasing the
|
||||
/// This creates another pointer to the same allocation, increasing the
|
||||
/// strong reference count.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -965,15 +970,19 @@ impl<T: ?Sized> Receiver for Arc<T> {}
|
|||
impl<T: Clone> Arc<T> {
|
||||
/// Makes a mutable reference into the given `Arc`.
|
||||
///
|
||||
/// If there are other `Arc` or [`Weak`][weak] pointers to the same value,
|
||||
/// then `make_mut` will invoke [`clone`][clone] on the inner value to
|
||||
/// ensure unique ownership. This is also referred to as clone-on-write.
|
||||
/// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation,
|
||||
/// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
|
||||
/// to ensure unique ownership. This is also referred to as clone-on-write.
|
||||
///
|
||||
/// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates
|
||||
/// any remaining `Weak` pointers.
|
||||
///
|
||||
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
|
||||
/// [get_mut]: struct.Arc.html#method.get_mut
|
||||
/// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -988,7 +997,7 @@ impl<T: Clone> Arc<T> {
|
|||
/// *Arc::make_mut(&mut data) += 1; // Won't clone anything
|
||||
/// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
|
||||
///
|
||||
/// // Now `data` and `other_data` point to different values.
|
||||
/// // Now `data` and `other_data` point to different allocations.
|
||||
/// assert_eq!(*data, 8);
|
||||
/// assert_eq!(*other_data, 12);
|
||||
/// ```
|
||||
|
|
@ -1048,14 +1057,14 @@ impl<T: Clone> Arc<T> {
|
|||
}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
/// Returns a mutable reference to the inner value, if there are
|
||||
/// no other `Arc` or [`Weak`][weak] pointers to the same value.
|
||||
/// Returns a mutable reference into the given `Arc`, if there are
|
||||
/// no other `Arc` or [`Weak`][weak] pointers to the same allocation.
|
||||
///
|
||||
/// Returns [`None`][option] otherwise, because it is not safe to
|
||||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when it's shared.
|
||||
/// the inner value when there are other pointers.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [option]: ../../std/option/enum.Option.html
|
||||
|
|
@ -1091,7 +1100,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value,
|
||||
/// Returns a mutable reference into the given `Arc`,
|
||||
/// without any check.
|
||||
///
|
||||
/// See also [`get_mut`], which is safe and does appropriate checks.
|
||||
|
|
@ -1100,7 +1109,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced
|
||||
/// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced
|
||||
/// for the duration of the returned borrow.
|
||||
/// This is trivially the case if no such pointers exist,
|
||||
/// for example immediately after `Arc::new`.
|
||||
|
|
@ -1424,10 +1433,10 @@ impl<T> Weak<T> {
|
|||
}
|
||||
|
||||
impl<T: ?Sized> Weak<T> {
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending
|
||||
/// the lifetime of the value if successful.
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
|
||||
/// dropping of the inner value if successful.
|
||||
///
|
||||
/// Returns [`None`] if the value has since been dropped.
|
||||
/// Returns [`None`] if the inner value has since been dropped.
|
||||
///
|
||||
/// [`Arc`]: struct.Arc.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
|
|
@ -1482,7 +1491,7 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Arc`) pointers pointing to this value.
|
||||
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0.
|
||||
///
|
||||
|
|
@ -1497,17 +1506,17 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
|
||||
/// Gets an approximation of the number of `Weak` pointers pointing to this
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0. If not,
|
||||
/// the returned value is at least 1, since `self` still points to the
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// # Accuracy
|
||||
///
|
||||
/// Due to implementation details, the returned value can be off by 1 in
|
||||
/// either direction when other threads are manipulating any `Arc`s or
|
||||
/// `Weak`s pointing to the same value.
|
||||
/// `Weak`s pointing to the same allocation.
|
||||
///
|
||||
/// [`Weak::new`]: #method.new
|
||||
#[unstable(feature = "weak_counts", issue = "57977")]
|
||||
|
|
@ -1548,14 +1557,14 @@ impl<T: ?Sized> Weak<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same value (not just
|
||||
/// values that compare as equal), or if both don't point to any value
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
/// [`ptr::eq`]), or if both don't point to any allocation
|
||||
/// (because they were created with `Weak::new()`).
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Since this compares pointers it means that `Weak::new()` will equal each
|
||||
/// other, even though they don't point to any value.
|
||||
/// other, even though they don't point to any allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1587,6 +1596,8 @@ impl<T: ?Sized> Weak<T> {
|
|||
/// let third = Arc::downgrade(&third_rc);
|
||||
/// assert!(!first.ptr_eq(&third));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
#[inline]
|
||||
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
|
||||
pub fn ptr_eq(&self, other: &Self) -> bool {
|
||||
|
|
@ -1596,7 +1607,7 @@ impl<T: ?Sized> Weak<T> {
|
|||
|
||||
#[stable(feature = "arc_weak", since = "1.4.0")]
|
||||
impl<T: ?Sized> Clone for Weak<T> {
|
||||
/// Makes a clone of the `Weak` pointer that points to the same value.
|
||||
/// Makes a clone of the `Weak` pointer that points to the same allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1726,6 +1737,8 @@ impl<T: ?Sized + PartialEq> ArcEqIdent<T> for Arc<T> {
|
|||
/// store large values, that are slow to clone, but also heavy to check for equality, causing this
|
||||
/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to
|
||||
/// the same value, than two `&T`s.
|
||||
///
|
||||
/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> {
|
||||
#[inline]
|
||||
|
|
@ -1743,10 +1756,11 @@ impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> {
|
|||
impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
|
||||
/// Equality for two `Arc`s.
|
||||
///
|
||||
/// Two `Arc`s are equal if their inner values are equal.
|
||||
/// Two `Arc`s are equal if their inner values are equal, even if they are
|
||||
/// stored in different allocation.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
|
||||
/// always equal.
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Arc`s that point to the same allocation are always equal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1766,8 +1780,8 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
|
|||
///
|
||||
/// Two `Arc`s are unequal if their inner values are unequal.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
|
||||
/// never unequal.
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Arc`s that point to the same value are never unequal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
18
src/liballoc/tests/boxed.rs
Normal file
18
src/liballoc/tests/boxed.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use std::ptr::NonNull;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[test]
|
||||
fn unitialized_zero_size_box() {
|
||||
assert_eq!(
|
||||
&*Box::<()>::new_uninit() as *const _,
|
||||
NonNull::<MaybeUninit<()>>::dangling().as_ptr(),
|
||||
);
|
||||
assert_eq!(
|
||||
Box::<[()]>::new_uninit_slice(4).as_ptr(),
|
||||
NonNull::<MaybeUninit<()>>::dangling().as_ptr(),
|
||||
);
|
||||
assert_eq!(
|
||||
Box::<[String]>::new_uninit_slice(0).as_ptr(),
|
||||
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
|
||||
);
|
||||
}
|
||||
|
|
@ -221,6 +221,18 @@ fn test_symmetric_difference() {
|
|||
&[-2, 1, 5, 11, 14, 22]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_symmetric_difference_size_hint() {
|
||||
let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
|
||||
let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
|
||||
let mut iter = x.symmetric_difference(&y);
|
||||
assert_eq!(iter.size_hint(), (0, Some(5)));
|
||||
assert_eq!(iter.next(), Some(&1));
|
||||
assert_eq!(iter.size_hint(), (0, Some(4)));
|
||||
assert_eq!(iter.next(), Some(&3));
|
||||
assert_eq!(iter.size_hint(), (0, Some(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union() {
|
||||
fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
|
||||
|
|
@ -235,6 +247,18 @@ fn test_union() {
|
|||
&[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union_size_hint() {
|
||||
let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
|
||||
let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
|
||||
let mut iter = x.union(&y);
|
||||
assert_eq!(iter.size_hint(), (3, Some(5)));
|
||||
assert_eq!(iter.next(), Some(&1));
|
||||
assert_eq!(iter.size_hint(), (2, Some(4)));
|
||||
assert_eq!(iter.next(), Some(&2));
|
||||
assert_eq!(iter.size_hint(), (1, Some(2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Only tests the simple function definition with respect to intersection
|
||||
fn test_is_disjoint() {
|
||||
|
|
@ -244,7 +268,7 @@ fn test_is_disjoint() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
// Also tests the trivial function definition of is_superset
|
||||
// Also implicitly tests the trivial function definition of is_superset
|
||||
fn test_is_subset() {
|
||||
fn is_subset(a: &[i32], b: &[i32]) -> bool {
|
||||
let set_a = a.iter().collect::<BTreeSet<_>>();
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(option_flattening)]
|
||||
#![feature(pattern)]
|
||||
#![feature(repeat_generic_slice)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_reserve)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
|
@ -15,6 +15,7 @@ use std::collections::hash_map::DefaultHasher;
|
|||
|
||||
mod arc;
|
||||
mod binary_heap;
|
||||
mod boxed;
|
||||
mod btree;
|
||||
mod cow_str;
|
||||
mod fmt;
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
diff a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs (rejected hunks)
|
||||
@@ -483,7 +483,7 @@ mod slice_index {
|
||||
}
|
||||
|
||||
#[test]
|
||||
- #[cfg(not(target_arch = "asmjs"))] // hits an OOM
|
||||
+ #[cfg(not(target_arch = "js"))] // hits an OOM
|
||||
#[cfg(not(miri))] // Miri is too slow
|
||||
fn simple_big() {
|
||||
fn a_million_letter_x() -> String {
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
//! of any `'static` type through runtime reflection.
|
||||
//!
|
||||
//! `Any` itself can be used to get a `TypeId`, and has more features when used
|
||||
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
|
||||
//! `downcast_ref` methods, to test if the contained value is of a given type,
|
||||
//! and to get a reference to the inner value as a type. As `&mut Any`, there
|
||||
//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is`
|
||||
//! and `downcast_ref` methods, to test if the contained value is of a given type,
|
||||
//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there
|
||||
//! is also the `downcast_mut` method, for getting a mutable reference to the
|
||||
//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
|
||||
//! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to
|
||||
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
|
||||
//!
|
||||
//! Note that &Any is limited to testing whether a value is of a specified
|
||||
//! Note that `&dyn Any` is limited to testing whether a value is of a specified
|
||||
//! concrete type, and cannot be used to test whether a type implements a trait.
|
||||
//!
|
||||
//! [`Box`]: ../../std/boxed/struct.Box.html
|
||||
|
|
@ -445,6 +445,15 @@ impl TypeId {
|
|||
///
|
||||
/// The current implementation uses the same infrastructure as compiler
|
||||
/// diagnostics and debuginfo, but this is not guaranteed.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// std::any::type_name::<Option<String>>(),
|
||||
/// "core::option::Option<alloc::string::String>",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "type_name", since = "1.38.0")]
|
||||
#[rustc_const_unstable(feature = "const_type_name")]
|
||||
pub const fn type_name<T: ?Sized>() -> &'static str {
|
||||
|
|
|
|||
|
|
@ -229,52 +229,6 @@ pub struct Cell<T: ?Sized> {
|
|||
value: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
impl<T:Copy> Cell<T> {
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
///
|
||||
/// let five = c.get();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get(&self) -> T {
|
||||
unsafe{ *self.value.get() }
|
||||
}
|
||||
|
||||
/// Updates the contained value using a function and returns the new value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_update)]
|
||||
///
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let new = c.update(|x| x + 1);
|
||||
///
|
||||
/// assert_eq!(new, 6);
|
||||
/// assert_eq!(c.get(), 6);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "cell_update", issue = "50186")]
|
||||
pub fn update<F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
let old = self.get();
|
||||
let new = f(old);
|
||||
self.set(new);
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
|
||||
|
||||
|
|
@ -448,6 +402,52 @@ impl<T> Cell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T:Copy> Cell<T> {
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
///
|
||||
/// let five = c.get();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get(&self) -> T {
|
||||
unsafe{ *self.value.get() }
|
||||
}
|
||||
|
||||
/// Updates the contained value using a function and returns the new value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_update)]
|
||||
///
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let new = c.update(|x| x + 1);
|
||||
///
|
||||
/// assert_eq!(new, 6);
|
||||
/// assert_eq!(c.get(), 6);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "cell_update", issue = "50186")]
|
||||
pub fn update<F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
let old = self.get();
|
||||
let new = f(old);
|
||||
self.set(new);
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Cell<T> {
|
||||
/// Returns a raw pointer to the underlying data in this cell.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -116,9 +116,9 @@ impl char {
|
|||
|
||||
// the code is split up here to improve execution speed for cases where
|
||||
// the `radix` is constant and 10 or smaller
|
||||
let val = if radix <= 10 {
|
||||
let val = if radix <= 10 {
|
||||
match self {
|
||||
'0' ..= '9' => self as u32 - '0' as u32,
|
||||
'0'..='9' => self as u32 - '0' as u32,
|
||||
_ => return None,
|
||||
}
|
||||
} else {
|
||||
|
|
@ -130,8 +130,11 @@ impl char {
|
|||
}
|
||||
};
|
||||
|
||||
if val < radix { Some(val) }
|
||||
else { None }
|
||||
if val < radix {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the hexadecimal Unicode escape of a
|
||||
|
|
@ -303,8 +306,8 @@ impl char {
|
|||
'\r' => EscapeDefaultState::Backslash('r'),
|
||||
'\n' => EscapeDefaultState::Backslash('n'),
|
||||
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
|
||||
'\x20' ..= '\x7e' => EscapeDefaultState::Char(self),
|
||||
_ => EscapeDefaultState::Unicode(self.escape_unicode())
|
||||
'\x20'..='\x7e' => EscapeDefaultState::Char(self),
|
||||
_ => EscapeDefaultState::Unicode(self.escape_unicode()),
|
||||
};
|
||||
EscapeDefault { state: init_state }
|
||||
}
|
||||
|
|
@ -436,30 +439,31 @@ impl char {
|
|||
pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
|
||||
let code = self as u32;
|
||||
unsafe {
|
||||
let len =
|
||||
if code < MAX_ONE_B && !dst.is_empty() {
|
||||
let len = if code < MAX_ONE_B && !dst.is_empty() {
|
||||
*dst.get_unchecked_mut(0) = code as u8;
|
||||
1
|
||||
} else if code < MAX_TWO_B && dst.len() >= 2 {
|
||||
*dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
|
||||
*dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT;
|
||||
2
|
||||
} else if code < MAX_THREE_B && dst.len() >= 3 {
|
||||
} else if code < MAX_THREE_B && dst.len() >= 3 {
|
||||
*dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
|
||||
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||
*dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||
*dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT;
|
||||
3
|
||||
} else if dst.len() >= 4 {
|
||||
*dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
|
||||
*dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
|
||||
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||
*dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
||||
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
|
||||
4
|
||||
} else {
|
||||
panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
|
||||
panic!(
|
||||
"encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
|
||||
from_u32_unchecked(code).len_utf8(),
|
||||
code,
|
||||
dst.len())
|
||||
dst.len(),
|
||||
)
|
||||
};
|
||||
from_utf8_unchecked_mut(dst.get_unchecked_mut(..len))
|
||||
}
|
||||
|
|
@ -515,15 +519,24 @@ impl char {
|
|||
*dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF);
|
||||
slice::from_raw_parts_mut(dst.as_mut_ptr(), 2)
|
||||
} else {
|
||||
panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
|
||||
panic!(
|
||||
"encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
|
||||
from_u32_unchecked(code).len_utf16(),
|
||||
code,
|
||||
dst.len())
|
||||
dst.len(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is an alphabetic code point, and false if not.
|
||||
/// Returns `true` if this `char` has the `Alphabetic` property.
|
||||
///
|
||||
/// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
|
||||
/// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -547,10 +560,14 @@ impl char {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is lowercase.
|
||||
/// Returns `true` if this `char` has the `Lowercase` property.
|
||||
///
|
||||
/// 'Lowercase' is defined according to the terms of the Unicode Derived Core
|
||||
/// Property `Lowercase`.
|
||||
/// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
|
||||
/// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -575,10 +592,14 @@ impl char {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is uppercase.
|
||||
/// Returns `true` if this `char` has the `Uppercase` property.
|
||||
///
|
||||
/// 'Uppercase' is defined according to the terms of the Unicode Derived Core
|
||||
/// Property `Uppercase`.
|
||||
/// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
|
||||
/// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -603,10 +624,12 @@ impl char {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is whitespace.
|
||||
/// Returns `true` if this `char` has the `White_Space` property.
|
||||
///
|
||||
/// 'Whitespace' is defined according to the terms of the Unicode Derived Core
|
||||
/// Property `White_Space`.
|
||||
/// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`].
|
||||
///
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -630,10 +653,10 @@ impl char {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is alphanumeric.
|
||||
/// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`].
|
||||
///
|
||||
/// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
|
||||
/// `Nd`, `Nl`, `No` and the Derived Core Property `Alphabetic`.
|
||||
/// [`is_alphabetic()`]: #method.is_alphabetic
|
||||
/// [`is_numeric()`]: #method.is_numeric
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -655,10 +678,15 @@ impl char {
|
|||
self.is_alphabetic() || self.is_numeric()
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is a control code point.
|
||||
/// Returns `true` if this `char` has the general category for control codes.
|
||||
///
|
||||
/// 'Control code point' is defined in terms of the Unicode General
|
||||
/// Category `Cc`.
|
||||
/// Control codes (code points with the general category of `Cc`) are described in Chapter 4
|
||||
/// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character
|
||||
/// Database][ucd] [`UnicodeData.txt`].
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -675,19 +703,29 @@ impl char {
|
|||
general_category::Cc(self)
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is an extended grapheme character.
|
||||
/// Returns `true` if this `char` has the `Grapheme_Extend` property.
|
||||
///
|
||||
/// 'Extended grapheme character' is defined in terms of the Unicode Shaping and Rendering
|
||||
/// Category `Grapheme_Extend`.
|
||||
/// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text
|
||||
/// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd]
|
||||
/// [`DerivedCoreProperties.txt`].
|
||||
///
|
||||
/// [uax29]: https://www.unicode.org/reports/tr29/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
|
||||
#[inline]
|
||||
pub(crate) fn is_grapheme_extended(self) -> bool {
|
||||
derived_property::Grapheme_Extend(self)
|
||||
}
|
||||
|
||||
/// Returns `true` if this `char` is numeric.
|
||||
/// Returns `true` if this `char` has one of the general categories for numbers.
|
||||
///
|
||||
/// 'Numeric'-ness is defined in terms of the Unicode General Categories
|
||||
/// `Nd`, `Nl`, `No`.
|
||||
/// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric
|
||||
/// characters, and `No` for other numeric characters) are specified in the [Unicode Character
|
||||
/// Database][ucd] [`UnicodeData.txt`].
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -713,25 +751,29 @@ impl char {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the lowercase equivalent of a `char`
|
||||
/// as one or more `char`s.
|
||||
/// Returns an iterator that yields the lowercase mapping of this `char` as one or more
|
||||
/// `char`s.
|
||||
///
|
||||
/// If a character does not have a lowercase equivalent, the same character
|
||||
/// will be returned back by the iterator.
|
||||
/// If this `char` does not have a lowercase mapping, the iterator yields the same `char`.
|
||||
///
|
||||
/// This performs complex unconditional mappings with no tailoring: it maps
|
||||
/// one Unicode character to its lowercase equivalent according to the
|
||||
/// [Unicode database] and the additional complex mappings
|
||||
/// [`SpecialCasing.txt`]. Conditional mappings (based on context or
|
||||
/// language) are not considered here.
|
||||
/// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character
|
||||
/// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
|
||||
///
|
||||
/// For a full reference, see [here][reference].
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
///
|
||||
/// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
/// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
|
||||
/// the `char`(s) given by [`SpecialCasing.txt`].
|
||||
///
|
||||
/// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
|
||||
/// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
|
||||
///
|
||||
/// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
|
||||
/// This operation performs an unconditional mapping without tailoring. That is, the conversion
|
||||
/// is independent of context and language.
|
||||
///
|
||||
/// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
|
||||
/// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -774,25 +816,29 @@ impl char {
|
|||
ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the uppercase equivalent of a `char`
|
||||
/// as one or more `char`s.
|
||||
/// Returns an iterator that yields the uppercase mapping of this `char` as one or more
|
||||
/// `char`s.
|
||||
///
|
||||
/// If a character does not have an uppercase equivalent, the same character
|
||||
/// will be returned back by the iterator.
|
||||
/// If this `char` does not have a uppercase mapping, the iterator yields the same `char`.
|
||||
///
|
||||
/// This performs complex unconditional mappings with no tailoring: it maps
|
||||
/// one Unicode character to its uppercase equivalent according to the
|
||||
/// [Unicode database] and the additional complex mappings
|
||||
/// [`SpecialCasing.txt`]. Conditional mappings (based on context or
|
||||
/// language) are not considered here.
|
||||
/// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
|
||||
/// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
|
||||
///
|
||||
/// For a full reference, see [here][reference].
|
||||
/// [ucd]: https://www.unicode.org/reports/tr44/
|
||||
/// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
|
||||
///
|
||||
/// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
/// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
|
||||
/// the `char`(s) given by [`SpecialCasing.txt`].
|
||||
///
|
||||
/// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
|
||||
/// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
|
||||
///
|
||||
/// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
|
||||
/// This operation performs an unconditional mapping without tailoring. That is, the conversion
|
||||
/// is independent of context and language.
|
||||
///
|
||||
/// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
|
||||
/// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
|
||||
///
|
||||
/// [Unicode Standard]: https://www.unicode.org/versions/latest/
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -775,10 +775,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
reason = "recently added",
|
||||
issue = "62482")]
|
||||
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
|
||||
assert!(!self.has_key, "attempted to begin a new map entry \
|
||||
without completing the previous one");
|
||||
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(!self.has_key, "attempted to begin a new map entry \
|
||||
without completing the previous one");
|
||||
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str("\n")?;
|
||||
|
|
@ -839,9 +839,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
reason = "recently added",
|
||||
issue = "62482")]
|
||||
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> {
|
||||
assert!(self.has_key, "attempted to format a map value before its key");
|
||||
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(self.has_key, "attempted to format a map value before its key");
|
||||
|
||||
if self.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state);
|
||||
|
|
@ -924,9 +924,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
|||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
assert!(!self.has_key, "attempted to finish a map with a partial entry");
|
||||
self.result.and_then(|_| {
|
||||
assert!(!self.has_key, "attempted to finish a map with a partial entry");
|
||||
|
||||
self.result.and_then(|_| self.fmt.write_str("}"))
|
||||
self.fmt.write_str("}")
|
||||
})
|
||||
}
|
||||
|
||||
fn is_pretty(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ pub struct Error;
|
|||
/// [`io::Write`]: ../../std/io/trait.Write.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Write {
|
||||
/// Writes a slice of bytes into this writer, returning whether the write
|
||||
/// Writes a string slice into this writer, returning whether the write
|
||||
/// succeeded.
|
||||
///
|
||||
/// This method can only succeed if the entire byte slice was successfully
|
||||
/// This method can only succeed if the entire string slice was successfully
|
||||
/// written, and this method will not return until all data has been
|
||||
/// written or an error occurs.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@
|
|||
#![feature(adx_target_feature)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(external_doc)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(associated_type_bounds)]
|
||||
|
||||
#[prelude_import]
|
||||
|
|
|
|||
|
|
@ -520,18 +520,20 @@ macro_rules! unreachable {
|
|||
});
|
||||
}
|
||||
|
||||
/// Indicates unfinished code.
|
||||
/// Indicates unfinished code by panicking with a message of "not yet implemented".
|
||||
///
|
||||
/// This can be useful if you are prototyping and are just looking to have your
|
||||
/// code type-check, or if you're implementing a trait that requires multiple
|
||||
/// methods, and you're only planning on using one of them.
|
||||
/// This allows the your code to type-check, which is useful if you are prototyping or
|
||||
/// implementing a trait that requires multiple methods which you don't plan of using all of.
|
||||
///
|
||||
/// There is no difference between `unimplemented!` and `todo!` apart from the
|
||||
/// name.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This will always [panic!](macro.panic.html)
|
||||
/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
|
||||
/// shorthand for `panic!` with a fixed, specific message.
|
||||
///
|
||||
/// Like `panic!`, this macro has a second form for displaying custom values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -539,38 +541,53 @@ macro_rules! unreachable {
|
|||
///
|
||||
/// ```
|
||||
/// trait Foo {
|
||||
/// fn bar(&self);
|
||||
/// fn bar(&self) -> u8;
|
||||
/// fn baz(&self);
|
||||
/// fn qux(&self) -> Result<u64, ()>;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// We want to implement `Foo` on one of our types, but we also want to work on
|
||||
/// just `bar()` first. In order for our code to compile, we need to implement
|
||||
/// `baz()`, so we can use `unimplemented!`:
|
||||
/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
|
||||
/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
|
||||
/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
|
||||
/// to allow our code to compile.
|
||||
///
|
||||
/// In the meantime, we want to have our program stop running once these
|
||||
/// unimplemented functions are reached.
|
||||
///
|
||||
/// ```
|
||||
/// # trait Foo {
|
||||
/// # fn bar(&self);
|
||||
/// # fn bar(&self) -> u8;
|
||||
/// # fn baz(&self);
|
||||
/// # fn qux(&self) -> Result<u64, ()>;
|
||||
/// # }
|
||||
/// struct MyStruct;
|
||||
///
|
||||
/// impl Foo for MyStruct {
|
||||
/// fn bar(&self) {
|
||||
/// // implementation goes here
|
||||
/// fn bar(&self) -> u8 {
|
||||
/// 1 + 1
|
||||
/// }
|
||||
///
|
||||
/// fn baz(&self) {
|
||||
/// // let's not worry about implementing baz() for now
|
||||
/// // We aren't sure how to even start writing baz yet,
|
||||
/// // so we have no logic here at all.
|
||||
/// // This will display "thread 'main' panicked at 'not yet implemented'".
|
||||
/// unimplemented!();
|
||||
/// }
|
||||
///
|
||||
/// fn qux(&self) -> Result<u64, ()> {
|
||||
/// let n = self.bar();
|
||||
/// // We have some logic here,
|
||||
/// // so we can use unimplemented! to display what we have so far.
|
||||
/// // This will display:
|
||||
/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
|
||||
/// unimplemented!("we need to divide by {}", n);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let s = MyStruct;
|
||||
/// s.bar();
|
||||
///
|
||||
/// // we aren't even using baz() yet, so this is fine.
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
|
|||
/// ```
|
||||
///
|
||||
/// [alignment]: ./fn.align_of.html
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_promotable]
|
||||
pub const fn size_of<T>() -> usize {
|
||||
|
|
@ -328,7 +328,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
|
|||
///
|
||||
/// assert_eq!(4, mem::align_of::<i32>());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_promotable]
|
||||
pub const fn align_of<T>() -> usize {
|
||||
|
|
@ -520,8 +520,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
/// A simple example:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mem_take)]
|
||||
///
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let mut v: Vec<i32> = vec![1, 2];
|
||||
|
|
@ -552,8 +550,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
/// `self`, allowing it to be returned:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(mem_take)]
|
||||
///
|
||||
/// use std::mem;
|
||||
///
|
||||
/// # struct Buffer<T> { buf: Vec<T> }
|
||||
|
|
@ -572,7 +568,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
///
|
||||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
#[inline]
|
||||
#[unstable(feature = "mem_take", issue = "61129")]
|
||||
#[stable(feature = "mem_take", since = "1.40.0")]
|
||||
pub fn take<T: Default>(dest: &mut T) -> T {
|
||||
replace(dest, T::default())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1058,7 +1058,7 @@ $EndFeature, "
|
|||
#[inline]
|
||||
pub fn saturating_mul(self, rhs: Self) -> Self {
|
||||
self.checked_mul(rhs).unwrap_or_else(|| {
|
||||
if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) {
|
||||
if (self < 0) == (rhs < 0) {
|
||||
Self::max_value()
|
||||
} else {
|
||||
Self::min_value()
|
||||
|
|
@ -1864,7 +1864,7 @@ if `self < 0`, this is equal to round towards +/- infinity.
|
|||
|
||||
# Panics
|
||||
|
||||
This function will panic if `rhs` is 0.
|
||||
This function will panic if `rhs` is 0 or the division results in overflow.
|
||||
|
||||
# Examples
|
||||
|
||||
|
|
@ -1903,7 +1903,7 @@ This is done as if by the Euclidean division algorithm -- given
|
|||
|
||||
# Panics
|
||||
|
||||
This function will panic if `rhs` is 0.
|
||||
This function will panic if `rhs` is 0 or the division results in overflow.
|
||||
|
||||
# Examples
|
||||
|
||||
|
|
@ -3694,6 +3694,10 @@ Since, for the positive integers, all common
|
|||
definitions of division are equal, this
|
||||
is exactly equal to `self / rhs`.
|
||||
|
||||
# Panics
|
||||
|
||||
This function will panic if `rhs` is 0.
|
||||
|
||||
# Examples
|
||||
|
||||
Basic usage:
|
||||
|
|
@ -3719,6 +3723,10 @@ Since, for the positive integers, all common
|
|||
definitions of division are equal, this
|
||||
is exactly equal to `self % rhs`.
|
||||
|
||||
# Panics
|
||||
|
||||
This function will panic if `rhs` is 0.
|
||||
|
||||
# Examples
|
||||
|
||||
Basic usage:
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ assert_eq!(n.trailing_zeros(), 3);
|
|||
/// wrapping the truncated bits to the end of the resulting
|
||||
/// integer.
|
||||
///
|
||||
/// Please note this isn't the same operation as the `>>` shifting
|
||||
/// Please note this isn't the same operation as the `<<` shifting
|
||||
/// operator!
|
||||
///
|
||||
/// # Examples
|
||||
|
|
@ -463,7 +463,7 @@ assert_eq!(n.trailing_zeros(), 3);
|
|||
/// wrapping the truncated bits to the beginning of the resulting
|
||||
/// integer.
|
||||
///
|
||||
/// Please note this isn't the same operation as the `<<` shifting
|
||||
/// Please note this isn't the same operation as the `>>` shifting
|
||||
/// operator!
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
|||
|
|
@ -1102,7 +1102,6 @@ impl<T: Default> Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
|
||||
impl<T: Deref> Option<T> {
|
||||
/// Converts from `Option<T>` (or `&Option<T>`) to `Option<&T::Target>`.
|
||||
///
|
||||
|
|
@ -1114,20 +1113,18 @@ impl<T: Deref> Option<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
///
|
||||
/// let x: Option<String> = Some("hey".to_owned());
|
||||
/// assert_eq!(x.as_deref(), Some("hey"));
|
||||
///
|
||||
/// let x: Option<String> = None;
|
||||
/// assert_eq!(x.as_deref(), None);
|
||||
/// ```
|
||||
#[stable(feature = "option_deref", since = "1.40.0")]
|
||||
pub fn as_deref(&self) -> Option<&T::Target> {
|
||||
self.as_ref().map(|t| t.deref())
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
|
||||
impl<T: DerefMut> Option<T> {
|
||||
/// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
|
||||
///
|
||||
|
|
@ -1137,14 +1134,13 @@ impl<T: DerefMut> Option<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
///
|
||||
/// let mut x: Option<String> = Some("hey".to_owned());
|
||||
/// assert_eq!(x.as_deref_mut().map(|x| {
|
||||
/// x.make_ascii_uppercase();
|
||||
/// x
|
||||
/// }), Some("HEY".to_owned().as_mut_str()));
|
||||
/// ```
|
||||
#[stable(feature = "option_deref", since = "1.40.0")]
|
||||
pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> {
|
||||
self.as_mut().map(|t| t.deref_mut())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ impl<T> [T] {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
// SAFETY: const sound because we transmute out the length field as a usize (which it must be)
|
||||
#[allow(unused_attributes)]
|
||||
#[allow_internal_unstable(const_fn_union)]
|
||||
pub const fn len(&self) -> usize {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -2167,6 +2167,7 @@ impl str {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline(always)]
|
||||
// SAFETY: const sound because we transmute two types with the same layout
|
||||
#[allow(unused_attributes)]
|
||||
#[allow_internal_unstable(const_fn_union)]
|
||||
pub const fn as_bytes(&self) -> &[u8] {
|
||||
#[repr(C)]
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
//!
|
||||
//! Each method takes an [`Ordering`] which represents the strength of
|
||||
//! the memory barrier for that operation. These orderings are the
|
||||
//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2].
|
||||
//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2].
|
||||
//!
|
||||
//! [`Ordering`]: enum.Ordering.html
|
||||
//!
|
||||
//! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations
|
||||
//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order
|
||||
//! [2]: ../../../nomicon/atomics.html
|
||||
//!
|
||||
//! Atomic variables are safe to share between threads (they implement [`Sync`])
|
||||
|
|
@ -113,8 +113,8 @@
|
|||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
|
||||
#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
|
||||
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
|
||||
#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
|
||||
|
||||
use self::Ordering::*;
|
||||
|
||||
|
|
@ -160,14 +160,14 @@ pub fn spin_loop_hint() {
|
|||
/// This type has the same in-memory representation as a [`bool`].
|
||||
///
|
||||
/// [`bool`]: ../../../std/primitive.bool.html
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[repr(C, align(1))]
|
||||
pub struct AtomicBool {
|
||||
v: UnsafeCell<u8>,
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for AtomicBool {
|
||||
/// Creates an `AtomicBool` initialized to `false`.
|
||||
|
|
@ -177,14 +177,14 @@ impl Default for AtomicBool {
|
|||
}
|
||||
|
||||
// Send is implicitly implemented for AtomicBool.
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl Sync for AtomicBool {}
|
||||
|
||||
/// A raw pointer type which can be safely shared between threads.
|
||||
///
|
||||
/// This type has the same in-memory representation as a `*mut T`.
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(target_pointer_width = "16", repr(C, align(2)))]
|
||||
#[cfg_attr(target_pointer_width = "32", repr(C, align(4)))]
|
||||
|
|
@ -193,7 +193,7 @@ pub struct AtomicPtr<T> {
|
|||
p: UnsafeCell<*mut T>,
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Default for AtomicPtr<T> {
|
||||
/// Creates a null `AtomicPtr<T>`.
|
||||
|
|
@ -202,10 +202,10 @@ impl<T> Default for AtomicPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T> Send for AtomicPtr<T> {}
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T> Sync for AtomicPtr<T> {}
|
||||
|
||||
|
|
@ -217,8 +217,8 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
|
|||
/// operations synchronize other memory while additionally preserving a total order of such
|
||||
/// operations across all threads.
|
||||
///
|
||||
/// Rust's memory orderings are [the same as
|
||||
/// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
|
||||
/// Rust's memory orderings are [the same as those of
|
||||
/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order).
|
||||
///
|
||||
/// For more information see the [nomicon].
|
||||
///
|
||||
|
|
@ -231,9 +231,9 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
|
|||
pub enum Ordering {
|
||||
/// No ordering constraints, only atomic operations.
|
||||
///
|
||||
/// Corresponds to LLVM's [`Monotonic`] ordering.
|
||||
/// Corresponds to [`memory_order_relaxed`] in C++20.
|
||||
///
|
||||
/// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic
|
||||
/// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Relaxed,
|
||||
/// When coupled with a store, all previous operations become ordered
|
||||
|
|
@ -246,11 +246,12 @@ pub enum Ordering {
|
|||
///
|
||||
/// This ordering is only applicable for operations that can perform a store.
|
||||
///
|
||||
/// Corresponds to LLVM's [`Release`] ordering.
|
||||
/// Corresponds to [`memory_order_release`] in C++20.
|
||||
///
|
||||
/// [`Release`]: https://llvm.org/docs/Atomics.html#release
|
||||
/// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
|
||||
/// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
|
||||
/// [`Release`]: #variant.Release
|
||||
/// [`Acquire`]: #variant.Acquire
|
||||
/// [`Relaxed`]: #variant.Relaxed
|
||||
/// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Release,
|
||||
/// When coupled with a load, if the loaded value was written by a store operation with
|
||||
|
|
@ -263,11 +264,12 @@ pub enum Ordering {
|
|||
///
|
||||
/// This ordering is only applicable for operations that can perform a load.
|
||||
///
|
||||
/// Corresponds to LLVM's [`Acquire`] ordering.
|
||||
/// Corresponds to [`memory_order_acquire`] in C++20.
|
||||
///
|
||||
/// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
|
||||
/// [`Release`]: https://llvm.org/docs/Atomics.html#release
|
||||
/// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
|
||||
/// [`Acquire`]: #variant.Acquire
|
||||
/// [`Release`]: #variant.Release
|
||||
/// [`Relaxed`]: #variant.Relaxed
|
||||
/// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Acquire,
|
||||
/// Has the effects of both [`Acquire`] and [`Release`] together:
|
||||
|
|
@ -275,28 +277,28 @@ pub enum Ordering {
|
|||
///
|
||||
/// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up
|
||||
/// not performing any store and hence it has just [`Acquire`] ordering. However,
|
||||
/// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses.
|
||||
/// `AcqRel` will never perform [`Relaxed`] accesses.
|
||||
///
|
||||
/// This ordering is only applicable for operations that combine both loads and stores.
|
||||
///
|
||||
/// Corresponds to LLVM's [`AcquireRelease`] ordering.
|
||||
/// Corresponds to [`memory_order_acq_rel`] in C++20.
|
||||
///
|
||||
/// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease
|
||||
/// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
|
||||
/// [`Release`]: https://llvm.org/docs/Atomics.html#release
|
||||
/// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic
|
||||
/// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering
|
||||
/// [`Acquire`]: #variant.Acquire
|
||||
/// [`Release`]: #variant.Release
|
||||
/// [`Relaxed`]: #variant.Relaxed
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
AcqRel,
|
||||
/// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store
|
||||
/// operations, respectively) with the additional guarantee that all threads see all
|
||||
/// sequentially consistent operations in the same order.
|
||||
///
|
||||
/// Corresponds to LLVM's [`SequentiallyConsistent`] ordering.
|
||||
/// Corresponds to [`memory_order_seq_cst`] in C++20.
|
||||
///
|
||||
/// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent
|
||||
/// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire
|
||||
/// [`Release`]: https://llvm.org/docs/Atomics.html#release
|
||||
/// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease
|
||||
/// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering
|
||||
/// [`Acquire`]: #variant.Acquire
|
||||
/// [`Release`]: #variant.Release
|
||||
/// [`AcqRel`]: #variant.AcqRel
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
SeqCst,
|
||||
}
|
||||
|
|
@ -304,7 +306,7 @@ pub enum Ordering {
|
|||
/// An [`AtomicBool`] initialized to `false`.
|
||||
///
|
||||
/// [`AtomicBool`]: struct.AtomicBool.html
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.34.0",
|
||||
|
|
@ -313,7 +315,7 @@ pub enum Ordering {
|
|||
)]
|
||||
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
impl AtomicBool {
|
||||
/// Creates a new `AtomicBool`.
|
||||
///
|
||||
|
|
@ -462,7 +464,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn swap(&self, val: bool, order: Ordering) -> bool {
|
||||
unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
|
||||
}
|
||||
|
|
@ -500,7 +502,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
|
||||
match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
|
||||
Ok(x) => x,
|
||||
|
|
@ -551,7 +553,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn compare_exchange(&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
|
|
@ -607,7 +609,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn compare_exchange_weak(&self,
|
||||
current: bool,
|
||||
new: bool,
|
||||
|
|
@ -658,7 +660,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
|
||||
unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
|
||||
}
|
||||
|
|
@ -700,7 +702,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
|
||||
// We can't use atomic_nand here because it can result in a bool with
|
||||
// an invalid value. This happens because the atomic operation is done
|
||||
|
|
@ -753,7 +755,7 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
|
||||
unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
|
||||
}
|
||||
|
|
@ -794,13 +796,13 @@ impl AtomicBool {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
|
||||
unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
impl<T> AtomicPtr<T> {
|
||||
/// Creates a new `AtomicPtr`.
|
||||
///
|
||||
|
|
@ -951,7 +953,7 @@ impl<T> AtomicPtr<T> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
|
||||
unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
|
||||
}
|
||||
|
|
@ -987,7 +989,7 @@ impl<T> AtomicPtr<T> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
|
||||
match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
|
||||
Ok(x) => x,
|
||||
|
|
@ -1029,7 +1031,7 @@ impl<T> AtomicPtr<T> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn compare_exchange(&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
|
|
@ -1089,7 +1091,7 @@ impl<T> AtomicPtr<T> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
pub fn compare_exchange_weak(&self,
|
||||
current: *mut T,
|
||||
new: *mut T,
|
||||
|
|
@ -1110,7 +1112,7 @@ impl<T> AtomicPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "atomic_bool_from", since = "1.24.0")]
|
||||
impl From<bool> for AtomicBool {
|
||||
/// Converts a `bool` into an `AtomicBool`.
|
||||
|
|
@ -1126,16 +1128,17 @@ impl From<bool> for AtomicBool {
|
|||
fn from(b: bool) -> Self { Self::new(b) }
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "atomic_from", since = "1.23.0")]
|
||||
impl<T> From<*mut T> for AtomicPtr<T> {
|
||||
#[inline]
|
||||
fn from(p: *mut T) -> Self { Self::new(p) }
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
macro_rules! atomic_int {
|
||||
($stable:meta,
|
||||
($cfg_cas:meta,
|
||||
$stable:meta,
|
||||
$stable_cxchg:meta,
|
||||
$stable_debug:meta,
|
||||
$stable_access:meta,
|
||||
|
|
@ -1356,7 +1359,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_swap(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1396,7 +1399,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn compare_and_swap(&self,
|
||||
current: $int_type,
|
||||
new: $int_type,
|
||||
|
|
@ -1454,7 +1457,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable_cxchg]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn compare_exchange(&self,
|
||||
current: $int_type,
|
||||
new: $int_type,
|
||||
|
|
@ -1506,7 +1509,7 @@ loop {
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable_cxchg]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn compare_exchange_weak(&self,
|
||||
current: $int_type,
|
||||
new: $int_type,
|
||||
|
|
@ -1544,7 +1547,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_add(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1576,7 +1579,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_sub(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1611,7 +1614,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_and(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1647,7 +1650,7 @@ assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable_nand]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_nand(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1682,7 +1685,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_or(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1717,7 +1720,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
|
|||
```"),
|
||||
#[inline]
|
||||
#[$stable]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { atomic_xor(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1767,7 +1770,7 @@ assert_eq!(x.load(Ordering::SeqCst), 9);
|
|||
#[unstable(feature = "no_more_cas",
|
||||
reason = "no more CAS loops in user code",
|
||||
issue = "48655")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_update<F>(&self,
|
||||
mut f: F,
|
||||
fetch_order: Ordering,
|
||||
|
|
@ -1828,7 +1831,7 @@ assert!(max_foo == 42);
|
|||
#[unstable(feature = "atomic_min_max",
|
||||
reason = "easier and faster min/max than writing manual CAS loop",
|
||||
issue = "48655")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { $max_fn(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1880,7 +1883,7 @@ assert_eq!(min_foo, 12);
|
|||
#[unstable(feature = "atomic_min_max",
|
||||
reason = "easier and faster min/max than writing manual CAS loop",
|
||||
issue = "48655")]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[$cfg_cas]
|
||||
pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
|
||||
unsafe { $min_fn(self.v.get(), val, order) }
|
||||
}
|
||||
|
|
@ -1890,8 +1893,9 @@ assert_eq!(min_foo, 12);
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "8"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1906,8 +1910,9 @@ atomic_int! {
|
|||
"AtomicI8::new(0)",
|
||||
i8 AtomicI8 ATOMIC_I8_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "8"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1922,8 +1927,9 @@ atomic_int! {
|
|||
"AtomicU8::new(0)",
|
||||
u8 AtomicU8 ATOMIC_U8_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "16")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "16"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1938,8 +1944,9 @@ atomic_int! {
|
|||
"AtomicI16::new(0)",
|
||||
i16 AtomicI16 ATOMIC_I16_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "16")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "16"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1954,8 +1961,9 @@ atomic_int! {
|
|||
"AtomicU16::new(0)",
|
||||
u16 AtomicU16 ATOMIC_U16_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "32")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "32"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1970,8 +1978,9 @@ atomic_int! {
|
|||
"AtomicI32::new(0)",
|
||||
i32 AtomicI32 ATOMIC_I32_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "32")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "32"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -1986,8 +1995,12 @@ atomic_int! {
|
|||
"AtomicU32::new(0)",
|
||||
u32 AtomicU32 ATOMIC_U32_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
#[cfg(any(
|
||||
all(bootstrap, target_has_atomic = "64"),
|
||||
target_has_atomic_load_store = "64"
|
||||
))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "64"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -2002,8 +2015,12 @@ atomic_int! {
|
|||
"AtomicI64::new(0)",
|
||||
i64 AtomicI64 ATOMIC_I64_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
#[cfg(any(
|
||||
all(bootstrap, target_has_atomic = "64"),
|
||||
target_has_atomic_load_store = "64"
|
||||
))]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "64"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||
|
|
@ -2018,8 +2035,9 @@ atomic_int! {
|
|||
"AtomicU64::new(0)",
|
||||
u64 AtomicU64 ATOMIC_U64_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "128")]
|
||||
#[cfg(target_has_atomic_load_store = "128")]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "128"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
|
|
@ -2034,8 +2052,9 @@ atomic_int! {
|
|||
"AtomicI128::new(0)",
|
||||
i128 AtomicI128 ATOMIC_I128_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "128")]
|
||||
#[cfg(target_has_atomic_load_store = "128")]
|
||||
atomic_int! {
|
||||
cfg(target_has_atomic = "128"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
unstable(feature = "integer_atomics", issue = "32976"),
|
||||
|
|
@ -2050,20 +2069,24 @@ atomic_int! {
|
|||
"AtomicU128::new(0)",
|
||||
u128 AtomicU128 ATOMIC_U128_INIT
|
||||
}
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 2 }
|
||||
}
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 4 }
|
||||
}
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
macro_rules! ptr_width {
|
||||
() => { 8 }
|
||||
}
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
atomic_int!{
|
||||
cfg(target_has_atomic = "ptr"),
|
||||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||
|
|
@ -2078,8 +2101,9 @@ atomic_int!{
|
|||
"AtomicIsize::new(0)",
|
||||
isize AtomicIsize ATOMIC_ISIZE_INIT
|
||||
}
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
atomic_int!{
|
||||
cfg(target_has_atomic = "ptr"),
|
||||
stable(feature = "rust1", since = "1.0.0"),
|
||||
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
|
||||
stable(feature = "atomic_debug", since = "1.3.0"),
|
||||
|
|
@ -2096,7 +2120,7 @@ atomic_int!{
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
fn strongest_failure_ordering(order: Ordering) -> Ordering {
|
||||
match order {
|
||||
Release => Relaxed,
|
||||
|
|
@ -2130,7 +2154,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_xchg_acq(dst, val),
|
||||
|
|
@ -2143,7 +2167,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// Returns the previous value (like __sync_fetch_and_add).
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_xadd_acq(dst, val),
|
||||
|
|
@ -2156,7 +2180,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// Returns the previous value (like __sync_fetch_and_sub).
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_xsub_acq(dst, val),
|
||||
|
|
@ -2168,7 +2192,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_compare_exchange<T>(dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
|
|
@ -2193,7 +2217,7 @@ unsafe fn atomic_compare_exchange<T>(dst: *mut T,
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
|
||||
old: T,
|
||||
new: T,
|
||||
|
|
@ -2218,7 +2242,7 @@ unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_and_acq(dst, val),
|
||||
|
|
@ -2230,7 +2254,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_nand_acq(dst, val),
|
||||
|
|
@ -2242,7 +2266,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_or_acq(dst, val),
|
||||
|
|
@ -2254,7 +2278,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_xor_acq(dst, val),
|
||||
|
|
@ -2267,7 +2291,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// returns the max value (signed comparison)
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_max_acq(dst, val),
|
||||
|
|
@ -2280,7 +2304,7 @@ unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// returns the min value (signed comparison)
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_min_acq(dst, val),
|
||||
|
|
@ -2293,7 +2317,7 @@ unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// returns the max value (signed comparison)
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_umax_acq(dst, val),
|
||||
|
|
@ -2306,7 +2330,7 @@ unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
|||
|
||||
/// returns the min value (signed comparison)
|
||||
#[inline]
|
||||
#[cfg(target_has_atomic = "cas")]
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
|
||||
match order {
|
||||
Acquire => intrinsics::atomic_umin_acq(dst, val),
|
||||
|
|
@ -2504,7 +2528,7 @@ pub fn compiler_fence(order: Ordering) {
|
|||
}
|
||||
|
||||
|
||||
#[cfg(target_has_atomic = "8")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))]
|
||||
#[stable(feature = "atomic_debug", since = "1.3.0")]
|
||||
impl fmt::Debug for AtomicBool {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -2512,7 +2536,7 @@ impl fmt::Debug for AtomicBool {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "atomic_debug", since = "1.3.0")]
|
||||
impl<T> fmt::Debug for AtomicPtr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -2520,7 +2544,7 @@ impl<T> fmt::Debug for AtomicPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))]
|
||||
#[stable(feature = "atomic_pointer", since = "1.24.0")]
|
||||
impl<T> fmt::Pointer for AtomicPtr<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> {
|
|||
/// This handle encapsulates a [`RawWaker`] instance, which defines the
|
||||
/// executor-specific wakeup behavior.
|
||||
///
|
||||
/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`].
|
||||
/// Implements [`Clone`], [`Send`], and [`Sync`].
|
||||
///
|
||||
/// [`RawWaker`]: struct.RawWaker.html
|
||||
#[repr(transparent)]
|
||||
|
|
|
|||
|
|
@ -319,6 +319,46 @@ mod debug_map {
|
|||
format!("{:#?}", Bar));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_err() {
|
||||
// Ensure errors in a map entry don't trigger panics (#65231)
|
||||
use std::fmt::Write;
|
||||
|
||||
struct ErrorFmt;
|
||||
|
||||
impl fmt::Debug for ErrorFmt {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Err(fmt::Error)
|
||||
}
|
||||
}
|
||||
|
||||
struct KeyValue<K, V>(usize, K, V);
|
||||
|
||||
impl<K, V> fmt::Debug for KeyValue<K, V>
|
||||
where
|
||||
K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut map = fmt.debug_map();
|
||||
|
||||
for _ in 0..self.0 {
|
||||
map.entry(&self.1, &self.2);
|
||||
}
|
||||
|
||||
map.finish()
|
||||
}
|
||||
}
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
assert!(write!(&mut buf, "{:?}", KeyValue(1, ErrorFmt, "bar")).is_err());
|
||||
assert!(write!(&mut buf, "{:?}", KeyValue(1, "foo", ErrorFmt)).is_err());
|
||||
|
||||
assert!(write!(&mut buf, "{:?}", KeyValue(2, ErrorFmt, "bar")).is_err());
|
||||
assert!(write!(&mut buf, "{:?}", KeyValue(2, "foo", ErrorFmt)).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_invalid_key_when_entry_is_incomplete() {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#![feature(extern_types)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(non_exhaustive)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(specialization)]
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ jobserver = "0.1"
|
|||
num_cpus = "1.0"
|
||||
scoped-tls = "1.0"
|
||||
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
||||
rustc-rayon = "0.2.0"
|
||||
rustc-rayon-core = "0.2.0"
|
||||
rustc-rayon = "0.3.0"
|
||||
rustc-rayon-core = "0.3.0"
|
||||
polonius-engine = "0.10.0"
|
||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
|
|
@ -29,6 +29,7 @@ rustc_index = { path = "../librustc_index" }
|
|||
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_expand = { path = "../libsyntax_expand" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
backtrace = "0.3.3"
|
||||
parking_lot = "0.9"
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ macro_rules! arena_types {
|
|||
rustc::hir::def_id::DefId,
|
||||
>,
|
||||
[few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes,
|
||||
[decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>,
|
||||
[few] lint_levels: rustc::lint::LintLevelMap,
|
||||
[few] stability_index: rustc::middle::stability::Index<'tcx>,
|
||||
[few] features: syntax::feature_gate::Features,
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use smallvec::SmallVec;
|
||||
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering};
|
||||
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering};
|
||||
use rustc_data_structures::sharded::{self, Sharded};
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::env;
|
||||
use std::hash::Hash;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::mem;
|
||||
use crate::ty::{self, TyCtxt};
|
||||
use crate::util::common::{ProfileQueriesMsg, profq_msg};
|
||||
use parking_lot::{Mutex, Condvar};
|
||||
|
||||
use crate::ich::{StableHashingContext, StableHashingContextProvider, Fingerprint};
|
||||
|
|
@ -31,7 +32,7 @@ rustc_index::newtype_index! {
|
|||
}
|
||||
|
||||
impl DepNodeIndex {
|
||||
const INVALID: DepNodeIndex = DepNodeIndex::MAX;
|
||||
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
@ -54,7 +55,7 @@ struct DepGraphData {
|
|||
/// tracking. The `current` field is the dependency graph of only the
|
||||
/// current compilation session: We don't merge the previous dep-graph into
|
||||
/// current one anymore.
|
||||
current: Lock<CurrentDepGraph>,
|
||||
current: CurrentDepGraph,
|
||||
|
||||
/// The dep-graph from the previous compilation session. It contains all
|
||||
/// nodes and edges as well as all fingerprints of nodes that have them.
|
||||
|
|
@ -75,9 +76,6 @@ struct DepGraphData {
|
|||
previous_work_products: FxHashMap<WorkProductId, WorkProduct>,
|
||||
|
||||
dep_node_debug: Lock<FxHashMap<DepNode, String>>,
|
||||
|
||||
// Used for testing, only populated when -Zquery-dep-graph is specified.
|
||||
loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>,
|
||||
}
|
||||
|
||||
pub fn hash_result<R>(hcx: &mut StableHashingContext<'_>, result: &R) -> Option<Fingerprint>
|
||||
|
|
@ -99,12 +97,11 @@ impl DepGraph {
|
|||
data: Some(Lrc::new(DepGraphData {
|
||||
previous_work_products: prev_work_products,
|
||||
dep_node_debug: Default::default(),
|
||||
current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
|
||||
current: CurrentDepGraph::new(prev_graph_node_count),
|
||||
emitting_diagnostics: Default::default(),
|
||||
emitting_diagnostics_cond_var: Condvar::new(),
|
||||
previous: prev_graph,
|
||||
colors: DepNodeColorMap::new(prev_graph_node_count),
|
||||
loaded_from_cache: Default::default(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
|
@ -122,13 +119,12 @@ impl DepGraph {
|
|||
}
|
||||
|
||||
pub fn query(&self) -> DepGraphQuery {
|
||||
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
|
||||
let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect();
|
||||
let data = self.data.as_ref().unwrap().current.data.lock();
|
||||
let nodes: Vec<_> = data.iter().map(|n| n.node).collect();
|
||||
let mut edges = Vec::new();
|
||||
for (from, edge_targets) in current_dep_graph.data.iter()
|
||||
.map(|d| (d.node, &d.edges)) {
|
||||
for (from, edge_targets) in data.iter().map(|d| (d.node, &d.edges)) {
|
||||
for &edge_target in edge_targets.iter() {
|
||||
let to = current_dep_graph.data[edge_target].node;
|
||||
let to = data[edge_target].node;
|
||||
edges.push((from, to));
|
||||
}
|
||||
}
|
||||
|
|
@ -207,7 +203,7 @@ impl DepGraph {
|
|||
read_set: Default::default(),
|
||||
}),
|
||||
|data, key, fingerprint, task| {
|
||||
data.borrow_mut().complete_task(key, task.unwrap(), fingerprint)
|
||||
data.complete_task(key, task.unwrap(), fingerprint)
|
||||
},
|
||||
hash_result)
|
||||
}
|
||||
|
|
@ -228,7 +224,7 @@ impl DepGraph {
|
|||
self.with_task_impl(key, cx, input, true, identity_fn,
|
||||
|_| None,
|
||||
|data, key, fingerprint, _| {
|
||||
data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint)
|
||||
data.alloc_node(key, SmallVec::new(), fingerprint)
|
||||
},
|
||||
hash_result::<R>)
|
||||
}
|
||||
|
|
@ -241,7 +237,7 @@ impl DepGraph {
|
|||
no_tcx: bool,
|
||||
task: fn(C, A) -> R,
|
||||
create_task: fn(DepNode) -> Option<TaskDeps>,
|
||||
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
|
||||
finish_task_and_alloc_depnode: fn(&CurrentDepGraph,
|
||||
DepNode,
|
||||
Fingerprint,
|
||||
Option<TaskDeps>) -> DepNodeIndex,
|
||||
|
|
@ -260,10 +256,6 @@ impl DepGraph {
|
|||
// - we can get an idea of the runtime cost.
|
||||
let mut hcx = cx.get_stable_hashing_context();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone()))
|
||||
};
|
||||
|
||||
let result = if no_tcx {
|
||||
task(cx, arg)
|
||||
} else {
|
||||
|
|
@ -279,10 +271,6 @@ impl DepGraph {
|
|||
})
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
|
||||
};
|
||||
|
||||
let current_fingerprint = hash_result(&mut hcx, &result);
|
||||
|
||||
let dep_node_index = finish_task_and_alloc_depnode(
|
||||
|
|
@ -363,7 +351,6 @@ impl DepGraph {
|
|||
(r, task_deps.into_inner())
|
||||
});
|
||||
let dep_node_index = data.current
|
||||
.borrow_mut()
|
||||
.complete_anon_task(dep_kind, task_deps);
|
||||
(result, dep_node_index)
|
||||
} else {
|
||||
|
|
@ -387,8 +374,7 @@ impl DepGraph {
|
|||
self.with_task_impl(key, cx, arg, false, task,
|
||||
|_| None,
|
||||
|data, key, fingerprint, _| {
|
||||
let mut current = data.borrow_mut();
|
||||
current.alloc_node(key, smallvec![], fingerprint)
|
||||
data.alloc_node(key, smallvec![], fingerprint)
|
||||
},
|
||||
hash_result)
|
||||
}
|
||||
|
|
@ -396,9 +382,9 @@ impl DepGraph {
|
|||
#[inline]
|
||||
pub fn read(&self, v: DepNode) {
|
||||
if let Some(ref data) = self.data {
|
||||
let current = data.current.borrow_mut();
|
||||
if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
|
||||
std::mem::drop(current);
|
||||
let map = data.current.node_to_node_index.get_shard_by_value(&v).lock();
|
||||
if let Some(dep_node_index) = map.get(&v).copied() {
|
||||
std::mem::drop(map);
|
||||
data.read_index(dep_node_index);
|
||||
} else {
|
||||
bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
|
||||
|
|
@ -419,8 +405,9 @@ impl DepGraph {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.current
|
||||
.borrow_mut()
|
||||
.node_to_node_index
|
||||
.get_shard_by_value(dep_node)
|
||||
.lock()
|
||||
.get(dep_node)
|
||||
.cloned()
|
||||
.unwrap()
|
||||
|
|
@ -429,7 +416,11 @@ impl DepGraph {
|
|||
#[inline]
|
||||
pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
|
||||
if let Some(ref data) = self.data {
|
||||
data.current.borrow_mut().node_to_node_index.contains_key(dep_node)
|
||||
data.current
|
||||
.node_to_node_index
|
||||
.get_shard_by_value(&dep_node)
|
||||
.lock()
|
||||
.contains_key(dep_node)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
@ -437,8 +428,8 @@ impl DepGraph {
|
|||
|
||||
#[inline]
|
||||
pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
|
||||
let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut();
|
||||
current.data[dep_node_index].fingerprint
|
||||
let data = self.data.as_ref().expect("dep graph enabled").current.data.lock();
|
||||
data[dep_node_index].fingerprint
|
||||
}
|
||||
|
||||
pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
|
||||
|
|
@ -492,32 +483,29 @@ impl DepGraph {
|
|||
|
||||
pub fn edge_deduplication_data(&self) -> Option<(u64, u64)> {
|
||||
if cfg!(debug_assertions) {
|
||||
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
|
||||
let current_dep_graph = &self.data.as_ref().unwrap().current;
|
||||
|
||||
Some((current_dep_graph.total_read_count,
|
||||
current_dep_graph.total_duplicate_read_count))
|
||||
Some((current_dep_graph.total_read_count.load(SeqCst),
|
||||
current_dep_graph.total_duplicate_read_count.load(SeqCst)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> SerializedDepGraph {
|
||||
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
|
||||
let data = self.data.as_ref().unwrap().current.data.lock();
|
||||
|
||||
let fingerprints: IndexVec<SerializedDepNodeIndex, _> =
|
||||
current_dep_graph.data.iter().map(|d| d.fingerprint).collect();
|
||||
data.iter().map(|d| d.fingerprint).collect();
|
||||
let nodes: IndexVec<SerializedDepNodeIndex, _> =
|
||||
current_dep_graph.data.iter().map(|d| d.node).collect();
|
||||
data.iter().map(|d| d.node).collect();
|
||||
|
||||
let total_edge_count: usize = current_dep_graph.data.iter()
|
||||
.map(|d| d.edges.len())
|
||||
.sum();
|
||||
let total_edge_count: usize = data.iter().map(|d| d.edges.len()).sum();
|
||||
|
||||
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
|
||||
let mut edge_list_data = Vec::with_capacity(total_edge_count);
|
||||
|
||||
for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated()
|
||||
.map(|(i, d)| (i, &d.edges)) {
|
||||
for (current_dep_node_index, edges) in data.iter_enumerated().map(|(i, d)| (i, &d.edges)) {
|
||||
let start = edge_list_data.len() as u32;
|
||||
// This should really just be a memcpy :/
|
||||
edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index())));
|
||||
|
|
@ -613,7 +601,11 @@ impl DepGraph {
|
|||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
{
|
||||
debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
|
||||
debug_assert!(!data.current
|
||||
.node_to_node_index
|
||||
.get_shard_by_value(dep_node)
|
||||
.lock()
|
||||
.contains_key(dep_node));
|
||||
debug_assert!(data.colors.get(prev_dep_node_index).is_none());
|
||||
}
|
||||
|
||||
|
|
@ -746,15 +738,13 @@ impl DepGraph {
|
|||
// There may be multiple threads trying to mark the same dep node green concurrently
|
||||
|
||||
let dep_node_index = {
|
||||
let mut current = data.current.borrow_mut();
|
||||
|
||||
// Copy the fingerprint from the previous graph,
|
||||
// so we don't have to recompute it
|
||||
let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
|
||||
|
||||
// We allocating an entry for the node in the current dependency graph and
|
||||
// adding all the appropriate edges imported from the previous graph
|
||||
current.intern_node(*dep_node, current_deps, fingerprint)
|
||||
data.current.intern_node(*dep_node, current_deps, fingerprint)
|
||||
};
|
||||
|
||||
// ... emitting any stored diagnostic ...
|
||||
|
|
@ -858,6 +848,8 @@ impl DepGraph {
|
|||
// This method will only load queries that will end up in the disk cache.
|
||||
// Other queries will not be executed.
|
||||
pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) {
|
||||
let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion");
|
||||
|
||||
let data = self.data.as_ref().unwrap();
|
||||
for prev_index in data.colors.values.indices() {
|
||||
match data.colors.get(prev_index) {
|
||||
|
|
@ -874,25 +866,6 @@ impl DepGraph {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) {
|
||||
debug!("mark_loaded_from_cache({:?}, {})",
|
||||
self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node,
|
||||
state);
|
||||
|
||||
self.data
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.loaded_from_cache
|
||||
.borrow_mut()
|
||||
.insert(dep_node_index, state);
|
||||
}
|
||||
|
||||
pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option<bool> {
|
||||
let data = self.data.as_ref().unwrap();
|
||||
let dep_node_index = data.current.borrow().node_to_node_index[dep_node];
|
||||
data.loaded_from_cache.borrow().get(&dep_node_index).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
/// A "work product" is an intermediate result that we save into the
|
||||
|
|
@ -947,9 +920,27 @@ struct DepNodeData {
|
|||
fingerprint: Fingerprint,
|
||||
}
|
||||
|
||||
/// `CurrentDepGraph` stores the dependency graph for the current session.
|
||||
/// It will be populated as we run queries or tasks.
|
||||
///
|
||||
/// The nodes in it are identified by an index (`DepNodeIndex`).
|
||||
/// The data for each node is stored in its `DepNodeData`, found in the `data` field.
|
||||
///
|
||||
/// We never remove nodes from the graph: they are only added.
|
||||
///
|
||||
/// This struct uses two locks internally. The `data` and `node_to_node_index` fields are
|
||||
/// locked separately. Operations that take a `DepNodeIndex` typically just access
|
||||
/// the data field.
|
||||
///
|
||||
/// The only operation that must manipulate both locks is adding new nodes, in which case
|
||||
/// we first acquire the `node_to_node_index` lock and then, once a new node is to be inserted,
|
||||
/// acquire the lock on `data.`
|
||||
pub(super) struct CurrentDepGraph {
|
||||
data: IndexVec<DepNodeIndex, DepNodeData>,
|
||||
node_to_node_index: FxHashMap<DepNode, DepNodeIndex>,
|
||||
data: Lock<IndexVec<DepNodeIndex, DepNodeData>>,
|
||||
node_to_node_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
|
||||
|
||||
/// Used to trap when a specific edge is added to the graph.
|
||||
/// This is used for debug purposes and is only active with `debug_assertions`.
|
||||
#[allow(dead_code)]
|
||||
forbidden_edge: Option<EdgeFilter>,
|
||||
|
||||
|
|
@ -966,8 +957,10 @@ pub(super) struct CurrentDepGraph {
|
|||
/// the `DepGraph` is created.
|
||||
anon_id_seed: Fingerprint,
|
||||
|
||||
total_read_count: u64,
|
||||
total_duplicate_read_count: u64,
|
||||
/// These are simple counters that are for profiling and
|
||||
/// debugging and only active with `debug_assertions`.
|
||||
total_read_count: AtomicU64,
|
||||
total_duplicate_read_count: AtomicU64,
|
||||
}
|
||||
|
||||
impl CurrentDepGraph {
|
||||
|
|
@ -1001,20 +994,20 @@ impl CurrentDepGraph {
|
|||
let new_node_count_estimate = (prev_graph_node_count * 102) / 100 + 200;
|
||||
|
||||
CurrentDepGraph {
|
||||
data: IndexVec::with_capacity(new_node_count_estimate),
|
||||
node_to_node_index: FxHashMap::with_capacity_and_hasher(
|
||||
new_node_count_estimate,
|
||||
data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)),
|
||||
node_to_node_index: Sharded::new(|| FxHashMap::with_capacity_and_hasher(
|
||||
new_node_count_estimate / sharded::SHARDS,
|
||||
Default::default(),
|
||||
),
|
||||
)),
|
||||
anon_id_seed: stable_hasher.finish(),
|
||||
forbidden_edge,
|
||||
total_read_count: 0,
|
||||
total_duplicate_read_count: 0,
|
||||
total_read_count: AtomicU64::new(0),
|
||||
total_duplicate_read_count: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn complete_task(
|
||||
&mut self,
|
||||
&self,
|
||||
node: DepNode,
|
||||
task_deps: TaskDeps,
|
||||
fingerprint: Fingerprint
|
||||
|
|
@ -1022,7 +1015,7 @@ impl CurrentDepGraph {
|
|||
self.alloc_node(node, task_deps.reads, fingerprint)
|
||||
}
|
||||
|
||||
fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex {
|
||||
fn complete_anon_task(&self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex {
|
||||
debug_assert!(!kind.is_eval_always());
|
||||
|
||||
let mut hasher = StableHasher::new();
|
||||
|
|
@ -1047,28 +1040,30 @@ impl CurrentDepGraph {
|
|||
}
|
||||
|
||||
fn alloc_node(
|
||||
&mut self,
|
||||
&self,
|
||||
dep_node: DepNode,
|
||||
edges: SmallVec<[DepNodeIndex; 8]>,
|
||||
fingerprint: Fingerprint
|
||||
) -> DepNodeIndex {
|
||||
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
|
||||
debug_assert!(!self.node_to_node_index
|
||||
.get_shard_by_value(&dep_node)
|
||||
.lock()
|
||||
.contains_key(&dep_node));
|
||||
self.intern_node(dep_node, edges, fingerprint)
|
||||
}
|
||||
|
||||
fn intern_node(
|
||||
&mut self,
|
||||
&self,
|
||||
dep_node: DepNode,
|
||||
edges: SmallVec<[DepNodeIndex; 8]>,
|
||||
fingerprint: Fingerprint
|
||||
) -> DepNodeIndex {
|
||||
debug_assert_eq!(self.node_to_node_index.len(), self.data.len());
|
||||
|
||||
match self.node_to_node_index.entry(dep_node) {
|
||||
match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) {
|
||||
Entry::Occupied(entry) => *entry.get(),
|
||||
Entry::Vacant(entry) => {
|
||||
let dep_node_index = DepNodeIndex::new(self.data.len());
|
||||
self.data.push(DepNodeData {
|
||||
let mut data = self.data.lock();
|
||||
let dep_node_index = DepNodeIndex::new(data.len());
|
||||
data.push(DepNodeData {
|
||||
node: dep_node,
|
||||
edges,
|
||||
fingerprint
|
||||
|
|
@ -1087,7 +1082,7 @@ impl DepGraphData {
|
|||
if let Some(task_deps) = icx.task_deps {
|
||||
let mut task_deps = task_deps.lock();
|
||||
if cfg!(debug_assertions) {
|
||||
self.current.lock().total_read_count += 1;
|
||||
self.current.total_read_count.fetch_add(1, SeqCst);
|
||||
}
|
||||
if task_deps.read_set.insert(source) {
|
||||
task_deps.reads.push(source);
|
||||
|
|
@ -1095,9 +1090,9 @@ impl DepGraphData {
|
|||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if let Some(target) = task_deps.node {
|
||||
let graph = self.current.lock();
|
||||
if let Some(ref forbidden_edge) = graph.forbidden_edge {
|
||||
let source = graph.data[source].node;
|
||||
let data = self.current.data.lock();
|
||||
if let Some(ref forbidden_edge) = self.current.forbidden_edge {
|
||||
let source = data[source].node;
|
||||
if forbidden_edge.test(&source, &target) {
|
||||
bug!("forbidden edge {:?} -> {:?} created",
|
||||
source,
|
||||
|
|
@ -1107,7 +1102,7 @@ impl DepGraphData {
|
|||
}
|
||||
}
|
||||
} else if cfg!(debug_assertions) {
|
||||
self.current.lock().total_duplicate_read_count += 1;
|
||||
self.current.total_duplicate_read_count.fetch_add(1, SeqCst);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -259,8 +259,8 @@ trait Foo {
|
|||
This is similar to the second sub-error, but subtler. It happens in situations
|
||||
like the following:
|
||||
|
||||
```compile_fail
|
||||
trait Super<A> {}
|
||||
```compile_fail,E0038
|
||||
trait Super<A: ?Sized> {}
|
||||
|
||||
trait Trait: Super<Self> {
|
||||
}
|
||||
|
|
@ -270,17 +270,21 @@ struct Foo;
|
|||
impl Super<Foo> for Foo{}
|
||||
|
||||
impl Trait for Foo {}
|
||||
|
||||
fn main() {
|
||||
let x: Box<dyn Trait>;
|
||||
}
|
||||
```
|
||||
|
||||
Here, the supertrait might have methods as follows:
|
||||
|
||||
```
|
||||
trait Super<A> {
|
||||
fn get_a(&self) -> A; // note that this is object safe!
|
||||
trait Super<A: ?Sized> {
|
||||
fn get_a(&self) -> &A; // note that this is object safe!
|
||||
}
|
||||
```
|
||||
|
||||
If the trait `Foo` was deriving from something like `Super<String>` or
|
||||
If the trait `Trait` was deriving from something like `Super<String>` or
|
||||
`Super<T>` (where `Foo` itself is `Foo<T>`), this is okay, because given a type
|
||||
`get_a()` will definitely return an object of that type.
|
||||
|
||||
|
|
@ -466,67 +470,6 @@ fn main() {
|
|||
```
|
||||
"##,
|
||||
|
||||
// This shouldn't really ever trigger since the repeated value error comes first
|
||||
E0136: r##"
|
||||
A binary can only have one entry point, and by default that entry point is the
|
||||
function `main()`. If there are multiple such functions, please rename one.
|
||||
"##,
|
||||
|
||||
E0137: r##"
|
||||
More than one function was declared with the `#[main]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0137
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn foo() {}
|
||||
|
||||
#[main]
|
||||
fn f() {} // error: multiple functions with a `#[main]` attribute
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[main]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn f() {} // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0138: r##"
|
||||
More than one function was declared with the `#[start]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0138
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize {}
|
||||
|
||||
#[start]
|
||||
fn f(argc: isize, argv: *const *const u8) -> isize {}
|
||||
// error: multiple 'start' functions
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[start]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0139: r##"
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
|
|
@ -1580,8 +1523,51 @@ where
|
|||
```
|
||||
"##,
|
||||
|
||||
E0495: r##"
|
||||
A lifetime cannot be determined in the given situation.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0495
|
||||
fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
|
||||
match (&t,) { // error!
|
||||
((u,),) => u,
|
||||
}
|
||||
}
|
||||
|
||||
let y = Box::new((42,));
|
||||
let x = transmute_lifetime(&y);
|
||||
```
|
||||
|
||||
In this code, you have two ways to solve this issue:
|
||||
1. Enforce that `'a` lives at least as long as `'b`.
|
||||
2. Use the same lifetime requirement for both input and output values.
|
||||
|
||||
So for the first solution, you can do it by replacing `'a` with `'a: 'b`:
|
||||
|
||||
```
|
||||
fn transmute_lifetime<'a: 'b, 'b, T>(t: &'a (T,)) -> &'b T {
|
||||
match (&t,) { // ok!
|
||||
((u,),) => u,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the second you can do it by simply removing `'b` so they both use `'a`:
|
||||
|
||||
```
|
||||
fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T {
|
||||
match (&t,) { // ok!
|
||||
((u,),) => u,
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0496: r##"
|
||||
A lifetime name is shadowing another lifetime name. Erroneous code example:
|
||||
A lifetime name is shadowing another lifetime name.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0496
|
||||
struct Foo<'a> {
|
||||
|
|
@ -1613,8 +1599,11 @@ fn main() {
|
|||
"##,
|
||||
|
||||
E0497: r##"
|
||||
A stability attribute was used outside of the standard library. Erroneous code
|
||||
example:
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
A stability attribute was used outside of the standard library.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
#[stable] // error: stability attributes may not be used outside of the
|
||||
|
|
@ -1626,33 +1615,6 @@ It is not possible to use stability attributes outside of the standard library.
|
|||
Also, for now, it is not possible to write deprecation messages either.
|
||||
"##,
|
||||
|
||||
E0512: r##"
|
||||
Transmute with two differently sized types was attempted. Erroneous code
|
||||
example:
|
||||
|
||||
```compile_fail,E0512
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0u16)); }
|
||||
// error: cannot transmute between types of different sizes,
|
||||
// or dependently-sized types
|
||||
}
|
||||
```
|
||||
|
||||
Please use types with same size or use the expected type directly. Example:
|
||||
|
||||
```
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
|
||||
// or:
|
||||
unsafe { takes_u8(0u8); } // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0517: r##"
|
||||
This error indicates that a `#[repr(..)]` attribute was placed on an
|
||||
unsupported item.
|
||||
|
|
@ -1787,6 +1749,27 @@ To understand better how closures work in Rust, read:
|
|||
https://doc.rust-lang.org/book/ch13-01-closures.html
|
||||
"##,
|
||||
|
||||
E0566: r##"
|
||||
Conflicting representation hints have been used on a same item.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
#[repr(u32, u64)] // warning!
|
||||
enum Repr { A }
|
||||
```
|
||||
|
||||
In most cases (if not all), using just one representation hint is more than
|
||||
enough. If you want to have a representation hint depending on the current
|
||||
architecture, use `cfg_attr`. Example:
|
||||
|
||||
```
|
||||
#[cfg_attr(linux, repr(u32))]
|
||||
#[cfg_attr(not(linux), repr(u64))]
|
||||
enum Repr { A }
|
||||
```
|
||||
"##,
|
||||
|
||||
E0580: r##"
|
||||
The `main` function was incorrectly declared.
|
||||
|
||||
|
|
@ -1847,84 +1830,6 @@ See [RFC 1522] for more details.
|
|||
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
|
||||
"##,
|
||||
|
||||
E0591: r##"
|
||||
Per [RFC 401][rfc401], if you have a function declaration `foo`:
|
||||
|
||||
```
|
||||
// For the purposes of this explanation, all of these
|
||||
// different kinds of `fn` declarations are equivalent:
|
||||
struct S;
|
||||
fn foo(x: S) { /* ... */ }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
extern "C" { fn foo(x: S); }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
impl S { fn foo(self) { /* ... */ } }
|
||||
```
|
||||
|
||||
the type of `foo` is **not** `fn(S)`, as one might expect.
|
||||
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
|
||||
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
|
||||
so you rarely notice this:
|
||||
|
||||
```
|
||||
# struct S;
|
||||
# fn foo(_: S) {}
|
||||
let x: fn(S) = foo; // OK, coerces
|
||||
```
|
||||
|
||||
The reason that this matter is that the type `fn(S)` is not specific to
|
||||
any particular function: it's a function _pointer_. So calling `x()` results
|
||||
in a virtual call, whereas `foo()` is statically dispatched, because the type
|
||||
of `foo` tells us precisely what function is being called.
|
||||
|
||||
As noted above, coercions mean that most code doesn't have to be
|
||||
concerned with this distinction. However, you can tell the difference
|
||||
when using **transmute** to convert a fn item into a fn pointer.
|
||||
|
||||
This is sometimes done as part of an FFI:
|
||||
|
||||
```compile_fail,E0591
|
||||
extern "C" fn foo(userdata: Box<i32>) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
# fn callback(_: extern "C" fn(*mut i32)) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo);
|
||||
callback(f);
|
||||
# }
|
||||
```
|
||||
|
||||
Here, transmute is being used to convert the types of the fn arguments.
|
||||
This pattern is incorrect because, because the type of `foo` is a function
|
||||
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
|
||||
is a function pointer, which is not zero-sized.
|
||||
This pattern should be rewritten. There are a few possible ways to do this:
|
||||
|
||||
- change the original fn declaration to match the expected signature,
|
||||
and do the cast in the fn body (the preferred option)
|
||||
- cast the fn item fo a fn pointer before calling transmute, as shown here:
|
||||
|
||||
```
|
||||
# extern "C" fn foo(_: Box<i32>) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
# }
|
||||
```
|
||||
|
||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||
Note though that use of this type is generally incorrect.
|
||||
The intention is typically to describe a function pointer, but just `fn()`
|
||||
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
|
||||
(Since these values are typically just passed to C code, however, this rarely
|
||||
makes a difference in practice.)
|
||||
|
||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
"##,
|
||||
|
||||
E0593: r##"
|
||||
You tried to supply an `Fn`-based type with an incorrect number of arguments
|
||||
than what was expected.
|
||||
|
|
@ -1941,21 +1846,6 @@ fn main() {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0601: r##"
|
||||
No `main` function was found in a binary crate. To fix this error, add a
|
||||
`main` function. For example:
|
||||
|
||||
```
|
||||
fn main() {
|
||||
// Your program will start here.
|
||||
println!("Hello world!");
|
||||
}
|
||||
```
|
||||
|
||||
If you don't know the basics of Rust, you can go look to the Rust Book to get
|
||||
started: https://doc.rust-lang.org/book/
|
||||
"##,
|
||||
|
||||
E0602: r##"
|
||||
An unknown lint was used on the command line.
|
||||
|
||||
|
|
@ -2115,6 +2005,24 @@ a (non-transparent) struct containing a single float, while `Grams` is a
|
|||
transparent wrapper around a float. This can make a difference for the ABI.
|
||||
"##,
|
||||
|
||||
E0697: r##"
|
||||
A closure has been used as `static`.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0697
|
||||
fn main() {
|
||||
static || {}; // used as `static`
|
||||
}
|
||||
```
|
||||
|
||||
Closures cannot be used as `static`. They "save" the environment,
|
||||
and as such a static closure would save only a static environment
|
||||
which would consist only of variables with a static lifetime. Given
|
||||
this it would be better to use a proper function. The easiest fix
|
||||
is to remove the `static` keyword.
|
||||
"##,
|
||||
|
||||
E0698: r##"
|
||||
When using generators (or async) all type variables must be bound so a
|
||||
generator can be constructed.
|
||||
|
|
@ -2234,6 +2142,25 @@ These attributes are meant to only be used by the standard library and are
|
|||
rejected in your own crates.
|
||||
"##,
|
||||
|
||||
E0736: r##"
|
||||
#[track_caller] and #[naked] cannot be applied to the same function.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0736
|
||||
#![feature(track_caller)]
|
||||
|
||||
#[naked]
|
||||
#[track_caller]
|
||||
fn foo() {}
|
||||
```
|
||||
|
||||
This is primarily due to ABI incompatibilities between the two attributes.
|
||||
See [RFC 2091] for details on this and other limitations.
|
||||
|
||||
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
|
||||
"##,
|
||||
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0101, // replaced with E0282
|
||||
|
|
@ -2243,7 +2170,7 @@ rejected in your own crates.
|
|||
// E0272, // on_unimplemented #0
|
||||
// E0273, // on_unimplemented #1
|
||||
// E0274, // on_unimplemented #2
|
||||
E0278, // requirement is not satisfied
|
||||
// E0278, // requirement is not satisfied
|
||||
E0279, // requirement is not satisfied
|
||||
E0280, // requirement is not satisfied
|
||||
// E0285, // overflow evaluation builtin bounds
|
||||
|
|
@ -2275,9 +2202,6 @@ rejected in your own crates.
|
|||
E0488, // lifetime of variable does not enclose its declaration
|
||||
E0489, // type/lifetime parameter not in scope here
|
||||
E0490, // a value of type `..` is borrowed for too long
|
||||
E0495, // cannot infer an appropriate lifetime due to conflicting
|
||||
// requirements
|
||||
E0566, // conflicting representation hints
|
||||
E0623, // lifetime mismatch where both parameters are anonymous regions
|
||||
E0628, // generators cannot have explicit parameters
|
||||
E0631, // type mismatch in closure arguments
|
||||
|
|
@ -2285,15 +2209,15 @@ rejected in your own crates.
|
|||
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
|
||||
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
|
||||
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
|
||||
E0697, // closures cannot be static
|
||||
E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||
// E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||
E0708, // `async` non-`move` closures with parameters are not currently
|
||||
// supported
|
||||
E0709, // multiple different lifetimes used in arguments of `async fn`
|
||||
// E0709, // multiple different lifetimes used in arguments of `async fn`
|
||||
E0710, // an unknown tool name found in scoped lint
|
||||
E0711, // a feature has been declared with conflicting stability attributes
|
||||
// E0702, // replaced with a generic attribute input check
|
||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||
E0727, // `async` generators are not yet supported
|
||||
E0728, // `await` must be in an `async` function or block
|
||||
E0739, // invalid track_caller application/syntax
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::ty::TyCtxt;
|
|||
use crate::ty::query::Providers;
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use syntax::symbol::sym;
|
||||
use syntax::{attr, symbol::sym};
|
||||
use syntax_pos::Span;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
|
@ -103,6 +103,8 @@ impl CheckAttrVisitor<'tcx> {
|
|||
self.check_marker(attr, item, target)
|
||||
} else if attr.check_name(sym::target_feature) {
|
||||
self.check_target_feature(attr, item, target)
|
||||
} else if attr.check_name(sym::track_caller) {
|
||||
self.check_track_caller(attr, &item, target)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
|
@ -135,6 +137,32 @@ impl CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
|
||||
fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
|
||||
if target != Target::Fn {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
attr.span,
|
||||
E0739,
|
||||
"attribute should be applied to function"
|
||||
)
|
||||
.span_label(item.span, "not a function")
|
||||
.emit();
|
||||
false
|
||||
} else if attr::contains_name(&item.attrs, sym::naked) {
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
attr.span,
|
||||
E0736,
|
||||
"cannot use `#[track_caller]` with `#[naked]`",
|
||||
)
|
||||
.emit();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
|
||||
fn check_non_exhaustive(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::ty;
|
|||
use crate::util::nodemap::DefIdMap;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax_expand::base::MacroKind;
|
||||
use syntax::ast::NodeId;
|
||||
use syntax_pos::Span;
|
||||
use rustc_macros::HashStable;
|
||||
|
|
|
|||
|
|
@ -64,14 +64,15 @@ use syntax::ast;
|
|||
use syntax::ptr::P as AstP;
|
||||
use syntax::ast::*;
|
||||
use syntax::errors;
|
||||
use syntax::ext::base::SpecialDerives;
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax_expand::base::SpecialDerives;
|
||||
use syntax::print::pprust;
|
||||
use syntax::parse::token::{self, Nonterminal, Token};
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
|
||||
use syntax::symbol::{kw, sym, Symbol};
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::parse::token::{self, Token};
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax_pos::hygiene::ExpnId;
|
||||
use syntax_pos::Span;
|
||||
|
||||
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
|
||||
|
|
@ -86,6 +87,11 @@ pub struct LoweringContext<'a> {
|
|||
|
||||
resolver: &'a mut dyn Resolver,
|
||||
|
||||
/// HACK(Centril): there is a cyclic dependency between the parser and lowering
|
||||
/// if we don't have this function pointer. To avoid that dependency so that
|
||||
/// librustc is independent of the parser, we use dynamic dispatch here.
|
||||
nt_to_tokenstream: NtToTokenstream,
|
||||
|
||||
/// The items being lowered are collected here.
|
||||
items: BTreeMap<hir::HirId, hir::Item>,
|
||||
|
||||
|
|
@ -180,6 +186,8 @@ pub trait Resolver {
|
|||
fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
|
||||
}
|
||||
|
||||
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
/// and if so, what meaning it has.
|
||||
#[derive(Debug)]
|
||||
|
|
@ -236,17 +244,21 @@ pub fn lower_crate(
|
|||
dep_graph: &DepGraph,
|
||||
krate: &Crate,
|
||||
resolver: &mut dyn Resolver,
|
||||
nt_to_tokenstream: NtToTokenstream,
|
||||
) -> hir::Crate {
|
||||
// We're constructing the HIR here; we don't care what we will
|
||||
// read, since we haven't even constructed the *input* to
|
||||
// incr. comp. yet.
|
||||
dep_graph.assert_ignored();
|
||||
|
||||
let _prof_timer = sess.prof.generic_activity("hir_lowering");
|
||||
|
||||
LoweringContext {
|
||||
crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
|
||||
sess,
|
||||
cstore,
|
||||
resolver,
|
||||
nt_to_tokenstream,
|
||||
items: BTreeMap::new(),
|
||||
trait_items: BTreeMap::new(),
|
||||
impl_items: BTreeMap::new(),
|
||||
|
|
@ -844,7 +856,7 @@ impl<'a> LoweringContext<'a> {
|
|||
/// header, we convert it to an in-band lifetime.
|
||||
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
|
||||
assert!(self.is_collecting_in_band_lifetimes);
|
||||
let index = self.lifetimes_to_define.len();
|
||||
let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len();
|
||||
let hir_name = ParamName::Fresh(index);
|
||||
self.lifetimes_to_define.push((span, hir_name));
|
||||
hir_name
|
||||
|
|
@ -1020,7 +1032,7 @@ impl<'a> LoweringContext<'a> {
|
|||
fn lower_token(&mut self, token: Token) -> TokenStream {
|
||||
match token.kind {
|
||||
token::Interpolated(nt) => {
|
||||
let tts = nt.to_tokenstream(&self.sess.parse_sess, token.span);
|
||||
let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span);
|
||||
self.lower_token_stream(tts)
|
||||
}
|
||||
_ => TokenTree::Token(token).into(),
|
||||
|
|
@ -3279,10 +3291,14 @@ impl<'a> LoweringContext<'a> {
|
|||
let id = self.sess.next_node_id();
|
||||
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
|
||||
}
|
||||
// This is the normal case.
|
||||
AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
|
||||
|
||||
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
|
||||
// `PassThrough` is the normal case.
|
||||
// `new_error_lifetime`, which would usually be used in the case of `ReportError`,
|
||||
// is unsuitable here, as these can occur from missing lifetime parameters in a
|
||||
// `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
|
||||
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
|
||||
// later, at which point a suitable error will be emitted.
|
||||
| AnonymousLifetimeMode::PassThrough
|
||||
| AnonymousLifetimeMode::ReportError => self.new_implicit_lifetime(span),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use smallvec::SmallVec;
|
|||
use syntax::attr;
|
||||
use syntax::ast::*;
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax::ext::base::SpecialDerives;
|
||||
use syntax_expand::base::SpecialDerives;
|
||||
use syntax::source_map::{respan, DesugaringKind, Spanned};
|
||||
use syntax::symbol::{kw, sym};
|
||||
use syntax_pos::Span;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::hir::map::definitions::*;
|
|||
use crate::hir::def_id::DefIndex;
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax_expand::hygiene::ExpnId;
|
||||
use syntax::visit;
|
||||
use syntax::symbol::{kw, sym};
|
||||
use syntax::parse::token::{self, Token};
|
||||
|
|
@ -90,7 +90,7 @@ impl<'a> DefCollector<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn visit_macro_invoc(&mut self, id: NodeId) {
|
||||
fn visit_macro_invoc(&mut self, id: NodeId) {
|
||||
self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use std::borrow::Borrow;
|
|||
use std::fmt::Write;
|
||||
use std::hash::Hash;
|
||||
use syntax::ast;
|
||||
use syntax::ext::hygiene::ExpnId;
|
||||
use syntax_expand::hygiene::ExpnId;
|
||||
use syntax::symbol::{Symbol, sym, InternedString};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ pub struct Definitions {
|
|||
/// A unique identifier that we can use to lookup a definition
|
||||
/// precisely. It combines the index of the definition's parent (if
|
||||
/// any) with a `DisambiguatedDefPathData`.
|
||||
#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct DefKey {
|
||||
/// The parent path.
|
||||
pub parent: Option<DefIndex>,
|
||||
|
|
@ -162,13 +162,13 @@ impl DefKey {
|
|||
/// between them. This introduces some artificial ordering dependency
|
||||
/// but means that if you have, e.g., two impls for the same type in
|
||||
/// the same module, they do get distinct `DefId`s.
|
||||
#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct DisambiguatedDefPathData {
|
||||
pub data: DefPathData,
|
||||
pub disambiguator: u32
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct DefPath {
|
||||
/// The path leading from the crate root to the item.
|
||||
pub data: Vec<DisambiguatedDefPathData>,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use rustc_data_structures::svh::Svh;
|
|||
use rustc_index::vec::IndexVec;
|
||||
use syntax::ast::{self, Name, NodeId};
|
||||
use syntax::source_map::Spanned;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax_expand::base::MacroKind;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
pub mod blocks;
|
||||
|
|
@ -1222,6 +1222,8 @@ pub fn map_crate<'hir>(sess: &crate::session::Session,
|
|||
forest: &'hir Forest,
|
||||
definitions: &'hir Definitions)
|
||||
-> Map<'hir> {
|
||||
let _prof_timer = sess.prof.generic_activity("build_hir_map");
|
||||
|
||||
// Build the reverse mapping of `node_to_hir_id`.
|
||||
let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated()
|
||||
.map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
|
||||
|
|
|
|||
|
|
@ -669,6 +669,12 @@ impl WhereClause {
|
|||
Some(self.span)
|
||||
}
|
||||
}
|
||||
|
||||
/// The `WhereClause` under normal circumstances points at either the predicates or the empty
|
||||
/// space where the `where` clause should be. Only of use for diagnostic suggestions.
|
||||
pub fn span_for_predicates_or_empty_place(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
/// A single predicate in a where-clause.
|
||||
|
|
@ -989,6 +995,15 @@ pub enum RangeEnd {
|
|||
Excluded,
|
||||
}
|
||||
|
||||
impl fmt::Display for RangeEnd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
RangeEnd::Included => "..=",
|
||||
RangeEnd::Excluded => "..",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub enum PatKind {
|
||||
/// Represents a wildcard pattern (i.e., `_`).
|
||||
|
|
@ -1053,6 +1068,13 @@ impl Mutability {
|
|||
MutImmutable => MutImmutable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invert(self) -> Self {
|
||||
match self {
|
||||
MutMutable => MutImmutable,
|
||||
MutImmutable => MutMutable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)]
|
||||
|
|
@ -1359,6 +1381,10 @@ impl Body {
|
|||
hir_id: self.value.hir_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generator_kind(&self) -> Option<GeneratorKind> {
|
||||
self.generator_kind
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of source expression that caused this generator to be created.
|
||||
|
|
@ -1548,6 +1574,19 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
|
||||
/// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
|
||||
/// silent, only signaling the ownership system. By doing this, suggestions that check the
|
||||
/// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps`
|
||||
/// beyond remembering to call this function before doing analysis on it.
|
||||
pub fn peel_drop_temps(&self) -> &Self {
|
||||
let mut expr = self;
|
||||
while let ExprKind::DropTemps(inner) = &expr.kind {
|
||||
expr = inner;
|
||||
}
|
||||
expr
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Expr {
|
||||
|
|
@ -2669,6 +2708,11 @@ pub struct CodegenFnAttrs {
|
|||
/// probably isn't set when this is set, this is for foreign items while
|
||||
/// `#[export_name]` is for Rust-defined functions.
|
||||
pub link_name: Option<Symbol>,
|
||||
/// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an
|
||||
/// imported function has in the dynamic library. Note that this must not
|
||||
/// be set when `link_name` is set. This is for foreign items with the
|
||||
/// "raw-dylib" kind.
|
||||
pub link_ordinal: Option<usize>,
|
||||
/// The `#[target_feature(enable = "...")]` attribute and the enabled
|
||||
/// features (only enabled features are supported right now).
|
||||
pub target_features: Vec<Symbol>,
|
||||
|
|
@ -2716,7 +2760,9 @@ bitflags! {
|
|||
const USED = 1 << 9;
|
||||
/// #[ffi_returns_twice], indicates that an extern function can return
|
||||
/// multiple times
|
||||
const FFI_RETURNS_TWICE = 1 << 10;
|
||||
const FFI_RETURNS_TWICE = 1 << 10;
|
||||
/// #[track_caller]: allow access to the caller location
|
||||
const TRACK_CALLER = 1 << 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2728,6 +2774,7 @@ impl CodegenFnAttrs {
|
|||
optimize: OptimizeAttr::None,
|
||||
export_name: None,
|
||||
link_name: None,
|
||||
link_ordinal: None,
|
||||
target_features: vec![],
|
||||
linkage: None,
|
||||
link_section: None,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::source_map::{SourceMap, Spanned};
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax::print::pp::{self, Breaks};
|
||||
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
|
||||
use syntax::print::pprust::{self, Comments, PrintState};
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::symbol::kw;
|
||||
use syntax::util::parser::{self, AssocOp, Fixity};
|
||||
use syntax_pos::{self, BytePos, FileName};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use std::cell::RefCell;
|
|||
|
||||
use syntax::ast;
|
||||
use syntax::source_map::SourceMap;
|
||||
use syntax::ext::hygiene::SyntaxContext;
|
||||
use syntax_expand::hygiene::SyntaxContext;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::tokenstream::DelimSpan;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
|
|||
Intel
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
|
||||
impl_stable_hash_for!(enum ::syntax_expand::base::MacroKind {
|
||||
Bang,
|
||||
Attr,
|
||||
Derive,
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
{
|
||||
sp = param.span;
|
||||
}
|
||||
(format!("the lifetime {} as defined on", br.name), sp)
|
||||
(format!("the lifetime `{}` as defined on", br.name), sp)
|
||||
}
|
||||
ty::ReFree(ty::FreeRegion {
|
||||
bound_region: ty::BoundRegion::BrNamed(_, name),
|
||||
|
|
@ -213,7 +213,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
{
|
||||
sp = param.span;
|
||||
}
|
||||
(format!("the lifetime {} as defined on", name), sp)
|
||||
(format!("the lifetime `{}` as defined on", name), sp)
|
||||
}
|
||||
ty::ReFree(ref fr) => match fr.bound_region {
|
||||
ty::BrAnon(idx) => (
|
||||
|
|
@ -221,7 +221,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.hir().span(node),
|
||||
),
|
||||
_ => (
|
||||
format!("the lifetime {} as defined on", region),
|
||||
format!("the lifetime `{}` as defined on", region),
|
||||
cm.def_span(self.hir().span(node)),
|
||||
),
|
||||
},
|
||||
|
|
@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
.filter(|(a, b)| a == b)
|
||||
.count();
|
||||
let len = sub1.len() - common_default_params;
|
||||
let consts_offset = len - sub1.consts().count();
|
||||
|
||||
// Only draw `<...>` if there're lifetime/type arguments.
|
||||
if len > 0 {
|
||||
|
|
@ -981,7 +982,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// ^ elided type as this type argument was the same in both sides
|
||||
let type_arguments = sub1.types().zip(sub2.types());
|
||||
let regions_len = sub1.regions().count();
|
||||
for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() {
|
||||
let num_display_types = consts_offset - regions_len;
|
||||
for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
|
||||
let i = i + regions_len;
|
||||
if ta1 == ta2 {
|
||||
values.0.push_normal("_");
|
||||
|
|
@ -994,6 +996,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||
}
|
||||
|
||||
// Do the same for const arguments, if they are equal, do not highlight and
|
||||
// elide them from the output.
|
||||
let const_arguments = sub1.consts().zip(sub2.consts());
|
||||
for (i, (ca1, ca2)) in const_arguments.enumerate() {
|
||||
let i = i + consts_offset;
|
||||
if ca1 == ca2 {
|
||||
values.0.push_normal("_");
|
||||
values.1.push_normal("_");
|
||||
} else {
|
||||
values.0.push_highlighted(ca1.to_string());
|
||||
values.1.push_highlighted(ca2.to_string());
|
||||
}
|
||||
self.push_comma(&mut values.0, &mut values.1, len, i);
|
||||
}
|
||||
|
||||
// Close the type argument bracket.
|
||||
// Only draw `<...>` if there're lifetime/type arguments.
|
||||
if len > 0 {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_data_structures::graph::implementation::{
|
||||
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
|
||||
};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -304,8 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
|
||||
self.iterate_until_fixed_point("Expansion", |constraint| {
|
||||
debug!("expansion: constraint={:?}", constraint);
|
||||
let mut process_constraint = |constraint: &Constraint<'tcx>| {
|
||||
let (a_region, b_vid, b_data, retain) = match *constraint {
|
||||
Constraint::RegSubVar(a_region, b_vid) => {
|
||||
let b_data = var_values.value_mut(b_vid);
|
||||
|
|
@ -331,7 +330,33 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
|
||||
let changed = self.expand_node(a_region, b_vid, b_data);
|
||||
(changed, retain)
|
||||
})
|
||||
};
|
||||
|
||||
// Using bitsets to track the remaining elements is faster than using a
|
||||
// `Vec` by itself (which requires removing elements, which requires
|
||||
// element shuffling, which is slow).
|
||||
let constraints: Vec<_> = self.data.constraints.keys().collect();
|
||||
let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
|
||||
let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
|
||||
let mut changed = true;
|
||||
while changed {
|
||||
changed = false;
|
||||
for index in live_indices.iter() {
|
||||
let constraint = constraints[index];
|
||||
let (edge_changed, retain) = process_constraint(constraint);
|
||||
if edge_changed {
|
||||
changed = true;
|
||||
}
|
||||
if !retain {
|
||||
let changed = killed_indices.insert(index);
|
||||
debug_assert!(changed);
|
||||
}
|
||||
}
|
||||
live_indices.subtract(&killed_indices);
|
||||
|
||||
// We could clear `killed_indices` here, but we don't need to and
|
||||
// it's cheaper not to.
|
||||
}
|
||||
}
|
||||
|
||||
// This function is very hot in some workloads. There's a single callsite
|
||||
|
|
@ -360,13 +385,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
match *b_data {
|
||||
VarValue::Value(cur_region) => {
|
||||
// Identical scopes can show up quite often, if the fixed point
|
||||
// iteration converges slowly, skip them
|
||||
// iteration converges slowly. Skip them. This is purely an
|
||||
// optimization.
|
||||
if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
|
||||
if a_scope == cur_scope {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a specialized version of the `lub_concrete_regions`
|
||||
// check below for a common case, here purely as an
|
||||
// optimization.
|
||||
if let ReEmpty = a_region {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut lub = self.lub_concrete_regions(a_region, cur_region);
|
||||
if lub == cur_region {
|
||||
return false;
|
||||
|
|
@ -407,8 +440,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
|
||||
/// Returns the smallest region `c` such that `a <= c` and `b <= c`.
|
||||
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
match (a, b) {
|
||||
(&ty::ReClosureBound(..), _)
|
||||
| (_, &ty::ReClosureBound(..))
|
||||
|
|
@ -468,7 +499,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
|
||||
// otherwise, we don't know what the free region is,
|
||||
// so we must conservatively say the LUB is static:
|
||||
tcx.lifetimes.re_static
|
||||
self.tcx().lifetimes.re_static
|
||||
}
|
||||
|
||||
(&ReScope(a_id), &ReScope(b_id)) => {
|
||||
|
|
@ -476,7 +507,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
// subtype of the region corresponding to an inner
|
||||
// block.
|
||||
let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
|
||||
tcx.mk_region(ReScope(lub))
|
||||
self.tcx().mk_region(ReScope(lub))
|
||||
}
|
||||
|
||||
(&ReEarlyBound(_), &ReEarlyBound(_))
|
||||
|
|
@ -490,7 +521,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
if a == b {
|
||||
a
|
||||
} else {
|
||||
tcx.lifetimes.re_static
|
||||
self.tcx().lifetimes.re_static
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -860,29 +891,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
|
||||
where
|
||||
F: FnMut(&Constraint<'tcx>) -> (bool, bool),
|
||||
{
|
||||
let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
|
||||
let mut iteration = 0;
|
||||
let mut changed = true;
|
||||
while changed {
|
||||
changed = false;
|
||||
iteration += 1;
|
||||
debug!("---- {} Iteration {}{}", "#", tag, iteration);
|
||||
constraints.retain(|constraint| {
|
||||
let (edge_changed, retain) = body(constraint);
|
||||
if edge_changed {
|
||||
debug!("updated due to constraint {:?}", constraint);
|
||||
changed = true;
|
||||
}
|
||||
retain
|
||||
});
|
||||
}
|
||||
debug!("---- {} Complete after {} iteration(s)", tag, iteration);
|
||||
}
|
||||
|
||||
fn bound_is_met(
|
||||
&self,
|
||||
bound: &VerifyBound<'tcx>,
|
||||
|
|
|
|||
|
|
@ -814,16 +814,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// Executes `f` and commit the bindings.
|
||||
pub fn commit_unconditionally<R, F>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
|
||||
{
|
||||
debug!("commit()");
|
||||
debug!("commit_unconditionally()");
|
||||
let snapshot = self.start_snapshot();
|
||||
let r = f();
|
||||
let r = f(&snapshot);
|
||||
self.commit_from(snapshot);
|
||||
r
|
||||
}
|
||||
|
||||
/// Executes `f` and commit the bindings if closure `f` returns `Ok(_)`.
|
||||
/// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
|
||||
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
|
||||
where
|
||||
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
|
||||
|
|
@ -843,19 +843,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
r
|
||||
}
|
||||
|
||||
/// Execute `f` in a snapshot, and commit the bindings it creates.
|
||||
pub fn in_snapshot<T, F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T,
|
||||
{
|
||||
debug!("in_snapshot()");
|
||||
let snapshot = self.start_snapshot();
|
||||
let r = f(&snapshot);
|
||||
self.commit_from(snapshot);
|
||||
r
|
||||
}
|
||||
|
||||
/// Executes `f` then unroll any bindings it creates.
|
||||
/// Execute `f` then unroll any bindings it creates.
|
||||
pub fn probe<R, F>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
|
||||
|
|
|
|||
|
|
@ -733,12 +733,12 @@ where
|
|||
// Skip lifetime parameters of the enclosing item(s)
|
||||
// Also skip the witness type, because that has no free regions.
|
||||
|
||||
for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
|
||||
for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) {
|
||||
upvar_ty.visit_with(self);
|
||||
}
|
||||
|
||||
substs.return_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.yield_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.as_generator().return_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self);
|
||||
}
|
||||
_ => {
|
||||
ty.super_visit_with(self);
|
||||
|
|
@ -902,7 +902,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
ty::Generator(def_id, substs, movability) => {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let substs =
|
||||
self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
|
||||
self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| {
|
||||
if index < generics.parent_count {
|
||||
// Accommodate missing regions in the parent kinds...
|
||||
self.fold_kind_mapping_missing_regions_to_empty(kind)
|
||||
|
|
@ -912,7 +912,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
}
|
||||
}));
|
||||
|
||||
self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability)
|
||||
self.tcx.mk_generator(def_id, substs, movability)
|
||||
}
|
||||
|
||||
ty::Param(..) => {
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
|||
/// retain the older (arguably incorrect) behavior of the
|
||||
/// compiler.
|
||||
///
|
||||
/// NB. The use of snapshot here is mostly an efficiency thing --
|
||||
/// we could search *all* region constraints, but that'd be a
|
||||
/// bigger set and the data structures are not setup for that. If
|
||||
/// NB. Although `_snapshot` isn't used, it's passed in to prove
|
||||
/// that we are in a snapshot, which guarantees that we can just
|
||||
/// search the "undo log" for edges. This is mostly an efficiency
|
||||
/// thing -- we could search *all* region constraints, but that'd be
|
||||
/// a bigger set and the data structures are not setup for that. If
|
||||
/// we wind up keeping some form of this check long term, it would
|
||||
/// probably be better to remove the snapshot parameter and to
|
||||
/// refactor the constraint set.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#![feature(const_transmute)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(inner_deref)]
|
||||
#![cfg_attr(windows, feature(libc))]
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
|
|
@ -57,9 +56,8 @@
|
|||
#![feature(test)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
#![cfg_attr(bootstrap, feature(proc_macro_hygiene))]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
|
|
@ -102,16 +100,12 @@ pub mod lint;
|
|||
pub mod middle {
|
||||
pub mod expr_use_visitor;
|
||||
pub mod cstore;
|
||||
pub mod dead;
|
||||
pub mod dependency_format;
|
||||
pub mod diagnostic_items;
|
||||
pub mod entry;
|
||||
pub mod exported_symbols;
|
||||
pub mod free_region;
|
||||
pub mod intrinsicck;
|
||||
pub mod lib_features;
|
||||
pub mod lang_items;
|
||||
pub mod liveness;
|
||||
pub mod mem_categorization;
|
||||
pub mod privacy;
|
||||
pub mod reachable;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ declare_lint! {
|
|||
declare_lint! {
|
||||
pub CONST_ERR,
|
||||
Deny,
|
||||
"constant evaluation detected erroneous expression"
|
||||
"constant evaluation detected erroneous expression",
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
|
@ -79,6 +80,12 @@ declare_lint! {
|
|||
"detects unreachable patterns"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub OVERLAPPING_PATTERNS,
|
||||
Warn,
|
||||
"detects overlapping patterns"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNUSED_MACROS,
|
||||
Warn,
|
||||
|
|
@ -368,6 +375,12 @@ pub mod parser {
|
|||
Allow,
|
||||
"possible meta-variable misuse at macro definition"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INCOMPLETE_INCLUDE,
|
||||
Deny,
|
||||
"trailing content in included file"
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
|
@ -416,6 +429,7 @@ declare_lint_pass! {
|
|||
DEAD_CODE,
|
||||
UNREACHABLE_CODE,
|
||||
UNREACHABLE_PATTERNS,
|
||||
OVERLAPPING_PATTERNS,
|
||||
UNUSED_MACROS,
|
||||
WARNINGS,
|
||||
UNUSED_FEATURES,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHa
|
|||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::feature_gate;
|
||||
use syntax::print::pprust;
|
||||
use syntax::source_map::MultiSpan;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
|
||||
|
|
@ -285,7 +286,7 @@ impl<'a> LintLevelsBuilder<'a> {
|
|||
tool_ident.span,
|
||||
E0710,
|
||||
"an unknown tool name found in scoped lint: `{}`",
|
||||
meta_item.path
|
||||
pprust::path_to_string(&meta_item.path),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ use crate::hir::intravisit;
|
|||
use crate::hir;
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::lint::builtin::parser::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
|
||||
use crate::lint::builtin::parser::INCOMPLETE_INCLUDE;
|
||||
use crate::session::{Session, DiagnosticMessageId};
|
||||
use crate::ty::TyCtxt;
|
||||
use crate::ty::query::Providers;
|
||||
|
|
@ -38,7 +39,7 @@ use syntax::ast;
|
|||
use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind};
|
||||
use syntax::early_buffered_lints::BufferedEarlyLintId;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax_expand::base::MacroKind;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -83,6 +84,7 @@ impl Lint {
|
|||
match lint_id {
|
||||
BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
BufferedEarlyLintId::MetaVariableMisuse => META_VARIABLE_MISUSE,
|
||||
BufferedEarlyLintId::IncompleteInclude => INCOMPLETE_INCLUDE,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ pub struct CrateSource {
|
|||
pub rmeta: Option<(PathBuf, PathKind)>,
|
||||
}
|
||||
|
||||
impl CrateSource {
|
||||
pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
|
||||
self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Copy, Clone,
|
||||
Ord, PartialOrd, Eq, PartialEq, Debug, HashStable)]
|
||||
pub enum DepKind {
|
||||
|
|
@ -96,6 +102,8 @@ pub enum NativeLibraryKind {
|
|||
NativeStaticNobundle,
|
||||
/// macOS-specific
|
||||
NativeFramework,
|
||||
/// Windows dynamic library without import library.
|
||||
NativeRawDylib,
|
||||
/// default way to specify a dynamic library
|
||||
NativeUnknown,
|
||||
}
|
||||
|
|
@ -206,7 +214,6 @@ pub trait CrateStore {
|
|||
fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
|
||||
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
|
||||
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
|
||||
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
|
||||
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
|
||||
fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
|
||||
|
||||
|
|
|
|||
|
|
@ -708,15 +708,22 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m);
|
||||
let def_id = if let Region::EarlyBound(_ ,def_id , _) = reg {
|
||||
def_id
|
||||
} else {
|
||||
bug!();
|
||||
};
|
||||
if let hir::ParamName::Plain(param_name) = name {
|
||||
if param_name.name == kw::UnderscoreLifetime {
|
||||
// Pick the elided lifetime "definition" if one exists
|
||||
// and use it to make an elision scope.
|
||||
self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many);
|
||||
elision = Some(reg);
|
||||
} else {
|
||||
lifetimes.insert(name, reg);
|
||||
}
|
||||
} else {
|
||||
self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many);
|
||||
lifetimes.insert(name, reg);
|
||||
}
|
||||
}
|
||||
|
|
@ -1615,7 +1622,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
_ => None,
|
||||
} {
|
||||
debug!("id = {:?} span = {:?} name = {:?}", id, span, name);
|
||||
|
||||
if name.name == kw::UnderscoreLifetime {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,7 +485,13 @@ pub fn provide(providers: &mut Providers<'_>) {
|
|||
}
|
||||
|
||||
pub fn report_unstable(
|
||||
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
|
||||
sess: &Session,
|
||||
feature: Symbol,
|
||||
reason: Option<Symbol>,
|
||||
issue: u32,
|
||||
is_soft: bool,
|
||||
span: Span,
|
||||
soft_handler: impl FnOnce(&'static lint::Lint, Span, &str),
|
||||
) {
|
||||
let msg = match reason {
|
||||
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
|
||||
|
|
@ -511,7 +517,7 @@ pub fn report_unstable(
|
|||
let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
if is_soft {
|
||||
sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
|
||||
soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg)
|
||||
} else {
|
||||
emit_feature_err(
|
||||
&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
|
||||
|
|
@ -779,10 +785,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Additionally, this function will also check if the item is deprecated. If so, and `id` is
|
||||
/// not `None`, a deprecated lint attached to `id` will be emitted.
|
||||
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
|
||||
let soft_handler =
|
||||
|lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg);
|
||||
match self.eval_stability(def_id, id, span) {
|
||||
EvalResult::Allow => {}
|
||||
EvalResult::Deny { feature, reason, issue, is_soft } =>
|
||||
report_unstable(self.sess, feature, reason, issue, is_soft, span),
|
||||
report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler),
|
||||
EvalResult::Unmarked => {
|
||||
// The API could be uncallable for other reasons, for example when a private module
|
||||
// was referenced.
|
||||
|
|
|
|||
|
|
@ -363,6 +363,8 @@ pub enum UndefinedBehaviorInfo {
|
|||
UbExperimental(String),
|
||||
/// Unreachable code was executed.
|
||||
Unreachable,
|
||||
/// An enum discriminant was set to a value which was outside the range of valid values.
|
||||
InvalidDiscriminant(ScalarMaybeUndef),
|
||||
}
|
||||
|
||||
impl fmt::Debug for UndefinedBehaviorInfo {
|
||||
|
|
@ -373,6 +375,8 @@ impl fmt::Debug for UndefinedBehaviorInfo {
|
|||
write!(f, "{}", msg),
|
||||
Unreachable =>
|
||||
write!(f, "entered unreachable code"),
|
||||
InvalidDiscriminant(val) =>
|
||||
write!(f, "encountered invalid enum discriminant {}", val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -389,10 +393,6 @@ pub enum UnsupportedOpInfo<'tcx> {
|
|||
/// Free-form case. Only for errors that are never caught!
|
||||
Unsupported(String),
|
||||
|
||||
/// FIXME(#64506) Error used to work around accessing projections of
|
||||
/// uninhabited types.
|
||||
UninhabitedValue,
|
||||
|
||||
// -- Everything below is not categorized yet --
|
||||
FunctionAbiMismatch(Abi, Abi),
|
||||
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
|
||||
|
|
@ -404,7 +404,6 @@ pub enum UnsupportedOpInfo<'tcx> {
|
|||
InvalidMemoryAccess,
|
||||
InvalidFunctionPointer,
|
||||
InvalidBool,
|
||||
InvalidDiscriminant(ScalarMaybeUndef),
|
||||
PointerOutOfBounds {
|
||||
ptr: Pointer,
|
||||
msg: CheckInAllocMsg,
|
||||
|
|
@ -489,8 +488,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
|
|||
write!(f, "incorrect alloc info: expected size {} and align {}, \
|
||||
got size {} and align {}",
|
||||
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
|
||||
InvalidDiscriminant(val) =>
|
||||
write!(f, "encountered invalid enum discriminant {}", val),
|
||||
InvalidMemoryAccess =>
|
||||
write!(f, "tried to access memory through an invalid pointer"),
|
||||
DanglingPointerDeref =>
|
||||
|
|
@ -556,8 +553,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
|
|||
not a power of two"),
|
||||
Unsupported(ref msg) =>
|
||||
write!(f, "{}", msg),
|
||||
UninhabitedValue =>
|
||||
write!(f, "tried to use an uninhabited value"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Panics if the `AllocId` does not refer to a function
|
||||
pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
|
||||
match self.get(id) {
|
||||
Some(GlobalAlloc::Function(instance)) => instance,
|
||||
_ => bug!("expected allocation ID {} to point to a function", id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
|
||||
/// call this function twice, even with the same `Allocation` will ICE the compiler.
|
||||
pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
|
||||
|
|
|
|||
|
|
@ -343,14 +343,19 @@ impl<'tcx, Tag> Scalar<Tag> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn check_raw(data: u128, size: u8, target_size: 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);
|
||||
}
|
||||
|
||||
/// Do not call this method! Use either `assert_bits` or `force_bits`.
|
||||
#[inline]
|
||||
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
|
||||
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);
|
||||
Self::check_raw(data, size, target_size);
|
||||
Ok(data)
|
||||
}
|
||||
Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use crate::ty::layout::VariantIdx;
|
|||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{
|
||||
self, AdtDef, CanonicalUserTypeAnnotations, GeneratorSubsts, Region, Ty, TyCtxt,
|
||||
self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
|
|
@ -2189,7 +2189,7 @@ pub enum AggregateKind<'tcx> {
|
|||
Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
|
||||
|
||||
Closure(DefId, SubstsRef<'tcx>),
|
||||
Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
|
||||
Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
|
||||
|
|
@ -2602,7 +2602,14 @@ impl<'tcx> Debug for Constant<'tcx> {
|
|||
impl<'tcx> Display for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "const ")?;
|
||||
write!(fmt, "{}", self.literal)
|
||||
// FIXME make the default pretty printing of raw pointers more detailed. Here we output the
|
||||
// debug representation of raw pointers, so that the raw pointers in the mir dump output are
|
||||
// detailed and just not '{pointer}'.
|
||||
if let ty::RawPtr(_) = self.literal.ty.kind {
|
||||
write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty)
|
||||
} else {
|
||||
write!(fmt, "{}", self.literal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
tcx.hir().as_local_hir_id(def_id)
|
||||
}
|
||||
InstanceDef::VtableShim(..) |
|
||||
InstanceDef::ReifyShim(..) |
|
||||
InstanceDef::Intrinsic(..) |
|
||||
InstanceDef::FnPtrShim(..) |
|
||||
InstanceDef::Virtual(..) |
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
let ty = place.ty(local_decls, tcx).ty;
|
||||
match ty.kind {
|
||||
ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx),
|
||||
ty::Generator(_, substs, _) => substs.discr_ty(tcx),
|
||||
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
|
||||
_ => {
|
||||
// This can only be `0`, for now, so `u8` will suffice.
|
||||
tcx.types.u8
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ty::subst::SubstsRef;
|
||||
use crate::ty::{CanonicalUserTypeAnnotation, GeneratorSubsts, Ty};
|
||||
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
|
||||
use crate::mir::*;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -158,22 +158,7 @@ macro_rules! make_mir_visitor {
|
|||
self.super_place_base(base, context, location);
|
||||
}
|
||||
|
||||
fn visit_projection(&mut self,
|
||||
base: & $($mutability)? PlaceBase<'tcx>,
|
||||
projection: & $($mutability)? [PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
self.super_projection(base, projection, context, location);
|
||||
}
|
||||
|
||||
fn visit_projection_elem(&mut self,
|
||||
base: & $($mutability)? PlaceBase<'tcx>,
|
||||
proj_base: & $($mutability)? [PlaceElem<'tcx>],
|
||||
elem: & $($mutability)? PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
self.super_projection_elem(base, proj_base, elem, context, location);
|
||||
}
|
||||
visit_place_fns!($($mutability)?);
|
||||
|
||||
fn visit_constant(&mut self,
|
||||
constant: & $($mutability)? Constant<'tcx>,
|
||||
|
|
@ -230,12 +215,6 @@ macro_rules! make_mir_visitor {
|
|||
self.super_substs(substs);
|
||||
}
|
||||
|
||||
fn visit_generator_substs(&mut self,
|
||||
substs: & $($mutability)? GeneratorSubsts<'tcx>,
|
||||
_: Location) {
|
||||
self.super_generator_substs(substs);
|
||||
}
|
||||
|
||||
fn visit_local_decl(&mut self,
|
||||
local: Local,
|
||||
local_decl: & $($mutability)? LocalDecl<'tcx>) {
|
||||
|
|
@ -628,7 +607,7 @@ macro_rules! make_mir_visitor {
|
|||
generator_substs,
|
||||
_movability,
|
||||
) => {
|
||||
self.visit_generator_substs(generator_substs, location);
|
||||
self.visit_substs(generator_substs, location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -687,28 +666,6 @@ macro_rules! make_mir_visitor {
|
|||
);
|
||||
}
|
||||
|
||||
fn super_place(&mut self,
|
||||
place: & $($mutability)? Place<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
let mut context = context;
|
||||
|
||||
if !place.projection.is_empty() {
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
}
|
||||
|
||||
self.visit_place_base(& $($mutability)? place.base, context, location);
|
||||
|
||||
self.visit_projection(& $($mutability)? place.base,
|
||||
& $($mutability)? place.projection,
|
||||
context,
|
||||
location);
|
||||
}
|
||||
|
||||
fn super_place_base(&mut self,
|
||||
place_base: & $($mutability)? PlaceBase<'tcx>,
|
||||
context: PlaceContext,
|
||||
|
|
@ -723,45 +680,6 @@ macro_rules! make_mir_visitor {
|
|||
}
|
||||
}
|
||||
|
||||
fn super_projection(&mut self,
|
||||
base: & $($mutability)? PlaceBase<'tcx>,
|
||||
projection: & $($mutability)? [PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location) {
|
||||
let mut cursor = projection;
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
self.visit_projection_elem(base, cursor, elem, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
fn super_projection_elem(&mut self,
|
||||
_base: & $($mutability)? PlaceBase<'tcx>,
|
||||
_proj_base: & $($mutability)? [PlaceElem<'tcx>],
|
||||
elem: & $($mutability)? PlaceElem<'tcx>,
|
||||
_context: PlaceContext,
|
||||
location: Location) {
|
||||
match elem {
|
||||
ProjectionElem::Field(_field, ty) => {
|
||||
self.visit_ty(ty, TyContext::Location(location));
|
||||
}
|
||||
ProjectionElem::Index(local) => {
|
||||
self.visit_local(
|
||||
local,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
}
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Subslice { from: _, to: _ } |
|
||||
ProjectionElem::ConstantIndex { offset: _,
|
||||
min_length: _,
|
||||
from_end: _ } |
|
||||
ProjectionElem::Downcast(_, _) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn super_local_decl(&mut self,
|
||||
local: Local,
|
||||
local_decl: & $($mutability)? LocalDecl<'tcx>) {
|
||||
|
|
@ -846,10 +764,6 @@ macro_rules! make_mir_visitor {
|
|||
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_generator_substs(&mut self,
|
||||
_substs: & $($mutability)? GeneratorSubsts<'tcx>) {
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
|
||||
fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
|
||||
|
|
@ -868,6 +782,141 @@ macro_rules! make_mir_visitor {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! visit_place_fns {
|
||||
(mut) => (
|
||||
fn super_place(
|
||||
&mut self,
|
||||
place: &mut Place<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
self.visit_place_base(&mut place.base, context, location);
|
||||
|
||||
if let Some(new_projection) = self.process_projection(&place.projection) {
|
||||
place.projection = new_projection;
|
||||
}
|
||||
}
|
||||
|
||||
fn process_projection(
|
||||
&mut self,
|
||||
projection: &'a [PlaceElem<'tcx>],
|
||||
) -> Option<Box<[PlaceElem<'tcx>]>> {
|
||||
let mut projection = Cow::Borrowed(projection);
|
||||
|
||||
for i in 0..projection.len() {
|
||||
if let Some(elem) = projection.get(i) {
|
||||
if let Some(elem) = self.process_projection_elem(elem) {
|
||||
let vec = projection.to_mut();
|
||||
vec[i] = elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match projection {
|
||||
Cow::Borrowed(_) => None,
|
||||
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_projection_elem(
|
||||
&mut self,
|
||||
_elem: &PlaceElem<'tcx>,
|
||||
) -> Option<PlaceElem<'tcx>> {
|
||||
None
|
||||
}
|
||||
);
|
||||
|
||||
() => (
|
||||
fn visit_projection(
|
||||
&mut self,
|
||||
base: &PlaceBase<'tcx>,
|
||||
projection: &[PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_projection(base, projection, context, location);
|
||||
}
|
||||
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
base: &PlaceBase<'tcx>,
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
elem: &PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_projection_elem(base, proj_base, elem, context, location);
|
||||
}
|
||||
|
||||
fn super_place(
|
||||
&mut self,
|
||||
place: &Place<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
let mut context = context;
|
||||
|
||||
if !place.projection.is_empty() {
|
||||
context = if context.is_mutating_use() {
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||
} else {
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
}
|
||||
|
||||
self.visit_place_base(&place.base, context, location);
|
||||
|
||||
self.visit_projection(&place.base,
|
||||
&place.projection,
|
||||
context,
|
||||
location);
|
||||
}
|
||||
|
||||
fn super_projection(
|
||||
&mut self,
|
||||
base: &PlaceBase<'tcx>,
|
||||
projection: &[PlaceElem<'tcx>],
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
let mut cursor = projection;
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
self.visit_projection_elem(base, cursor, elem, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
fn super_projection_elem(
|
||||
&mut self,
|
||||
_base: &PlaceBase<'tcx>,
|
||||
_proj_base: &[PlaceElem<'tcx>],
|
||||
elem: &PlaceElem<'tcx>,
|
||||
_context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
match elem {
|
||||
ProjectionElem::Field(_field, ty) => {
|
||||
self.visit_ty(ty, TyContext::Location(location));
|
||||
}
|
||||
ProjectionElem::Index(local) => {
|
||||
self.visit_local(
|
||||
local,
|
||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
||||
location
|
||||
);
|
||||
}
|
||||
ProjectionElem::Deref |
|
||||
ProjectionElem::Subslice { from: _, to: _ } |
|
||||
ProjectionElem::ConstantIndex { offset: _,
|
||||
min_length: _,
|
||||
from_end: _ } |
|
||||
ProjectionElem::Downcast(_, _) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
make_mir_visitor!(Visitor,);
|
||||
make_mir_visitor!(MutVisitor,mut);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ rustc_queries! {
|
|||
/// predicate gets in the way of some checks, which are intended
|
||||
/// to operate over only the actual where-clauses written by the
|
||||
/// user.)
|
||||
query predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
|
||||
query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
|
|
@ -184,12 +184,10 @@ rustc_queries! {
|
|||
/// predicates (where-clauses) directly defined on it. This is
|
||||
/// equal to the `explicit_predicates_of` predicates plus the
|
||||
/// `inferred_outlives_of` predicates.
|
||||
query predicates_defined_on(_: DefId)
|
||||
-> &'tcx ty::GenericPredicates<'tcx> {}
|
||||
query predicates_defined_on(_: DefId) -> ty::GenericPredicates<'tcx> {}
|
||||
|
||||
/// Returns the predicates written explicitly by the user.
|
||||
query explicit_predicates_of(_: DefId)
|
||||
-> &'tcx ty::GenericPredicates<'tcx> {}
|
||||
query explicit_predicates_of(_: DefId) -> ty::GenericPredicates<'tcx> {}
|
||||
|
||||
/// Returns the inferred outlives predicates (e.g., for `struct
|
||||
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
|
||||
|
|
@ -201,14 +199,13 @@ rustc_queries! {
|
|||
/// evaluate them even during type conversion, often before the
|
||||
/// full predicates are available (note that supertraits have
|
||||
/// additional acyclicity requirements).
|
||||
query super_predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
|
||||
query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
|
||||
desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
/// To avoid cycles within the predicates of a single item we compute
|
||||
/// per-type-parameter predicates for resolving `T::AssocTy`.
|
||||
query type_param_predicates(key: (DefId, DefId))
|
||||
-> &'tcx ty::GenericPredicates<'tcx> {
|
||||
query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "computing the bounds for type parameter `{}`", {
|
||||
let id = tcx.hir().as_local_hir_id(key.1).unwrap();
|
||||
|
|
@ -231,6 +228,12 @@ rustc_queries! {
|
|||
cycle_delay_bug
|
||||
}
|
||||
|
||||
query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool {
|
||||
anon
|
||||
no_force
|
||||
desc { "checking if `{:?}` has trivial dropck", ty }
|
||||
}
|
||||
|
||||
query adt_dtorck_constraint(
|
||||
_: DefId
|
||||
) -> Result<DtorckConstraint<'tcx>, NoSolution> {}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,15 @@ use syntax;
|
|||
use syntax::ast::{self, IntTy, UintTy, MetaItemKind};
|
||||
use syntax::source_map::{FileName, FilePathMapping};
|
||||
use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
|
||||
use syntax::parse::{ParseSess, new_parser_from_source_str};
|
||||
use syntax::parse::new_parser_from_source_str;
|
||||
use syntax::parse::token;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::symbol::{sym, Symbol};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::source_map::SourceMap;
|
||||
|
||||
use errors::emitter::HumanReadableErrorType;
|
||||
use errors::{ColorConfig, FatalError, Handler};
|
||||
use errors::{ColorConfig, FatalError, Handler, SourceMapperDyn};
|
||||
|
||||
use getopts;
|
||||
|
||||
|
|
@ -1316,10 +1317,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
|
||||
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||
"enable queries of the dependency graph for regression testing"),
|
||||
profile_queries: bool = (false, parse_bool, [UNTRACKED],
|
||||
"trace and profile the queries of the incremental compilation framework"),
|
||||
profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
|
||||
"trace and profile the queries and keys of the incremental compilation framework"),
|
||||
no_analysis: bool = (false, parse_bool, [UNTRACKED],
|
||||
"parse and expand the source, but run no analysis"),
|
||||
extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
|
||||
|
|
@ -1345,7 +1342,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
mir_opt_level: usize = (1, parse_uint, [TRACKED],
|
||||
"set the MIR optimization level (0-3, default: 1)"),
|
||||
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"emit noalias metadata for mutable references (default: yes on LLVM >= 6)"),
|
||||
"emit noalias metadata for mutable references (default: no)"),
|
||||
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
"dump MIR state to file.
|
||||
`val` is used to select which passes and functions to dump. For example:
|
||||
|
|
@ -1471,6 +1468,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"which mangling version to use for symbol names"),
|
||||
binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
|
||||
"include artifacts (sysroot, crate dependencies) used during compilation in dep-info"),
|
||||
insert_sideeffect: bool = (false, parse_bool, [TRACKED],
|
||||
"fix undefined behavior when a thread doesn't eventually make progress \
|
||||
(such as entering an empty infinite loop) by inserting llvm.sideeffect"),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
|
|
@ -1514,22 +1514,25 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
|
|||
}
|
||||
for &i in &[8, 16, 32, 64, 128] {
|
||||
if i >= min_atomic_width && i <= max_atomic_width {
|
||||
let s = i.to_string();
|
||||
ret.insert((
|
||||
sym::target_has_atomic,
|
||||
Some(Symbol::intern(&s)),
|
||||
));
|
||||
if &s == wordsz {
|
||||
let mut insert_atomic = |s| {
|
||||
ret.insert((
|
||||
sym::target_has_atomic,
|
||||
Some(Symbol::intern("ptr")),
|
||||
sym::target_has_atomic_load_store,
|
||||
Some(Symbol::intern(s)),
|
||||
));
|
||||
if atomic_cas {
|
||||
ret.insert((
|
||||
sym::target_has_atomic,
|
||||
Some(Symbol::intern(s))
|
||||
));
|
||||
}
|
||||
};
|
||||
let s = i.to_string();
|
||||
insert_atomic(&s);
|
||||
if &s == wordsz {
|
||||
insert_atomic("ptr");
|
||||
}
|
||||
}
|
||||
}
|
||||
if atomic_cas {
|
||||
ret.insert((sym::target_has_atomic, Some(Symbol::intern("cas"))));
|
||||
}
|
||||
if sess.opts.debug_assertions {
|
||||
ret.insert((Symbol::intern("debug_assertions"), None));
|
||||
}
|
||||
|
|
@ -1855,6 +1858,7 @@ struct NullEmitter;
|
|||
|
||||
impl errors::emitter::Emitter for NullEmitter {
|
||||
fn emit_diagnostic(&mut self, _: &errors::Diagnostic) {}
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> { None }
|
||||
}
|
||||
|
||||
// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
|
||||
|
|
@ -2036,11 +2040,7 @@ pub fn parse_error_format(
|
|||
return error_format;
|
||||
}
|
||||
|
||||
pub fn build_session_options_and_crate_config(
|
||||
matches: &getopts::Matches,
|
||||
) -> (Options, FxHashSet<(String, Option<String>)>) {
|
||||
let color = parse_color(matches);
|
||||
|
||||
fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
|
||||
let edition = match matches.opt_str("edition") {
|
||||
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_|
|
||||
early_error(
|
||||
|
|
@ -2067,19 +2067,14 @@ pub fn build_session_options_and_crate_config(
|
|||
)
|
||||
}
|
||||
|
||||
let (json_rendered, json_artifact_notifications) = parse_json(matches);
|
||||
|
||||
let error_format = parse_error_format(matches, color, json_rendered);
|
||||
|
||||
let unparsed_crate_types = matches.opt_strs("crate-type");
|
||||
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
|
||||
.unwrap_or_else(|e| early_error(error_format, &e[..]));
|
||||
|
||||
|
||||
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
|
||||
|
||||
let mut debugging_opts = build_debugging_options(matches, error_format);
|
||||
edition
|
||||
}
|
||||
|
||||
fn check_debug_option_stability(
|
||||
debugging_opts: &DebuggingOptions,
|
||||
error_format: ErrorOutputType,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
) {
|
||||
if !debugging_opts.unstable_options {
|
||||
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
|
||||
early_error(
|
||||
|
|
@ -2095,7 +2090,13 @@ pub fn build_session_options_and_crate_config(
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_output_types(
|
||||
debugging_opts: &DebuggingOptions,
|
||||
matches: &getopts::Matches,
|
||||
error_format: ErrorOutputType,
|
||||
) -> OutputTypes {
|
||||
let mut output_types = BTreeMap::new();
|
||||
if !debugging_opts.parse_only {
|
||||
for list in matches.opt_strs("emit") {
|
||||
|
|
@ -2120,14 +2121,19 @@ pub fn build_session_options_and_crate_config(
|
|||
if output_types.is_empty() {
|
||||
output_types.insert(OutputType::Exe, None);
|
||||
}
|
||||
OutputTypes(output_types)
|
||||
}
|
||||
|
||||
let mut cg = build_codegen_options(matches, error_format);
|
||||
let mut codegen_units = cg.codegen_units;
|
||||
fn should_override_cgus_and_disable_thinlto(
|
||||
output_types: &OutputTypes,
|
||||
matches: &getopts::Matches,
|
||||
error_format: ErrorOutputType,
|
||||
mut codegen_units: Option<usize>,
|
||||
) -> (bool, Option<usize>) {
|
||||
let mut disable_thinlto = false;
|
||||
|
||||
// Issue #30063: if user requests LLVM-related output to one
|
||||
// particular path, disable codegen-units.
|
||||
let incompatible: Vec<_> = output_types
|
||||
let incompatible: Vec<_> = output_types.0
|
||||
.iter()
|
||||
.map(|ot_path| ot_path.0)
|
||||
.filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
|
||||
|
|
@ -2159,6 +2165,17 @@ pub fn build_session_options_and_crate_config(
|
|||
}
|
||||
}
|
||||
|
||||
if codegen_units == Some(0) {
|
||||
early_error(
|
||||
error_format,
|
||||
"value for codegen units must be a positive non-zero integer",
|
||||
);
|
||||
}
|
||||
|
||||
(disable_thinlto, codegen_units)
|
||||
}
|
||||
|
||||
fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) {
|
||||
if debugging_opts.threads == 0 {
|
||||
early_error(
|
||||
error_format,
|
||||
|
|
@ -2172,16 +2189,15 @@ pub fn build_session_options_and_crate_config(
|
|||
"optimization fuel is incompatible with multiple threads",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if codegen_units == Some(0) {
|
||||
early_error(
|
||||
error_format,
|
||||
"value for codegen units must be a positive non-zero integer",
|
||||
);
|
||||
}
|
||||
|
||||
let incremental = match (&debugging_opts.incremental, &cg.incremental) {
|
||||
(&Some(ref path1), &Some(ref path2)) => {
|
||||
fn select_incremental_path(
|
||||
debugging_opts: &DebuggingOptions,
|
||||
cg: &CodegenOptions,
|
||||
error_format: ErrorOutputType,
|
||||
) -> Option<PathBuf> {
|
||||
match (&debugging_opts.incremental, &cg.incremental) {
|
||||
(Some(path1), Some(path2)) => {
|
||||
if path1 != path2 {
|
||||
early_error(
|
||||
error_format,
|
||||
|
|
@ -2195,25 +2211,19 @@ pub fn build_session_options_and_crate_config(
|
|||
Some(path1)
|
||||
}
|
||||
}
|
||||
(&Some(ref path), &None) => Some(path),
|
||||
(&None, &Some(ref path)) => Some(path),
|
||||
(&None, &None) => None,
|
||||
}.map(|m| PathBuf::from(m));
|
||||
|
||||
if debugging_opts.profile && incremental.is_some() {
|
||||
early_error(
|
||||
error_format,
|
||||
"can't instrument with gcov profiling when compiling incrementally",
|
||||
);
|
||||
}
|
||||
|
||||
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
|
||||
early_error(
|
||||
error_format,
|
||||
"options `-C profile-generate` and `-C profile-use` are exclusive",
|
||||
);
|
||||
}
|
||||
(Some(path), None) => Some(path),
|
||||
(None, Some(path)) => Some(path),
|
||||
(None, None) => None,
|
||||
}.map(|m| PathBuf::from(m))
|
||||
}
|
||||
|
||||
fn collect_print_requests(
|
||||
cg: &mut CodegenOptions,
|
||||
dopts: &mut DebuggingOptions,
|
||||
matches: &getopts::Matches,
|
||||
is_unstable_enabled: bool,
|
||||
error_format: ErrorOutputType,
|
||||
) -> Vec<PrintRequest> {
|
||||
let mut prints = Vec::<PrintRequest>::new();
|
||||
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
|
||||
prints.push(PrintRequest::TargetCPUs);
|
||||
|
|
@ -2231,72 +2241,105 @@ pub fn build_session_options_and_crate_config(
|
|||
prints.push(PrintRequest::CodeModels);
|
||||
cg.code_model = None;
|
||||
}
|
||||
if debugging_opts
|
||||
if dopts
|
||||
.tls_model
|
||||
.as_ref()
|
||||
.map_or(false, |s| s == "help")
|
||||
{
|
||||
prints.push(PrintRequest::TlsModels);
|
||||
debugging_opts.tls_model = None;
|
||||
dopts.tls_model = None;
|
||||
}
|
||||
|
||||
let cg = cg;
|
||||
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
|
||||
"crate-name" => PrintRequest::CrateName,
|
||||
"file-names" => PrintRequest::FileNames,
|
||||
"sysroot" => PrintRequest::Sysroot,
|
||||
"cfg" => PrintRequest::Cfg,
|
||||
"target-list" => PrintRequest::TargetList,
|
||||
"target-cpus" => PrintRequest::TargetCPUs,
|
||||
"target-features" => PrintRequest::TargetFeatures,
|
||||
"relocation-models" => PrintRequest::RelocationModels,
|
||||
"code-models" => PrintRequest::CodeModels,
|
||||
"tls-models" => PrintRequest::TlsModels,
|
||||
"native-static-libs" => PrintRequest::NativeStaticLibs,
|
||||
"target-spec-json" => {
|
||||
if is_unstable_enabled {
|
||||
PrintRequest::TargetSpec
|
||||
} else {
|
||||
early_error(
|
||||
error_format,
|
||||
"the `-Z unstable-options` flag must also be passed to \
|
||||
enable the target-spec-json print option",
|
||||
);
|
||||
}
|
||||
}
|
||||
req => early_error(error_format, &format!("unknown print request `{}`", req)),
|
||||
}));
|
||||
|
||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
|
||||
let target_triple = if let Some(target) = matches.opt_str("target") {
|
||||
if target.ends_with(".json") {
|
||||
prints
|
||||
}
|
||||
|
||||
fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple {
|
||||
match matches.opt_str("target") {
|
||||
Some(target) if target.ends_with(".json") => {
|
||||
let path = Path::new(&target);
|
||||
TargetTriple::from_path(&path).unwrap_or_else(|_|
|
||||
early_error(error_format, &format!("target file {:?} does not exist", path)))
|
||||
} else {
|
||||
TargetTriple::TargetTriple(target)
|
||||
}
|
||||
Some(target) => TargetTriple::TargetTriple(target),
|
||||
_ => TargetTriple::from_triple(host_triple()),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_opt_level(
|
||||
matches: &getopts::Matches,
|
||||
cg: &CodegenOptions,
|
||||
error_format: ErrorOutputType,
|
||||
) -> OptLevel {
|
||||
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
|
||||
// to use them interchangeably. However, because they're technically different flags,
|
||||
// we need to work out manually which should take precedence if both are supplied (i.e.
|
||||
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
|
||||
// comparing them. Note that if a flag is not found, its position will be `None`, which
|
||||
// always compared less than `Some(_)`.
|
||||
let max_o = matches.opt_positions("O").into_iter().max();
|
||||
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
|
||||
if let Some("opt-level") = s.splitn(2, '=').next() {
|
||||
Some(i)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).max();
|
||||
if max_o > max_c {
|
||||
OptLevel::Default
|
||||
} else {
|
||||
TargetTriple::from_triple(host_triple())
|
||||
};
|
||||
let opt_level = {
|
||||
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
|
||||
// to use them interchangeably. However, because they're technically different flags,
|
||||
// we need to work out manually which should take precedence if both are supplied (i.e.
|
||||
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
|
||||
// comparing them. Note that if a flag is not found, its position will be `None`, which
|
||||
// always compared less than `Some(_)`.
|
||||
let max_o = matches.opt_positions("O").into_iter().max();
|
||||
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
|
||||
if let Some("opt-level") = s.splitn(2, '=').next() {
|
||||
Some(i)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).max();
|
||||
if max_o > max_c {
|
||||
OptLevel::Default
|
||||
} else {
|
||||
match cg.opt_level.as_ref().map(String::as_ref) {
|
||||
None => OptLevel::No,
|
||||
Some("0") => OptLevel::No,
|
||||
Some("1") => OptLevel::Less,
|
||||
Some("2") => OptLevel::Default,
|
||||
Some("3") => OptLevel::Aggressive,
|
||||
Some("s") => OptLevel::Size,
|
||||
Some("z") => OptLevel::SizeMin,
|
||||
Some(arg) => {
|
||||
early_error(
|
||||
error_format,
|
||||
&format!(
|
||||
"optimization level needs to be \
|
||||
between 0-3, s or z (instead was `{}`)",
|
||||
arg
|
||||
),
|
||||
);
|
||||
}
|
||||
match cg.opt_level.as_ref().map(String::as_ref) {
|
||||
None => OptLevel::No,
|
||||
Some("0") => OptLevel::No,
|
||||
Some("1") => OptLevel::Less,
|
||||
Some("2") => OptLevel::Default,
|
||||
Some("3") => OptLevel::Aggressive,
|
||||
Some("s") => OptLevel::Size,
|
||||
Some("z") => OptLevel::SizeMin,
|
||||
Some(arg) => {
|
||||
early_error(
|
||||
error_format,
|
||||
&format!(
|
||||
"optimization level needs to be \
|
||||
between 0-3, s or z (instead was `{}`)",
|
||||
arg
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
|
||||
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
|
||||
// for more details.
|
||||
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
|
||||
}
|
||||
}
|
||||
|
||||
fn select_debuginfo(
|
||||
matches: &getopts::Matches,
|
||||
cg: &CodegenOptions,
|
||||
error_format: ErrorOutputType,
|
||||
) -> DebugInfo {
|
||||
let max_g = matches.opt_positions("g").into_iter().max();
|
||||
let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| {
|
||||
if let Some("debuginfo") = s.splitn(2, '=').next() {
|
||||
|
|
@ -2305,7 +2348,7 @@ pub fn build_session_options_and_crate_config(
|
|||
None
|
||||
}
|
||||
}).max();
|
||||
let debuginfo = if max_g > max_c {
|
||||
if max_g > max_c {
|
||||
DebugInfo::Full
|
||||
} else {
|
||||
match cg.debuginfo {
|
||||
|
|
@ -2323,14 +2366,14 @@ pub fn build_session_options_and_crate_config(
|
|||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut search_paths = vec![];
|
||||
for s in &matches.opt_strs("L") {
|
||||
search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
|
||||
}
|
||||
}
|
||||
|
||||
let libs = matches
|
||||
fn parse_libs(
|
||||
matches: &getopts::Matches,
|
||||
error_format: ErrorOutputType,
|
||||
) -> Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> {
|
||||
matches
|
||||
.opt_strs("l")
|
||||
.into_iter()
|
||||
.map(|s| {
|
||||
|
|
@ -2369,52 +2412,23 @@ pub fn build_session_options_and_crate_config(
|
|||
let new_name = name_parts.next();
|
||||
(name.to_owned(), new_name.map(|n| n.to_owned()), kind)
|
||||
})
|
||||
.collect();
|
||||
.collect()
|
||||
}
|
||||
|
||||
let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
|
||||
let test = matches.opt_present("test");
|
||||
|
||||
let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
|
||||
|
||||
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
|
||||
"crate-name" => PrintRequest::CrateName,
|
||||
"file-names" => PrintRequest::FileNames,
|
||||
"sysroot" => PrintRequest::Sysroot,
|
||||
"cfg" => PrintRequest::Cfg,
|
||||
"target-list" => PrintRequest::TargetList,
|
||||
"target-cpus" => PrintRequest::TargetCPUs,
|
||||
"target-features" => PrintRequest::TargetFeatures,
|
||||
"relocation-models" => PrintRequest::RelocationModels,
|
||||
"code-models" => PrintRequest::CodeModels,
|
||||
"tls-models" => PrintRequest::TlsModels,
|
||||
"native-static-libs" => PrintRequest::NativeStaticLibs,
|
||||
"target-spec-json" => {
|
||||
if is_unstable_enabled {
|
||||
PrintRequest::TargetSpec
|
||||
} else {
|
||||
early_error(
|
||||
error_format,
|
||||
"the `-Z unstable-options` flag must also be passed to \
|
||||
enable the target-spec-json print option",
|
||||
);
|
||||
}
|
||||
}
|
||||
req => early_error(error_format, &format!("unknown print request `{}`", req)),
|
||||
}));
|
||||
|
||||
let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) {
|
||||
fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode {
|
||||
match dopts.borrowck.as_ref().map(|s| &s[..]) {
|
||||
None | Some("migrate") => BorrowckMode::Migrate,
|
||||
Some("mir") => BorrowckMode::Mir,
|
||||
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
|
||||
};
|
||||
|
||||
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
|
||||
early_warn(
|
||||
error_format,
|
||||
"-C remark requires \"-C debuginfo=n\" to show source locations",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_externs(
|
||||
matches: &getopts::Matches,
|
||||
debugging_opts: &DebuggingOptions,
|
||||
error_format: ErrorOutputType,
|
||||
is_unstable_enabled: bool,
|
||||
) -> Externs {
|
||||
if matches.opt_present("extern-private") && !debugging_opts.unstable_options {
|
||||
early_error(
|
||||
ErrorOutputType::default(),
|
||||
|
|
@ -2455,10 +2469,14 @@ pub fn build_session_options_and_crate_config(
|
|||
// flag
|
||||
entry.is_private_dep |= private;
|
||||
}
|
||||
Externs(externs)
|
||||
}
|
||||
|
||||
let crate_name = matches.opt_str("crate-name");
|
||||
|
||||
let remap_path_prefix = matches
|
||||
fn parse_remap_path_prefix(
|
||||
matches: &getopts::Matches,
|
||||
error_format: ErrorOutputType
|
||||
) -> Vec<(PathBuf, PathBuf)> {
|
||||
matches
|
||||
.opt_strs("remap-path-prefix")
|
||||
.into_iter()
|
||||
.map(|remap| {
|
||||
|
|
@ -2473,42 +2491,130 @@ pub fn build_session_options_and_crate_config(
|
|||
),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
.collect()
|
||||
}
|
||||
|
||||
(
|
||||
Options {
|
||||
crate_types,
|
||||
optimize: opt_level,
|
||||
debuginfo,
|
||||
lint_opts,
|
||||
lint_cap,
|
||||
describe_lints,
|
||||
output_types: OutputTypes(output_types),
|
||||
search_paths,
|
||||
maybe_sysroot: sysroot_opt,
|
||||
target_triple,
|
||||
test,
|
||||
incremental,
|
||||
debugging_opts,
|
||||
prints,
|
||||
borrowck_mode,
|
||||
cg,
|
||||
pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
let color = parse_color(matches);
|
||||
|
||||
let edition = parse_crate_edition(matches);
|
||||
|
||||
let (json_rendered, json_artifact_notifications) = parse_json(matches);
|
||||
|
||||
let error_format = parse_error_format(matches, color, json_rendered);
|
||||
|
||||
let unparsed_crate_types = matches.opt_strs("crate-type");
|
||||
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
|
||||
.unwrap_or_else(|e| early_error(error_format, &e[..]));
|
||||
|
||||
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
|
||||
|
||||
let mut debugging_opts = build_debugging_options(matches, error_format);
|
||||
check_debug_option_stability(&debugging_opts, error_format, json_rendered);
|
||||
|
||||
let output_types = parse_output_types(&debugging_opts, matches, error_format);
|
||||
|
||||
let mut cg = build_codegen_options(matches, error_format);
|
||||
let (disable_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
|
||||
&output_types,
|
||||
matches,
|
||||
error_format,
|
||||
cg.codegen_units,
|
||||
);
|
||||
|
||||
check_thread_count(&debugging_opts, error_format);
|
||||
|
||||
let incremental = select_incremental_path(&debugging_opts, &cg, error_format);
|
||||
|
||||
if debugging_opts.profile && incremental.is_some() {
|
||||
early_error(
|
||||
error_format,
|
||||
externs: Externs(externs),
|
||||
crate_name,
|
||||
alt_std_name: None,
|
||||
libs,
|
||||
unstable_features: UnstableFeatures::from_environment(),
|
||||
debug_assertions,
|
||||
actually_rustdoc: false,
|
||||
cli_forced_codegen_units: codegen_units,
|
||||
cli_forced_thinlto_off: disable_thinlto,
|
||||
remap_path_prefix,
|
||||
edition,
|
||||
json_artifact_notifications,
|
||||
},
|
||||
cfg,
|
||||
)
|
||||
"can't instrument with gcov profiling when compiling incrementally",
|
||||
);
|
||||
}
|
||||
|
||||
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
|
||||
early_error(
|
||||
error_format,
|
||||
"options `-C profile-generate` and `-C profile-use` are exclusive",
|
||||
);
|
||||
}
|
||||
|
||||
let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
|
||||
let prints = collect_print_requests(
|
||||
&mut cg,
|
||||
&mut debugging_opts,
|
||||
matches,
|
||||
is_unstable_enabled,
|
||||
error_format,
|
||||
);
|
||||
|
||||
let cg = cg;
|
||||
|
||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
|
||||
let target_triple = parse_target_triple(matches, error_format);
|
||||
let opt_level = parse_opt_level(matches, &cg, error_format);
|
||||
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
|
||||
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
|
||||
// for more details.
|
||||
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
|
||||
let debuginfo = select_debuginfo(matches, &cg, error_format);
|
||||
|
||||
let mut search_paths = vec![];
|
||||
for s in &matches.opt_strs("L") {
|
||||
search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
|
||||
}
|
||||
|
||||
let libs = parse_libs(matches, error_format);
|
||||
|
||||
let test = matches.opt_present("test");
|
||||
|
||||
let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format);
|
||||
|
||||
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
|
||||
early_warn(
|
||||
error_format,
|
||||
"-C remark requires \"-C debuginfo=n\" to show source locations",
|
||||
);
|
||||
}
|
||||
|
||||
let externs = parse_externs(matches, &debugging_opts, error_format, is_unstable_enabled);
|
||||
|
||||
let crate_name = matches.opt_str("crate-name");
|
||||
|
||||
let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
|
||||
|
||||
Options {
|
||||
crate_types,
|
||||
optimize: opt_level,
|
||||
debuginfo,
|
||||
lint_opts,
|
||||
lint_cap,
|
||||
describe_lints,
|
||||
output_types,
|
||||
search_paths,
|
||||
maybe_sysroot: sysroot_opt,
|
||||
target_triple,
|
||||
test,
|
||||
incremental,
|
||||
debugging_opts,
|
||||
prints,
|
||||
borrowck_mode,
|
||||
cg,
|
||||
error_format,
|
||||
externs,
|
||||
crate_name,
|
||||
alt_std_name: None,
|
||||
libs,
|
||||
unstable_features: UnstableFeatures::from_environment(),
|
||||
debug_assertions,
|
||||
actually_rustdoc: false,
|
||||
cli_forced_codegen_units: codegen_units,
|
||||
cli_forced_thinlto_off: disable_thinlto,
|
||||
remap_path_prefix,
|
||||
edition,
|
||||
json_artifact_notifications,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_crate_type_option() -> RustcOptGroup {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ use crate::lint;
|
|||
use crate::middle::cstore;
|
||||
use crate::session::config::{
|
||||
build_configuration,
|
||||
build_session_options_and_crate_config,
|
||||
to_crate_config
|
||||
build_session_options,
|
||||
to_crate_config,
|
||||
parse_cfgspecs,
|
||||
};
|
||||
use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
|
||||
use crate::session::build_session;
|
||||
|
|
@ -18,6 +19,16 @@ use syntax::symbol::sym;
|
|||
use syntax::edition::{Edition, DEFAULT_EDITION};
|
||||
use syntax;
|
||||
use super::Options;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
||||
pub fn build_session_options_and_crate_config(
|
||||
matches: &getopts::Matches,
|
||||
) -> (Options, FxHashSet<(String, Option<String>)>) {
|
||||
(
|
||||
build_session_options(matches),
|
||||
parse_cfgspecs(matches.opt_strs("cfg")),
|
||||
)
|
||||
}
|
||||
|
||||
impl ExternEntry {
|
||||
fn new_public<S: Into<String>,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||
|
||||
use crate::lint;
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
|
||||
use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
|
||||
use crate::session::search_paths::{PathKind, SearchPath};
|
||||
use crate::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use crate::util::common::{duration_to_secs_str, ErrorReported};
|
||||
use crate::util::common::ProfileQueriesMsg;
|
||||
|
||||
use rustc_data_structures::base_n;
|
||||
use rustc_data_structures::sync::{
|
||||
|
|
@ -25,11 +24,11 @@ use errors::emitter::HumanReadableErrorType;
|
|||
use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::allocator::AllocatorKind;
|
||||
use syntax_expand::allocator::AllocatorKind;
|
||||
use syntax::feature_gate::{self, AttributeType};
|
||||
use syntax::json::JsonEmitter;
|
||||
use syntax::source_map;
|
||||
use syntax::parse::{self, ParseSess};
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
use crate::util::profiling::{SelfProfiler, SelfProfilerRef};
|
||||
|
|
@ -46,7 +45,7 @@ use std::fmt;
|
|||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use std::sync::{Arc, mpsc};
|
||||
use std::sync::Arc;
|
||||
|
||||
mod code_stats;
|
||||
pub mod config;
|
||||
|
|
@ -125,9 +124,6 @@ pub struct Session {
|
|||
/// `-Zquery-dep-graph` is specified.
|
||||
pub cgu_reuse_tracker: CguReuseTracker,
|
||||
|
||||
/// Used by `-Z profile-queries` in `util::common`.
|
||||
pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
|
||||
|
||||
/// Used by `-Z self-profile`.
|
||||
pub prof: SelfProfilerRef,
|
||||
|
||||
|
|
@ -509,13 +505,6 @@ impl Session {
|
|||
pub fn time_extended(&self) -> bool {
|
||||
self.opts.debugging_opts.time_passes
|
||||
}
|
||||
pub fn profile_queries(&self) -> bool {
|
||||
self.opts.debugging_opts.profile_queries
|
||||
|| self.opts.debugging_opts.profile_queries_and_keys
|
||||
}
|
||||
pub fn profile_queries_and_keys(&self) -> bool {
|
||||
self.opts.debugging_opts.profile_queries_and_keys
|
||||
}
|
||||
pub fn instrument_mcount(&self) -> bool {
|
||||
self.opts.debugging_opts.instrument_mcount
|
||||
}
|
||||
|
|
@ -637,6 +626,14 @@ impl Session {
|
|||
.output_types
|
||||
.contains_key(&OutputType::LlvmAssembly)
|
||||
|| self.opts.output_types.contains_key(&OutputType::Bitcode);
|
||||
|
||||
// Address sanitizer and memory sanitizer use alloca name when reporting an issue.
|
||||
let more_names = match self.opts.debugging_opts.sanitizer {
|
||||
Some(Sanitizer::Address) => true,
|
||||
Some(Sanitizer::Memory) => true,
|
||||
_ => more_names,
|
||||
};
|
||||
|
||||
self.opts.debugging_opts.fewer_names || !more_names
|
||||
}
|
||||
|
||||
|
|
@ -1162,7 +1159,7 @@ fn build_session_(
|
|||
);
|
||||
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
|
||||
|
||||
let parse_sess = parse::ParseSess::with_span_handler(
|
||||
let parse_sess = ParseSess::with_span_handler(
|
||||
span_diagnostic,
|
||||
source_map,
|
||||
);
|
||||
|
|
@ -1234,7 +1231,6 @@ fn build_session_(
|
|||
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
||||
cgu_reuse_tracker,
|
||||
prof: SelfProfilerRef::new(self_profiler),
|
||||
profile_channel: Lock::new(None),
|
||||
perf_stats: PerfStats {
|
||||
symbol_hash_time: Lock::new(Duration::from_secs(0)),
|
||||
decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
|
||||
|
|
|
|||
|
|
@ -453,21 +453,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn find_similar_impl_candidates(&self,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Vec<ty::TraitRef<'tcx>>
|
||||
{
|
||||
let simp = fast_reject::simplify_type(self.tcx,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
true);
|
||||
fn find_similar_impl_candidates(
|
||||
&self,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
) -> Vec<ty::TraitRef<'tcx>> {
|
||||
let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
|
||||
let all_impls = self.tcx.all_impls(trait_ref.def_id());
|
||||
|
||||
match simp {
|
||||
Some(simp) => all_impls.iter().filter_map(|&def_id| {
|
||||
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||
let imp_simp = fast_reject::simplify_type(self.tcx,
|
||||
imp.self_ty(),
|
||||
true);
|
||||
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
|
||||
if let Some(imp_simp) = imp_simp {
|
||||
if simp != imp_simp {
|
||||
return None
|
||||
|
|
@ -482,10 +478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn report_similar_impl_candidates(&self,
|
||||
impl_candidates: Vec<ty::TraitRef<'tcx>>,
|
||||
err: &mut DiagnosticBuilder<'_>)
|
||||
{
|
||||
fn report_similar_impl_candidates(
|
||||
&self,
|
||||
impl_candidates: Vec<ty::TraitRef<'tcx>>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
if impl_candidates.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -718,12 +715,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
// these notes will often be of the form
|
||||
// "the type `T` can't be frobnicated"
|
||||
// which is somewhat confusing.
|
||||
err.help(&format!("consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate()));
|
||||
} else if !have_alt_message {
|
||||
// Can't show anything else useful, try to find similar impls.
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
||||
self.report_similar_impl_candidates(impl_candidates, &mut err);
|
||||
self.suggest_restricting_param_bound(
|
||||
&mut err,
|
||||
&trait_ref,
|
||||
obligation.cause.body_id,
|
||||
);
|
||||
} else {
|
||||
if !have_alt_message {
|
||||
// Can't show anything else useful, try to find similar impls.
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
||||
self.report_similar_impl_candidates(impl_candidates, &mut err);
|
||||
}
|
||||
self.suggest_change_mut(
|
||||
&obligation,
|
||||
&mut err,
|
||||
&trait_ref,
|
||||
points_at_arg,
|
||||
);
|
||||
}
|
||||
|
||||
// If this error is due to `!: Trait` not implemented but `(): Trait` is
|
||||
|
|
@ -955,6 +963,175 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
err.emit();
|
||||
}
|
||||
|
||||
fn suggest_restricting_param_bound(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: &ty::PolyTraitRef<'_>,
|
||||
body_id: hir::HirId,
|
||||
) {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let (param_ty, projection) = match &self_ty.kind {
|
||||
ty::Param(_) => (true, None),
|
||||
ty::Projection(projection) => (false, Some(projection)),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let mut suggest_restriction = |generics: &hir::Generics, msg| {
|
||||
let span = generics.where_clause.span_for_predicates_or_empty_place();
|
||||
if !span.from_expansion() && span.desugaring_kind().is_none() {
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
|
||||
&format!("consider further restricting {}", msg),
|
||||
format!(
|
||||
"{} {} ",
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
","
|
||||
} else {
|
||||
" where"
|
||||
},
|
||||
trait_ref.to_predicate(),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
|
||||
// don't suggest `T: Sized + ?Sized`.
|
||||
let mut hir_id = body_id;
|
||||
while let Some(node) = self.tcx.hir().find(hir_id) {
|
||||
match node {
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Method(..), ..
|
||||
}) if param_ty && self_ty == self.tcx.types.self_param => {
|
||||
// Restricting `Self` for a single method.
|
||||
suggest_restriction(&generics, "`Self`");
|
||||
return;
|
||||
}
|
||||
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Method(..), ..
|
||||
}) |
|
||||
hir::Node::ImplItem(hir::ImplItem {
|
||||
generics,
|
||||
kind: hir::ImplItemKind::Method(..), ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, _, _), ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
|
||||
}) if projection.is_some() => {
|
||||
// Missing associated type bound.
|
||||
suggest_restriction(&generics, "the associated type");
|
||||
return;
|
||||
}
|
||||
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::TyAlias(_, generics), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::TraitAlias(generics, _), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
|
||||
hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
|
||||
if param_ty => {
|
||||
// Missing generic type parameter bound.
|
||||
let restrict_msg = "consider further restricting this bound";
|
||||
let param_name = self_ty.to_string();
|
||||
for param in generics.params.iter().filter(|p| {
|
||||
¶m_name == std::convert::AsRef::<str>::as_ref(&p.name.ident().as_str())
|
||||
}) {
|
||||
if param_name.starts_with("impl ") {
|
||||
// `impl Trait` in argument:
|
||||
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
restrict_msg,
|
||||
// `impl CurrentTrait + MissingTrait`
|
||||
format!("{} + {}", param.name.ident(), trait_ref),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if generics.where_clause.predicates.is_empty() &&
|
||||
param.bounds.is_empty()
|
||||
{
|
||||
// If there are no bounds whatsoever, suggest adding a constraint
|
||||
// to the type parameter:
|
||||
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
"consider restricting this bound",
|
||||
format!("{}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if !generics.where_clause.predicates.is_empty() {
|
||||
// There is a `where` clause, so suggest expanding it:
|
||||
// `fn foo<T>(t: T) where T: Debug {}` →
|
||||
// `fn foo<T>(t: T) where T: Debug, T: Trait {}`
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||
&format!(
|
||||
"consider further restricting type parameter `{}`",
|
||||
param_name,
|
||||
),
|
||||
format!(", {}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// If there is no `where` clause lean towards constraining to the
|
||||
// type parameter:
|
||||
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
|
||||
let sp = param.span.with_hi(span.hi());
|
||||
let span = self.tcx.sess.source_map()
|
||||
.span_through_char(sp, ':');
|
||||
if sp != param.span && sp != span {
|
||||
// Only suggest if we have high certainty that the span
|
||||
// covers the colon in `foo<T: Trait>`.
|
||||
err.span_suggestion(span, restrict_msg, format!(
|
||||
"{} + ",
|
||||
trait_ref.to_predicate(),
|
||||
), Applicability::MachineApplicable);
|
||||
} else {
|
||||
err.span_label(param.span, &format!(
|
||||
"consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate(),
|
||||
));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hir::Node::Crate => return,
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
hir_id = self.tcx.hir().get_parent_item(hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
|
||||
/// suggestion to borrow the initializer in order to use have a slice instead.
|
||||
fn suggest_borrow_on_unsized_slice(
|
||||
|
|
@ -1081,9 +1258,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
let substs = self.tcx.mk_substs_trait(trait_type, &[]);
|
||||
let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
|
||||
let new_obligation = Obligation::new(ObligationCause::dummy(),
|
||||
obligation.param_env,
|
||||
new_trait_ref.to_predicate());
|
||||
let new_obligation = Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
obligation.param_env,
|
||||
new_trait_ref.to_predicate(),
|
||||
);
|
||||
|
||||
if self.predicate_may_hold(&new_obligation) {
|
||||
let sp = self.tcx.sess.source_map()
|
||||
|
|
@ -1105,6 +1284,77 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if the trait bound is implemented for a different mutability and note it in the
|
||||
/// final error.
|
||||
fn suggest_change_mut(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
|
||||
points_at_arg: bool,
|
||||
) {
|
||||
let span = obligation.cause.span;
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
let refs_number = snippet.chars()
|
||||
.filter(|c| !c.is_whitespace())
|
||||
.take_while(|c| *c == '&')
|
||||
.count();
|
||||
if let Some('\'') = snippet.chars()
|
||||
.filter(|c| !c.is_whitespace())
|
||||
.skip(refs_number)
|
||||
.next()
|
||||
{ // Do not suggest removal of borrow from type arguments.
|
||||
return;
|
||||
}
|
||||
let trait_ref = self.resolve_vars_if_possible(trait_ref);
|
||||
if trait_ref.has_infer_types() {
|
||||
// Do not ICE while trying to find if a reborrow would succeed on a trait with
|
||||
// unresolved bindings.
|
||||
return;
|
||||
}
|
||||
|
||||
if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
|
||||
let trait_type = match mutability {
|
||||
hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type),
|
||||
hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type),
|
||||
};
|
||||
|
||||
let substs = self.tcx.mk_substs_trait(&trait_type, &[]);
|
||||
let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs);
|
||||
let new_obligation = Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
obligation.param_env,
|
||||
new_trait_ref.to_predicate(),
|
||||
);
|
||||
|
||||
if self.evaluate_obligation_no_overflow(
|
||||
&new_obligation,
|
||||
).must_apply_modulo_regions() {
|
||||
let sp = self.tcx.sess.source_map()
|
||||
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
|
||||
if points_at_arg &&
|
||||
mutability == hir::Mutability::MutImmutable &&
|
||||
refs_number > 0
|
||||
{
|
||||
err.span_suggestion(
|
||||
sp,
|
||||
"consider changing this borrow's mutability",
|
||||
"&mut ".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"`{}` is implemented for `{:?}`, but not for `{:?}`",
|
||||
trait_ref,
|
||||
trait_type,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_semicolon_removal(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ pub struct VtableImplData<'tcx, N> {
|
|||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct VtableGeneratorData<'tcx, N> {
|
||||
pub generator_def_id: DefId,
|
||||
pub substs: ty::GeneratorSubsts<'tcx>,
|
||||
pub substs: SubstsRef<'tcx>,
|
||||
/// Nested obligations. This can be non-empty if the generator
|
||||
/// signature contains associated types.
|
||||
pub nested: Vec<N>
|
||||
|
|
|
|||
|
|
@ -1259,7 +1259,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
|
|||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
||||
) -> Progress<'tcx> {
|
||||
let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx());
|
||||
let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
|
||||
let Normalized {
|
||||
value: gen_sig,
|
||||
obligations
|
||||
|
|
@ -1505,8 +1505,8 @@ fn assoc_ty_def(
|
|||
|
||||
if let Some(assoc_item) = trait_def
|
||||
.ancestors(tcx, impl_def_id)
|
||||
.defs(tcx, assoc_ty_name, ty::AssocKind::Type, trait_def_id)
|
||||
.next() {
|
||||
.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
|
||||
|
||||
assoc_item
|
||||
} else {
|
||||
// This is saying that neither the trait nor
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::iter::FromIterator;
|
|||
use syntax::source_map::Span;
|
||||
use crate::ty::subst::GenericArg;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::query::Providers;
|
||||
|
||||
impl<'cx, 'tcx> At<'cx, 'tcx> {
|
||||
/// Given a type `ty` of some value being dropped, computes a set
|
||||
|
|
@ -33,7 +34,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
|
|||
// Quick check: there are a number of cases that we know do not require
|
||||
// any destructor.
|
||||
let tcx = self.infcx.tcx;
|
||||
if trivial_dropck_outlives(tcx, ty) {
|
||||
if tcx.trivial_dropck_outlives(ty) {
|
||||
return InferOk {
|
||||
value: vec![],
|
||||
obligations: vec![],
|
||||
|
|
@ -207,15 +208,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
| ty::Error => true,
|
||||
|
||||
// [T; N] and [T] have same properties as T.
|
||||
ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
|
||||
ty::Array(ty, _) | ty::Slice(ty) => tcx.trivial_dropck_outlives(ty),
|
||||
|
||||
// (T1..Tn) and closures have same properties as T1..Tn --
|
||||
// check if *any* of those are trivial.
|
||||
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
|
||||
ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())),
|
||||
ty::Closure(def_id, ref substs) => substs
|
||||
.as_closure()
|
||||
.upvar_tys(def_id, tcx)
|
||||
.all(|t| trivial_dropck_outlives(tcx, t)),
|
||||
.all(|t| tcx.trivial_dropck_outlives(t)),
|
||||
|
||||
ty::Adt(def, _) => {
|
||||
if Some(def.did) == tcx.lang_items().manually_drop() {
|
||||
|
|
@ -243,3 +244,10 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn provide(p: &mut Providers<'_>) {
|
||||
*p = Providers {
|
||||
trivial_dropck_outlives,
|
||||
..*p
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
|||
// Helper function that canonicalizes and runs the query. If an
|
||||
// overflow results, we re-run it in the local context so we can
|
||||
// report a nice error.
|
||||
fn evaluate_obligation_no_overflow(
|
||||
crate fn evaluate_obligation_no_overflow(
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> EvaluationResult {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue