[[package]]
name = "assert_cli"
-version = "0.5.4"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build_helper"
version = "0.1.0"
-[[package]]
-name = "bytecount"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "byteorder"
version = "1.2.2"
name = "clippy-mini-macro-test"
version = "0.2.0"
-[[package]]
-name = "clippy_lints"
-version = "0.0.197"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "clippy_lints"
version = "0.0.200"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "difference"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "difference"
version = "2.0.0"
[[package]]
name = "languageserver-types"
-version = "0.39.0"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rls"
-version = "0.127.0"
+version = "0.128.0"
dependencies = [
"cargo 0.28.0",
"cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.197 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.200",
"env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.6.1",
+ "rustfmt-nightly 0.7.0",
"serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rls-analysis"
-version = "0.12.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rls-data"
-version = "0.15.0"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "rls-data"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "rls-rustc"
version = "0.2.2"
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_data_structures"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_errors"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_target"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-serialize"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-ap-syntax"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
-version = "113.0.0"
+version = "128.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustfmt-nightly"
-version = "0.6.1"
+version = "0.7.0"
dependencies = [
- "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "assert_cli 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "skeptic"
-version = "0.13.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "smallvec"
version = "0.6.0"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
-"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930"
+"checksum assert_cli 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da59dbd8df54562665b925b427221ceda9b771408cb8a6cbd2125d3b001330b"
"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
-"checksum bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "882585cd7ec84e902472df34a5e01891202db3bf62614e1f0afe459c1afcf744"
"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
"checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3"
"checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5f60682a4c264e7f8d77b82e7788938a76befdf949d4a98026d19099c9d873"
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
-"checksum clippy_lints 0.0.197 (registry+https://github.com/rust-lang/crates.io-index)" = "ee3b543abb36b1557180d41dd3758581254644d85d021df7f8f8cb395054581c"
"checksum cmake 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5cf678ceebedde428000cb3a34465cf3606d1a48da17014948a916deac39da7c"
"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc"
"checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
"checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4cdd5e52d71aca47050e5b25f03082609c63a1e76b7362ebdd010895b3f854"
+"checksum languageserver-types 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "017cf5ade4be5ebeb06277ccd281c268dbd2e0801128d3992b4b4057f34dd432"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb"
"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
-"checksum rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a41488cf5dc99d6ce383319d2978756567b70d4ed0539eb0d9ce07763e732e46"
+"checksum rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da9794cd1f80f2cb888c00641a32f9855d0226c954ee31cef145784914c7142e"
"checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2"
-"checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510"
"checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988"
"checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a01334797c5c4cf56cc40bb9636d7b4c4a076665b9b9b7f100fd666cf0a02ffc"
-"checksum rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03d6f8f7da0de905f6ef80dc14dce3bbc372430622b6aeb421cf13190bc70e8a"
-"checksum rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfd6183804a685c48601651d8c8c7b0daa8f83b0b5e24edfbcb6a0337085127"
-"checksum rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f223157f51bf0e0621bef099de862468892ee4c4b83056f48f63e1bc00ccb72"
-"checksum rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2104a55a87d65cba8a845656f1f19a35da52af403863cd2a4bd5876ba522d879"
-"checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323"
-"checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63"
+"checksum rustc-ap-rustc_cratesio_shim 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7374a2b466e6e3ce489e045302e304849355faf7fd033d4d95e6e86e48c313b4"
+"checksum rustc-ap-rustc_data_structures 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b3c3e566868a04735852eb333db958453a53cacdd935fe508e0c9fd822ea88"
+"checksum rustc-ap-rustc_errors 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b81dc5e8a8e63befb0eaf1c9443e269dee6f8daced4e3149fe8a80947fd682e"
+"checksum rustc-ap-rustc_target 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6bb7f1df7a4ca231cbe35a5eaebdc22cd2258c0393e856513b5186dec720e4"
+"checksum rustc-ap-serialize 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1ab72257c28395c45a27a5812d94515ec43e639add4820eafc919a71c1714c3"
+"checksum rustc-ap-syntax 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf9ca2901388714e9ccc7de7281ef06cec55d9f245252ba1d635bc86c730d9a"
+"checksum rustc-ap-syntax_pos 128.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5217444369a36e98e11f4ac976f03878704893832e2e0b57d49f2f31438139f"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99"
"checksum rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d69983f8613a9c3ba1a3bbf5e8bdf2fd5c42317b1d8dd8623ca8030173bf8a6b"
"checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
-"checksum skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4474d6da9593171bcb086890fc344a3a12783cb24e5b141f8a5d0e43561f4b6"
"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
"checksum socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
//! A support library for macro authors when defining new macros.
//!
//! This library, provided by the standard distribution, provides the types
-//! consumed in the interfaces of procedurally defined macro definitions.
-//! Currently the primary use of this crate is to provide the ability to define
-//! new custom derive modes through `#[proc_macro_derive]`.
+//! consumed in the interfaces of procedurally defined macro definitions such as
+//! function-like macros `#[proc_macro]`, macro attribures `#[proc_macro_attribute]` and
+//! custom derive attributes`#[proc_macro_derive]`.
//!
-//! Note that this crate is intentionally very bare-bones currently. The main
-//! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
-//! implementations, indicating that it can only go to and come from a string.
+//! Note that this crate is intentionally bare-bones currently.
//! This functionality is intended to be expanded over time as more surface
//! area for macro authors is stabilized.
//!
use syntax::ast;
use syntax::errors::DiagnosticBuilder;
use syntax::parse::{self, token};
-use syntax::symbol::Symbol;
+use syntax::symbol::{keywords, Symbol};
use syntax::tokenstream;
-use syntax::parse::lexer::comments;
+use syntax::parse::lexer::{self, comments};
use syntax_pos::{FileMap, Pos, SyntaxContext, FileName};
use syntax_pos::hygiene::Mark;
/// The main type provided by this crate, representing an abstract stream of
-/// tokens.
+/// tokens, or, more specifically, a sequence of token trees.
+/// The type provide interfaces for iterating over those token trees and, conversely,
+/// collecting a number of token trees into one stream.
///
-/// This is both the input and output of `#[proc_macro_derive]` definitions.
-/// Currently it's required to be a list of valid Rust items, but this
-/// restriction may be lifted in the future.
+/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
+/// and `#[proc_macro_derive]` definitions.
///
/// The API of this type is intentionally bare-bones, but it'll be expanded over
/// time!
#[derive(Clone)]
pub struct TokenStream(tokenstream::TokenStream);
-#[unstable(feature = "proc_macro", issue = "38356")]
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl !Send for TokenStream {}
-#[unstable(feature = "proc_macro", issue = "38356")]
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl !Sync for TokenStream {}
/// Error returned from `TokenStream::from_str`.
_inner: (),
}
-#[unstable(feature = "proc_macro", issue = "38356")]
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl !Send for LexError {}
-#[unstable(feature = "proc_macro", issue = "38356")]
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl !Sync for LexError {}
impl TokenStream {
- /// Returns an empty `TokenStream`.
+ /// Returns an empty `TokenStream` containing no token trees.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn empty() -> TokenStream {
TokenStream(tokenstream::TokenStream::empty())
}
}
+/// Attempts to break the string into tokens and parse those tokens into a token stream.
+/// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
+/// or characters not existing in the language.
+///
+/// NOTE: Some errors may cause panics instead of returning `LexError`. We reserve the right to
+/// change these errors into `LexError`s later.
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl FromStr for TokenStream {
type Err = LexError;
}
}
+/// Prints the token stream as a string that is supposed to be losslessly convertible back
+/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
+/// with `Delimiter::None` delimiters and negative numeric literals.
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+/// Prints token in a form convenient for debugging.
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl fmt::Debug for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+/// Creates a token stream containing a single token tree.
#[unstable(feature = "proc_macro", issue = "38356")]
impl From<TokenTree> for TokenStream {
fn from(tree: TokenTree) -> TokenStream {
}
}
+/// Collects a number of token trees into a single stream.
#[unstable(feature = "proc_macro", issue = "38356")]
impl iter::FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
}
}
-#[unstable(feature = "proc_macro", issue = "38356")]
+/// A "flattening" operation on token streams, collects token trees
+/// from multiple token streams into a single stream.
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl iter::FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
let mut builder = tokenstream::TokenStreamBuilder::new();
}
}
-/// Implementation details for the `TokenTree` type, such as iterators.
+/// Public implementation details for the `TokenStream` type, such as iterators.
#[unstable(feature = "proc_macro", issue = "38356")]
pub mod token_stream {
use syntax::tokenstream;
use {TokenTree, TokenStream, Delimiter};
- /// An iterator over `TokenTree`s.
+ /// An iterator over `TokenStream`'s `TokenTree`s.
+ /// The iteration is "shallow", e.g. the iterator doesn't recurse into delimited groups,
+ /// and returns whole groups as token trees.
#[derive(Clone)]
#[unstable(feature = "proc_macro", issue = "38356")]
pub struct IntoIter {
let next = self.cursor.next_as_stream()?;
Some(TokenTree::from_internal(next, &mut self.stack))
})?;
+ // HACK: The condition "dummy span + group with empty delimiter" represents an AST
+ // fragment approximately converted into a token stream. This may happen, for
+ // example, with inputs to proc macro attributes, including derives. Such "groups"
+ // need to flattened during iteration over stream's token trees.
+ // Eventually this needs to be removed in favor of keeping original token trees
+ // and not doing the roundtrip through AST.
if tree.span().0 == DUMMY_SP {
if let TokenTree::Group(ref group) = tree {
if group.delimiter() == Delimiter::None {
/// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
/// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
-/// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
+/// the `TokenStream` `[Ident("a"), Punct('+', Alone), Ident("b")]`.
///
/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
/// To quote `$` itself, use `$$`.
}
/// The span of the invocation of the current procedural macro.
+ /// Identifiers created with this span will be resolved as if they were written
+ /// directly at the macro call location (call-site hygiene) and other code
+ /// at the macro call site will be able to refer to them as well.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn call_site() -> Span {
::__internal::with_sess(|(_, mark)| Span(mark.expn_info().unwrap().call_site))
diagnostic_method!(help, Level::Help);
}
+/// Prints a span in a form convenient for debugging.
#[unstable(feature = "proc_macro", issue = "38356")]
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[unstable(feature = "proc_macro", issue = "38356")]
#[derive(Clone)]
pub enum TokenTree {
- /// A delimited tokenstream
+ /// A token stream surrounded by bracket delimiters.
Group(Group),
- /// A unicode identifier
- Term(Term),
- /// A punctuation character (`+`, `,`, `$`, etc.).
- Op(Op),
+ /// An identifier.
+ Ident(Ident),
+ /// A single punctuation character (`+`, `,`, `$`, etc.).
+ Punct(Punct),
/// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
Literal(Literal),
}
impl !Sync for TokenTree {}
impl TokenTree {
- /// Returns the span of this token, accessing the `span` method of each of
- /// the internal tokens.
+ /// Returns the span of this tree, delegating to the `span` method of
+ /// the contained token or a delimited stream.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn span(&self) -> Span {
match *self {
TokenTree::Group(ref t) => t.span(),
- TokenTree::Term(ref t) => t.span(),
- TokenTree::Op(ref t) => t.span(),
+ TokenTree::Ident(ref t) => t.span(),
+ TokenTree::Punct(ref t) => t.span(),
TokenTree::Literal(ref t) => t.span(),
}
}
pub fn set_span(&mut self, span: Span) {
match *self {
TokenTree::Group(ref mut t) => t.set_span(span),
- TokenTree::Term(ref mut t) => t.set_span(span),
- TokenTree::Op(ref mut t) => t.set_span(span),
+ TokenTree::Ident(ref mut t) => t.set_span(span),
+ TokenTree::Punct(ref mut t) => t.set_span(span),
TokenTree::Literal(ref mut t) => t.set_span(span),
}
}
}
+/// Prints token treee in a form convenient for debugging.
#[unstable(feature = "proc_macro", issue = "38356")]
impl fmt::Debug for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// so don't bother with an extra layer of indirection
match *self {
TokenTree::Group(ref tt) => tt.fmt(f),
- TokenTree::Term(ref tt) => tt.fmt(f),
- TokenTree::Op(ref tt) => tt.fmt(f),
+ TokenTree::Ident(ref tt) => tt.fmt(f),
+ TokenTree::Punct(ref tt) => tt.fmt(f),
TokenTree::Literal(ref tt) => tt.fmt(f),
}
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl From<Term> for TokenTree {
- fn from(g: Term) -> TokenTree {
- TokenTree::Term(g)
+impl From<Ident> for TokenTree {
+ fn from(g: Ident) -> TokenTree {
+ TokenTree::Ident(g)
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl From<Op> for TokenTree {
- fn from(g: Op) -> TokenTree {
- TokenTree::Op(g)
+impl From<Punct> for TokenTree {
+ fn from(g: Punct) -> TokenTree {
+ TokenTree::Punct(g)
}
}
}
}
+/// Prints the token tree as a string that is supposed to be losslessly convertible back
+/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
+/// with `Delimiter::None` delimiters and negative numeric literals.
#[unstable(feature = "proc_macro", issue = "38356")]
impl fmt::Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TokenTree::Group(ref t) => t.fmt(f),
- TokenTree::Term(ref t) => t.fmt(f),
- TokenTree::Op(ref t) => t.fmt(f),
+ TokenTree::Ident(ref t) => t.fmt(f),
+ TokenTree::Punct(ref t) => t.fmt(f),
TokenTree::Literal(ref t) => t.fmt(f),
}
}
}
-/// A delimited token stream
+/// A delimited token stream.
///
-/// A `Group` internally contains a `TokenStream` which is delimited by a
-/// `Delimiter`. Groups represent multiple tokens internally and have a `Span`
-/// for the entire stream.
+/// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s.
#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
pub struct Group {
Brace,
/// `[ ... ]`
Bracket,
- /// An implicit delimiter, e.g. `$var`, where $var is `...`.
+ /// `Ø ... Ø`
+ /// An implicit delimiter, that may, for example, appear around tokens coming from a
+ /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
+ /// `$var * 3` where `$var` is `1 + 2`.
+ /// Implicit delimiters may not survive roundtrip of a token stream through a string.
None,
}
impl Group {
- /// Creates a new `group` with the given delimiter and token stream.
+ /// Creates a new `Group` with the given delimiter and token stream.
///
/// This constructor will set the span for this group to
/// `Span::call_site()`. To change the span you can use the `set_span`
}
}
+/// Prints the group as a string that should be losslessly convertible back
+/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
+/// with `Delimiter::None` delimiters.
#[unstable(feature = "proc_macro", issue = "38356")]
impl fmt::Display for Group {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
-/// An `Op` is an operator like `+` or `-`, and only represents one character.
+/// An `Punct` is an single punctuation character like `+`, `-` or `#`.
///
-/// Operators like `+=` are represented as two instance of `Op` with different
+/// Multicharacter operators like `+=` are represented as two instances of `Punct` with different
/// forms of `Spacing` returned.
#[unstable(feature = "proc_macro", issue = "38356")]
-#[derive(Copy, Clone, Debug)]
-pub struct Op {
- op: char,
+#[derive(Clone, Debug)]
+pub struct Punct {
+ ch: char,
spacing: Spacing,
span: Span,
}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl !Send for Op {}
+impl !Send for Punct {}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl !Sync for Op {}
+impl !Sync for Punct {}
-/// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
+/// Whether an `Punct` is followed immediately by another `Punct` or
+/// followed by another token or whitespace.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[unstable(feature = "proc_macro", issue = "38356")]
pub enum Spacing {
- /// e.g. `+` is `Alone` in `+ =`.
+ /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`.
Alone,
- /// e.g. `+` is `Joint` in `+=`.
+ /// E.g. `+` is `Joint` in `+=` or `'#`.
+ /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`.
Joint,
}
-impl Op {
- /// Creates a new `Op` from the given character and spacing.
+impl Punct {
+ /// Creates a new `Punct` from the given character and spacing.
+ /// The `ch` argument must be a valid punctuation character permitted by the language,
+ /// otherwise the function will panic.
///
- /// The returned `Op` will have the default span of `Span::call_site()`
+ /// The returned `Punct` will have the default span of `Span::call_site()`
/// which can be further configured with the `set_span` method below.
#[unstable(feature = "proc_macro", issue = "38356")]
- pub fn new(op: char, spacing: Spacing) -> Op {
- Op {
- op: op,
+ pub fn new(ch: char, spacing: Spacing) -> Punct {
+ const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
+ '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
+ if !LEGAL_CHARS.contains(&ch) {
+ panic!("unsupported character `{:?}`", ch)
+ }
+ Punct {
+ ch: ch,
spacing: spacing,
span: Span::call_site(),
}
}
- /// Returns the character this operation represents, for example `'+'`
+ /// Returns the value of this punctuation character as `char`.
#[unstable(feature = "proc_macro", issue = "38356")]
- pub fn op(&self) -> char {
- self.op
+ pub fn as_char(&self) -> char {
+ self.ch
}
- /// Returns the spacing of this operator, indicating whether it's a joint
- /// operator with more operators coming next in the token stream or an
- /// `Alone` meaning that the operator has ended.
+ /// Returns the spacing of this punctuation character, indicating whether it's immediately
+ /// followed by another `Punct` in the token stream, so they can potentially be combined into
+ /// a multicharacter operator (`Joint`), or it's followed by some other token or whitespace
+ /// (`Alone`) so the operator has certainly ended.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn spacing(&self) -> Spacing {
self.spacing
}
- /// Returns the span for this operator character
+ /// Returns the span for this punctuation character.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn span(&self) -> Span {
self.span
}
- /// Configure the span for this operator's character
+ /// Configure the span for this punctuation character.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
}
+/// Prints the punctuation character as a string that should be losslessly convertible
+/// back into the same character.
#[unstable(feature = "proc_macro", issue = "38356")]
-impl fmt::Display for Op {
+impl fmt::Display for Punct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
TokenStream::from(TokenTree::from(self.clone())).fmt(f)
}
}
-/// An interned string.
-#[derive(Copy, Clone, Debug)]
+/// An identifier (`ident`).
+#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
-pub struct Term {
+pub struct Ident {
sym: Symbol,
span: Span,
+ is_raw: bool,
}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl !Send for Term {}
+impl !Send for Ident {}
#[unstable(feature = "proc_macro", issue = "38356")]
-impl !Sync for Term {}
+impl !Sync for Ident {}
-impl Term {
- /// Creates a new `Term` with the given `string` as well as the specified
+impl Ident {
+ /// Creates a new `Ident` with the given `string` as well as the specified
/// `span`.
+ /// The `string` argument must be a valid identifier permitted by the
+ /// language, otherwise the function will panic.
///
/// Note that `span`, currently in rustc, configures the hygiene information
- /// for this identifier. As of this time `Span::call_site()` explicitly
- /// opts-in to **non-hygienic** information (aka copy/pasted code) while
- /// spans like `Span::def_site()` will opt-in to hygienic information,
- /// meaning that code at the call site of the macro can't access this
- /// identifier.
+ /// for this identifier.
+ ///
+ /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene
+ /// meaning that identifiers created with this span will be resolved as if they were written
+ /// directly at the location of the macro call, and other code at the macro call site will be
+ /// able to refer to them as well.
+ ///
+ /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene
+ /// meaning that identifiers created with this span will be resolved at the location of the
+ /// macro definition and other code at the macro call site will not be able to refer to them.
///
/// Due to the current importance of hygiene this constructor, unlike other
/// tokens, requires a `Span` to be specified at construction.
#[unstable(feature = "proc_macro", issue = "38356")]
- pub fn new(string: &str, span: Span) -> Term {
- Term {
+ pub fn new(string: &str, span: Span) -> Ident {
+ if !lexer::is_valid_ident(string) {
+ panic!("`{:?}` is not a valid identifier", string)
+ }
+ Ident {
sym: Symbol::intern(string),
span,
+ is_raw: false,
}
}
- // FIXME: Remove this, do not stabilize
- /// Get a reference to the interned string.
+ /// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
#[unstable(feature = "proc_macro", issue = "38356")]
- pub fn as_str(&self) -> &str {
- unsafe { &*(&*self.sym.as_str() as *const str) }
+ pub fn new_raw(string: &str, span: Span) -> Ident {
+ let mut ident = Ident::new(string, span);
+ if ident.sym == keywords::Underscore.name() ||
+ token::is_path_segment_keyword(ast::Ident::with_empty_ctxt(ident.sym)) {
+ panic!("`{:?}` is not a valid raw identifier", string)
+ }
+ ident.is_raw = true;
+ ident
}
- /// Returns the span of this `Term`, encompassing the entire string returned
+ /// Returns the span of this `Ident`, encompassing the entire string returned
/// by `as_str`.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn span(&self) -> Span {
self.span
}
- /// Configures the span of this `Term`, possibly changing hygiene
- /// information.
+ /// Configures the span of this `Ident`, possibly changing its hygiene context.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
}
+/// Prints the identifier as a string that should be losslessly convertible
+/// back into the same identifier.
#[unstable(feature = "proc_macro", issue = "38356")]
-impl fmt::Display for Term {
+impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.is_raw {
+ f.write_str("r#")?;
+ }
self.sym.as_str().fmt(f)
}
}
-/// A literal character (`'a'`), string (`"hello"`), a number (`2.3`), etc.
+/// A literal string (`"hello"`), byte string (`b"hello"`),
+/// character (`'a'`), byte character (`b'a'`), an integer or floating point number
+/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
+/// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
pub struct Literal {
/// This function will create an integer like `1u32` where the integer
/// value specified is the first part of the token and the integral is
/// also suffixed at the end.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// Literals created through this method have the `Span::call_site()`
/// span by default, which can be configured with the `set_span` method
/// specified on this token, meaning that invocations like
/// `Literal::i8_unsuffixed(1)` are equivalent to
/// `Literal::u32_unsuffixed(1)`.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// Literals created through this method have the `Span::call_site()`
/// span by default, which can be configured with the `set_span` method
/// This constructor is similar to those like `Literal::i8_unsuffixed` where
/// the float's value is emitted directly into the token but no suffix is
/// used, so it may be inferred to be a `f64` later in the compiler.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
///
/// specified is the preceding part of the token and `f32` is the suffix of
/// the token. This token will always be inferred to be an `f32` in the
/// compiler.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
///
/// This constructor is similar to those like `Literal::i8_unsuffixed` where
/// the float's value is emitted directly into the token but no suffix is
/// used, so it may be inferred to be a `f64` later in the compiler.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
///
/// specified is the preceding part of the token and `f64` is the suffix of
/// the token. This token will always be inferred to be an `f64` in the
/// compiler.
+ /// Literals created from negative numbers may not survive rountrips through
+ /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
///
}
}
+/// Prints the literal as a string that should be losslessly convertible
+/// back into the same literal (except for possible rounding for floating point literals).
#[unstable(feature = "proc_macro", issue = "38356")]
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
})
}
macro_rules! op {
- ($a:expr) => (tt!(Op::new($a, op_kind)));
+ ($a:expr) => (tt!(Punct::new($a, op_kind)));
($a:expr, $b:expr) => ({
- stack.push(tt!(Op::new($b, op_kind)));
- tt!(Op::new($a, Spacing::Joint))
+ stack.push(tt!(Punct::new($b, op_kind)));
+ tt!(Punct::new($a, Spacing::Joint))
});
($a:expr, $b:expr, $c:expr) => ({
- stack.push(tt!(Op::new($c, op_kind)));
- stack.push(tt!(Op::new($b, Spacing::Joint)));
- tt!(Op::new($a, Spacing::Joint))
+ stack.push(tt!(Punct::new($c, op_kind)));
+ stack.push(tt!(Punct::new($b, Spacing::Joint)));
+ tt!(Punct::new($a, Spacing::Joint))
})
}
Pound => op!('#'),
Dollar => op!('$'),
Question => op!('?'),
+ SingleQuote => op!('\''),
- Ident(ident, false) | Lifetime(ident) => {
- tt!(Term::new(&ident.name.as_str(), Span(span)))
+ Ident(ident, false) => {
+ tt!(self::Ident::new(&ident.name.as_str(), Span(span)))
}
Ident(ident, true) => {
- tt!(Term::new(&format!("r#{}", ident), Span(span)))
+ tt!(self::Ident::new_raw(&ident.name.as_str(), Span(span)))
+ }
+ Lifetime(ident) => {
+ let ident = ident.without_first_quote();
+ stack.push(tt!(self::Ident::new(&ident.name.as_str(), Span(span))));
+ tt!(Punct::new('\'', Spacing::Joint))
}
Literal(lit, suffix) => tt!(self::Literal { lit, suffix, span: Span(span) }),
DocComment(c) => {
let style = comments::doc_comment_style(&c.as_str());
let stripped = comments::strip_doc_comment_decoration(&c.as_str());
let stream = vec![
- tt!(Term::new("doc", Span(span))),
- tt!(Op::new('=', Spacing::Alone)),
+ tt!(self::Ident::new("doc", Span(span))),
+ tt!(Punct::new('=', Spacing::Alone)),
tt!(self::Literal::string(&stripped)),
].into_iter().collect();
stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
if style == ast::AttrStyle::Inner {
- stack.push(tt!(Op::new('!', Spacing::Alone)));
+ stack.push(tt!(Punct::new('!', Spacing::Alone)));
}
- tt!(Op::new('#', Spacing::Alone))
+ tt!(Punct::new('#', Spacing::Alone))
}
Interpolated(_) => {
use syntax::parse::token::*;
use syntax::tokenstream::{TokenTree, Delimited};
- let (op, kind, span) = match self {
- self::TokenTree::Op(tt) => (tt.op(), tt.spacing(), tt.span()),
+ let (ch, kind, span) = match self {
+ self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()),
self::TokenTree::Group(tt) => {
return TokenTree::Delimited(tt.span.0, Delimited {
delim: tt.delimiter.to_internal(),
tts: tt.stream.0.into(),
}).into();
},
- self::TokenTree::Term(tt) => {
- let ident = ast::Ident::new(tt.sym, tt.span.0);
- let sym_str = tt.sym.to_string();
- let token = if sym_str.starts_with("'") {
- Lifetime(ident)
- } else if sym_str.starts_with("r#") {
- let name = Symbol::intern(&sym_str[2..]);
- let ident = ast::Ident::new(name, ident.span);
- Ident(ident, true)
- } else {
- Ident(ident, false)
- };
+ self::TokenTree::Ident(tt) => {
+ let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
return TokenTree::Token(tt.span.0, token).into();
}
self::TokenTree::Literal(self::Literal {
}
};
- let token = match op {
+ let token = match ch {
'=' => Eq,
'<' => Lt,
'>' => Gt,
'#' => Pound,
'$' => Dollar,
'?' => Question,
- _ => panic!("unsupported character {}", op),
+ '\'' => SingleQuote,
+ _ => unreachable!(),
};
let tree = TokenTree::Token(span.0, token);
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[doc(hidden)]
pub mod __internal {
- pub use quote::{LiteralKind, Quoter, unquote};
+ pub use quote::{LiteralKind, SpannedSymbol, Quoter, unquote};
use std::cell::Cell;
//! This quasiquoter uses macros 2.0 hygiene to reliably access
//! items from `proc_macro`, to build a `proc_macro::TokenStream`.
-use {Delimiter, Literal, Spacing, Span, Term, Op, Group, TokenStream, TokenTree};
+use {Delimiter, Literal, Spacing, Span, Ident, Punct, Group, TokenStream, TokenTree};
use syntax::ext::base::{ExtCtxt, ProcMacro};
use syntax::parse::token;
+use syntax::symbol::Symbol;
use syntax::tokenstream;
pub struct Quoter;
}
macro_rules! quote_tok {
- (,) => { tt2ts!(Op::new(',', Spacing::Alone)) };
- (.) => { tt2ts!(Op::new('.', Spacing::Alone)) };
- (:) => { tt2ts!(Op::new(':', Spacing::Alone)) };
- (|) => { tt2ts!(Op::new('|', Spacing::Alone)) };
+ (,) => { tt2ts!(Punct::new(',', Spacing::Alone)) };
+ (.) => { tt2ts!(Punct::new('.', Spacing::Alone)) };
+ (:) => { tt2ts!(Punct::new(':', Spacing::Alone)) };
+ (|) => { tt2ts!(Punct::new('|', Spacing::Alone)) };
(::) => {
[
- TokenTree::from(Op::new(':', Spacing::Joint)),
- TokenTree::from(Op::new(':', Spacing::Alone)),
+ TokenTree::from(Punct::new(':', Spacing::Joint)),
+ TokenTree::from(Punct::new(':', Spacing::Alone)),
].iter()
.cloned()
.map(|mut x| {
})
.collect::<TokenStream>()
};
- (!) => { tt2ts!(Op::new('!', Spacing::Alone)) };
- (<) => { tt2ts!(Op::new('<', Spacing::Alone)) };
- (>) => { tt2ts!(Op::new('>', Spacing::Alone)) };
- (_) => { tt2ts!(Op::new('_', Spacing::Alone)) };
+ (!) => { tt2ts!(Punct::new('!', Spacing::Alone)) };
+ (<) => { tt2ts!(Punct::new('<', Spacing::Alone)) };
+ (>) => { tt2ts!(Punct::new('>', Spacing::Alone)) };
+ (_) => { tt2ts!(Punct::new('_', Spacing::Alone)) };
(0) => { tt2ts!(Literal::i8_unsuffixed(0)) };
- (&) => { tt2ts!(Op::new('&', Spacing::Alone)) };
- ($i:ident) => { tt2ts!(Term::new(stringify!($i), Span::def_site())) };
+ (&) => { tt2ts!(Punct::new('&', Spacing::Alone)) };
+ ($i:ident) => { tt2ts!(Ident::new(stringify!($i), Span::def_site())) };
}
macro_rules! quote_tree {
if after_dollar {
after_dollar = false;
match tree {
- TokenTree::Term(_) => {
+ TokenTree::Ident(_) => {
let tree = TokenStream::from(tree);
return Some(quote!(::__internal::unquote(&(unquote tree)),));
}
- TokenTree::Op(ref tt) if tt.op() == '$' => {}
+ TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
_ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
}
- } else if let TokenTree::Op(tt) = tree {
- if tt.op() == '$' {
+ } else if let TokenTree::Punct(ref tt) = tree {
+ if tt.as_char() == '$' {
after_dollar = true;
return None;
}
impl Quote for TokenTree {
fn quote(self) -> TokenStream {
match self {
- TokenTree::Op(tt) => quote!(::TokenTree::Op( (quote tt) )),
+ TokenTree::Punct(tt) => quote!(::TokenTree::Punct( (quote tt) )),
TokenTree::Group(tt) => quote!(::TokenTree::Group( (quote tt) )),
- TokenTree::Term(tt) => quote!(::TokenTree::Term( (quote tt) )),
+ TokenTree::Ident(tt) => quote!(::TokenTree::Ident( (quote tt) )),
TokenTree::Literal(tt) => quote!(::TokenTree::Literal( (quote tt) )),
}
}
}
}
-impl Quote for Op {
+impl Quote for Punct {
fn quote(self) -> TokenStream {
- quote!(::Op::new((quote self.op()), (quote self.spacing())))
+ quote!(::Punct::new((quote self.as_char()), (quote self.spacing())))
}
}
-impl Quote for Term {
+impl Quote for Ident {
fn quote(self) -> TokenStream {
- quote!(::Term::new((quote self.sym.as_str()), (quote self.span())))
+ quote!(::Ident::new((quote self.sym.as_str()), (quote self.span())))
}
}
macro_rules! literals {
($($i:ident),*; $($raw:ident),*) => {
+ pub struct SpannedSymbol {
+ sym: Symbol,
+ span: Span,
+ }
+
+ impl SpannedSymbol {
+ pub fn new(string: &str, span: Span) -> SpannedSymbol {
+ SpannedSymbol { sym: Symbol::intern(string), span }
+ }
+ }
+
+ impl Quote for SpannedSymbol {
+ fn quote(self) -> TokenStream {
+ quote!(::__internal::SpannedSymbol::new((quote self.sym.as_str()),
+ (quote self.span)))
+ }
+ }
+
pub enum LiteralKind {
$($i,)*
$($raw(u16),)*
}
impl LiteralKind {
- pub fn with_contents_and_suffix(self, contents: Term, suffix: Option<Term>)
- -> Literal {
+ pub fn with_contents_and_suffix(self, contents: SpannedSymbol,
+ suffix: Option<SpannedSymbol>) -> Literal {
let sym = contents.sym;
let suffix = suffix.map(|t| t.sym);
match self {
}
impl Literal {
- fn kind_contents_and_suffix(self) -> (LiteralKind, Term, Option<Term>) {
+ fn kind_contents_and_suffix(self) -> (LiteralKind, SpannedSymbol, Option<SpannedSymbol>)
+ {
let (kind, contents) = match self.lit {
$(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
$(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
};
- let suffix = self.suffix.map(|sym| Term::new(&sym.as_str(), self.span()));
- (kind, Term::new(&contents.as_str(), self.span()), suffix)
+ let suffix = self.suffix.map(|sym| SpannedSymbol::new(&sym.as_str(), self.span()));
+ (kind, SpannedSymbol::new(&contents.as_str(), self.span()), suffix)
}
}
scope_cf_kind: ScopeCfKind) -> (region::Scope, CFGIndex) {
match destination.target_id {
- hir::ScopeTarget::Block(block_expr_id) => {
+ Ok(loop_id) => {
for b in &self.breakable_block_scopes {
- if b.block_expr_id == self.tcx.hir.node_to_hir_id(block_expr_id).local_id {
- let scope_id = self.tcx.hir.node_to_hir_id(block_expr_id).local_id;
+ if b.block_expr_id == self.tcx.hir.node_to_hir_id(loop_id).local_id {
+ let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id;
return (region::Scope::Node(scope_id), match scope_cf_kind {
ScopeCfKind::Break => b.break_index,
ScopeCfKind::Continue => bug!("can't continue to block"),
});
}
}
- span_bug!(expr.span, "no block expr for id {}", block_expr_id);
- }
- hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => {
for l in &self.loop_scopes {
if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id {
let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id;
});
}
}
- span_bug!(expr.span, "no loop scope for id {}", loop_id);
+ span_bug!(expr.span, "no scope for id {}", loop_id);
}
- hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
- span_bug!(expr.span, "loop scope error: {}", err),
+ Err(err) => span_bug!(expr.span, "scope error: {}", err),
}
}
}
if let Some(ref label) = destination.label {
visitor.visit_label(label);
match destination.target_id {
- ScopeTarget::Block(node_id) |
- ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
- visitor.visit_def_mention(Def::Label(node_id)),
- ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
+ Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)),
+ Err(_) => {},
};
}
walk_list!(visitor, visit_expr, opt_expr);
if let Some(ref label) = destination.label {
visitor.visit_label(label);
match destination.target_id {
- ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
- ScopeTarget::Loop(LoopIdResult::Ok(node_id)) =>
- visitor.visit_def_mention(Def::Label(node_id)),
- ScopeTarget::Loop(LoopIdResult::Err(_)) => {},
+ Ok(node_id) => visitor.visit_def_mention(Def::Label(node_id)),
+ Err(_) => {},
};
}
}
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
match destination {
Some((id, label)) => {
- let target = if let Def::Label(loop_id) = self.expect_full_def(id) {
- hir::LoopIdResult::Ok(self.lower_node_id(loop_id).node_id)
+ let target_id = if let Def::Label(loop_id) = self.expect_full_def(id) {
+ Ok(self.lower_node_id(loop_id).node_id)
} else {
- hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
+ Err(hir::LoopIdError::UnresolvedLabel)
};
hir::Destination {
label: self.lower_label(Some(label)),
- target_id: hir::ScopeTarget::Loop(target),
+ target_id,
}
}
None => {
- let loop_id = self.loop_scopes
+ let target_id = self.loop_scopes
.last()
- .map(|innermost_loop_id| *innermost_loop_id);
+ .map(|innermost_loop_id| *innermost_loop_id)
+ .map(|id| Ok(self.lower_node_id(id).node_id))
+ .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
+ .into();
hir::Destination {
label: None,
- target_id: hir::ScopeTarget::Loop(
- loop_id
- .map(|id| Ok(self.lower_node_id(id).node_id))
- .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
- .into(),
- ),
+ target_id,
}
}
}
let destination = if self.is_in_loop_condition && opt_label.is_none() {
hir::Destination {
label: None,
- target_id: hir::ScopeTarget::Loop(
- Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
- ),
+ target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
}
} else {
self.lower_loop_destination(opt_label.map(|label| (e.id, label)))
hir::ExprAgain(if self.is_in_loop_condition && opt_label.is_none() {
hir::Destination {
label: None,
- target_id: hir::ScopeTarget::Loop(
- Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
- ),
+ target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
}
} else {
self.lower_loop_destination(opt_label.map(|label| (e.id, label)))
hir::ExprBreak(
hir::Destination {
label: None,
- target_id: hir::ScopeTarget::Block(catch_node),
+ target_id: Ok(catch_node),
},
Some(from_err_expr),
),
}
}
-// FIXME(cramertj) this should use `Result` once master compiles w/ a vesion of Rust where
-// `Result` implements `Encodable`/`Decodable`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum LoopIdResult {
- Ok(NodeId),
- Err(LoopIdError),
-}
-impl Into<Result<NodeId, LoopIdError>> for LoopIdResult {
- fn into(self) -> Result<NodeId, LoopIdError> {
- match self {
- LoopIdResult::Ok(ok) => Ok(ok),
- LoopIdResult::Err(err) => Err(err),
- }
- }
-}
-impl From<Result<NodeId, LoopIdError>> for LoopIdResult {
- fn from(res: Result<NodeId, LoopIdError>) -> Self {
- match res {
- Ok(ok) => LoopIdResult::Ok(ok),
- Err(err) => LoopIdResult::Err(err),
- }
- }
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum ScopeTarget {
- Block(NodeId),
- Loop(LoopIdResult),
-}
-
-impl ScopeTarget {
- pub fn opt_id(self) -> Option<NodeId> {
- match self {
- ScopeTarget::Block(node_id) |
- ScopeTarget::Loop(LoopIdResult::Ok(node_id)) => Some(node_id),
- ScopeTarget::Loop(LoopIdResult::Err(_)) => None,
- }
- }
-}
-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub struct Destination {
// This is `Some(_)` iff there is an explicit user-specified `label
// These errors are caught and then reported during the diagnostics pass in
// librustc_passes/loops.rs
- pub target_id: ScopeTarget,
+ pub target_id: Result<NodeId, LoopIdError>,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
impl_stable_hash_for_spanned!(ast::Ident);
-impl_stable_hash_for!(enum hir::LoopIdResult {
- Ok(node_id),
- Err(loop_id_error)
-});
-
impl_stable_hash_for!(enum hir::LoopIdError {
OutsideLoopScope,
UnlabeledCfInWhileCondition,
UnresolvedLabel
});
-impl_stable_hash_for!(enum hir::ScopeTarget {
- Block(node_id),
- Loop(loop_id_result)
-});
-
impl<'a> HashStable<StableHashingContext<'a>> for ast::Ident {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
token::Token::Pound |
token::Token::Dollar |
token::Token::Question |
+ token::Token::SingleQuote |
token::Token::Whitespace |
token::Token::Comment |
token::Token::Eof => {}
// it probably doesn't now)
break_ln: NodeMap<LiveNode>,
cont_ln: NodeMap<LiveNode>,
-
- // mappings from node ID to LiveNode for "breakable" blocks-- currently only `catch {...}`
- breakable_block_ln: NodeMap<LiveNode>,
}
impl<'a, 'tcx> Liveness<'a, 'tcx> {
users: vec![invalid_users(); num_live_nodes * num_vars],
break_ln: NodeMap(),
cont_ln: NodeMap(),
- breakable_block_ln: NodeMap(),
}
}
fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
-> LiveNode {
if blk.targeted_by_break {
- self.breakable_block_ln.insert(blk.id, succ);
+ self.break_ln.insert(blk.id, succ);
}
let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
blk.stmts.iter().rev().fold(succ, |succ, stmt| {
hir::ExprBreak(label, ref opt_expr) => {
// Find which label this break jumps to
let target = match label.target_id {
- hir::ScopeTarget::Block(node_id) =>
- self.breakable_block_ln.get(&node_id),
- hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) =>
- self.break_ln.get(&node_id),
- hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
- span_bug!(expr.span, "loop scope error: {}", err),
+ Ok(node_id) => self.break_ln.get(&node_id),
+ Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
}.map(|x| *x);
// Now that we know the label we're going to,
hir::ExprAgain(label) => {
// Find which label this expr continues to
let sc = match label.target_id {
- hir::ScopeTarget::Block(_) => bug!("can't `continue` to a non-loop block"),
- hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(node_id)) => node_id,
- hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
- span_bug!(expr.span, "loop scope error: {}", err),
+ Ok(node_id) => node_id,
+ Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
};
// Now that we know the label we're going to,
}
ObligationCauseCode::ReturnType(_) |
ObligationCauseCode::BlockTailExpression(_) => (),
+ ObligationCauseCode::TrivialBound => {
+ err.help("see issue #48214");
+ if tcx.sess.opts.unstable_features.is_nightly_build() {
+ err.help("add #![feature(trivial_bounds)] to the \
+ crate attributes to enable",
+ );
+ }
+ }
}
}
ty::Predicate::Trait(ref data) => {
let trait_obligation = obligation.with(data.clone());
- if data.is_global() {
+ if data.is_global() && !data.has_late_bound_regions() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if selcx.infcx().predicate_must_hold(&obligation) {
/// Block implicit return
BlockTailExpression(ast::NodeId),
+
+ /// #[feature(trivial_bounds)] is not enabled
+ TrivialBound,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
let predicates: Vec<_> =
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
- .filter(|p| !p.is_global()) // (*)
.collect();
- // (*) Any predicate like `i32: Trait<u32>` or whatever doesn't
- // need to be in the *environment* to be proven, so screen those
- // out. This is important for the soundness of inter-fn
- // caching. Note though that we should probably check that these
- // predicates hold at the point where the environment is
- // constructed, but I am not currently doing so out of laziness.
- // -nmatsakis
-
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
predicates);
/// There is no built-in impl. There may be some other
/// candidate (a where-clause or user-defined impl).
None,
- /// There is *no* impl for this, builtin or not. Ignore
- /// all where-clauses.
- Never,
/// It is unknown whether there is an impl.
Ambiguous
}
mut obligation: TraitObligation<'tcx>)
-> Result<EvaluationResult, OverflowError>
{
- debug!("evaluate_trait_predicate_recursively({:?})",
- obligation);
+ debug!("evaluate_trait_predicate_recursively({:?})", obligation);
- if !self.intercrate.is_some() && obligation.is_global() {
- // If a param env is consistent, global obligations do not depend on its particular
- // value in order to work, so we can clear out the param env and get better
- // caching. (If the current param env is inconsistent, we don't care what happens).
+ if self.intercrate.is_none() && obligation.is_global()
+ && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst()) {
+ // If a param env has no global bounds, global obligations do not
+ // depend on its particular value in order to work, so we can clear
+ // out the param env and get better caching.
debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation);
obligation.param_env = obligation.param_env.without_caller_bounds();
}
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions,
&mut candidates)?;
- } else if lang_items.unsize_trait() == Some(def_id) {
- self.assemble_candidates_for_unsizing(obligation, &mut candidates);
- } else {
- if lang_items.clone_trait() == Some(def_id) {
- // Same builtin conditions as `Copy`, i.e. every type which has builtin support
- // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
- // types have builtin support for `Clone`.
- let clone_conditions = self.copy_clone_conditions(obligation);
- self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
- }
-
- self.assemble_generator_candidates(obligation, &mut candidates)?;
- self.assemble_closure_candidates(obligation, &mut candidates)?;
- self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
- self.assemble_candidates_from_impls(obligation, &mut candidates)?;
- self.assemble_candidates_from_object_ty(obligation, &mut candidates);
+ } else if lang_items.unsize_trait() == Some(def_id) {
+ self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+ } else {
+ if lang_items.clone_trait() == Some(def_id) {
+ // Same builtin conditions as `Copy`, i.e. every type which has builtin support
+ // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
+ // types have builtin support for `Clone`.
+ let clone_conditions = self.copy_clone_conditions(obligation);
+ self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
+ }
+
+ self.assemble_generator_candidates(obligation, &mut candidates)?;
+ self.assemble_closure_candidates(obligation, &mut candidates)?;
+ self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
+ self.assemble_candidates_from_impls(obligation, &mut candidates)?;
+ self.assemble_candidates_from_object_ty(obligation, &mut candidates);
}
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
// BUILTIN BOUNDS
//
// These cover the traits that are built-in to the language
- // itself. This includes `Copy` and `Sized` for sure. For the
- // moment, it also includes `Send` / `Sync` and a few others, but
- // those will hopefully change to library-defined traits in the
- // future.
+ // itself: `Copy`, `Clone` and `Sized`.
- // HACK: if this returns an error, selection exits without considering
- // other impls.
fn assemble_builtin_bound_candidates<'o>(&mut self,
conditions: BuiltinImplConditions<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>)
debug!("assemble_builtin_bound_candidates: ambiguous builtin");
Ok(candidates.ambiguous = true)
}
- BuiltinImplConditions::Never => { Err(Unimplemented) }
}
}
fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
-> BuiltinImplConditions<'tcx>
{
- use self::BuiltinImplConditions::{Ambiguous, None, Never, Where};
+ use self::BuiltinImplConditions::{Ambiguous, None, Where};
// NOTE: binder moved to (*)
let self_ty = self.infcx.shallow_resolve(
Where(ty::Binder::dummy(Vec::new()))
}
- ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
+ ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => None,
ty::TyTuple(tys) => {
Where(ty::Binder::bind(tys.last().into_iter().cloned().collect()))
let self_ty = self.infcx.shallow_resolve(
obligation.predicate.skip_binder().self_ty());
- use self::BuiltinImplConditions::{Ambiguous, None, Never, Where};
+ use self::BuiltinImplConditions::{Ambiguous, None, Where};
match self_ty.sty {
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
ty::TyGenerator(..) | ty::TyGeneratorWitness(..) | ty::TyForeign(..) |
ty::TyRef(_, _, hir::MutMutable) => {
- Never
+ None
}
ty::TyArray(element_ty, _) => {
if is_copy_trait || is_clone_trait {
Where(ty::Binder::bind(substs.upvar_tys(def_id, self.tcx()).collect()))
} else {
- Never
+ None
}
}
super::IntrinsicType => Some(super::IntrinsicType),
super::MethodReceiver => Some(super::MethodReceiver),
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
+ super::TrivialBound => Some(super::TrivialBound),
}
}
}
}
&ty::TyParam(ref p) => {
- self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+ self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
if p.is_self() {
self.add_flags(TypeFlags::HAS_SELF);
} else {
&ty::TyGenerator(_, ref substs, _) => {
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
- self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+ self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
self.add_substs(&substs.substs);
}
&ty::TyClosure(_, ref substs) => {
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
- self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
+ self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
self.add_substs(&substs.substs);
}
&ty::TyInfer(infer) => {
- self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right?
+ self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
self.add_flags(TypeFlags::HAS_TY_INFER);
match infer {
ty::FreshTy(_) |
/// Indicates whether this value references only 'global'
/// types/lifetimes that are the same regardless of what fn we are
- /// in. This is used for caching. Errs on the side of returning
- /// false.
+ /// in. This is used for caching.
fn is_global(&self) -> bool {
- !self.has_type_flags(TypeFlags::HAS_LOCAL_NAMES)
+ !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
+ }
+
+ /// True if there are any late-bound regions
+ fn has_late_bound_regions(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
}
}
// true if there are "names" of types and regions and so forth
// that are local to a particular fn
- const HAS_LOCAL_NAMES = 1 << 10;
+ const HAS_FREE_LOCAL_NAMES = 1 << 10;
// Present if the type belongs in a local type context.
// Only set for TyInfer other than Fresh.
// ought to be true only for the results of canonicalization.
const HAS_CANONICAL_VARS = 1 << 13;
+ /// Does this have any `ReLateBound` regions? Used to check
+ /// if a global bound is safe to evaluate.
+ const HAS_RE_LATE_BOUND = 1 << 14;
+
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits;
TypeFlags::HAS_TY_ERR.bits |
TypeFlags::HAS_PROJECTION.bits |
TypeFlags::HAS_TY_CLOSURE.bits |
- TypeFlags::HAS_LOCAL_NAMES.bits |
+ TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
TypeFlags::KEEP_IN_LOCAL_TCX.bits |
- TypeFlags::HAS_CANONICAL_VARS.bits;
+ TypeFlags::HAS_CANONICAL_VARS.bits |
+ TypeFlags::HAS_RE_LATE_BOUND.bits;
}
}
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_RE_SKOL;
}
- ty::ReLateBound(..) => { }
+ ty::ReLateBound(..) => {
+ flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
+ }
ty::ReEarlyBound(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_RE_EARLY_BOUND;
}
match *self {
- ty::ReStatic | ty::ReEmpty | ty::ReErased => (),
- _ => flags = flags | TypeFlags::HAS_LOCAL_NAMES,
+ ty::ReStatic | ty::ReEmpty | ty::ReErased | ty::ReLateBound(..) => (),
+ _ => flags = flags | TypeFlags::HAS_FREE_LOCAL_NAMES,
}
debug!("type_flags({:?}) = {:?}", self, flags);
self.0 += 1;
}
}
+
+/// Lint for trait and lifetime bounds that don't depend on type parameters
+/// which either do nothing, or stop the item from being used.
+pub struct TrivialConstraints;
+
+declare_lint! {
+ TRIVIAL_BOUNDS,
+ Warn,
+ "these bounds don't depend on an type parameters"
+}
+
+impl LintPass for TrivialConstraints {
+ fn get_lints(&self) -> LintArray {
+ lint_array!(TRIVIAL_BOUNDS)
+ }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
+ fn check_item(
+ &mut self,
+ cx: &LateContext<'a, 'tcx>,
+ item: &'tcx hir::Item,
+ ) {
+ use rustc::ty::fold::TypeFoldable;
+ use rustc::ty::Predicate::*;
+
+
+ if cx.tcx.features().trivial_bounds {
+ let def_id = cx.tcx.hir.local_def_id(item.id);
+ let predicates = cx.tcx.predicates_of(def_id);
+ for predicate in &predicates.predicates {
+ let predicate_kind_name = match *predicate {
+ Trait(..) => "Trait",
+ TypeOutlives(..) |
+ RegionOutlives(..) => "Lifetime",
+
+ // Ignore projections, as they can only be global
+ // if the trait bound is global
+ Projection(..) |
+ // Ignore bounds that a user can't type
+ WellFormed(..) |
+ ObjectSafe(..) |
+ ClosureKind(..) |
+ Subtype(..) |
+ ConstEvaluatable(..) => continue,
+ };
+ if predicate.is_global() {
+ cx.span_lint(
+ TRIVIAL_BOUNDS,
+ item.span,
+ &format!("{} bound {} does not depend on any type \
+ or lifetime parameters", predicate_kind_name, predicate),
+ );
+ }
+ }
+ }
+ }
+}
UnreachablePub,
TypeAliasBounds,
UnusedBrokenConst,
+ TrivialConstraints,
);
add_builtin_with_new!(sess,
hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
hir::ExprBreak(dest, ref value) => {
match dest.target_id {
- hir::ScopeTarget::Block(target_id) |
- hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break {
+ Ok(target_id) => ExprKind::Break {
label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(target_id).local_id),
value: value.to_ref(),
},
- hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
- bug!("invalid loop id for break: {}", err)
+ Err(err) => bug!("invalid loop id for break: {}", err)
}
}
hir::ExprAgain(dest) => {
match dest.target_id {
- hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"),
- hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue {
+ Ok(loop_id) => ExprKind::Continue {
label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id),
},
- hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) =>
- bug!("invalid loop id for continue: {}", err)
+ Err(err) => bug!("invalid loop id for continue: {}", err)
}
}
hir::ExprMatch(ref discr, ref arms, _) => {
self.with_context(Closure, |v| v.visit_nested_body(b));
}
hir::ExprBreak(label, ref opt_expr) => {
- let loop_id = match label.target_id {
- hir::ScopeTarget::Block(_) => return,
- hir::ScopeTarget::Loop(loop_res) => {
- match loop_res.into() {
- Ok(loop_id) => loop_id,
- Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
- Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
- self.emit_unlabled_cf_in_while_condition(e.span, "break");
- ast::DUMMY_NODE_ID
- },
- Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
- }
- }
+ let loop_id = match label.target_id.into() {
+ Ok(loop_id) => loop_id,
+ Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
+ Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
+ self.emit_unlabled_cf_in_while_condition(e.span, "break");
+ ast::DUMMY_NODE_ID
+ },
+ Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
};
+ if loop_id != ast::DUMMY_NODE_ID {
+ match self.hir_map.find(loop_id).unwrap() {
+ hir::map::NodeBlock(_) => return,
+ _=> (),
+ }
+ }
if opt_expr.is_some() {
let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
self.require_loop("break", e.span);
}
hir::ExprAgain(label) => {
- if let hir::ScopeTarget::Loop(
- hir::LoopIdResult::Err(
- hir::LoopIdError::UnlabeledCfInWhileCondition)) = label.target_id {
+ if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.target_id {
self.emit_unlabled_cf_in_while_condition(e.span, "continue");
}
self.require_loop("continue", e.span)
let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
- let ret_ty = fn_sig.output();
- fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType);
- let ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty);
- fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
+ let declared_ret_ty = fn_sig.output();
+ fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+ let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &declared_ret_ty);
+ fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
fn_sig = fcx.tcx.mk_fn_sig(
fn_sig.inputs().iter().cloned(),
- ret_ty,
+ revealed_ret_ty,
fn_sig.variadic,
fn_sig.unsafety,
fn_sig.abi
actual_return_ty = fcx.next_diverging_ty_var(
TypeVariableOrigin::DivergingFn(span));
}
- fcx.demand_suptype(span, ret_ty, actual_return_ty);
+ fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
if id == fn_id {
match entry_type {
config::EntryMain => {
- let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+ let substs = fcx.tcx.mk_substs(iter::once(Kind::from(declared_ret_ty)));
let trait_ref = ty::TraitRef::new(term_id, substs);
let return_ty_span = decl.output.span();
let cause = traits::ObligationCause::new(
tcx.mk_nil()
}
hir::ExprBreak(destination, ref expr_opt) => {
- if let Some(target_id) = destination.target_id.opt_id() {
+ if let Ok(target_id) = destination.target_id {
let (e_ty, cause);
if let Some(ref e) = *expr_opt {
// If this is a break with a value, we need to type-check
let param_env = self.param_env;
self.inherited.enter(|inh| {
let fcx = FnCtxt::new(&inh, param_env, id);
+ if !inh.tcx.features().trivial_bounds {
+ // As predicates are cached rather than obligations, this
+ // needsto be called first so that they are checked with an
+ // empty param_env.
+ check_false_global_bounds(&fcx, span, id);
+ }
let wf_tys = f(&fcx, fcx.tcx.global_tcx());
fcx.select_all_obligations_or_error();
fcx.regionck_item(id, span, &wf_tys);
}
}
+/// Feature gates RFC 2056 - trivial bounds, checking for global bounds that
+/// aren't true.
+fn check_false_global_bounds<'a, 'gcx, 'tcx>(
+ fcx: &FnCtxt<'a, 'gcx, 'tcx>,
+ span: Span,
+ id: ast::NodeId,
+) {
+ use rustc::ty::TypeFoldable;
+
+ let empty_env = ty::ParamEnv::empty();
+
+ let def_id = fcx.tcx.hir.local_def_id(id);
+ let predicates = fcx.tcx.predicates_of(def_id).predicates;
+ // Check elaborated bounds
+ let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
+
+ for pred in implied_obligations {
+ // Match the existing behavior.
+ if pred.is_global() && !pred.has_late_bound_regions() {
+ let obligation = traits::Obligation::new(
+ traits::ObligationCause::new(
+ span,
+ id,
+ traits::TrivialBound,
+ ),
+ empty_env,
+ pred,
+ );
+ fcx.register_predicate(obligation);
+ }
+ }
+
+ fcx.select_all_obligations_or_error();
+}
+
pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
}
+/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
+///
+/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one
+/// will be created for the handler.
+pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::CodeMap>>)
+ -> errors::Handler
+{
+ // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
+ // stick to the defaults
+ let sessopts = config::basic_options();
+ let emitter: Box<dyn Emitter + sync::Send> = match error_format {
+ ErrorOutputType::HumanReadable(color_config) => Box::new(
+ EmitterWriter::stderr(
+ color_config,
+ codemap.map(|cm| cm as _),
+ false,
+ sessopts.debugging_opts.teach,
+ ).ui_testing(sessopts.debugging_opts.ui_testing)
+ ),
+ ErrorOutputType::Json(pretty) => {
+ let codemap = codemap.unwrap_or_else(
+ || Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())));
+ Box::new(
+ JsonEmitter::stderr(
+ None,
+ codemap,
+ pretty,
+ sessopts.debugging_opts.suggestion_applicability,
+ ).ui_testing(sessopts.debugging_opts.ui_testing)
+ )
+ },
+ ErrorOutputType::Short(color_config) => Box::new(
+ EmitterWriter::stderr(
+ color_config,
+ codemap.map(|cm| cm as _),
+ true,
+ false)
+ ),
+ };
+
+ errors::Handler::with_emitter_and_flags(
+ emitter,
+ errors::HandlerFlags {
+ can_emit_warnings: true,
+ treat_err_as_bug: false,
+ external_macro_backtrace: false,
+ ..Default::default()
+ },
+ )
+}
+
pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
externs: config::Externs,
},
error_format,
edition,
- ..config::basic_options().clone()
+ ..config::basic_options()
};
driver::spawn_thread_pool(sessopts, move |sessopts| {
let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
- let emitter: Box<dyn Emitter + sync::Send> = match error_format {
- ErrorOutputType::HumanReadable(color_config) => Box::new(
- EmitterWriter::stderr(
- color_config,
- Some(codemap.clone()),
- false,
- sessopts.debugging_opts.teach,
- ).ui_testing(sessopts.debugging_opts.ui_testing)
- ),
- ErrorOutputType::Json(pretty) => Box::new(
- JsonEmitter::stderr(
- None,
- codemap.clone(),
- pretty,
- sessopts.debugging_opts.suggestion_applicability,
- ).ui_testing(sessopts.debugging_opts.ui_testing)
- ),
- ErrorOutputType::Short(color_config) => Box::new(
- EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
- ),
- };
-
- let diagnostic_handler = errors::Handler::with_emitter_and_flags(
- emitter,
- errors::HandlerFlags {
- can_emit_warnings: true,
- treat_err_as_bug: false,
- external_macro_backtrace: false,
- ..Default::default()
- },
- );
+ let diagnostic_handler = new_handler(error_format, Some(codemap.clone()));
let mut sess = session::build_session_(
sessopts, cpath, diagnostic_handler, codemap,
use std::fs;
use std::path::Path;
use std::str;
+use errors;
use html::markdown::Markdown;
#[derive(Clone)]
impl ExternalHtml {
pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
- md_before_content: &[String], md_after_content: &[String])
+ md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler)
-> Option<ExternalHtml> {
- load_external_files(in_header)
+ load_external_files(in_header, diag)
.and_then(|ih|
- load_external_files(before_content)
+ load_external_files(before_content, diag)
.map(|bc| (ih, bc))
)
.and_then(|(ih, bc)|
- load_external_files(md_before_content)
+ load_external_files(md_before_content, diag)
.map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[]))))
)
.and_then(|(ih, bc)|
- load_external_files(after_content)
+ load_external_files(after_content, diag)
.map(|ac| (ih, bc, ac))
)
.and_then(|(ih, bc, ac)|
- load_external_files(md_after_content)
+ load_external_files(md_after_content, diag)
.map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[]))))
)
.map(|(ih, bc, ac)|
BadUtf8,
}
-pub fn load_string<P: AsRef<Path>>(file_path: P) -> Result<String, LoadStringError> {
+pub fn load_string<P: AsRef<Path>>(file_path: P, diag: &errors::Handler)
+ -> Result<String, LoadStringError>
+{
let file_path = file_path.as_ref();
let contents = match fs::read(file_path) {
Ok(bytes) => bytes,
Err(e) => {
- eprintln!("error reading `{}`: {}", file_path.display(), e);
+ diag.struct_err(&format!("error reading `{}`: {}", file_path.display(), e)).emit();
return Err(LoadStringError::ReadFail);
}
};
match str::from_utf8(&contents) {
Ok(s) => Ok(s.to_string()),
Err(_) => {
- eprintln!("error reading `{}`: not UTF-8", file_path.display());
+ diag.struct_err(&format!("error reading `{}`: not UTF-8", file_path.display())).emit();
Err(LoadStringError::BadUtf8)
}
}
}
-fn load_external_files(names: &[String]) -> Option<String> {
+fn load_external_files(names: &[String], diag: &errors::Handler) -> Option<String> {
let mut out = String::new();
for name in names {
- let s = match load_string(name) {
+ let s = match load_string(name, diag) {
Ok(s) => s,
Err(_) => return None,
};
token::Lifetime(..) => Class::Lifetime,
token::Eof | token::Interpolated(..) |
- token::Tilde | token::At | token::DotEq => Class::None,
+ token::Tilde | token::At | token::DotEq | token::SingleQuote => Class::None,
};
// Anything that didn't return above is the simple case where we the
use std::collections::{BTreeMap, BTreeSet};
use std::default::Default;
use std::env;
-use std::fmt::Display;
-use std::io;
-use std::io::Write;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::mpsc::channel;
use syntax::edition::Edition;
use externalfiles::ExternalHtml;
+use rustc::session::{early_warn, early_error};
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{ErrorOutputType, RustcOptGroup, Externs, CodegenOptions};
use rustc::session::config::{nightly_options, build_codegen_options};
fn get_args() -> Option<Vec<String>> {
env::args_os().enumerate()
.map(|(i, arg)| arg.into_string().map_err(|arg| {
- print_error(format!("Argument {} is not valid Unicode: {:?}", i, arg));
+ early_warn(ErrorOutputType::default(),
+ &format!("Argument {} is not valid Unicode: {:?}", i, arg));
}).ok())
.collect()
}
let matches = match options.parse(&args[1..]) {
Ok(m) => m,
Err(err) => {
- print_error(err);
- return 1;
+ early_error(ErrorOutputType::default(), &err.to_string());
}
};
// Check for unstable options.
nightly_options::check_nightly_options(&matches, &opts());
- // check for deprecated options
- check_deprecated_options(&matches);
-
if matches.opt_present("h") || matches.opt_present("help") {
usage("rustdoc");
return 0;
return 0;
}
+ let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
+ Some("auto") => ColorConfig::Auto,
+ Some("always") => ColorConfig::Always,
+ Some("never") => ColorConfig::Never,
+ None => ColorConfig::Auto,
+ Some(arg) => {
+ early_error(ErrorOutputType::default(),
+ &format!("argument for --color must be `auto`, `always` or `never` \
+ (instead was `{}`)", arg));
+ }
+ };
+ let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
+ Some("human") => ErrorOutputType::HumanReadable(color),
+ Some("json") => ErrorOutputType::Json(false),
+ Some("pretty-json") => ErrorOutputType::Json(true),
+ Some("short") => ErrorOutputType::Short(color),
+ None => ErrorOutputType::HumanReadable(color),
+ Some(arg) => {
+ early_error(ErrorOutputType::default(),
+ &format!("argument for --error-format must be `human`, `json` or \
+ `short` (instead was `{}`)", arg));
+ }
+ };
+
+ let diag = core::new_handler(error_format, None);
+
+ // check for deprecated options
+ check_deprecated_options(&matches, &diag);
+
let to_check = matches.opt_strs("theme-checker");
if !to_check.is_empty() {
let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css"));
println!("rustdoc: [theme-checker] Starting tests!");
for theme_file in to_check.iter() {
print!(" - Checking \"{}\"...", theme_file);
- let (success, differences) = theme::test_theme_against(theme_file, &paths);
+ let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag);
if !differences.is_empty() || !success {
println!(" FAILED");
errors += 1;
}
if matches.free.is_empty() {
- print_error("missing file operand");
+ diag.struct_err("missing file operand").emit();
return 1;
}
if matches.free.len() > 1 {
- print_error("too many file operands");
+ diag.struct_err("too many file operands").emit();
return 1;
}
let input = &matches.free[0];
- let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
- Some("auto") => ColorConfig::Auto,
- Some("always") => ColorConfig::Always,
- Some("never") => ColorConfig::Never,
- None => ColorConfig::Auto,
- Some(arg) => {
- print_error(&format!("argument for --color must be `auto`, `always` or `never` \
- (instead was `{}`)", arg));
- return 1;
- }
- };
- let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
- Some("human") => ErrorOutputType::HumanReadable(color),
- Some("json") => ErrorOutputType::Json(false),
- Some("pretty-json") => ErrorOutputType::Json(true),
- Some("short") => ErrorOutputType::Short(color),
- None => ErrorOutputType::HumanReadable(color),
- Some(arg) => {
- print_error(&format!("argument for --error-format must be `human`, `json` or \
- `short` (instead was `{}`)", arg));
- return 1;
- }
- };
-
let mut libs = SearchPaths::new();
for s in &matches.opt_strs("L") {
libs.add_path(s, error_format);
let externs = match parse_externs(&matches) {
Ok(ex) => ex,
Err(err) => {
- print_error(err);
+ diag.struct_err(&err.to_string()).emit();
return 1;
}
};
if let Some(ref p) = css_file_extension {
if !p.is_file() {
- writeln!(
- &mut io::stderr(),
- "rustdoc: option --extend-css argument must be a file."
- ).unwrap();
+ diag.struct_err("option --extend-css argument must be a file").emit();
return 1;
}
}
.iter()
.map(|s| (PathBuf::from(&s), s.to_owned())) {
if !theme_file.is_file() {
- println!("rustdoc: option --themes arguments must all be files");
+ diag.struct_err("option --themes arguments must all be files").emit();
return 1;
}
- let (success, ret) = theme::test_theme_against(&theme_file, &paths);
+ let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
if !success || !ret.is_empty() {
- println!("rustdoc: invalid theme: \"{}\"", theme_s);
- println!(" Check what's wrong with the \"theme-checker\" option");
+ diag.struct_err(&format!("invalid theme: \"{}\"", theme_s))
+ .help("check what's wrong with the --theme-checker option")
+ .emit();
return 1;
}
themes.push(theme_file);
&matches.opt_strs("html-before-content"),
&matches.opt_strs("html-after-content"),
&matches.opt_strs("markdown-before-content"),
- &matches.opt_strs("markdown-after-content")) {
+ &matches.opt_strs("markdown-after-content"), &diag) {
Some(eh) => eh,
None => return 3,
};
let edition = match edition.parse() {
Ok(e) => e,
Err(_) => {
- print_error("could not parse edition");
+ diag.struct_err("could not parse edition").emit();
return 1;
}
};
match (should_test, markdown_input) {
(true, true) => {
return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot,
- display_warnings, linker, edition, cg)
+ display_warnings, linker, edition, cg, &diag)
}
(true, false) => {
return test::run(Path::new(input), cfgs, libs, externs, test_args, crate_name,
(false, true) => return markdown::render(Path::new(input),
output.unwrap_or(PathBuf::from("doc")),
&matches, &external_html,
- !matches.opt_present("markdown-no-toc")),
+ !matches.opt_present("markdown-no-toc"), &diag),
(false, false) => {}
}
let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format,
move |out| {
let Output { krate, passes, renderinfo } = out;
+ let diag = core::new_handler(error_format, None);
info!("going to format");
match output_format.as_ref().map(|s| &**s) {
Some("html") | None => {
0
}
Some(s) => {
- print_error(format!("unknown output format: {}", s));
+ diag.struct_err(&format!("unknown output format: {}", s)).emit();
1
}
}
});
res.unwrap_or_else(|s| {
- print_error(format!("input error: {}", s));
+ diag.struct_err(&format!("input error: {}", s)).emit();
1
})
}
-/// Prints an uniformized error message on the standard error output
-fn print_error<T>(error_message: T) where T: Display {
- writeln!(
- &mut io::stderr(),
- "rustdoc: {}\nTry 'rustdoc --help' for more information.",
- error_message
- ).unwrap();
-}
-
/// Looks inside the command line arguments to extract the relevant input format
/// and files and then generates the necessary rustdoc output for formatting.
fn acquire_input<R, F>(input: PathBuf,
krate.version = crate_version;
+ let diag = core::new_handler(error_format, None);
+
+ fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
+ let mut msg = diag.struct_warn(&format!("the `#![doc({})]` attribute is \
+ considered deprecated", name));
+ msg.warn("please see https://github.com/rust-lang/rust/issues/44136");
+
+ if name == "no_default_passes" {
+ msg.help("you may want to use `#![doc(document_private_items)]`");
+ }
+
+ msg.emit();
+ }
+
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
let name = name.as_ref().map(|s| &s[..]);
if attr.is_word() {
if name == Some("no_default_passes") {
+ report_deprecated_attr("no_default_passes", &diag);
default_passes = false;
}
} else if let Some(value) = attr.value_str() {
let sink = match name {
- Some("passes") => &mut passes,
- Some("plugins") => &mut plugins,
+ Some("passes") => {
+ report_deprecated_attr("passes = \"...\"", &diag);
+ &mut passes
+ },
+ Some("plugins") => {
+ report_deprecated_attr("plugins = \"...\"", &diag);
+ &mut plugins
+ },
_ => continue,
};
for p in value.as_str().split_whitespace() {
sink.push(p.to_string());
}
}
+
+ if attr.is_word() && name == Some("document_private_items") {
+ default_passes = false;
+
+ passes = vec![
+ String::from("collapse-docs"),
+ String::from("unindent-comments"),
+ ];
+ }
}
if default_passes {
}
/// Prints deprecation warnings for deprecated options
-fn check_deprecated_options(matches: &getopts::Matches) {
+fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
let deprecated_flags = [
"input-format",
"output-format",
for flag in deprecated_flags.into_iter() {
if matches.opt_present(flag) {
- eprintln!("WARNING: the '{}' flag is considered deprecated", flag);
- eprintln!("WARNING: please see https://github.com/rust-lang/rust/issues/44136");
- }
- }
+ let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated",
+ flag));
+ err.warn("please see https://github.com/rust-lang/rust/issues/44136");
+
+ if *flag == "no-defaults" {
+ err.help("you may want to use --document-private-items");
+ }
- if matches.opt_present("no-defaults") {
- eprintln!("WARNING: (you may want to use --document-private-items)");
+ err.emit();
+ }
}
}
use std::io::prelude::*;
use std::path::{PathBuf, Path};
+use errors;
use getopts;
use testing;
use rustc::session::search_paths::SearchPaths;
/// Render `input` (e.g. "foo.md") into an HTML file in `output`
/// (e.g. output = "bar" => "bar/foo.html").
pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
- external_html: &ExternalHtml, include_toc: bool) -> isize {
+ external_html: &ExternalHtml, include_toc: bool, diag: &errors::Handler) -> isize {
output.push(input.file_stem().unwrap());
output.set_extension("html");
css.push_str(&s)
}
- let input_str = match load_string(input) {
+ let input_str = match load_string(input, diag) {
Ok(s) => s,
Err(LoadStringError::ReadFail) => return 1,
Err(LoadStringError::BadUtf8) => return 2,
let mut out = match File::create(&output) {
Err(e) => {
- eprintln!("rustdoc: {}: {}", output.display(), e);
+ diag.struct_err(&format!("{}: {}", output.display(), e)).emit();
return 4;
}
Ok(f) => f
let (metadata, text) = extract_leading_metadata(&input_str);
if metadata.is_empty() {
- eprintln!("rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`");
+ diag.struct_err("invalid markdown file: no initial lines starting with `# ` or `%`").emit();
return 5;
}
let title = metadata[0];
match err {
Err(e) => {
- eprintln!("rustdoc: cannot write to `{}`: {}", output.display(), e);
+ diag.struct_err(&format!("cannot write to `{}`: {}", output.display(), e)).emit();
6
}
Ok(_) => 0,
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>,
display_warnings: bool, linker: Option<PathBuf>, edition: Edition,
- cg: CodegenOptions) -> isize {
- let input_str = match load_string(input) {
+ cg: CodegenOptions, diag: &errors::Handler) -> isize {
+ let input_str = match load_string(input, diag) {
Ok(s) => s,
Err(LoadStringError::ReadFail) => return 1,
Err(LoadStringError::BadUtf8) => return 2,
use std::io::Read;
use std::path::Path;
+use errors::Handler;
+
macro_rules! try_something {
- ($e:expr, $out:expr) => ({
+ ($e:expr, $diag:expr, $out:expr) => ({
match $e {
Ok(c) => c,
Err(e) => {
- eprintln!("rustdoc: got an error: {}", e);
+ $diag.struct_err(&e.to_string()).emit();
return $out;
}
}
}
}
-pub fn test_theme_against<P: AsRef<Path>>(f: &P, against: &CssPath) -> (bool, Vec<String>) {
- let mut file = try_something!(File::open(f), (false, Vec::new()));
+pub fn test_theme_against<P: AsRef<Path>>(f: &P, against: &CssPath, diag: &Handler)
+ -> (bool, Vec<String>)
+{
+ let mut file = try_something!(File::open(f), diag, (false, Vec::new()));
let mut data = Vec::with_capacity(1000);
- try_something!(file.read_to_end(&mut data), (false, Vec::new()));
+ try_something!(file.read_to_end(&mut data), diag, (false, Vec::new()));
let paths = load_css_paths(&data);
let mut ret = Vec::new();
get_differences(against, &paths, &mut ret);
}
}
+ #[cfg(target_os = "linux")]
+ pub fn get_cloexec(&self) -> io::Result<bool> {
+ unsafe {
+ Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0)
+ }
+ }
+
#[cfg(not(any(target_env = "newlib",
target_os = "solaris",
target_os = "emscripten",
// Currently the standard library supports Linux 2.6.18 which did not
// have the O_CLOEXEC flag (passed above). If we're running on an older
- // Linux kernel then the flag is just ignored by the OS, so we continue
- // to explicitly ask for a CLOEXEC fd here.
+ // Linux kernel then the flag is just ignored by the OS. After we open
+ // the first file, we check whether it has CLOEXEC set. If it doesn't,
+ // we will explicitly ask for a CLOEXEC fd for every further file we
+ // open, if it does, we will skip that step.
//
// The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc
// that we support, so we only do this on Linux currently.
- if cfg!(target_os = "linux") {
- fd.set_cloexec()?;
+ #[cfg(target_os = "linux")]
+ fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> {
+ use sync::atomic::{AtomicUsize, Ordering};
+
+ const OPEN_CLOEXEC_UNKNOWN: usize = 0;
+ const OPEN_CLOEXEC_SUPPORTED: usize = 1;
+ const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2;
+ static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN);
+
+ let need_to_set;
+ match OPEN_CLOEXEC.load(Ordering::Relaxed) {
+ OPEN_CLOEXEC_UNKNOWN => {
+ need_to_set = !fd.get_cloexec()?;
+ OPEN_CLOEXEC.store(if need_to_set {
+ OPEN_CLOEXEC_NOTSUPPORTED
+ } else {
+ OPEN_CLOEXEC_SUPPORTED
+ }, Ordering::Relaxed);
+ },
+ OPEN_CLOEXEC_SUPPORTED => need_to_set = false,
+ OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true,
+ _ => unreachable!(),
+ }
+ if need_to_set {
+ fd.set_cloexec()?;
+ }
+ Ok(())
+ }
+
+ #[cfg(not(target_os = "linux"))]
+ fn ensure_cloexec(_: &FileDesc) -> io::Result<()> {
+ Ok(())
}
+ ensure_cloexec(&fd)?;
Ok(File(fd))
}
// wait for either pipe to become readable using `poll`
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
- // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
- // EAGAIN. If we hit EOF, then this will happen because the underlying
- // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
- // this case we flip the other fd back into blocking mode and read
- // whatever's leftover on that file descriptor.
- let read = |fd: &FileDesc, dst: &mut Vec<u8>| {
- match fd.read_to_end(dst) {
- Ok(_) => Ok(true),
- Err(e) => {
- if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
- e.raw_os_error() == Some(libc::EAGAIN) {
- Ok(false)
- } else {
- Err(e)
- }
- }
- }
- };
if fds[0].revents != 0 && read(&p1, v1)? {
p2.set_nonblocking(false)?;
return p2.read_to_end(v2).map(|_| ());
return p1.read_to_end(v1).map(|_| ());
}
}
+
+ // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
+ // EAGAIN. If we hit EOF, then this will happen because the underlying
+ // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
+ // this case we flip the other fd back into blocking mode and read
+ // whatever's leftover on that file descriptor.
+ fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
+ match fd.read_to_end(dst) {
+ Ok(_) => Ok(true),
+ Err(e) => {
+ if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
+ e.raw_os_error() == Some(libc::EAGAIN) {
+ Ok(false)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
}
token::Pound => "Pound",
token::Dollar => "Dollar",
token::Question => "Question",
+ token::SingleQuote => "SingleQuote",
token::Eof => "Eof",
token::Whitespace | token::Comment | token::Shebang(_) => {
// Allows use of the :literal macro fragment specifier (RFC 1576)
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
+
+ // inconsistent bounds in where clauses
+ (active, trivial_bounds, "1.28.0", Some(48214), None),
);
declare_features! (
(c > '\x7f' && c.is_xid_continue())
}
+// The string is a valid identifier or a lifetime identifier.
+pub fn is_valid_ident(s: &str) -> bool {
+ let mut chars = s.chars();
+ ident_start(chars.next()) && chars.all(|ch| ident_continue(Some(ch)))
+}
+
#[cfg(test)]
mod tests {
use super::*;
Pound,
Dollar,
Question,
+ /// Used by proc macros for representing lifetimes, not generated by lexer right now.
+ SingleQuote,
/// An opening delimiter, eg. `{`
OpenDelim(DelimToken),
/// A closing delimiter, eg. `}`
Colon => ModSep,
_ => return None,
},
+ SingleQuote => match joint {
+ Ident(ident, false) => Lifetime(ident),
+ _ => return None,
+ },
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
token::Pound => "#".to_string(),
token::Dollar => "$".to_string(),
token::Question => "?".to_string(),
+ token::SingleQuote => "'".to_string(),
/* Literals */
token::Literal(lit, suf) => {
fn assert_inline(slice: &mut &[TokenTree]) {
match &slice[0] {
- TokenTree::Op(tt) => assert_eq!(tt.op(), '#'),
+ TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
_ => panic!("expected '#' char"),
}
match &slice[1] {
fn assert_doc(slice: &mut &[TokenTree]) {
match &slice[0] {
- TokenTree::Op(tt) => {
- assert_eq!(tt.op(), '#');
+ TokenTree::Punct(tt) => {
+ assert_eq!(tt.as_char(), '#');
assert_eq!(tt.spacing(), Spacing::Alone);
}
_ => panic!("expected #"),
}
match &tokens[0] {
- TokenTree::Term(tt) => assert_eq!("doc", &*tt.to_string()),
+ TokenTree::Ident(tt) => assert_eq!("doc", &*tt.to_string()),
_ => panic!("expected `doc`"),
}
match &tokens[1] {
- TokenTree::Op(tt) => {
- assert_eq!(tt.op(), '=');
+ TokenTree::Punct(tt) => {
+ assert_eq!(tt.as_char(), '=');
assert_eq!(tt.spacing(), Spacing::Alone);
}
_ => panic!("expected equals"),
fn assert_invoc(slice: &mut &[TokenTree]) {
match &slice[0] {
- TokenTree::Op(tt) => assert_eq!(tt.op(), '#'),
+ TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
_ => panic!("expected '#' char"),
}
match &slice[1] {
fn assert_foo(slice: &mut &[TokenTree]) {
match &slice[0] {
- TokenTree::Term(tt) => assert_eq!(&*tt.to_string(), "fn"),
+ TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "fn"),
_ => panic!("expected fn"),
}
match &slice[1] {
- TokenTree::Term(tt) => assert_eq!(&*tt.to_string(), "foo"),
+ TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "foo"),
_ => panic!("expected foo"),
}
match &slice[2] {
TokenTree::Group(b) => {
TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream())))
}
- TokenTree::Op(b) => TokenTree::Op(b),
- TokenTree::Term(a) => TokenTree::Term(a),
+ TokenTree::Punct(b) => TokenTree::Punct(b),
+ TokenTree::Ident(a) => TokenTree::Ident(a),
TokenTree::Literal(a) => {
if a.to_string() != "\"foo\"" {
TokenTree::Literal(a)
// force-host
// no-prefer-dynamic
-#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
// aux-build:issue_38586.rs
// ignore-stage1
-#![feature(proc_macro)]
-
#[macro_use]
extern crate issue_38586;
// aux-build:bang_proc_macro2.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
#![allow(unused_macros)]
extern crate bang_proc_macro2;
// aux-build:bang_proc_macro.rs
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(proc_macro_non_items)]
#[macro_use]
extern crate bang_proc_macro;
// aux-build:proc-macro-gates.rs
-#![feature(proc_macro, stmt_expr_attributes)]
+#![feature(use_extern_macros, stmt_expr_attributes)]
extern crate proc_macro_gates as foo;
// Check that when there are vacuous predicates in the environment
// (which make a fn uncallable) we don't erroneously cache those and
// then consider them satisfied elsewhere. The current technique for
-// doing this is just to filter "global" predicates out of the
-// environment, which means that we wind up with an error in the
-// function `vacuous`, because even though `i32: Bar<u32>` is implied
-// by its where clause, that where clause never holds.
+// doing this is to not use global caches when there is a chance that
+// the environment contains such a predicate.
+// We still error for `i32: Bar<u32>` pending #48214
trait Foo<X,Y>: Bar<X> {
}
}
pub fn poison<S>(victim: String) where <String as Mirror<S>>::Image: Copy {
- loop { drop(victim); } //~ ERROR use of moved value
+ loop { drop(victim); }
}
fn main() {
panic!("Invalid macro usage in cond: {}", cond);
}
let is_else = match test {
- TokenTree::Term(word) => &*word.to_string() == "else",
+ TokenTree::Ident(ref word) => &*word.to_string() == "else",
_ => false,
};
conds.push(if is_else || input.peek().is_none() {
// no-prefer-dynamic
#![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
+#![feature(proc_macro, proc_macro_non_items)]
extern crate proc_macro;
// no-prefer-dynamic
#![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
+#![feature(proc_macro, proc_macro_non_items)]
extern crate proc_macro;
// aux-build:cond_plugin.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate cond_plugin;
// aux-build:hello_macro.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate hello_macro;
let mut count = 0;
for token in input {
match &token {
- TokenTree::Op(tt) if tt.spacing() == Spacing::Alone => {
+ TokenTree::Punct(tt) if tt.spacing() == Spacing::Alone => {
count += 1;
}
TokenTree::Group(tt) => {
// except according to those terms.
// no-prefer-dynamic
-#![feature(proc_macro)]
+
#![crate_type = "proc-macro"]
extern crate proc_macro;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(proc_macro)]
+#![feature(use_extern_macros)]
extern crate hygiene_example_codegen;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn lifetimes_bang(input: TokenStream) -> TokenStream {
+ // Roundtrip through token trees
+ input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn lifetimes_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ // Roundtrip through AST
+ input
+}
+
+#[proc_macro_derive(Lifetimes)]
+pub fn lifetimes_derive(input: TokenStream) -> TokenStream {
+ // Roundtrip through a string
+ format!("mod m {{ {} }}", input).parse().unwrap()
+}
assert_eq!(a.delimiter(), b.delimiter());
assert_eq(a.stream(), b.stream());
}
- (TokenTree::Op(a), TokenTree::Op(b)) => {
- assert_eq!(a.op(), b.op());
+ (TokenTree::Punct(a), TokenTree::Punct(b)) => {
+ assert_eq!(a.as_char(), b.as_char());
assert_eq!(a.spacing(), b.spacing());
}
(TokenTree::Literal(a), TokenTree::Literal(b)) => {
assert_eq!(a.to_string(), b.to_string());
}
- (TokenTree::Term(a), TokenTree::Term(b)) => {
+ (TokenTree::Ident(a), TokenTree::Ident(b)) => {
assert_eq!(a.to_string(), b.to_string());
}
(a, b) => panic!("{:?} != {:?}", a, b),
// aux-build:bang-macro.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate bang_macro;
use bang_macro::rewrite;
// aux-build:count_compound_ops.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate count_compound_ops;
use count_compound_ops::count_compound_ops;
// aux-build:derive-attr-cfg.rs
// ignore-stage1
-#![feature(proc_macro)]
+#![feature(use_extern_macros)]
extern crate derive_attr_cfg;
use derive_attr_cfg::Foo;
// aux-build:hygiene_example.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate hygiene_example;
use hygiene_example::hello;
// aux-build:issue-39889.rs
// ignore-stage1
-#![feature(proc_macro)]
+#![feature(use_extern_macros)]
#![allow(unused)]
extern crate issue_39889;
// aux-build:issue-40001-plugin.rs
// ignore-stage1
-#![feature(proc_macro, plugin)]
+#![feature(plugin)]
#![plugin(issue_40001_plugin)]
#[whitelisted_attr]
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:lifetimes.rs
+// ignore-stage1
+
+#![feature(proc_macro)]
+
+extern crate lifetimes;
+use lifetimes::*;
+
+lifetimes_bang! {
+ fn bang<'a>() -> &'a u8 { &0 }
+}
+
+#[lifetimes_attr]
+fn attr<'a>() -> &'a u8 { &1 }
+
+#[derive(Lifetimes)]
+pub struct Lifetimes<'a> {
+ pub field: &'a u8,
+}
+
+fn main() {
+ assert_eq!(bang::<'static>(), &0);
+ assert_eq!(attr::<'static>(), &1);
+ let l1 = Lifetimes { field: &0 };
+ let l2 = m::Lifetimes { field: &1 };
+}
// aux-build:negative-token.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(proc_macro_non_items)]
extern crate negative_token;
// ignore-pretty
-#![feature(proc_macro)]
+#![feature(use_extern_macros)]
#[macro_use]
extern crate span_test_macros;
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(termination_trait_lib)]
+
+fn main() -> impl std::process::Termination { }
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![doc(no_default_passes, passes = "collapse-docs unindent-comments")]
+
+struct SomeStruct;
+
+pub struct OtherStruct;
--- /dev/null
+warning: the `#![doc(no_default_passes)]` attribute is considered deprecated
+ |
+ = warning: please see https://github.com/rust-lang/rust/issues/44136
+ = help: you may want to use `#![doc(document_private_items)]`
+
+warning: the `#![doc(passes = "...")]` attribute is considered deprecated
+ |
+ = warning: please see https://github.com/rust-lang/rust/issues/44136
+
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn invalid_punct(_: TokenStream) -> TokenStream {
+ TokenTree::from(Punct::new('`', Spacing::Alone)).into()
+}
+
+#[proc_macro]
+pub fn invalid_ident(_: TokenStream) -> TokenStream {
+ TokenTree::from(Ident::new("*", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn invalid_raw_ident(_: TokenStream) -> TokenStream {
+ TokenTree::from(Ident::new_raw("self", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn lexer_failure(_: TokenStream) -> TokenStream {
+ "a b ) c".parse().expect("parsing failed without panic")
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn single_quote_alone(_: TokenStream) -> TokenStream {
+ // `&'a u8`, but the `'` token is not joint
+ let trees: Vec<TokenTree> = vec![
+ Punct::new('&', Spacing::Alone).into(),
+ Punct::new('\'', Spacing::Alone).into(),
+ Ident::new("a", Span::call_site()).into(),
+ Ident::new("u8", Span::call_site()).into(),
+ ];
+ trees.into_iter().collect()
+}
// no-prefer-dynamic
#![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib)]
extern crate proc_macro;
// aux-build:plugin.rs
// ignore-stage1
-#![feature(proc_macro)]
-
#[macro_use] extern crate plugin;
#[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked
error: proc-macro derive panicked
- --> $DIR/issue-36935.rs:18:15
+ --> $DIR/issue-36935.rs:16:15
|
LL | #[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked
| ^^^
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_punct!(); //~ ERROR proc macro panicked
--- /dev/null
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-1.rs:16:1
+ |
+LL | invalid_punct!(); //~ ERROR proc macro panicked
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: message: unsupported character `'`'`
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_ident!(); //~ ERROR proc macro panicked
--- /dev/null
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-2.rs:16:1
+ |
+LL | invalid_ident!(); //~ ERROR proc macro panicked
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: message: `"*"` is not a valid identifier
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_raw_ident!(); //~ ERROR proc macro panicked
--- /dev/null
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-3.rs:16:1
+ |
+LL | invalid_raw_ident!(); //~ ERROR proc macro panicked
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: message: `"self"` is not a valid raw identifier
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+lexer_failure!(); //~ ERROR proc macro panicked
+ //~| ERROR unexpected close delimiter: `)`
--- /dev/null
+error: unexpected close delimiter: `)`
+ --> $DIR/invalid-punct-ident-4.rs:16:1
+ |
+LL | lexer_failure!(); //~ ERROR proc macro panicked
+ | ^^^^^^^^^^^^^^^^^
+
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-4.rs:16:1
+ |
+LL | lexer_failure!(); //~ ERROR proc macro panicked
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:lifetimes.rs
+
+#![feature(proc_macro, proc_macro_non_items)]
+
+extern crate lifetimes;
+
+use lifetimes::*;
+
+type A = single_quote_alone!(); //~ ERROR expected type, found `'`
--- /dev/null
+error: expected type, found `'`
+ --> $DIR/lifetimes.rs:19:10
+ |
+LL | type A = single_quote_alone!(); //~ ERROR expected type, found `'`
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
.help("input must be: `===`"))
}
- if let TokenTree::Op(tt) = tree {
- if tt.op() == '=' {
+ if let TokenTree::Punct(ref tt) = tree {
+ if tt.as_char() == '=' {
count += 1;
last_span = span;
continue
// aux-build:parent-source-spans.rs
// ignore-stage1
-#![feature(proc_macro, decl_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, decl_macro, proc_macro_non_items)]
extern crate parent_source_spans;
// aux-build:three-equals.rs
// ignore-stage1
-#![feature(proc_macro, proc_macro_non_items)]
+#![feature(use_extern_macros, proc_macro_non_items)]
extern crate three_equals;
// aux-build:bang_proc_macro.rs
#![feature(proc_macro)]
-#![allow(unused_macros)]
#[macro_use]
extern crate derive_foo;
error: cannot find derive macro `FooWithLongNan` in this scope
- --> $DIR/resolve-error.rs:37:10
+ --> $DIR/resolve-error.rs:36:10
|
LL | #[derive(FooWithLongNan)]
| ^^^^^^^^^^^^^^ help: try: `FooWithLongName`
error: cannot find attribute macro `attr_proc_macra` in this scope
- --> $DIR/resolve-error.rs:41:3
+ --> $DIR/resolve-error.rs:40:3
|
LL | #[attr_proc_macra]
| ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
error: cannot find attribute macro `FooWithLongNan` in this scope
- --> $DIR/resolve-error.rs:45:3
+ --> $DIR/resolve-error.rs:44:3
|
LL | #[FooWithLongNan]
| ^^^^^^^^^^^^^^
error: cannot find derive macro `Dlone` in this scope
- --> $DIR/resolve-error.rs:49:10
+ --> $DIR/resolve-error.rs:48:10
|
LL | #[derive(Dlone)]
| ^^^^^ help: try: `Clone`
error: cannot find derive macro `Dlona` in this scope
- --> $DIR/resolve-error.rs:53:10
+ --> $DIR/resolve-error.rs:52:10
|
LL | #[derive(Dlona)]
| ^^^^^ help: try: `Clona`
error: cannot find derive macro `attr_proc_macra` in this scope
- --> $DIR/resolve-error.rs:57:10
+ --> $DIR/resolve-error.rs:56:10
|
LL | #[derive(attr_proc_macra)]
| ^^^^^^^^^^^^^^^
error: cannot find macro `FooWithLongNama!` in this scope
- --> $DIR/resolve-error.rs:62:5
+ --> $DIR/resolve-error.rs:61:5
|
LL | FooWithLongNama!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
error: cannot find macro `attr_proc_macra!` in this scope
- --> $DIR/resolve-error.rs:65:5
+ --> $DIR/resolve-error.rs:64:5
|
LL | attr_proc_macra!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
error: cannot find macro `Dlona!` in this scope
- --> $DIR/resolve-error.rs:68:5
+ --> $DIR/resolve-error.rs:67:5
|
LL | Dlona!();
| ^^^^^
error: cannot find macro `bang_proc_macrp!` in this scope
- --> $DIR/resolve-error.rs:71:5
+ --> $DIR/resolve-error.rs:70:5
|
LL | bang_proc_macrp!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+
+#![allow(unused)]
+#![deny(trivial_bounds)] // Ignored without the trivial_bounds feature flag.
+
+struct A where i32: Copy;
+
+fn main() {}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused)]
+#![allow(type_alias_bounds)]
+
+pub trait Foo {
+ fn test(&self);
+}
+
+fn generic_function<X: Foo>(x: X) {}
+
+enum E where i32: Foo { V } //~ ERROR
+
+struct S where i32: Foo; //~ ERROR
+
+trait T where i32: Foo {} //~ ERROR
+
+union U where i32: Foo { f: i32 } //~ ERROR
+
+type Y where i32: Foo = (); // OK - bound is ignored
+
+impl Foo for () where i32: Foo { //~ ERROR
+ fn test(&self) {
+ 3i32.test();
+ Foo::test(&4i32);
+ generic_function(5i32);
+ }
+}
+
+fn f() where i32: Foo //~ ERROR
+{
+ let s = S;
+ 3i32.test();
+ Foo::test(&4i32);
+ generic_function(5i32);
+}
+
+fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { //~ ERROR
+ -s
+}
+
+fn use_for() where i32: Iterator { //~ ERROR
+ for _ in 2i32 {}
+}
+
+trait A {}
+
+impl A for i32 {}
+
+struct Dst<X: ?Sized> {
+ x: X,
+}
+
+struct TwoStrs(str, str) where str: Sized; //~ ERROR
+
+fn unsized_local() where Dst<A>: Sized { //~ ERROR
+ let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+}
+
+fn return_str() -> str where str: Sized { //~ ERROR
+ *"Sized".to_string().into_boxed_str()
+}
+
+// This is currently accepted because the function pointer isn't
+// considered global.
+fn global_hr(x: fn(&())) where fn(&()): Foo { // OK
+ x.test();
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:20:1
+ |
+LL | enum E where i32: Foo { V } //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:22:1
+ |
+LL | struct S where i32: Foo; //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:24:1
+ |
+LL | trait T where i32: Foo {} //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:26:1
+ |
+LL | union U where i32: Foo { f: i32 } //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:30:1
+ |
+LL | / impl Foo for () where i32: Foo { //~ ERROR
+LL | | fn test(&self) {
+LL | | 3i32.test();
+LL | | Foo::test(&4i32);
+LL | | generic_function(5i32);
+LL | | }
+LL | | }
+ | |_^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:38:1
+ |
+LL | / fn f() where i32: Foo //~ ERROR
+LL | | {
+LL | | let s = S;
+LL | | 3i32.test();
+LL | | Foo::test(&4i32);
+LL | | generic_function(5i32);
+LL | | }
+ | |_^ the trait `Foo` is not implemented for `i32`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `std::string::String: std::ops::Neg` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:46:1
+ |
+LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { //~ ERROR
+LL | | -s
+LL | | }
+ | |_^ the trait `std::ops::Neg` is not implemented for `std::string::String`
+ |
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `i32: std::iter::Iterator` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:50:1
+ |
+LL | / fn use_for() where i32: Iterator { //~ ERROR
+LL | | for _ in 2i32 {}
+LL | | }
+ | |_^ `i32` is not an iterator; maybe try calling `.iter()` or a similar method
+ |
+ = help: the trait `std::iter::Iterator` is not implemented for `i32`
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:62:1
+ |
+LL | struct TwoStrs(str, str) where str: Sized; //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `str` does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `A + 'static: std::marker::Sized` is not satisfied in `Dst<A + 'static>`
+ --> $DIR/feature-gate-trivial_bounds.rs:64:1
+ |
+LL | / fn unsized_local() where Dst<A>: Sized { //~ ERROR
+LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+LL | | }
+ | |_^ `A + 'static` does not have a constant size known at compile-time
+ |
+ = help: within `Dst<A + 'static>`, the trait `std::marker::Sized` is not implemented for `A + 'static`
+ = note: required because it appears within the type `Dst<A + 'static>`
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/feature-gate-trivial_bounds.rs:68:1
+ |
+LL | / fn return_str() -> str where str: Sized { //~ ERROR
+LL | | *"Sized".to_string().into_boxed_str()
+LL | | }
+ | |_^ `str` does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = help: see issue #48214
+ = help: add #![feature(trivial_bounds)] to the crate attributes to enable
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
...
LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
| ------------------------------------------- first implementation here
+ |
+ = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that an `impl Trait` that is not `impl Termination` will not work.
+fn main() -> impl Copy { }
+//~^ ERROR `main` has invalid return type `impl std::marker::Copy`
--- /dev/null
+error[E0277]: `main` has invalid return type `impl std::marker::Copy`
+ --> $DIR/termination-trait-impl-trait.rs:12:14
+ |
+LL | fn main() -> impl Copy { }
+ | ^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// Inconsistent bounds with trait implementations
+
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+trait A {
+ fn foo(&self) -> Self where Self: Copy;
+}
+
+impl A for str {
+ fn foo(&self) -> Self where Self: Copy { *"" }
+}
+
+impl A for i32 {
+ fn foo(&self) -> Self { 3 }
+}
+
+fn main() {}
--- /dev/null
+error[E0596]: cannot borrow immutable item `**t` as mutable
+ --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
+ |
+LL | *t //~ ERROR
+ | ^^ cannot borrow as mutable
+ |
+ = note: the value which is causing this path not to be mutable is...: `*t`
+
+error[E0596]: cannot borrow immutable item `**t` as mutable
+ --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
+ |
+LL | {*t} //~ ERROR
+ | ^^ cannot borrow as mutable
+ |
+ = note: the value which is causing this path not to be mutable is...: `*t`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that reborrows are still illegal with Copy mutable references
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ *t //~ ERROR
+}
+
+fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ {*t} //~ ERROR
+}
+
+fn main() {}
--- /dev/null
+error[E0389]: cannot borrow data mutably in a `&` reference
+ --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
+ |
+LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ | --------------- use `&'a mut &'a mut i32` here to make mutable
+LL | *t //~ ERROR
+ | ^^ assignment into an immutable reference
+
+error[E0389]: cannot borrow data mutably in a `&` reference
+ --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
+ |
+LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ | --------------- use `&'a mut &'a mut i32` here to make mutable
+LL | {*t} //~ ERROR
+ | ^^ assignment into an immutable reference
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0389`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// Check tautalogically false `Copy` bounds
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+fn copy_string(t: String) -> String where String: Copy {
+ is_copy(&t);
+ let x = t;
+ drop(t);
+ t
+}
+
+fn copy_out_string(t: &String) -> String where String: Copy {
+ *t
+}
+
+fn copy_string_with_param<T>(x: String) where String: Copy {
+ let y = x;
+ let z = x;
+}
+
+// Check that no reborrowing occurs
+fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
+ is_copy(t);
+ let x = *t;
+ drop(x);
+ x
+}
+
+fn is_copy<T: Copy>(t: &T) {}
+
+
+fn main() {}
--- /dev/null
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-copy.rs:16:1
+ |
+LL | / fn copy_string(t: String) -> String where String: Copy {
+LL | | is_copy(&t);
+LL | | let x = t;
+LL | | drop(t);
+LL | | t
+LL | | }
+ | |_^
+ |
+ = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-copy.rs:23:1
+ |
+LL | / fn copy_out_string(t: &String) -> String where String: Copy {
+LL | | *t
+LL | | }
+ | |_^
+
+warning: Trait bound std::string::String: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-copy.rs:27:1
+ |
+LL | / fn copy_string_with_param<T>(x: String) where String: Copy {
+LL | | let y = x;
+LL | | let z = x;
+LL | | }
+ | |_^
+
+warning: Trait bound for<'b> &'b mut i32: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-copy.rs:33:1
+ |
+LL | / fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy {
+LL | | is_copy(t);
+LL | | let x = *t;
+LL | | drop(x);
+LL | | x
+LL | | }
+ | |_^
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// Check tautalogically false `Sized` bounds
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+trait A {}
+
+impl A for i32 {}
+
+struct T<X: ?Sized> {
+ x: X,
+}
+
+struct S(str, str) where str: Sized;
+
+fn unsized_local() where for<'a> T<A + 'a>: Sized {
+ let x: T<A> = *(Box::new(T { x: 1 }) as Box<T<A>>);
+}
+
+fn return_str() -> str where str: Sized {
+ *"Sized".to_string().into_boxed_str()
+}
+
+fn main() {}
--- /dev/null
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-sized.rs:24:1
+ |
+LL | struct S(str, str) where str: Sized;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound for<'a> T<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-sized.rs:26:1
+ |
+LL | / fn unsized_local() where for<'a> T<A + 'a>: Sized {
+LL | | let x: T<A> = *(Box::new(T { x: 1 }) as Box<T<A>>);
+LL | | }
+ | |_^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-sized.rs:30:1
+ |
+LL | / fn return_str() -> str where str: Sized {
+LL | | *"Sized".to_string().into_boxed_str()
+LL | | }
+ | |_^
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+// Test that inconsistent bounds are used in well-formedness checks
+#![feature(trivial_bounds)]
+
+use std::fmt::Debug;
+
+pub fn foo() where Vec<str>: Debug, str: Copy {
+ let x = vec![*"1"];
+ println!("{:?}", x);
+}
+
+fn main() {}
--- /dev/null
+warning: Trait bound std::vec::Vec<str>: std::fmt::Debug does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:1
+ |
+LL | / pub fn foo() where Vec<str>: Debug, str: Copy {
+LL | | let x = vec![*"1"];
+LL | | println!("{:?}", x);
+LL | | }
+ | |_^
+ |
+ = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound str: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent-well-formed.rs:17:1
+ |
+LL | / pub fn foo() where Vec<str>: Debug, str: Copy {
+LL | | let x = vec![*"1"];
+LL | | println!("{:?}", x);
+LL | | }
+ | |_^
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+
+// Check that tautalogically false bounds are accepted, and are used
+// in type inference.
+#![feature(trivial_bounds)]
+#![allow(unused)]
+
+pub trait Foo {
+ fn test(&self);
+}
+
+fn generic_function<X: Foo>(x: X) {}
+
+enum E where i32: Foo { V }
+
+struct S where i32: Foo;
+
+trait T where i32: Foo {}
+
+union U where i32: Foo { f: i32 }
+
+type Y where i32: Foo = ();
+
+impl Foo for () where i32: Foo {
+ fn test(&self) {
+ 3i32.test();
+ Foo::test(&4i32);
+ generic_function(5i32);
+ }
+}
+
+fn f() where i32: Foo {
+ let s = S;
+ 3i32.test();
+ Foo::test(&4i32);
+ generic_function(5i32);
+}
+
+fn g() where &'static str: Foo {
+ "Foo".test();
+ Foo::test(&"Foo");
+ generic_function("Foo");
+}
+
+trait A {}
+
+impl A for i32 {}
+
+struct Dst<X: ?Sized> {
+ x: X,
+}
+
+struct TwoStrs(str, str) where str: Sized;
+
+fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
+ let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+}
+
+fn return_str() -> str where str: Sized {
+ *"Sized".to_string().into_boxed_str()
+}
+
+fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+ -s
+}
+
+fn use_for() where i32: Iterator {
+ for _ in 2i32 {}
+}
+
+fn main() {}
--- /dev/null
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:24:1
+ |
+LL | enum E where i32: Foo { V }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(trivial_bounds)] on by default
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:26:1
+ |
+LL | struct S where i32: Foo;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:28:1
+ |
+LL | trait T where i32: Foo {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:30:1
+ |
+LL | union U where i32: Foo { f: i32 }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: where clauses are not enforced in type aliases
+ --> $DIR/trivial-bounds-inconsistent.rs:32:14
+ |
+LL | type Y where i32: Foo = ();
+ | ^^^^^^^^
+ |
+ = note: #[warn(type_alias_bounds)] on by default
+ = help: the clause will not be checked when the type alias is used, and should be removed
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:32:1
+ |
+LL | type Y where i32: Foo = ();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:34:1
+ |
+LL | / impl Foo for () where i32: Foo {
+LL | | fn test(&self) {
+LL | | 3i32.test();
+LL | | Foo::test(&4i32);
+LL | | generic_function(5i32);
+LL | | }
+LL | | }
+ | |_^
+
+warning: Trait bound i32: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:42:1
+ |
+LL | / fn f() where i32: Foo {
+LL | | let s = S;
+LL | | 3i32.test();
+LL | | Foo::test(&4i32);
+LL | | generic_function(5i32);
+LL | | }
+ | |_^
+
+warning: Trait bound &'static str: Foo does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:49:1
+ |
+LL | / fn g() where &'static str: Foo {
+LL | | "Foo".test();
+LL | | Foo::test(&"Foo");
+LL | | generic_function("Foo");
+LL | | }
+ | |_^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:63:1
+ |
+LL | struct TwoStrs(str, str) where str: Sized;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Trait bound for<'a> Dst<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:65:1
+ |
+LL | / fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
+LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+LL | | }
+ | |_^
+
+warning: Trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:69:1
+ |
+LL | / fn return_str() -> str where str: Sized {
+LL | | *"Sized".to_string().into_boxed_str()
+LL | | }
+ | |_^
+
+warning: Trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:73:1
+ |
+LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> {
+LL | | -s
+LL | | }
+ | |_^
+
+warning: Trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-inconsistent.rs:77:1
+ |
+LL | / fn use_for() where i32: Iterator {
+LL | | for _ in 2i32 {}
+LL | | }
+ | |_^
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that false Copy bounds don't leak
+#![feature(trivial_bounds)]
+
+fn copy_out_string(t: &String) -> String where String: Copy {
+ *t
+}
+
+fn move_out_string(t: &String) -> String {
+ *t //~ ERROR
+}
+
+fn main() {}
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/trivial-bounds-leak-copy.rs:19:5
+ |
+LL | *t //~ ERROR
+ | ^^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that false bounds don't leak
+#![feature(trivial_bounds)]
+
+pub trait Foo {
+ fn test(&self);
+}
+
+fn return_str() -> str where str: Sized {
+ *"Sized".to_string().into_boxed_str()
+}
+
+fn cant_return_str() -> str { //~ ERROR
+ *"Sized".to_string().into_boxed_str()
+}
+
+fn my_function() where i32: Foo
+{
+ 3i32.test();
+ Foo::test(&4i32);
+ generic_function(5i32);
+}
+
+fn foo() {
+ 3i32.test(); //~ ERROR
+ Foo::test(&4i32); //~ ERROR
+ generic_function(5i32); //~ ERROR
+}
+
+fn generic_function<T: Foo>(t: T) {}
+
+fn main() {}
+
--- /dev/null
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+ --> $DIR/trivial-bounds-leak.rs:22:25
+ |
+LL | fn cant_return_str() -> str { //~ ERROR
+ | ^^^ `str` does not have a constant size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: the return type of a function must have a statically known size
+
+error[E0599]: no method named `test` found for type `i32` in the current scope
+ --> $DIR/trivial-bounds-leak.rs:34:10
+ |
+LL | 3i32.test(); //~ ERROR
+ | ^^^^
+ |
+ = help: items from traits can only be used if the trait is implemented and in scope
+ = note: the following trait defines an item `test`, perhaps you need to implement it:
+ candidate #1: `Foo`
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/trivial-bounds-leak.rs:35:5
+ |
+LL | Foo::test(&4i32); //~ ERROR
+ | ^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+note: required by `Foo::test`
+ --> $DIR/trivial-bounds-leak.rs:15:5
+ |
+LL | fn test(&self);
+ | ^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+ --> $DIR/trivial-bounds-leak.rs:36:5
+ |
+LL | generic_function(5i32); //~ ERROR
+ | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
+ |
+note: required by `generic_function`
+ --> $DIR/trivial-bounds-leak.rs:39:1
+ |
+LL | fn generic_function<T: Foo>(t: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trivial_bounds)]
+#![allow(unused)]
+#![deny(trivial_bounds)]
+
+struct A where i32: Copy; //~ ERROR
+
+trait X<T: Copy> {}
+
+trait Y<T>: Copy {}
+
+trait Z {
+ type S: Copy;
+}
+
+// Check only the bound the user writes trigger the lint
+fn trivial_elaboration<T>() where T: X<i32> + Z<S = i32>, i32: Y<T> {} // OK
+
+fn global_param() where i32: X<()> {} //~ ERROR
+
+// Should only error on the trait bound, not the implicit
+// projection bound <i32 as Z>::S == i32.
+fn global_projection() where i32: Z<S = i32> {} //~ ERROR
+
+impl A {
+ fn new() -> A { A }
+}
+
+// Lifetime bounds should be linted as well
+fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+//~^ ERROR
+//~| ERROR
+
+fn local_lifetimes<'a>() where i32: 'a, &'a str: 'a {} // OK
+
+fn global_outlives() where 'static: 'static {} //~ ERROR
+
+// Check that each bound is checked individually
+fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR
+
+fn main() {}
--- /dev/null
+error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:15:1
+ |
+LL | struct A where i32: Copy; //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/trivial-bounds-lint.rs:13:9
+ |
+LL | #![deny(trivial_bounds)]
+ | ^^^^^^^^^^^^^^
+
+error: Trait bound i32: X<()> does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:28:1
+ |
+LL | fn global_param() where i32: X<()> {} //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Trait bound i32: Z does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:32:1
+ |
+LL | fn global_projection() where i32: Z<S = i32> {} //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Lifetime bound i32 : 'static does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:39:1
+ |
+LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Lifetime bound &'static str : 'static does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:39:1
+ |
+LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Lifetime bound 'static : 'static does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:45:1
+ |
+LL | fn global_outlives() where 'static: 'static {} //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Trait bound i32: std::marker::Copy does not depend on any type or lifetime parameters
+ --> $DIR/trivial-bounds-lint.rs:48:1
+ |
+LL | fn mixed_bounds<T: Copy>() where i32: X<T> + Copy {} //~ ERROR
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
-Subproject commit d2ade31a52a417257742de72c5936a8a342a34b5
+Subproject commit 3e3df0485004bc1343bc8200b68c67ac7c479b28
-Subproject commit 0f8029f251b569a010cb5cfc5a8bff8bf3c949ac
+Subproject commit db8cb0b8d6942d42a322b1d36b2504977404f362