diff --git a/Cargo.lock b/Cargo.lock index f19238140b806..041a24aae6c53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,7 +140,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -156,7 +156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -208,8 +208,8 @@ dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", - "git2-curl 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -219,7 +219,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -228,11 +228,10 @@ dependencies = [ "pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.4 (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.81 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -252,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (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.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -328,7 +327,7 @@ dependencies = [ "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -360,7 +359,7 @@ dependencies = [ "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.4 (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.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -430,8 +429,8 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -450,7 +449,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -484,7 +483,7 @@ version = "0.22.0" dependencies = [ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -618,7 +617,7 @@ dependencies = [ [[package]] name = "datafrog" -version = "0.1.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -683,7 +682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -894,12 +893,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "git2" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -908,11 +907,11 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", - "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -949,7 +948,7 @@ dependencies = [ "pest_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1097,12 +1096,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" -version = "8.0.1" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1124,7 +1123,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1156,7 +1155,7 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1214,14 +1213,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.6" @@ -1271,7 +1262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1303,7 +1294,7 @@ dependencies = [ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1390,8 +1381,10 @@ dependencies = [ "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-workspace-hack 1.0.0", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1629,10 +1622,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "polonius-engine" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1965,10 +1958,12 @@ dependencies = [ "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1988,9 +1983,10 @@ dependencies = [ "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", "rustfmt-nightly 1.0.1", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2023,7 +2019,7 @@ 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)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2038,7 +2034,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2075,7 +2071,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_apfloat 0.0.0", @@ -2263,6 +2259,7 @@ version = "1.0.0" dependencies = [ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2526,7 +2523,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", @@ -2709,12 +2706,12 @@ dependencies = [ [[package]] name = "rustfix" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2740,7 +2737,7 @@ dependencies = [ "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2797,7 +2794,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2807,8 +2804,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" @@ -2825,7 +2825,7 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2835,7 +2835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2917,7 +2917,7 @@ dependencies = [ "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3134,7 +3134,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3154,7 +3154,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3252,7 +3252,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3428,7 +3428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" -"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" +"checksum datafrog 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" @@ -3461,8 +3461,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" -"checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" -"checksum git2-curl 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0173e317f8ba21f3fff0f71549fead5e42e67961dbd402bf69f42775f3cc78b4" +"checksum git2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7339329bfa14a00223244311560d11f8f489b453fb90092af97f267a6090ab0" +"checksum git2-curl 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d58551e903ed7e2d6fe3a2f3c7efa3a784ec29b19d0fbb035aaf0497c183fbdd" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd" @@ -3481,19 +3481,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" "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 jsonrpc-core 9.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e9cbeda300803d381390fb65e8158437728c39e6987ed23bee82728b73511a7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68de833188ada4e175d04a028f03f244f6370eedbcc75a05604d47d925933f69" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" -"checksum libgit2-sys 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4916b5addc78ec36cc309acfcdf0b9f9d97ab7b84083118b248709c5b7029356" +"checksum libgit2-sys 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "48441cb35dc255da8ae72825689a95368bf510659ae1ad55dc4aa88cb1789bf1" "checksum libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d75d7966bda4730b722d1eab8e668df445368a24394bae9fc1e8dc0ab3dbe4f4" "checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd" "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614" @@ -3538,7 +3537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201" +"checksum polonius-engine 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2490c396085801abf88df91758bad806b0890354f0875d624e62ecf0579a8145" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" @@ -3593,7 +3592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b" +"checksum rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56" "checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" @@ -3602,7 +3601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "c91eb5b0190ae87b4e2e39cbba6e3bed3ac6186935fe265f0426156c4c49961b" +"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" "checksum serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)" = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" diff --git a/Cargo.toml b/Cargo.toml index 667c55791bd17..c693985a2ad83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,6 @@ members = [ "src/tools/rustdoc-themes", ] exclude = [ - "src/tools/rls/test_data", "build", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", diff --git a/README.md b/README.md index dc013a1ad2be6..7eb5e8067eda2 100644 --- a/README.md +++ b/README.md @@ -186,18 +186,15 @@ fetch snapshots, and an OS that can execute the available snapshot binaries. Snapshot binaries are currently built and tested on several platforms: -| Platform / Architecture | x86 | x86_64 | -|--------------------------------|-----|--------| -| Windows (7, 8, Server 2008 R2) | ✓ | ✓ | -| Linux (2.6.18 or later) | ✓ | ✓ | -| OSX (10.7 Lion or later) | ✓ | ✓ | +| Platform / Architecture | x86 | x86_64 | +|--------------------------|-----|--------| +| Windows (7, 8, 10, ...) | ✓ | ✓ | +| Linux (2.6.18 or later) | ✓ | ✓ | +| OSX (10.7 Lion or later) | ✓ | ✓ | You may find that other platforms work, but these are our officially supported build environments that are most likely to work. -Rust currently needs between 600MiB and 1.5GiB of RAM to build, depending on platform. -If it hits swap, it will take a very long time to build. - There is more advice about hacking on Rust in [CONTRIBUTING.md]. [CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md diff --git a/config.toml.example b/config.toml.example index f75e220de47e7..236d18dda8eb0 100644 --- a/config.toml.example +++ b/config.toml.example @@ -144,6 +144,10 @@ # target when running tests, otherwise this can be omitted. #nodejs = "node" +# The eslint executable to use. Note that this is only used for linting js files +# during the test phase. It can be omitted. +#eslint = "eslint" + # Python interpreter to use for various tasks throughout the build, notably # rustdoc tests, the lldb python interpreter, and some dist bits and pieces. # Note that Python 2 is currently required. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8655cf0eb3053..872cd200266eb 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -136,6 +136,7 @@ pub struct Config { pub libdir: Option, pub mandir: Option, pub codegen_tests: bool, + pub eslint: Option, pub nodejs: Option, pub gdb: Option, pub python: Option, @@ -202,6 +203,7 @@ struct Build { gdb: Option, locked_deps: Option, vendor: Option, + eslint: Option, nodejs: Option, python: Option, full_bootstrap: Option, @@ -444,6 +446,7 @@ impl Config { }; + config.eslint = build.eslint.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b6f3f97e627fd..f1ad0e1f91ce1 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -283,13 +283,6 @@ impl Step for Rls { SourceType::Submodule, &[]); - // Copy `src/tools/rls/test_data` to a writable drive. - let test_workspace_path = builder.out.join("rls-test-data"); - let test_data_path = test_workspace_path.join("test_data"); - builder.create_dir(&test_data_path); - builder.cp_r(&builder.src.join("src/tools/rls/test_data"), &test_data_path); - cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path); - builder.add_rustc_lib_path(compiler, &mut cargo); cargo.arg("--") .args(builder.config.cmd.test_args()); @@ -616,6 +609,14 @@ impl Step for RustdocJS { "No nodejs found, skipping \"src/test/rustdoc-js\" tests" ); } + + if let Some(ref eslint) = builder.config.eslint { + let mut command = Command::new(eslint); + command.args(&["src/librustdoc/html/static"]); + builder.run(&mut command); + } else { + builder.info("No eslint found, skipping js linting"); + } } } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 1a5a874049900..7782351a552d4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -140,7 +140,7 @@ impl Step for ToolBuild { }); if is_expected && !duplicates.is_empty() { - println!("duplicate artfacts found when compiling a tool, this \ + println!("duplicate artifacts found when compiling a tool, this \ typically means that something was recompiled because \ a transitive dependency has different features activated \ than in a previous build:\n"); diff --git a/src/doc/rust.css b/src/doc/rust.css index 5f216169efe2c..631f64a11dbae 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -1,15 +1,3 @@ -/** - * Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT - * file at the top-level directory of this distribution and at - * http://rust-lang.org/COPYRIGHT. - * With elements taken from Bootstrap v3.0.2 (MIT licensed). - * - * Licensed under the Apache License, Version 2.0 or the MIT license - * , at your - * option. This file may not be copied, modified, or distributed - * except according to those terms. - */ @font-face { font-family: 'Fira Sans'; font-style: normal; diff --git a/src/doc/unstable-book/src/language-features/non-ascii-idents.md b/src/doc/unstable-book/src/language-features/non-ascii-idents.md index efb5495fe26ac..46957c00bf95c 100644 --- a/src/doc/unstable-book/src/language-features/non-ascii-idents.md +++ b/src/doc/unstable-book/src/language-features/non-ascii-idents.md @@ -1,8 +1,8 @@ # `non_ascii_idents` -The tracking issue for this feature is: [#28979] +The tracking issue for this feature is: [#55467] -[#28979]: https://github.com/rust-lang/rust/issues/28979 +[#55467]: https://github.com/rust-lang/rust/issues/55467 ------------------------ diff --git a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md new file mode 100644 index 0000000000000..bcdeafc4b1137 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md @@ -0,0 +1,36 @@ +# `type_alias_enum_variants` + +The tracking issue for this feature is: [#49683] + +[#49683]: https://github.com/rust-lang/rust/issues/49683 + +------------------------ + +The `type_alias_enum_variants` feature enables the use of variants on type +aliases that refer to enums, as both a constructor and a pattern. That is, +it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same +as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type +`Enum`). + +Note that since `Self` exists as a type alias, this feature also enables the +use of the syntax `Self::Variant` within an impl block for an enum type. + +```rust +#![feature(type_alias_enum_variants)] + +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type Alias = Foo; + +fn main() { + let t = Alias::Bar(0); + let t = Alias::Baz { i: 0 }; + match t { + Alias::Bar(_i) => {} + Alias::Baz { i: _i } => {} + } +} +``` diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 73e2c4494feef..a1e7533449c69 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -27,6 +27,9 @@ //! will then parse the format string and determine if the list of arguments //! provided is suitable to pass to this format string. //! +//! To convert a single value to a string, use the [`to_string`] method. This +//! will use the [`Display`] formatting trait. +//! //! ## Positional parameters //! //! Each formatting argument is allowed to specify which value argument it's @@ -487,6 +490,7 @@ //! [`write!`]: ../../std/macro.write.html //! [`Debug`]: trait.Debug.html //! [`format!`]: ../../std/macro.format.html +//! [`to_string`]: ../../std/string/trait.ToString.html //! [`writeln!`]: ../../std/macro.writeln.html //! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt //! [`std::io::Write`]: ../../std/io/trait.Write.html diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 1978efda097f2..db91b07fa71b4 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -73,9 +73,14 @@ macro_rules! vec { /// The same convention is used with [`print!`] and [`write!`] macros, /// depending on the intended destination of the string. /// +/// To convert a single value to a string, use the [`to_string`] method. This +/// will use the [`Display`] formatting trait. +/// /// [fmt]: ../std/fmt/index.html /// [`print!`]: ../std/macro.print.html /// [`write!`]: ../std/macro.write.html +/// [`to_string`]: ../std/string/trait.ToString.html +/// [`Display`]: ../std/fmt/trait.Display.html /// /// # Panics /// diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 74b3ce4f978b9..ed90b7de26417 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -53,6 +53,17 @@ /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d /// implementation of [`clone`] calls [`clone`] on each field. /// +/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on +/// generic parameters. +/// +/// ``` +/// // `derive` implements Clone for Reading when T is Clone. +/// #[derive(Clone)] +/// struct Reading { +/// frequency: T, +/// } +/// ``` +/// /// ## How can I implement `Clone`? /// /// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally: @@ -60,21 +71,21 @@ /// Manual implementations should be careful to uphold this invariant; however, unsafe code /// must not rely on it to ensure memory safety. /// -/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard -/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of -/// `Clone` cannot be `derive`d, but can be implemented as: +/// An example is a generic struct holding a function pointer. In this case, the +/// implementation of `Clone` cannot be `derive`d, but can be implemented as: /// /// [`Copy`]: ../../std/marker/trait.Copy.html /// [`clone`]: trait.Clone.html#tymethod.clone /// /// ``` -/// #[derive(Copy)] -/// struct Stats { -/// frequencies: [i32; 100], -/// } +/// struct Generate(fn() -> T); +/// +/// impl Copy for Generate {} /// -/// impl Clone for Stats { -/// fn clone(&self) -> Stats { *self } +/// impl Clone for Generate { +/// fn clone(&self) -> Self { +/// *self +/// } /// } /// ``` /// diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9336b130d1bb2..f420d0d00a401 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -472,9 +472,11 @@ impl Ord for Reverse { /// Then you must define an implementation for `cmp()`. You may find it useful to use /// `cmp()` on your type's fields. /// -/// Implementations of `PartialEq`, `PartialOrd`, and `Ord` *must* agree with each other. It's -/// easy to accidentally make them disagree by deriving some of the traits and manually -/// implementing others. +/// Implementations of `PartialEq`, `PartialOrd`, and `Ord` *must* +/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if +/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for +/// all `a` and `b`. It's easy to accidentally make them disagree by +/// deriving some of the traits and manually implementing others. /// /// Here's an example where you want to sort people by height only, disregarding `id` /// and `name`: diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index d8508631bf9c3..e31ac691e3a3c 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -25,7 +25,7 @@ //! values. //! //! However, these restrictions are usually not necessary. Many types are always freely -//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect +//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the effect //! of [`Pin`]. For `T: Unpin`, `Pin>` and `Box` function identically, as do //! `Pin<&mut T>` and `&mut T`. //! diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index b9420f32a9492..55a72d7a9a94d 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -591,7 +591,7 @@ pub unsafe fn read(src: *const T) -> T { /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. /// -/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// Note that even if `T` has size `0`, the pointer must be non-NULL. /// /// [`Copy`]: ../marker/trait.Copy.html /// [`read`]: ./fn.read.html @@ -759,7 +759,7 @@ pub unsafe fn write(dst: *mut T, src: T) { /// /// * `dst` must be [valid] for writes. /// -/// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. +/// Note that even if `T` has size `0`, the pointer must be non-NULL. /// /// [valid]: ../ptr/index.html#safety /// diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index fc8325e5915c4..32ae878909f30 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -144,7 +144,7 @@ pub struct Parser<'a> { /// `Some(raw count)` when the string is "raw", used to position spans correctly style: Option, /// Start and end byte offset of every successfully parsed argument - pub arg_places: Vec<(usize, usize)>, + pub arg_places: Vec<(SpanIndex, SpanIndex)>, /// Characters that need to be shifted skips: Vec, /// Span offset of the last opening brace seen, used for error reporting @@ -154,7 +154,7 @@ pub struct Parser<'a> { } #[derive(Clone, Copy, Debug)] -pub struct SpanIndex(usize); +pub struct SpanIndex(pub usize); impl SpanIndex { pub fn unwrap(self) -> usize { @@ -166,7 +166,6 @@ impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option> { - let raw = self.raw(); if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { @@ -180,7 +179,7 @@ impl<'a> Iterator for Parser<'a> { } else { let arg = self.argument(); if let Some(arg_pos) = self.must_consume('}').map(|end| { - (pos + raw + 1, end + raw + 2) + (self.to_span_index(pos), self.to_span_index(end + 1)) }) { self.arg_places.push(arg_pos); } diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 4a22b69eda80b..d8dd2e0a11337 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -12,6 +12,7 @@ #![panic_runtime] #![allow(unused_features)] +#![feature(cfg_target_vendor)] #![feature(core_intrinsics)] #![feature(libc)] #![feature(nll)] @@ -57,7 +58,7 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { core::intrinsics::abort(); } - #[cfg(target_env="sgx")] + #[cfg(all(target_vendor="fortanix", target_env="sgx"))] unsafe fn abort() -> ! { extern "C" { pub fn panic_exit() -> !; } panic_exit(); diff --git a/src/libproc_macro/bridge/rpc.rs b/src/libproc_macro/bridge/rpc.rs index ed5136462cf3d..74ae711a47372 100644 --- a/src/libproc_macro/bridge/rpc.rs +++ b/src/libproc_macro/bridge/rpc.rs @@ -1,4 +1,4 @@ -//! Serialization for client<->server communication. +//! Serialization for client-server communication. use std::any::Any; use std::char; @@ -71,15 +71,18 @@ macro_rules! rpc_encode_decode { (enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => { impl),+)*> Encode for $name $(<$($T),+>)* { fn encode(self, w: &mut Writer, s: &mut S) { - // HACK(eddyb) `Tag` enum duplicated between the + // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. - #[repr(u8)] enum Tag { $($variant),* } #[allow(non_upper_case_globals)] - impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* } + mod tag { + #[repr(u8)] enum Tag { $($variant),* } + + $(pub const $variant: u8 = Tag::$variant as u8;)* + } match self { $($name::$variant $(($field))* => { - ::$variant.encode(w, s); + tag::$variant.encode(w, s); $($field.encode(w, s);)* })* } @@ -90,14 +93,17 @@ macro_rules! rpc_encode_decode { for $name $(<$($T),+>)* { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { - // HACK(eddyb) `Tag` enum duplicated between the + // HACK(eddyb): `Tag` enum duplicated between the // two impls as there's no other place to stash it. - #[repr(u8)] enum Tag { $($variant),* } #[allow(non_upper_case_globals)] - impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* } + mod tag { + #[repr(u8)] enum Tag { $($variant),* } + + $(pub const $variant: u8 = Tag::$variant as u8;)* + } match u8::decode(r, s) { - $(::$variant => { + $(tag::$variant => { $(let $field = DecodeMut::decode(r, s);)* $name::$variant $(($field))* })* diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 8604efbc5742d..504e016e5b803 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -17,7 +17,7 @@ jobserver = "0.1" lazy_static = "1.0.0" scoped-tls = { version = "0.1.1", features = ["nightly"] } log = { version = "0.4", features = ["release_max_level_info", "std"] } -polonius-engine = "0.5.0" +polonius-engine = "0.6.2" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e5fd0aa3c9cbd..070551c0b7b0a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -423,17 +423,6 @@ impl DefId { } } -impl DepKind { - #[inline] - pub fn fingerprint_needed_for_crate_hash(self) -> bool { - match self { - DepKind::HirBody | - DepKind::Krate => true, - _ => false, - } - } -} - define_dep_nodes!( <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 18c3e600778a3..961638151a2a8 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -6,6 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::sync::{Lrc, Lock}; use std::env; use std::hash::Hash; +use std::collections::hash_map::Entry; use ty::{self, TyCtxt}; use util::common::{ProfileQueriesMsg, profq_msg}; @@ -21,12 +22,6 @@ use super::prev::PreviousDepGraph; #[derive(Clone)] pub struct DepGraph { data: Option>, - - // A vector mapping depnodes from the current graph to their associated - // result value fingerprints. Do not rely on the length of this vector - // being the same as the number of nodes in the graph. The vector can - // contain an arbitrary number of zero-entries at the end. - fingerprints: Lrc>> } newtype_index! { @@ -81,30 +76,23 @@ impl DepGraph { pub fn new(prev_graph: PreviousDepGraph, prev_work_products: FxHashMap) -> DepGraph { - // Pre-allocate the fingerprints array. We over-allocate a little so - // that we hopefully don't have to re-allocate during this compilation - // session. let prev_graph_node_count = prev_graph.node_count(); - let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO, - (prev_graph_node_count * 115) / 100); DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: Lock::new(CurrentDepGraph::new()), + current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)), previous: prev_graph, colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)), loaded_from_cache: Default::default(), })), - fingerprints: Lrc::new(Lock::new(fingerprints)), } } pub fn new_disabled() -> DepGraph { DepGraph { data: None, - fingerprints: Lrc::new(Lock::new(IndexVec::new())), } } @@ -116,12 +104,12 @@ impl DepGraph { pub fn query(&self) -> DepGraphQuery { let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - let nodes: Vec<_> = current_dep_graph.nodes.iter().cloned().collect(); + let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect(); let mut edges = Vec::new(); - for (index, edge_targets) in current_dep_graph.edges.iter_enumerated() { - let from = current_dep_graph.nodes[index]; + for (from, edge_targets) in current_dep_graph.data.iter() + .map(|d| (d.node, &d.edges)) { for &edge_target in edge_targets.iter() { - let to = current_dep_graph.nodes[edge_target]; + let to = current_dep_graph.data[edge_target].node; edges.push((from, to)); } } @@ -201,7 +189,7 @@ impl DepGraph { reads: SmallVec::new(), read_set: Default::default(), })), - |data, key, task| data.borrow_mut().complete_task(key, task)) + |data, key, fingerprint, task| data.borrow_mut().complete_task(key, task, fingerprint)) } /// Creates a new dep-graph input with value `input` @@ -219,7 +207,9 @@ impl DepGraph { self.with_task_impl(key, cx, input, true, identity_fn, |_| OpenTask::Ignore, - |data, key, _| data.borrow_mut().alloc_node(key, SmallVec::new())) + |data, key, fingerprint, _| { + data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) + }) } fn with_task_impl<'gcx, C, A, R>( @@ -232,6 +222,7 @@ impl DepGraph { create_task: fn(DepNode) -> OpenTask, finish_task_and_alloc_depnode: fn(&Lock, DepNode, + Fingerprint, OpenTask) -> DepNodeIndex ) -> (R, DepNodeIndex) where @@ -271,26 +262,17 @@ impl DepGraph { profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) }; - let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task); - let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); let current_fingerprint = stable_hasher.finish(); - // Store the current fingerprint - { - let mut fingerprints = self.fingerprints.borrow_mut(); - - if dep_node_index.index() >= fingerprints.len() { - fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO); - } - - debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO, - "DepGraph::with_task() - Duplicate fingerprint \ - insertion for {:?}", key); - fingerprints[dep_node_index] = current_fingerprint; - } + let dep_node_index = finish_task_and_alloc_depnode( + &data.current, + key, + current_fingerprint, + open_task + ); // Determine the color of the new DepNode. if let Some(prev_index) = data.previous.node_to_index_opt(&key) { @@ -312,25 +294,7 @@ impl DepGraph { (result, dep_node_index) } else { - if key.kind.fingerprint_needed_for_crate_hash() { - let mut hcx = cx.get_stable_hashing_context(); - let result = task(cx, arg); - let mut stable_hasher = StableHasher::new(); - result.hash_stable(&mut hcx, &mut stable_hasher); - let fingerprint = stable_hasher.finish(); - - let mut fingerprints = self.fingerprints.borrow_mut(); - let dep_node_index = DepNodeIndex::new(fingerprints.len()); - fingerprints.push(fingerprint); - - debug_assert!(fingerprints[dep_node_index] == fingerprint, - "DepGraph::with_task() - Assigned fingerprint to \ - unexpected index for {:?}", key); - - (result, dep_node_index) - } else { - (task(cx, arg), DepNodeIndex::INVALID) - } + (task(cx, arg), DepNodeIndex::INVALID) } } @@ -381,7 +345,9 @@ impl DepGraph { { self.with_task_impl(key, cx, arg, false, task, |key| OpenTask::EvalAlways { node: key }, - |data, key, task| data.borrow_mut().complete_eval_always_task(key, task)) + |data, key, fingerprint, task| { + data.borrow_mut().complete_eval_always_task(key, task, fingerprint) + }) } #[inline] @@ -427,17 +393,8 @@ impl DepGraph { #[inline] pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - match self.fingerprints.borrow().get(dep_node_index) { - Some(&fingerprint) => fingerprint, - None => { - if let Some(ref data) = self.data { - let dep_node = data.current.borrow().nodes[dep_node_index]; - bug!("Could not find current fingerprint for {:?}", dep_node) - } else { - bug!("Could not find current fingerprint for {:?}", dep_node_index) - } - } - } + let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut(); + current.data[dep_node_index].fingerprint } pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { @@ -498,17 +455,20 @@ impl DepGraph { pub fn serialize(&self) -> SerializedDepGraph { let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - let fingerprints = self.fingerprints.borrow().clone().convert_index_type(); - let nodes = current_dep_graph.nodes.clone().convert_index_type(); + let fingerprints: IndexVec = + current_dep_graph.data.iter().map(|d| d.fingerprint).collect(); + let nodes: IndexVec = + current_dep_graph.data.iter().map(|d| d.node).collect(); - let total_edge_count: usize = current_dep_graph.edges.iter() - .map(|v| v.len()) - .sum(); + let total_edge_count: usize = current_dep_graph.data.iter() + .map(|d| d.edges.len()) + .sum(); let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(total_edge_count); - for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() { + for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated() + .map(|(i, d)| (i, &d.edges)) { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index()))); @@ -700,34 +660,14 @@ impl DepGraph { let (dep_node_index, did_allocation) = { let mut current = data.current.borrow_mut(); - if let Some(&dep_node_index) = current.node_to_node_index.get(&dep_node) { - // Someone else allocated it before us - (dep_node_index, false) - } else { - // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - (current.alloc_node(*dep_node, current_deps), true) - } - }; - - // ... copying the fingerprint from the previous graph too, so we don't - // have to recompute it ... - { + // Copy the fingerprint from the previous graph, + // so we don't have to recompute it let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); - let mut fingerprints = self.fingerprints.borrow_mut(); - - if dep_node_index.index() >= fingerprints.len() { - fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO); - } - // Multiple threads can all write the same fingerprint here - #[cfg(not(parallel_queries))] - debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO, - "DepGraph::try_mark_green() - Duplicate fingerprint \ - insertion for {:?}", dep_node); - - fingerprints[dep_node_index] = fingerprint; - } + // We allocating an entry for the node in the current dependency graph and + // adding all the appropriate edges imported from the previous graph + current.intern_node(*dep_node, current_deps, fingerprint) + }; // ... emitting any stored diagnostic ... if did_allocation { @@ -814,7 +754,7 @@ impl DepGraph { pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { debug!("mark_loaded_from_cache({:?}, {})", - self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index], + self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node, state); self.data @@ -877,9 +817,15 @@ pub enum WorkProductFileKind { BytecodeCompressed, } +#[derive(Clone)] +struct DepNodeData { + node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint, +} + pub(super) struct CurrentDepGraph { - nodes: IndexVec, - edges: IndexVec>, + data: IndexVec, node_to_node_index: FxHashMap, forbidden_edge: Option, @@ -901,7 +847,7 @@ pub(super) struct CurrentDepGraph { } impl CurrentDepGraph { - fn new() -> CurrentDepGraph { + fn new(prev_graph_node_count: usize) -> CurrentDepGraph { use std::time::{SystemTime, UNIX_EPOCH}; let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); @@ -924,10 +870,17 @@ impl CurrentDepGraph { None }; + // Pre-allocate the dep node structures. We over-allocate a little so + // that we hopefully don't have to re-allocate during this compilation + // session. + let new_node_count_estimate = (prev_graph_node_count * 115) / 100; + CurrentDepGraph { - nodes: IndexVec::new(), - edges: IndexVec::new(), - node_to_node_index: Default::default(), + data: IndexVec::with_capacity(new_node_count_estimate), + node_to_node_index: FxHashMap::with_capacity_and_hasher( + new_node_count_estimate, + Default::default(), + ), anon_id_seed: stable_hasher.finish(), forbidden_edge, total_read_count: 0, @@ -935,7 +888,12 @@ impl CurrentDepGraph { } } - fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { + fn complete_task( + &mut self, + key: DepNode, + task: OpenTask, + fingerprint: Fingerprint + ) -> DepNodeIndex { if let OpenTask::Regular(task) = task { let RegularOpenTask { node, @@ -956,17 +914,17 @@ impl CurrentDepGraph { // better in general. node.kind != DepKind::DefSpan && reads.iter().any(|&i| { - !(self.nodes[i].kind == DepKind::CrateMetadata || - self.nodes[i].kind == DepKind::Krate) + !(self.data[i].node.kind == DepKind::CrateMetadata || + self.data[i].node.kind == DepKind::Krate) }) { bug!("Input node {:?} with unexpected reads: {:?}", node, - reads.iter().map(|&i| self.nodes[i]).collect::>()) + reads.iter().map(|&i| self.data[i].node).collect::>()) } } - self.alloc_node(node, reads) + self.alloc_node(node, reads, fingerprint) } else { bug!("complete_task() - Expected regular task to be popped") } @@ -984,7 +942,7 @@ impl CurrentDepGraph { let mut hasher = StableHasher::new(); for &read in reads.iter() { - let read_dep_node = self.nodes[read]; + let read_dep_node = self.data[read].node; ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher); @@ -1001,23 +959,24 @@ impl CurrentDepGraph { hash: fingerprint, }; - if let Some(&index) = self.node_to_node_index.get(&target_dep_node) { - index - } else { - self.alloc_node(target_dep_node, reads) - } + self.intern_node(target_dep_node, reads, Fingerprint::ZERO).0 } else { bug!("pop_anon_task() - Expected anonymous task to be popped") } } - fn complete_eval_always_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex { + fn complete_eval_always_task( + &mut self, + key: DepNode, + task: OpenTask, + fingerprint: Fingerprint + ) -> DepNodeIndex { if let OpenTask::EvalAlways { node, } = task { debug_assert_eq!(node, key); let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)]; - self.alloc_node(node, smallvec![krate_idx]) + self.alloc_node(node, smallvec![krate_idx], fingerprint) } else { bug!("complete_eval_always_task() - Expected eval always task to be popped"); } @@ -1036,7 +995,7 @@ impl CurrentDepGraph { if cfg!(debug_assertions) { if let Some(ref forbidden_edge) = self.forbidden_edge { let target = &task.node; - let source = self.nodes[source]; + let source = self.data[source].node; if forbidden_edge.test(&source, &target) { bug!("forbidden edge {:?} -> {:?} created", source, @@ -1061,18 +1020,37 @@ impl CurrentDepGraph { }) } - fn alloc_node(&mut self, - dep_node: DepNode, - edges: SmallVec<[DepNodeIndex; 8]>) - -> DepNodeIndex { - debug_assert_eq!(self.edges.len(), self.nodes.len()); - debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len()); + fn alloc_node( + &mut self, + dep_node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint + ) -> DepNodeIndex { debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); - let dep_node_index = DepNodeIndex::new(self.nodes.len()); - self.nodes.push(dep_node); - self.node_to_node_index.insert(dep_node, dep_node_index); - self.edges.push(edges); - dep_node_index + self.intern_node(dep_node, edges, fingerprint).0 + } + + fn intern_node( + &mut self, + dep_node: DepNode, + edges: SmallVec<[DepNodeIndex; 8]>, + fingerprint: Fingerprint + ) -> (DepNodeIndex, bool) { + debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); + + match self.node_to_node_index.entry(dep_node) { + Entry::Occupied(entry) => (*entry.get(), false), + Entry::Vacant(entry) => { + let dep_node_index = DepNodeIndex::new(self.data.len()); + self.data.push(DepNodeData { + node: dep_node, + edges, + fingerprint + }); + entry.insert(dep_node_index); + (dep_node_index, true) + } + } } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index d073a4dd0c9c2..4bc52e82f9be1 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1552,7 +1552,8 @@ fn takes_u8(_: u8) {} fn main() { unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: transmute called with types of different sizes + // error: cannot transmute between types of different sizes, + // or dependently-sized types } ``` diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2f0a95445a886..d4f891c874a40 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -454,7 +454,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_vis(&item.vis); - visitor.visit_name(item.span, item.name); + visitor.visit_ident(item.ident); match item.node { ItemKind::ExternCrate(orig_name) => { visitor.visit_id(item.id); @@ -472,7 +472,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_nested_body(body); } ItemKind::Fn(ref declaration, header, ref generics, body_id) => { - visitor.visit_fn(FnKind::ItemFn(item.name, + visitor.visit_fn(FnKind::ItemFn(item.ident.name, generics, header, &item.vis, @@ -528,7 +528,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { ItemKind::Union(ref struct_definition, ref generics) => { visitor.visit_generics(generics); visitor.visit_id(item.id); - visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); + visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.id, + item.span); } ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => { visitor.visit_id(item.id); @@ -569,9 +570,9 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant, generics: &'v Generics, parent_item_id: NodeId) { - visitor.visit_name(variant.span, variant.node.name); + visitor.visit_ident(variant.node.ident); visitor.visit_variant_data(&variant.node.data, - variant.node.name, + variant.node.ident.name, generics, parent_item_id, variant.span); @@ -720,7 +721,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) { visitor.visit_id(foreign_item.id); visitor.visit_vis(&foreign_item.vis); - visitor.visit_name(foreign_item.span, foreign_item.name); + visitor.visit_ident(foreign_item.ident); match foreign_item.node { ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 32514caff876c..359bd37488241 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1360,7 +1360,7 @@ impl<'a> LoweringContext<'a> { let exist_ty_item = hir::Item { id: exist_ty_id.node_id, hir_id: exist_ty_id.hir_id, - name: keywords::Invalid.name(), + ident: keywords::Invalid.ident(), attrs: Default::default(), node: exist_ty_item_kind, vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited), @@ -1563,7 +1563,7 @@ impl<'a> LoweringContext<'a> { fn lower_variant(&mut self, v: &Variant) -> hir::Variant { Spanned { node: hir::VariantKind { - name: v.node.ident.name, + ident: v.node.ident, attrs: self.lower_attrs(&v.node.attrs), data: self.lower_variant_data(&v.node.data), disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), @@ -2737,7 +2737,7 @@ impl<'a> LoweringContext<'a> { fn lower_item_kind( &mut self, id: NodeId, - name: &mut Name, + ident: &mut Ident, attrs: &hir::HirVec, vis: &mut hir::Visibility, i: &ItemKind, @@ -2751,7 +2751,7 @@ impl<'a> LoweringContext<'a> { span: use_tree.span, }; - self.lower_use_tree(use_tree, &prefix, id, vis, name, attrs) + self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { let value = self.lower_body(None, |this| this.lower_expr(e)); @@ -2943,7 +2943,7 @@ impl<'a> LoweringContext<'a> { prefix: &Path, id: NodeId, vis: &mut hir::Visibility, - name: &mut Name, + ident: &mut Ident, attrs: &hir::HirVec, ) -> hir::ItemKind { debug!("lower_use_tree(tree={:?})", tree); @@ -2959,28 +2959,28 @@ impl<'a> LoweringContext<'a> { match tree.kind { UseTreeKind::Simple(rename, id1, id2) => { - *name = tree.ident().name; + *ident = tree.ident(); - // First apply the prefix to the path + // First, apply the prefix to the path. let mut path = Path { segments, span: path.span, }; - // Correctly resolve `self` imports + // Correctly resolve `self` imports. if path.segments.len() > 1 && path.segments.last().unwrap().ident.name == keywords::SelfLower.name() { let _ = path.segments.pop(); if rename.is_none() { - *name = path.segments.last().unwrap().ident.name; + *ident = path.segments.last().unwrap().ident; } } let parent_def_index = self.current_hir_id_owner.last().unwrap().0; let mut defs = self.expect_full_def_from_use(id); - // we want to return *something* from this function, so hang onto the first item - // for later + // We want to return *something* from this function, so hold onto the first item + // for later. let ret_def = defs.next().unwrap_or(Def::Err); // Here, we are looping over namespaces, if they exist for the definition @@ -2990,7 +2990,7 @@ impl<'a> LoweringContext<'a> { // two imports. for (def, &new_node_id) in defs.zip([id1, id2].iter()) { let vis = vis.clone(); - let name = name.clone(); + let ident = ident.clone(); let mut path = path.clone(); for seg in &mut path.segments { seg.id = self.sess.next_node_id(); @@ -3031,7 +3031,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id.node_id, hir_id: new_id.hir_id, - name: name, + ident, attrs: attrs.clone(), node: item, vis, @@ -3057,8 +3057,8 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { - // Nested imports are desugared into simple - // imports. So if we start with + // Nested imports are desugared into simple imports. + // So, if we start with // // ``` // pub(x) use foo::{a, b}; @@ -3079,14 +3079,14 @@ impl<'a> LoweringContext<'a> { // `self.items`. However, the structure of this // function also requires us to return one item, and // for that we return the `{}` import (called the - // "`ListStem`"). + // `ListStem`). let prefix = Path { segments, span: prefix.span.to(path.span), }; - // Add all the nested PathListItems to the HIR. + // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { self.allocate_hir_id_counter(id, &use_tree); @@ -3096,10 +3096,10 @@ impl<'a> LoweringContext<'a> { } = self.lower_node_id(id); let mut vis = vis.clone(); - let mut name = name.clone(); + let mut ident = ident.clone(); let mut prefix = prefix.clone(); - // Give the segments new ids since they are being cloned. + // Give the segments new node-ids since they are being cloned. for seg in &mut prefix.segments { seg.id = self.sess.next_node_id(); } @@ -3114,7 +3114,7 @@ impl<'a> LoweringContext<'a> { &prefix, new_id, &mut vis, - &mut name, + &mut ident, attrs); let vis_kind = match vis.node { @@ -3138,7 +3138,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id, hir_id: new_hir_id, - name, + ident, attrs: attrs.clone(), node: item, vis, @@ -3165,7 +3165,7 @@ impl<'a> LoweringContext<'a> { *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); } hir::VisibilityKind::Restricted { .. } => { - // do nothing here, as described in the comment on the match + // Do nothing here, as described in the comment on the match. } } @@ -3413,7 +3413,7 @@ impl<'a> LoweringContext<'a> { } pub fn lower_item(&mut self, i: &Item) -> Option { - let mut name = i.ident.name; + let mut ident = i.ident; let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { @@ -3421,7 +3421,7 @@ impl<'a> LoweringContext<'a> { attr::contains_name(&i.attrs, "rustc_doc_only_macro") { let body = self.lower_token_stream(def.stream()); self.exported_macros.push(hir::MacroDef { - name, + name: ident.name, vis, attrs, id: i.id, @@ -3433,14 +3433,14 @@ impl<'a> LoweringContext<'a> { return None; } - let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node); + let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); Some(hir::Item { id: node_id, hir_id, - name, + ident, attrs, node, vis, @@ -3453,7 +3453,7 @@ impl<'a> LoweringContext<'a> { let def_id = self.resolver.definitions().local_def_id(node_id); hir::ForeignItem { id: node_id, - name: i.ident.name, + ident: i.ident, attrs: self.lower_attrs(&i.attrs), node: match i.node { ForeignItemKind::Fn(ref fdec, ref generics) => { diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 895e1e782ab6e..837a20ac0f2f0 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -228,7 +228,7 @@ impl<'a> FnLikeNode<'a> { ast::ItemKind::Fn(ref decl, header, ref generics, block) => item_fn(ItemFnParts { id: i.id, - name: i.name, + name: i.ident.name, decl: &decl, body: block, vis: &i.vis, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index d00d7b9f44e60..78acea9f58814 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -41,21 +41,69 @@ pub(super) struct NodeCollector<'a, 'hir> { // We are collecting DepNode::HirBody hashes here so we can compute the // crate hash from then later on. - hir_body_nodes: Vec<(DefPathHash, DepNodeIndex)>, + hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, +} + +fn input_dep_node_and_hash<'a, I>( + dep_graph: &DepGraph, + hcx: &mut StableHashingContext<'a>, + dep_node: DepNode, + input: I, +) -> (DepNodeIndex, Fingerprint) +where + I: HashStable>, +{ + let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; + + let hash = if dep_graph.is_fully_enabled() { + dep_graph.fingerprint_of(dep_node_index) + } else { + let mut stable_hasher = StableHasher::new(); + input.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() + }; + + (dep_node_index, hash) +} + +fn alloc_hir_dep_nodes<'a, I>( + dep_graph: &DepGraph, + hcx: &mut StableHashingContext<'a>, + def_path_hash: DefPathHash, + item_like: I, + hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, +) -> (DepNodeIndex, DepNodeIndex) +where + I: HashStable>, +{ + let sig = dep_graph.input_task( + def_path_hash.to_dep_node(DepKind::Hir), + &mut *hcx, + HirItemLike { item_like: &item_like, hash_bodies: false }, + ).1; + let (full, hash) = input_dep_node_and_hash( + dep_graph, + hcx, + def_path_hash.to_dep_node(DepKind::HirBody), + HirItemLike { item_like: &item_like, hash_bodies: true }, + ); + hir_body_nodes.push((def_path_hash, hash)); + (sig, full) } impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root(krate: &'hir Crate, dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, - hcx: StableHashingContext<'a>, + mut hcx: StableHashingContext<'a>, source_map: &'a SourceMap) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); + let mut hir_body_nodes = Vec::new(); + // Allocate DepNodes for the root module - let (root_mod_sig_dep_index, root_mod_full_dep_index); - { + let (root_mod_sig_dep_index, root_mod_full_dep_index) = { let Crate { ref module, // Crate attributes are not copied over to the root `Mod`, so hash @@ -73,28 +121,23 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { body_ids: _, } = *krate; - root_mod_sig_dep_index = dep_graph.input_task( - root_mod_def_path_hash.to_dep_node(DepKind::Hir), - &hcx, - HirItemLike { item_like: (module, attrs, span), hash_bodies: false }, - ).1; - root_mod_full_dep_index = dep_graph.input_task( - root_mod_def_path_hash.to_dep_node(DepKind::HirBody), - &hcx, - HirItemLike { item_like: (module, attrs, span), hash_bodies: true }, - ).1; - } + alloc_hir_dep_nodes( + dep_graph, + &mut hcx, + root_mod_def_path_hash, + (module, attrs, span), + &mut hir_body_nodes, + ) + }; { dep_graph.input_task( DepNode::new_no_params(DepKind::AllLocalTraitImpls), - &hcx, + &mut hcx, &krate.trait_impls, ); } - let hir_body_nodes = vec![(root_mod_def_path_hash, root_mod_full_dep_index)]; - let mut collector = NodeCollector { krate, source_map, @@ -129,10 +172,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let node_hashes = self .hir_body_nodes .iter() - .fold(Fingerprint::ZERO, |fingerprint, &(def_path_hash, dep_node_index)| { - fingerprint.combine( - def_path_hash.0.combine(self.dep_graph.fingerprint_of(dep_node_index)) - ) + .fold(Fingerprint::ZERO, |combined_fingerprint, &(def_path_hash, fingerprint)| { + combined_fingerprint.combine(def_path_hash.0.combine(fingerprint)) }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { @@ -159,17 +200,19 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { source_file_names.sort_unstable(); - let (_, crate_dep_node_index) = self - .dep_graph - .input_task(DepNode::new_no_params(DepKind::Krate), - &self.hcx, - (((node_hashes, upstream_crates), source_file_names), - (commandline_args_hash, - crate_disambiguator.to_fingerprint()))); - - let svh = Svh::new(self.dep_graph - .fingerprint_of(crate_dep_node_index) - .to_smaller_hash()); + let crate_hash_input = ( + ((node_hashes, upstream_crates), source_file_names), + (commandline_args_hash, crate_disambiguator.to_fingerprint()) + ); + + let (_, crate_hash) = input_dep_node_and_hash( + self.dep_graph, + &mut self.hcx, + DepNode::new_no_params(DepKind::Krate), + crate_hash_input, + ); + + let svh = Svh::new(crate_hash.to_smaller_hash()); (self.map, svh) } @@ -251,19 +294,15 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - self.current_signature_dep_index = self.dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &self.hcx, - HirItemLike { item_like, hash_bodies: false }, - ).1; - - self.current_full_dep_index = self.dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::HirBody), - &self.hcx, - HirItemLike { item_like, hash_bodies: true }, - ).1; - - self.hir_body_nodes.push((def_path_hash, self.current_full_dep_index)); + let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes( + self.dep_graph, + &mut self.hcx, + def_path_hash, + item_like, + &mut self.hir_body_nodes, + ); + self.current_signature_dep_index = signature_dep_index; + self.current_full_dep_index = full_dep_index; self.current_dep_node_owner = dep_node_owner; self.currently_in_body = false; diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d7c51f1e5fd36..188d487d64485 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -813,11 +813,11 @@ impl<'hir> Map<'hir> { /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { - Node::Item(i) => i.name, - Node::ForeignItem(i) => i.name, + Node::Item(i) => i.ident.name, + Node::ForeignItem(fi) => fi.ident.name, Node::ImplItem(ii) => ii.ident.name, Node::TraitItem(ti) => ti.ident.name, - Node::Variant(v) => v.node.name, + Node::Variant(v) => v.node.ident.name, Node::Field(f) => f.ident.name, Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, @@ -953,7 +953,7 @@ impl<'a, 'hir> NodesMatchingSuffix<'a, 'hir> { loop { if let Node::Item(item) = map.find(id)? { if item_is_mod(&item) { - return Some((id, item.name)) + return Some((id, item.ident.name)) } } let parent = map.get_parent(id); @@ -1009,9 +1009,9 @@ trait Named { impl Named for Spanned { fn name(&self) -> Name { self.node.name() } } -impl Named for Item { fn name(&self) -> Name { self.name } } -impl Named for ForeignItem { fn name(&self) -> Name { self.name } } -impl Named for VariantKind { fn name(&self) -> Name { self.name } } +impl Named for Item { fn name(&self) -> Name { self.ident.name } } +impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } +impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } } impl Named for StructField { fn name(&self) -> Name { self.ident.name } } impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } @@ -1194,7 +1194,7 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { } Some(Node::Variant(ref variant)) => { format!("variant {} in {}{}", - variant.node.name, + variant.node.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 56144129ef4c2..7e87171a5edf7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -420,7 +420,7 @@ pub struct GenericArgs { /// The generic arguments for this path segment. pub args: HirVec, /// Bindings (equality constraints) on associated types, if present. - /// E.g., `Foo`. + /// E.g., `Foo`. pub bindings: HirVec, /// Were arguments written in parenthesized form `Fn(T) -> U`? /// This is required mostly for pretty-printing and diagnostics, @@ -2015,7 +2015,7 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct VariantKind { - pub name: Name, + pub ident: Ident, pub attrs: HirVec, pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1` @@ -2090,6 +2090,15 @@ impl VisibilityKind { VisibilityKind::Restricted { .. } => true, } } + + pub fn descr(&self) -> &'static str { + match *self { + VisibilityKind::Public => "public", + VisibilityKind::Inherited => "private", + VisibilityKind::Crate(..) => "crate-visible", + VisibilityKind::Restricted { .. } => "restricted", + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2176,7 +2185,7 @@ pub struct ItemId { /// The name might be a dummy name in case of anonymous items #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { - pub name: Name, + pub ident: Ident, pub id: NodeId, pub hir_id: HirId, pub attrs: HirVec, @@ -2331,7 +2340,7 @@ pub enum AssociatedItemKind { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignItem { - pub name: Name, + pub ident: Ident, pub attrs: HirVec, pub node: ForeignItemKind, pub id: NodeId, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index e19da011be1d6..d7acdefcc7d71 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -452,7 +452,7 @@ impl<'a> State<'a> { abi: Abi::Rust, asyncness: hir::IsAsync::NotAsync, }, - Some(item.name), + Some(item.ident.name), generics, &item.vis, arg_names, @@ -466,7 +466,7 @@ impl<'a> State<'a> { if m { self.word_space("mut")?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&t)?; self.s.word(";")?; @@ -475,7 +475,7 @@ impl<'a> State<'a> { } hir::ForeignItemKind::Type => { self.head(visibility_qualified(&item.vis, "type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end the head-ibox self.end() // end the outer cbox @@ -535,7 +535,7 @@ impl<'a> State<'a> { self.s.word("as")?; self.s.space()?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.s.word(";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block @@ -546,10 +546,10 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { - if path.segments.last().unwrap().ident.name != item.name { + if path.segments.last().unwrap().ident != item.ident { self.s.space()?; self.word_space("as")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; } self.s.word(";")?; } @@ -564,7 +564,7 @@ impl<'a> State<'a> { if m == hir::MutMutable { self.word_space("mut")?; } - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&ty)?; self.s.space()?; @@ -577,7 +577,7 @@ impl<'a> State<'a> { } hir::ItemKind::Const(ref ty, expr) => { self.head(visibility_qualified(&item.vis, "const"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.word_space(":")?; self.print_type(&ty)?; self.s.space()?; @@ -592,7 +592,7 @@ impl<'a> State<'a> { self.head("")?; self.print_fn(decl, header, - Some(item.name), + Some(item.ident.name), typarams, &item.vis, &[], @@ -604,7 +604,7 @@ impl<'a> State<'a> { } hir::ItemKind::Mod(ref _mod) => { self.head(visibility_qualified(&item.vis, "mod"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.nbsp()?; self.bopen()?; self.print_mod(_mod, &item.attrs)?; @@ -624,7 +624,7 @@ impl<'a> State<'a> { } hir::ItemKind::Ty(ref ty, ref generics) => { self.head(visibility_qualified(&item.vis, "type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox @@ -637,7 +637,7 @@ impl<'a> State<'a> { } hir::ItemKind::Existential(ref exist) => { self.head(visibility_qualified(&item.vis, "existential type"))?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&exist.generics.params)?; self.end()?; // end the inner ibox @@ -659,15 +659,16 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } hir::ItemKind::Enum(ref enum_definition, ref params) => { - self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?; + self.print_enum_def(enum_definition, params, item.ident.name, item.span, + &item.vis)?; } hir::ItemKind::Struct(ref struct_def, ref generics) => { self.head(visibility_qualified(&item.vis, "struct"))?; - self.print_struct(struct_def, generics, item.name, item.span, true)?; + self.print_struct(struct_def, generics, item.ident.name, item.span, true)?; } hir::ItemKind::Union(ref struct_def, ref generics) => { self.head(visibility_qualified(&item.vis, "union"))?; - self.print_struct(struct_def, generics, item.name, item.span, true)?; + self.print_struct(struct_def, generics, item.ident.name, item.span, true)?; } hir::ItemKind::Impl(unsafety, polarity, @@ -714,7 +715,7 @@ impl<'a> State<'a> { self.print_is_auto(is_auto)?; self.print_unsafety(unsafety)?; self.word_nbsp("trait")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { @@ -739,7 +740,7 @@ impl<'a> State<'a> { self.head("")?; self.print_visibility(&item.vis)?; self.word_nbsp("trait")?; - self.print_name(item.name)?; + self.print_ident(item.ident)?; self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax @@ -897,7 +898,7 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> { self.head("")?; let generics = hir::Generics::empty(); - self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; + self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false)?; if let Some(ref d) = v.node.disr_expr { self.s.space()?; self.word_space("=")?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index bf9efb54b600f..8ff60e5f56225 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -818,7 +818,7 @@ impl_stable_hash_for!(struct hir::EnumDef { }); impl_stable_hash_for!(struct hir::VariantKind { - name, + ident -> (ident.name), attrs, data, disr_expr @@ -852,7 +852,7 @@ impl<'a> HashStable> for hir::Item { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Item { - name, + ident, ref attrs, id: _, hir_id: _, @@ -862,7 +862,7 @@ impl<'a> HashStable> for hir::Item { } = *self; hcx.hash_hir_item_like(|hcx| { - name.hash_stable(hcx, hasher); + ident.name.hash_stable(hcx, hasher); attrs.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher); @@ -926,7 +926,7 @@ impl<'a> HashStable> for hir::AssociatedItemKind { } impl_stable_hash_for!(struct hir::ForeignItem { - name, + ident -> (ident.name), attrs, node, id, diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index dbabff9ee88c2..002ac7cc7a9bb 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -494,22 +494,5 @@ impl<'a, 'gcx> HashStable> for mir::ClosureOutlivesSubj impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted }); -impl<'a, 'gcx> HashStable> for mir::UserTypeAnnotation<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - mir::UserTypeAnnotation::Ty(ref ty) => { - ty.hash_stable(hcx, hasher); - } - mir::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => { - def_id.hash_stable(hcx, hasher); - substs.hash_stable(hcx, hasher); - } - } - } -} - impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base, projs }); impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents }); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 65b8f04e30a12..b2fe4b7561c5a 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1251,3 +1251,29 @@ impl_stable_hash_for!( goal, } ); + +impl<'a, 'gcx> HashStable> for ty::UserTypeAnnotation<'gcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + ty::UserTypeAnnotation::Ty(ref ty) => { + ty.hash_stable(hcx, hasher); + } + ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => { + def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + } + } + } +} + +impl<'a> HashStable> for ty::UserTypeAnnotationIndex { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.index().hash_stable(hcx, hasher); + } +} diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 75407835a1b55..4cce8343c02c8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -132,12 +132,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ReEmpty => ("the empty lifetime".to_owned(), None), + ty::RePlaceholder(_) => (format!("any other region"), None), + // FIXME(#13998) RePlaceholder should probably print like // ReFree rather than dumping Debug output on the user. // // We shouldn't really be having unification failures with ReVar // and ReLateBound though. - ty::RePlaceholder(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } @@ -324,8 +326,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the error. If all of these fails, we fall back to a rather // general bit of code that displays the error information RegionResolutionError::ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(region_scope_tree, origin, sub, sup) - .emit(); + if sub.is_placeholder() || sup.is_placeholder() { + self.report_placeholder_failure(region_scope_tree, origin, sub, sup) + .emit(); + } else { + self.report_concrete_failure(region_scope_tree, origin, sub, sup) + .emit(); + } } RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => { @@ -339,20 +346,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } RegionResolutionError::SubSupConflict( + _, var_origin, sub_origin, sub_r, sup_origin, sup_r, ) => { - self.report_sub_sup_conflict( - region_scope_tree, - var_origin, - sub_origin, - sub_r, - sup_origin, - sup_r, - ); + if sub_r.is_placeholder() { + self.report_placeholder_failure( + region_scope_tree, + sub_origin, + sub_r, + sup_r, + ) + .emit(); + } else if sup_r.is_placeholder() { + self.report_placeholder_failure( + region_scope_tree, + sup_origin, + sub_r, + sup_r, + ) + .emit(); + } else { + self.report_sub_sup_conflict( + region_scope_tree, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ); + } } } } @@ -407,7 +433,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { errors.sort_by_key(|u| match *u { RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::SubSupConflict(ref rvo, _, _, _, _) => rvo.span(), + RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), }); errors } @@ -956,6 +982,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diag.span_label(span, message); } } + self.suggest_as_ref_where_appropriate(span, &exp_found, diag); } diag.note_expected_found(&"type", expected, found); @@ -972,6 +999,72 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.note_error_origin(diag, &cause); } + /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate, + /// suggest it. + fn suggest_as_ref_where_appropriate( + &self, + span: Span, + exp_found: &ty::error::ExpectedFound>, + diag: &mut DiagnosticBuilder<'tcx>, + ) { + match (&exp_found.expected.sty, &exp_found.found.sty) { + (TyKind::Adt(exp_def, exp_substs), TyKind::Ref(_, found_ty, _)) => { + if let TyKind::Adt(found_def, found_substs) = found_ty.sty { + let path_str = format!("{:?}", exp_def); + if exp_def == &found_def { + let opt_msg = "you can convert from `&Option` to `Option<&T>` using \ + `.as_ref()`"; + let result_msg = "you can convert from `&Result` to \ + `Result<&T, &E>` using `.as_ref()`"; + let have_as_ref = &[ + ("std::option::Option", opt_msg), + ("core::option::Option", opt_msg), + ("std::result::Result", result_msg), + ("core::result::Result", result_msg), + ]; + if let Some(msg) = have_as_ref.iter() + .filter_map(|(path, msg)| if &path_str == path { + Some(msg) + } else { + None + }).next() + { + let mut show_suggestion = true; + for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { + match exp_ty.sty { + TyKind::Ref(_, exp_ty, _) => { + match (&exp_ty.sty, &found_ty.sty) { + (_, TyKind::Param(_)) | + (_, TyKind::Infer(_)) | + (TyKind::Param(_), _) | + (TyKind::Infer(_), _) => {} + _ if ty::TyS::same_type(exp_ty, found_ty) => {} + _ => show_suggestion = false, + }; + } + TyKind::Param(_) | TyKind::Infer(_) => {} + _ => show_suggestion = false, + } + } + if let (Ok(snippet), true) = ( + self.tcx.sess.source_map().span_to_snippet(span), + show_suggestion, + ) { + diag.span_suggestion_with_applicability( + span, + msg, + format!("{}.as_ref()", snippet), + Applicability::MachineApplicable, + ); + } + } + } + } + } + _ => {} + } + } + pub fn report_and_explain_type_error( &self, trace: TypeTrace<'tcx>, @@ -1239,6 +1332,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (&sup_origin, &sub_origin) { (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => { + debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); + debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); + debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); + debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); + debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); + debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); + debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); + debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); + debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values); + if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = ( self.values_str(&sup_trace.values), self.values_str(&sub_trace.values), diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index ecf59daeaf12e..f7ba546fa7f3b 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -8,6 +8,7 @@ use util::common::ErrorReported; mod different_lifetimes; mod find_anon_type; mod named_anon_conflict; +mod placeholder_error; mod outlives_closure; mod static_impl_trait; mod util; @@ -58,10 +59,11 @@ impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { // Due to the improved diagnostics returned by the MIR borrow checker, only a subset of // the nice region errors are required when running under the MIR borrow checker. self.try_report_named_anon_conflict() + .or_else(|| self.try_report_placeholder_conflict()) } pub fn try_report(&self) -> Option { - self.try_report_named_anon_conflict() + self.try_report_from_nll() .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_outlives_closure()) .or_else(|| self.try_report_static_impl_trait()) @@ -69,8 +71,8 @@ impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) { match (&self.error, self.regions) { - (&Some(ConcreteFailure(ref origin, sub, sup)), None) => (origin.span(), sub, sup), - (&Some(SubSupConflict(_, ref origin, sub, _, sup)), None) => (origin.span(), sub, sup), + (Some(ConcreteFailure(origin, sub, sup)), None) => (origin.span(), sub, sup), + (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => (origin.span(), sub, sup), (None, Some((span, sub, sup))) => (span, sub, sup), (Some(_), Some(_)) => panic!("incorrectly built NiceRegionError"), _ => panic!("trying to report on an incorrect lifetime failure"), diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index 789796d95cb14..c4c71037d8b35 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -36,7 +36,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// ...because it cannot outlive this closure /// ``` pub(super) fn try_report_outlives_closure(&self) -> Option { - if let Some(SubSupConflict(origin, + if let Some(SubSupConflict(_, + origin, ref sub_origin, _, ref sup_origin, diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs new file mode 100644 index 0000000000000..0dda636a9bd53 --- /dev/null +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -0,0 +1,307 @@ +use hir::def_id::DefId; +use infer::error_reporting::nice_region_error::NiceRegionError; +use infer::lexical_region_resolve::RegionResolutionError; +use infer::ValuePairs; +use infer::{SubregionOrigin, TypeTrace}; +use traits::{ObligationCause, ObligationCauseCode}; +use ty; +use ty::error::ExpectedFound; +use ty::subst::Substs; +use util::common::ErrorReported; +use util::ppaux::RegionHighlightMode; + +impl NiceRegionError<'me, 'gcx, 'tcx> { + /// When given a `ConcreteFailure` for a function with arguments containing a named region and + /// an anonymous region, emit an descriptive diagnostic error. + pub(super) fn try_report_placeholder_conflict(&self) -> Option { + match &self.error { + /////////////////////////////////////////////////////////////////////////// + // NB. The ordering of cases in this match is very + // sensitive, because we are often matching against + // specific cases and then using an `_` to match all + // others. + + /////////////////////////////////////////////////////////////////////////// + // Check for errors from comparing trait failures -- first + // with two placeholders, then with one. + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_placeholder @ ty::RePlaceholder(_), + _, + sup_placeholder @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(self.tcx.mk_region(ty::ReVar(*vid))), + cause, + Some(sub_placeholder), + Some(sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )) + } + + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_placeholder @ ty::RePlaceholder(_), + _, + _, + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(self.tcx.mk_region(ty::ReVar(*vid))), + cause, + Some(sub_placeholder), + None, + expected.def_id, + expected.substs, + found.substs, + )) + } + + Some(RegionResolutionError::SubSupConflict( + vid, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + _, + _, + sup_placeholder @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(self.tcx.mk_region(ty::ReVar(*vid))), + cause, + None, + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )) + } + + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region @ ty::RePlaceholder(_), + sup_region @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + None, + cause, + Some(*sub_region), + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )) + } + + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region @ ty::RePlaceholder(_), + sup_region, + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(sup_region), + cause, + Some(*sub_region), + None, + expected.def_id, + expected.substs, + found.substs, + )) + } + + Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sub_region, + sup_region @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(sub_region), + cause, + None, + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )) + } + + _ => None, + } + } + + // error[E0308]: implementation of `Foo` does not apply to enough lifetimes + // --> /home/nmatsakis/tmp/foo.rs:12:5 + // | + // 12 | all::<&'static u32>(); + // | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + // | + // = note: Due to a where-clause on the function `all`, + // = note: `T` must implement `...` for any two lifetimes `'1` and `'2`. + // = note: However, the type `T` only implements `...` for some specific lifetime `'2`. + fn try_report_placeholders_trait( + &self, + vid: Option>, + cause: &ObligationCause<'tcx>, + sub_placeholder: Option>, + sup_placeholder: Option>, + trait_def_id: DefId, + expected_substs: &'tcx Substs<'tcx>, + actual_substs: &'tcx Substs<'tcx>, + ) -> ErrorReported { + let mut err = self.tcx.sess.struct_span_err( + cause.span(&self.tcx), + &format!( + "implementation of `{}` is not general enough", + self.tcx.item_path_str(trait_def_id), + ), + ); + + match cause.code { + ObligationCauseCode::ItemObligation(def_id) => { + err.note(&format!( + "Due to a where-clause on `{}`,", + self.tcx.item_path_str(def_id), + )); + } + _ => (), + } + + let expected_trait_ref = ty::TraitRef { + def_id: trait_def_id, + substs: expected_substs, + }; + let actual_trait_ref = ty::TraitRef { + def_id: trait_def_id, + substs: actual_substs, + }; + + // Search the expected and actual trait references to see (a) + // whether the sub/sup placeholders appear in them (sometimes + // you have a trait ref like `T: Foo`, where the + // placeholder was created as part of an inner type) and (b) + // whether the inference variable appears. In each case, + // assign a counter value in each case if so. + let mut counter = 0; + let mut has_sub = None; + let mut has_sup = None; + let mut has_vid = None; + + self.tcx.for_each_free_region(&expected_trait_ref, |r| { + if Some(r) == sub_placeholder && has_sub.is_none() { + has_sub = Some(counter); + counter += 1; + } else if Some(r) == sup_placeholder && has_sup.is_none() { + has_sup = Some(counter); + counter += 1; + } + }); + + self.tcx.for_each_free_region(&actual_trait_ref, |r| { + if Some(r) == vid && has_vid.is_none() { + has_vid = Some(counter); + counter += 1; + } + }); + + let self_ty_has_vid = self + .tcx + .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); + + RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { + RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { + match (has_sub, has_sup) { + (Some(n1), Some(n2)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any two lifetimes `'{}` and `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + )); + } + (Some(n), _) | (_, Some(n)) => { + err.note(&format!( + "`{}` must implement `{}` \ + for any lifetime `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + n, + )); + } + (None, None) => { + err.note(&format!( + "`{}` must implement `{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + )); + } + } + }) + }); + + RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { + Some(n) => { + if self_ty_has_vid { + err.note(&format!( + "but `{}` only implements `{}` for the lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } else { + err.note(&format!( + "but `{}` only implements `{}` for some lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n + )); + } + } + None => { + err.note(&format!( + "but `{}` only implements `{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + )); + } + }); + + err.emit(); + ErrorReported + } +} diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 6d2d2ee93ab50..9fc3bb05cdab1 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -11,6 +11,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { pub(super) fn try_report_static_impl_trait(&self) -> Option { if let Some(ref error) = self.error { if let RegionResolutionError::SubSupConflict( + _, var_origin, sub_origin, sub_r, diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 91da3197d3c1f..e45a4b17cdd9c 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -442,4 +442,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } } + + pub(super) fn report_placeholder_failure( + &self, + region_scope_tree: ®ion::ScopeTree, + placeholder_origin: SubregionOrigin<'tcx>, + sub: Region<'tcx>, + sup: Region<'tcx>, + ) -> DiagnosticBuilder<'tcx> { + // I can't think how to do better than this right now. -nikomatsakis + match placeholder_origin { + infer::Subtype(trace) => { + let terr = TypeError::RegionsPlaceholderMismatch; + self.report_and_explain_type_error(trace, &terr) + } + + _ => { + self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup) + } + } + } } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 3a3a21d0f1d4a..709e8c0ba9b24 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -1,31 +1,23 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use super::{CombinedSnapshot, - InferCtxt, - HigherRankedType, - SubregionOrigin, - PlaceholderMap}; use super::combine::CombineFields; -use super::region_constraints::{TaintDirections}; +use super::{HigherRankedType, InferCtxt, PlaceholderMap}; -use ty::{self, TyCtxt, Binder, TypeFoldable}; -use ty::error::TypeError; use ty::relate::{Relate, RelateResult, TypeRelation}; -use syntax_pos::Span; -use util::nodemap::{FxHashMap, FxHashSet}; - -pub struct HrMatchResult { - pub value: U, -} +use ty::{self, Binder, TypeFoldable}; impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { - pub fn higher_ranked_sub(&mut self, a: &Binder, b: &Binder, a_is_expected: bool) - -> RelateResult<'tcx, Binder> - where T: Relate<'tcx> + pub fn higher_ranked_sub( + &mut self, + a: &Binder, + b: &Binder, + a_is_expected: bool, + ) -> RelateResult<'tcx, Binder> + where + T: Relate<'tcx>, { - debug!("higher_ranked_sub(a={:?}, b={:?})", - a, b); + debug!("higher_ranked_sub(a={:?}, b={:?})", a, b); // Rather than checking the subtype relationship between `a` and `b` // as-is, we need to do some extra work here in order to make sure @@ -35,279 +27,37 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // please see the large comment at the end of the file in the (inlined) module // `doc`. - // Start a snapshot so we can examine "all bindings that were - // created as part of this type comparison". - return self.infcx.commit_if_ok(|snapshot| { - let span = self.trace.cause.span; - - // First, we instantiate each bound region in the supertype with a - // fresh placeholder region. - let (b_prime, placeholder_map) = - self.infcx.replace_bound_vars_with_placeholders(b); - - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other pre-existing region variables -- can name - // the placeholders. - let (a_prime, _) = self.infcx.replace_bound_vars_with_fresh_vars( - span, - HigherRankedType, - a - ); - - debug!("a_prime={:?}", a_prime); - debug!("b_prime={:?}", b_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - - // Presuming type comparison succeeds, we need to check - // that the placeholder regions do not "leak". - self.infcx.leak_check(!a_is_expected, span, &placeholder_map, snapshot)?; - - // We are finished with the placeholder regions now so pop - // them off. - self.infcx.pop_placeholders(placeholder_map, snapshot); - - debug!("higher_ranked_sub: OK result={:?}", result); - - Ok(ty::Binder::bind(result)) - }); - } - - /// The value consists of a pair `(t, u)` where `t` is the - /// *matcher* and `u` is a *value*. The idea is to find a - /// substitution `S` such that `S(t) == b`, and then return - /// `S(u)`. In other words, find values for the late-bound regions - /// in `a` that can make `t == b` and then replace the LBR in `u` - /// with those values. - /// - /// This routine is (as of this writing) used in trait matching, - /// particularly projection. - /// - /// NB. It should not happen that there are LBR appearing in `U` - /// that do not appear in `T`. If that happens, those regions are - /// unconstrained, and this routine replaces them with `'static`. - pub fn higher_ranked_match(&mut self, - a_pair: &Binder<(T, U)>, - b_match: &T, - a_is_expected: bool) - -> RelateResult<'tcx, HrMatchResult> - where T: Relate<'tcx>, - U: TypeFoldable<'tcx> - { - debug!("higher_ranked_match(a={:?}, b={:?})", - a_pair, b_match); - - // Start a snapshot so we can examine "all bindings that were - // created as part of this type comparison". - return self.infcx.commit_if_ok(|snapshot| { - // First, we instantiate each bound region in the matcher - // with a placeholder region. - let ((a_match, a_value), placeholder_map) = - self.infcx.replace_bound_vars_with_placeholders(a_pair); + let span = self.trace.cause.span; - debug!("higher_ranked_match: a_match={:?}", a_match); - debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map); + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. + let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b); - // Equate types now that bound regions have been replaced. - self.equate(a_is_expected).relate(&a_match, &b_match)?; + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other pre-existing region variables -- can name + // the placeholders. + let (a_prime, _) = + self.infcx + .replace_bound_vars_with_fresh_vars(span, HigherRankedType, a); - // Map each placeholder region to a vector of other regions that it - // must be equated with. (Note that this vector may include other - // placeholder regions from `placeholder_map`.) - let placeholder_resolution_map: FxHashMap<_, _> = - placeholder_map - .iter() - .map(|(&br, &placeholder)| { - let tainted_regions = - self.infcx.tainted_regions(snapshot, - placeholder, - TaintDirections::incoming()); // [1] + debug!("a_prime={:?}", a_prime); + debug!("b_prime={:?}", b_prime); - // [1] this routine executes after the placeholder - // regions have been *equated* with something - // else, so examining the incoming edges ought to - // be enough to collect all constraints + // Compare types now that bound regions have been replaced. + let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; - (placeholder, (br, tainted_regions)) - }) - .collect(); + debug!("higher_ranked_sub: OK result={:?}", result); - // For each placeholder region, pick a representative -- which can - // be any region from the sets above, except for other members of - // `placeholder_map`. There should always be a representative if things - // are properly well-formed. - let placeholder_representatives: FxHashMap<_, _> = - placeholder_resolution_map - .iter() - .map(|(&placeholder, &(_, ref regions))| { - let representative = - regions.iter() - .filter(|&&r| !placeholder_resolution_map.contains_key(r)) - .cloned() - .next() - .unwrap_or_else(|| { - bug!("no representative region for `{:?}` in `{:?}`", - placeholder, regions) - }); - - (placeholder, representative) - }) - .collect(); - - // Equate all the members of each placeholder set with the - // representative. - for (placeholder, &(_br, ref regions)) in &placeholder_resolution_map { - let representative = &placeholder_representatives[placeholder]; - debug!("higher_ranked_match: \ - placeholder={:?} representative={:?} regions={:?}", - placeholder, representative, regions); - for region in regions.iter() - .filter(|&r| !placeholder_resolution_map.contains_key(r)) - .filter(|&r| r != representative) - { - let origin = SubregionOrigin::Subtype(self.trace.clone()); - self.infcx.borrow_region_constraints() - .make_eqregion(origin, - *representative, - *region); - } - } - - // Replace the placeholder regions appearing in value with - // their representatives - let a_value = - fold_regions_in( - self.tcx(), - &a_value, - |r, _| placeholder_representatives.get(&r).cloned().unwrap_or(r)); - - debug!("higher_ranked_match: value={:?}", a_value); - - // We are now done with these placeholder variables. - self.infcx.pop_placeholders(placeholder_map, snapshot); - - Ok(HrMatchResult { value: a_value }) - }); + Ok(ty::Binder::bind(result)) } } -fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - unbound_value: &T, - mut fldr: F) - -> T - where T: TypeFoldable<'tcx>, - F: FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, -{ - tcx.fold_regions(unbound_value, &mut false, |region, current_depth| { - // we should only be encountering "escaping" late-bound regions here, - // because the ones at the current level should have been replaced - // with fresh variables - assert!(match *region { - ty::ReLateBound(..) => false, - _ => true - }); - - fldr(region, current_depth) - }) -} - impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn tainted_regions(&self, - snapshot: &CombinedSnapshot<'a, 'tcx>, - r: ty::Region<'tcx>, - directions: TaintDirections) - -> FxHashSet> { - self.borrow_region_constraints().tainted( - self.tcx, - &snapshot.region_constraints_snapshot, - r, - directions) - } - - fn region_vars_confined_to_snapshot(&self, - snapshot: &CombinedSnapshot<'a, 'tcx>) - -> Vec - { - /*! - * Returns the set of region variables that do not affect any - * types/regions which existed before `snapshot` was - * started. This is used in the sub/lub/glb computations. The - * idea here is that when we are computing lub/glb of two - * regions, we sometimes create intermediate region variables. - * Those region variables may touch some of the placeholder or - * other "forbidden" regions we created to replace bound - * regions, but they don't really represent an "external" - * constraint. - * - * However, sometimes fresh variables are created for other - * purposes too, and those *may* represent an external - * constraint. In particular, when a type variable is - * instantiated, we create region variables for all the - * regions that appear within, and if that type variable - * pre-existed the snapshot, then those region variables - * represent external constraints. - * - * An example appears in the unit test - * `sub_free_bound_false_infer`. In this test, we want to - * know whether - * - * ```rust - * fn(_#0t) <: for<'a> fn(&'a int) - * ``` - * - * Note that the subtype has a type variable. Because the type - * variable can't be instantiated with a region that is bound - * in the fn signature, this comparison ought to fail. But if - * we're not careful, it will succeed. - * - * The reason is that when we walk through the subtyping - * algorithm, we begin by replacing `'a` with a placeholder - * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This - * can be made true by unifying `_#0t` with `&'1 int`. In the - * process, we create a fresh variable for the placeholder - * region, `'$2`, and hence we have that `_#0t == &'$2 - * int`. However, because `'$2` was created during the sub - * computation, if we're not careful we will erroneously - * assume it is one of the transient region variables - * representing a lub/glb internally. Not good. - * - * To prevent this, we check for type variables which were - * unified during the snapshot, and say that any region - * variable created during the snapshot but which finds its - * way into a type variable is considered to "escape" the - * snapshot. - */ - - let mut region_vars = - self.borrow_region_constraints().vars_created_since_snapshot( - &snapshot.region_constraints_snapshot); - - let escaping_types = - self.type_variables.borrow_mut().types_escaping_snapshot(&snapshot.type_snapshot); - - let mut escaping_region_vars = FxHashSet::default(); - for ty in &escaping_types { - self.tcx.collect_regions(ty, &mut escaping_region_vars); - } - - region_vars.retain(|®ion_vid| { - let r = ty::ReVar(region_vid); - !escaping_region_vars.contains(&r) - }); - - debug!("region_vars_confined_to_snapshot: region_vars={:?} escaping_types={:?}", - region_vars, - escaping_types); - - region_vars - } - /// Replace all regions (resp. types) bound by `binder` with placeholder /// regions (resp. types) and return a map indicating which bound-region - /// was replaced with what placeholder region. This is the first step of - /// checking subtyping when higher-ranked things are involved. + /// placeholder region. This is the first step of checking subtyping + /// when higher-ranked things are involved. /// /// **Important:** you must call this function from within a snapshot. /// Moreover, before committing the snapshot, you must eventually call @@ -354,201 +104,4 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { (result, map) } - - /// Searches the region constraints created since `snapshot` was started - /// and checks to determine whether any of the placeholder regions created - /// in `placeholder_map` would "escape" -- meaning that they are related to - /// other regions in some way. If so, the higher-ranked subtyping doesn't - /// hold. See `README.md` for more details. - pub fn leak_check(&self, - overly_polymorphic: bool, - _span: Span, - placeholder_map: &PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>) - -> RelateResult<'tcx, ()> - { - debug!("leak_check: placeholder_map={:?}", - placeholder_map); - - // If the user gave `-Zno-leak-check`, then skip the leak - // check completely. This is wildly unsound and also not - // unlikely to cause an ICE or two. It is intended for use - // only during a transition period, in which the MIR typeck - // uses the "universe-style" check, and the rest of typeck - // uses the more conservative leak check. Since the leak - // check is more conservative, we can't test the - // universe-style check without disabling it. - if self.tcx.sess.opts.debugging_opts.no_leak_check { - return Ok(()); - } - - let new_vars = self.region_vars_confined_to_snapshot(snapshot); - for (&placeholder_br, &placeholder) in placeholder_map { - // The inputs to a placeholder variable can only - // be itself or other new variables. - let incoming_taints = self.tainted_regions(snapshot, - placeholder, - TaintDirections::both()); - for &tainted_region in &incoming_taints { - // Each placeholder should only be relatable to itself - // or new variables: - match *tainted_region { - ty::ReVar(vid) => { - if new_vars.contains(&vid) { - continue; - } - } - _ => { - if tainted_region == placeholder { continue; } - } - }; - - debug!("{:?} (which replaced {:?}) is tainted by {:?}", - placeholder, - placeholder_br, - tainted_region); - - return Err(if overly_polymorphic { - debug!("Overly polymorphic!"); - TypeError::RegionsOverlyPolymorphic(placeholder_br, tainted_region) - } else { - debug!("Not as polymorphic!"); - TypeError::RegionsInsufficientlyPolymorphic(placeholder_br, tainted_region) - }) - } - } - - Ok(()) - } - - /// This code converts from placeholder regions back to late-bound - /// regions. It works by replacing each region in the taint set of a - /// placeholder region with a bound-region. The bound region will be bound - /// by the outer-most binder in `value`; the caller must ensure that there is - /// such a binder and it is the right place. - /// - /// This routine is only intended to be used when the leak-check has - /// passed; currently, it's used in the trait matching code to create - /// a set of nested obligations from an impl that matches against - /// something higher-ranked. More details can be found in - /// `librustc/middle/traits/README.md`. - /// - /// As a brief example, consider the obligation `for<'a> Fn(&'a int) - /// -> &'a int`, and the impl: - /// - /// impl Fn for SomethingOrOther - /// where A : Clone - /// { ... } - /// - /// Here we will have replaced `'a` with a placeholder region - /// `'0`. This means that our substitution will be `{A=>&'0 - /// int, R=>&'0 int}`. - /// - /// When we apply the substitution to the bounds, we will wind up with - /// `&'0 int : Clone` as a predicate. As a last step, we then go and - /// replace `'0` with a late-bound region `'a`. The depth is matched - /// to the depth of the predicate, in this case 1, so that the final - /// predicate is `for<'a> &'a int : Clone`. - pub fn plug_leaks(&self, - placeholder_map: PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>, - value: T) -> T - where T : TypeFoldable<'tcx> - { - debug!("plug_leaks(placeholder_map={:?}, value={:?})", - placeholder_map, - value); - - if placeholder_map.is_empty() { - return value; - } - - // Compute a mapping from the "taint set" of each placeholder - // region back to the `ty::BoundRegion` that it originally - // represented. Because `leak_check` passed, we know that - // these taint sets are mutually disjoint. - let inv_placeholder_map: FxHashMap, ty::BoundRegion> = - placeholder_map - .iter() - .flat_map(|(&placeholder_br, &placeholder)| { - self.tainted_regions(snapshot, placeholder, TaintDirections::both()) - .into_iter() - .map(move |tainted_region| (tainted_region, placeholder_br)) - }) - .collect(); - - debug!("plug_leaks: inv_placeholder_map={:?}", - inv_placeholder_map); - - // Remove any instantiated type variables from `value`; those can hide - // references to regions from the `fold_regions` code below. - let value = self.resolve_type_vars_if_possible(&value); - - // Map any placeholder byproducts back to a late-bound - // region. Put that late-bound region at whatever the outermost - // binder is that we encountered in `value`. The caller is - // responsible for ensuring that (a) `value` contains at least one - // binder and (b) that binder is the one we want to use. - let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| { - match inv_placeholder_map.get(&r) { - None => r, - Some(br) => { - // It is the responsibility of the caller to ensure - // that each placeholder region appears within a - // binder. In practice, this routine is only used by - // trait checking, and all of the placeholder regions - // appear inside predicates, which always have - // binders, so this assert is satisfied. - assert!(current_depth > ty::INNERMOST); - - // since leak-check passed, this placeholder region - // should only have incoming edges from variables - // (which ought not to escape the snapshot, but we - // don't check that) or itself - assert!( - match *r { - ty::ReVar(_) => true, - ty::RePlaceholder(index) => index.name == *br, - _ => false, - }, - "leak-check would have us replace {:?} with {:?}", - r, br); - - self.tcx.mk_region(ty::ReLateBound( - current_depth.shifted_out(1), - br.clone(), - )) - } - } - }); - - self.pop_placeholders(placeholder_map, snapshot); - - debug!("plug_leaks: result={:?}", result); - - result - } - - /// Pops the placeholder regions found in `placeholder_map` from the region - /// inference context. Whenever you create placeholder regions via - /// `replace_bound_vars_with_placeholders`, they must be popped before you - /// commit the enclosing snapshot (if you do not commit, e.g., within a - /// probe or as a result of an error, then this is not necessary, as - /// popping happens as part of the rollback). - /// - /// Note: popping also occurs implicitly as part of `leak_check`. - pub fn pop_placeholders( - &self, - placeholder_map: PlaceholderMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>, - ) { - debug!("pop_placeholders({:?})", placeholder_map); - let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect(); - self.borrow_region_constraints().pop_placeholders(&placeholder_regions); - self.universe.set(snapshot.universe); - if !placeholder_map.is_empty() { - self.projection_cache.borrow_mut().rollback_placeholder( - &snapshot.projection_cache_snapshot); - } - } } diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index de64800ee8d35..dbf8f270ab0c9 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -73,12 +73,13 @@ pub enum RegionResolutionError<'tcx> { /// `a` (but none of the known bounds are sufficient). GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region<'tcx>), - /// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`: + /// `SubSupConflict(v, v_origin, sub_origin, sub_r, sup_origin, sup_r)`: /// - /// Could not infer a value for `v` because `sub_r <= v` (due to - /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and + /// Could not infer a value for `v` (which has origin `v_origin`) + /// because `sub_r <= v` (due to `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and /// `sub_r <= sup_r` does not hold. SubSupConflict( + RegionVid, RegionVariableOrigin, SubregionOrigin<'tcx>, Region<'tcx>, @@ -215,23 +216,41 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { ) -> bool { debug!("expand_node({:?}, {:?} == {:?})", a_region, b_vid, b_data); - // Check if this relationship is implied by a given. match *a_region { + // Check if this relationship is implied by a given. ty::ReEarlyBound(_) | ty::ReFree(_) => if self.data.givens.contains(&(a_region, b_vid)) { debug!("given"); return false; }, + _ => {} } + match *b_data { VarValue::Value(cur_region) => { - let lub = self.lub_concrete_regions(a_region, cur_region); + let mut lub = self.lub_concrete_regions(a_region, cur_region); if lub == cur_region { return false; } + // Watch out for `'b: !1` relationships, where the + // universe of `'b` can't name the placeholder `!1`. In + // that case, we have to grow `'b` to be `'static` for the + // relationship to hold. This is obviously a kind of sub-optimal + // choice -- in the future, when we incorporate a knowledge + // of the parameter environment, we might be able to find a + // tighter bound than `'static`. + // + // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.) + let b_universe = self.var_infos[b_vid].universe; + if let ty::RePlaceholder(p) = lub { + if b_universe.cannot_name(p.universe) { + lub = self.tcx().types.re_static; + } + } + debug!( "Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub @@ -554,10 +573,22 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { lower_bounds.sort_by_key(region_order_key); upper_bounds.sort_by_key(region_order_key); + let node_universe = self.var_infos[node_idx].universe; + for lower_bound in &lower_bounds { + let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region { + if node_universe.cannot_name(p.universe) { + self.tcx().types.re_static + } else { + lower_bound.region + } + } else { + lower_bound.region + }; + for upper_bound in &upper_bounds { if !self.region_rels - .is_subregion_of(lower_bound.region, upper_bound.region) + .is_subregion_of(effective_lower_bound, upper_bound.region) { let origin = self.var_infos[node_idx].origin.clone(); debug!( @@ -566,6 +597,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { origin, node_idx, lower_bound.region, upper_bound.region ); errors.push(RegionResolutionError::SubSupConflict( + node_idx, origin, lower_bound.origin.clone(), lower_bound.region, @@ -580,9 +612,10 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { span_bug!( self.var_infos[node_idx].origin.span(), "collect_error_for_expanding_node() could not find \ - error for var {:?}, lower_bounds={:?}, \ - upper_bounds={:?}", + error for var {:?} in universe {:?}, lower_bounds={:#?}, \ + upper_bounds={:#?}", node_idx, + node_universe, lower_bounds, upper_bounds ); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c000e3aa013f8..2d3fb137fafdd 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -32,7 +32,6 @@ use ty::{FloatVid, IntVid, TyVid}; use util::nodemap::FxHashMap; use self::combine::CombineFields; -use self::higher_ranked::HrMatchResult; use self::lexical_region_resolve::LexicalRegionResolutions; use self::outlives::env::OutlivesEnvironment; use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; @@ -226,7 +225,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub type PlaceholderMap<'tcx> = BTreeMap>; /// See `error_reporting` module for more details -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum ValuePairs<'tcx> { Types(ExpectedFound>), Regions(ExpectedFound>), @@ -868,6 +867,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { r } + /// Scan the constraints produced since `snapshot` began and returns: + /// + /// - None -- if none of them involve "region outlives" constraints + /// - Some(true) -- if there are `'a: 'b` constraints where `'a` or `'b` is a placehodler + /// - Some(false) -- if there are `'a: 'b` constraints but none involve placeholders + pub fn region_constraints_added_in_snapshot( + &self, + snapshot: &CombinedSnapshot<'a, 'tcx>, + ) -> Option { + self.borrow_region_constraints().region_constraints_added_in_snapshot( + &snapshot.region_constraints_snapshot, + ) + } + pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) { self.borrow_region_constraints().add_given(sub, sup); } @@ -939,39 +952,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return None; } - Some(self.commit_if_ok(|snapshot| { - let ( - ty::SubtypePredicate { - a_is_expected, - a, - b, - }, - placeholder_map, - ) = self.replace_bound_vars_with_placeholders(predicate); + let ( + ty::SubtypePredicate { + a_is_expected, + a, + b, + }, + _, + ) = self.replace_bound_vars_with_placeholders(predicate); - let cause_span = cause.span; - let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, cause_span, &placeholder_map, snapshot)?; - self.pop_placeholders(placeholder_map, snapshot); - Ok(ok.unit()) - })) + Some( + self.at(cause, param_env) + .sub_exp(a_is_expected, a, b) + .map(|ok| ok.unit()), + ) } pub fn region_outlives_predicate( &self, cause: &traits::ObligationCause<'tcx>, predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, - ) -> UnitResult<'tcx> { - self.commit_if_ok(|snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = - self.replace_bound_vars_with_placeholders(predicate); - let origin = SubregionOrigin::from_obligation_cause(cause, || { - RelateRegionParamBound(cause.span) - }); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, cause.span, &placeholder_map, snapshot)?; - Ok(self.pop_placeholders(placeholder_map, snapshot)) - }) + ) { + let (ty::OutlivesPredicate(r_a, r_b), _) = + self.replace_bound_vars_with_placeholders(predicate); + let origin = + SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` } pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { @@ -1380,46 +1386,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.replace_bound_vars(value, fld_r, fld_t) } - /// Given a higher-ranked projection predicate like: - /// - /// for<'a> >::Output = &'a u32 - /// - /// and a target trait-ref like: - /// - /// > - /// - /// find a substitution `S` for the higher-ranked regions (here, - /// `['a => 'x]`) such that the predicate matches the trait-ref, - /// and then return the value (here, `&'a u32`) but with the - /// substitution applied (hence, `&'x u32`). - /// - /// See `higher_ranked_match` in `higher_ranked/mod.rs` for more - /// details. - pub fn match_poly_projection_predicate( - &self, - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - match_a: ty::PolyProjectionPredicate<'tcx>, - match_b: ty::TraitRef<'tcx>, - ) -> InferResult<'tcx, HrMatchResult>> { - let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty)); - let trace = TypeTrace { - cause, - values: TraitRefs(ExpectedFound::new( - true, - match_pair.skip_binder().0, - match_b, - )), - }; - - let mut combine = self.combine_fields(trace, param_env); - let result = combine.higher_ranked_match(&match_pair, &match_b, true)?; - Ok(InferOk { - value: result, - obligations: combine.obligations, - }) - } - /// See `verify_generic_bound` method in `region_constraints` pub fn verify_generic_bound( &self, @@ -1434,18 +1400,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .verify_generic_bound(origin, kind, a, bound); } - pub fn type_moves_by_default( + pub fn type_is_copy_modulo_regions( &self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, span: Span, ) -> bool { let ty = self.resolve_type_vars_if_possible(&ty); + // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. if !self.in_progress_tables.is_some() || !ty.has_closure_types() { if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { - return ty.moves_by_default(self.tcx.global_tcx(), param_env, span); + return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span); } } @@ -1455,7 +1422,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span) + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) } /// Obtains the latest type of the given closure; this may be a diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 66ebbe111dbce..56ae850226c91 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -17,8 +17,6 @@ use ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; -mod taint; - #[derive(Default)] pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. @@ -130,6 +128,16 @@ pub enum Constraint<'tcx> { RegSubReg(Region<'tcx>, Region<'tcx>), } +impl Constraint<'_> { + pub fn involves_placeholders(&self) -> bool { + match self { + Constraint::VarSubVar(_, _) => false, + Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(), + Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(), + } + } +} + /// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or /// associated type) must outlive the region `R`. `T` is known to /// outlive `RS`. Therefore verify that `R <= RS[i]` for some @@ -326,6 +334,8 @@ impl TaintDirections { } } +pub struct ConstraintInfo {} + impl<'tcx> RegionConstraintCollector<'tcx> { pub fn new() -> Self { Self::default() @@ -487,7 +497,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); - let u_vid = self.unification_table + let u_vid = self + .unification_table .new_key(unify_key::RegionVidKey { min_vid: vid }); assert_eq!(vid, u_vid); if self.in_snapshot() { @@ -519,7 +530,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); - let constraints_to_kill: Vec = self.undo_log + let constraints_to_kill: Vec = self + .undo_log .iter() .enumerate() .rev() @@ -822,37 +834,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> { .filter_map(|&elt| match elt { AddVar(vid) => Some(vid), _ => None, - }) - .collect() - } - - /// Computes all regions that have been related to `r0` since the - /// mark `mark` was made---`r0` itself will be the first - /// entry. The `directions` parameter controls what kind of - /// relations are considered. For example, one can say that only - /// "incoming" edges to `r0` are desired, in which case one will - /// get the set of regions `{r|r <= r0}`. This is used when - /// checking whether placeholder regions are being improperly - /// related to other regions. - pub fn tainted( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - mark: &RegionSnapshot, - r0: Region<'tcx>, - directions: TaintDirections, - ) -> FxHashSet> { - debug!( - "tainted(mark={:?}, r0={:?}, directions={:?})", - mark, r0, directions - ); + }).collect() + } - // `result_set` acts as a worklist: we explore all outgoing - // edges and add any new regions we find to result_set. This - // is not a terribly efficient implementation. - let mut taint_set = taint::TaintSet::new(directions, r0); - taint_set.fixed_point(tcx, &self.undo_log[mark.length..], &self.data.verifys); - debug!("tainted: result={:?}", taint_set); - return taint_set.into_set(); + /// See [`RegionInference::region_constraints_added_in_snapshot`] + pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> Option { + self.undo_log[mark.length..] + .iter() + .map(|&elt| match elt { + AddConstraint(constraint) => Some(constraint.involves_placeholders()), + _ => None, + }).max() + .unwrap_or(None) } } diff --git a/src/librustc/infer/region_constraints/taint.rs b/src/librustc/infer/region_constraints/taint.rs deleted file mode 100644 index 6743f37972ae5..0000000000000 --- a/src/librustc/infer/region_constraints/taint.rs +++ /dev/null @@ -1,85 +0,0 @@ -use super::*; - -#[derive(Debug)] -pub(super) struct TaintSet<'tcx> { - directions: TaintDirections, - regions: FxHashSet>, -} - -impl<'tcx> TaintSet<'tcx> { - pub(super) fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { - let mut regions = FxHashSet::default(); - regions.insert(initial_region); - TaintSet { - directions: directions, - regions: regions, - } - } - - pub(super) fn fixed_point( - &mut self, - tcx: TyCtxt<'_, '_, 'tcx>, - undo_log: &[UndoLog<'tcx>], - verifys: &[Verify<'tcx>], - ) { - let mut prev_len = 0; - while prev_len < self.len() { - debug!( - "tainted: prev_len = {:?} new_len = {:?}", - prev_len, - self.len() - ); - - prev_len = self.len(); - - for undo_entry in undo_log { - match undo_entry { - &AddConstraint(Constraint::VarSubVar(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::RegSubVar(a, b)) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddConstraint(Constraint::VarSubReg(a, b)) => { - self.add_edge(tcx.mk_region(ReVar(a)), b); - } - &AddConstraint(Constraint::RegSubReg(a, b)) => { - self.add_edge(a, b); - } - &AddGiven(a, b) => { - self.add_edge(a, tcx.mk_region(ReVar(b))); - } - &AddVerify(i) => { - span_bug!( - verifys[i].origin.span(), - "we never add verifications while doing higher-ranked things", - ) - } - &Purged | &AddCombination(..) | &AddVar(..) => {} - } - } - } - } - - pub(super) fn into_set(self) -> FxHashSet> { - self.regions - } - - fn len(&self) -> usize { - self.regions.len() - } - - fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) { - if self.directions.incoming { - if self.regions.contains(&target) { - self.regions.insert(source); - } - } - - if self.directions.outgoing { - if self.regions.contains(&source) { - self.regions.insert(target); - } - } - } -} diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 3cc9bffa9a423..0c769c91801b8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -557,7 +557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { self.warn_dead_code( item.id, span, - item.name, + item.ident.name, item.node.descriptive_variant(), participle, ); @@ -572,7 +572,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { g: &'tcx hir::Generics, id: ast::NodeId) { if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.name, + self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.ident.name, "variant", "constructed"); } else { intravisit::walk_variant(self, variant, g, id); @@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) { if self.should_warn_about_foreign_item(fi) { - self.warn_dead_code(fi.id, fi.span, fi.name, + self.warn_dead_code(fi.id, fi.span, fi.ident.name, fi.node.descriptive_variant(), "used"); } intravisit::walk_foreign_item(self, fi); diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 2add525f0940d..6b593a1a9f9b2 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -86,7 +86,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, "main") { EntryPointType::MainAttr - } else if item.name == "main" { + } else if item.ident.name == "main" { if at_root { // This is a top-level function so can be 'main'. EntryPointType::MainNamed diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f9bcbb3222955..c1aa25b6b75c2 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -976,7 +976,7 @@ fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx move_reason: MoveReason) -> ConsumeMode { - if mc.type_moves_by_default(param_env, cmt.ty, cmt.span) { + if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) { Move(move_reason) } else { Copy diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 2010926ede5e6..1716daaa107c4 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -97,11 +97,11 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { format!("{} bits", size.bits()) } Ok(SizeSkeleton::Pointer { tail, .. }) => { - format!("pointer to {}", tail) + format!("pointer to `{}`", tail) } Err(LayoutError::Unknown(bad)) => { if bad == ty { - "this type's size can vary".to_owned() + "this type does not have a fixed size".to_owned() } else { format!("size can vary because of {}", bad) } @@ -110,11 +110,16 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { } }; - struct_span_err!(self.tcx.sess, span, E0512, - "transmute called with types of different sizes") - .note(&format!("source type: {} ({})", from, skeleton_string(from, sk_from))) - .note(&format!("target type: {} ({})", to, skeleton_string(to, sk_to))) - .emit(); + let mut err = struct_span_err!(self.tcx.sess, span, E0512, + "cannot transmute between types of different sizes, \ + or dependently-sized types"); + if from == to { + err.note(&format!("`{}` does not have a fixed size", from)); + } else { + err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) + .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); + } + err.emit() } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 207382d5e1f45..370f0d1a6c6d7 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -443,15 +443,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - pub fn type_moves_by_default(&self, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - span: Span) - -> bool { - self.infcx.map(|infcx| infcx.type_moves_by_default(param_env, ty, span)) + pub fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool { + self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span)) .or_else(|| { self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { - ty.moves_by_default(self.tcx.global_tcx(), param_env, span) + ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span) }) }) .unwrap_or(true) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f774b13f98301..2936405ebd0b7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -27,9 +27,12 @@ use syntax::ast::{self, Name}; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use ty::subst::{CanonicalUserSubsts, Subst, Substs}; -use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; +use ty::subst::{Subst, Substs}; use ty::layout::VariantIdx; +use ty::{ + self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, + UserTypeAnnotationIndex, UserTypeAnnotation, +}; use util::ppaux; pub use mir::interpret::AssertMessage; @@ -121,6 +124,9 @@ pub struct Mir<'tcx> { /// variables and temporaries. pub local_decls: LocalDecls<'tcx>, + /// User type annotations + pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, + /// Number of arguments this function takes. /// /// Starting at local 1, `arg_count` locals will be provided by the caller @@ -161,7 +167,8 @@ impl<'tcx> Mir<'tcx> { source_scope_local_data: ClearCrossCrate>, promoted: IndexVec>, yield_ty: Option>, - local_decls: IndexVec>, + local_decls: LocalDecls<'tcx>, + user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, upvar_decls: Vec, span: Span, @@ -185,6 +192,7 @@ impl<'tcx> Mir<'tcx> { generator_drop: None, generator_layout: None, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg: None, @@ -418,6 +426,7 @@ impl_stable_hash_for!(struct Mir<'tcx> { generator_drop, generator_layout, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg, @@ -2040,7 +2049,7 @@ impl<'tcx> Debug for Place<'tcx> { Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1), Projection(ref data) => match data.elem { ProjectionElem::Downcast(ref adt_def, index) => { - write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name) + write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident) } ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base), ProjectionElem::Field(field, ty) => { @@ -2232,7 +2241,7 @@ pub enum AggregateKind<'tcx> { &'tcx AdtDef, VariantIdx, &'tcx Substs<'tcx>, - Option>, + Option, Option, ), @@ -2446,38 +2455,11 @@ pub struct Constant<'tcx> { /// indicate that `Vec<_>` was explicitly specified. /// /// Needed for NLL to impose user-given type constraints. - pub user_ty: Option>, + pub user_ty: Option, pub literal: &'tcx ty::Const<'tcx>, } -/// A user-given type annotation attached to a constant. These arise -/// from constants that are named via paths, like `Foo::::new` and -/// so forth. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub enum UserTypeAnnotation<'tcx> { - Ty(CanonicalTy<'tcx>), - - /// The canonical type is the result of `type_of(def_id)` with the - /// given substitutions applied. - TypeOf(DefId, CanonicalUserSubsts<'tcx>), -} - -EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> { - (UserTypeAnnotation::Ty)(ty), - (UserTypeAnnotation::TypeOf)(def, substs), - } -} - -EnumLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> { - type Lifted = UserTypeAnnotation<'tcx>; - (UserTypeAnnotation::Ty)(ty), - (UserTypeAnnotation::TypeOf)(def, substs), - } -} - /// A collection of projections into user types. /// /// They are projections because a binding can occur a part of a @@ -2537,6 +2519,48 @@ impl<'tcx> UserTypeProjections<'tcx> { pub fn projections(&self) -> impl Iterator> { self.contents.iter().map(|&(ref user_type, _span)| user_type) } + + pub fn push_projection( + mut self, + user_ty: &UserTypeProjection<'tcx>, + span: Span, + ) -> Self { + self.contents.push((user_ty.clone(), span)); + self + } + + fn map_projections( + mut self, + mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx> + ) -> Self { + self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect(); + self + } + + pub fn index(self) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.index()) + } + + pub fn subslice(self, from: u32, to: u32) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to)) + } + + pub fn deref(self) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.deref()) + } + + pub fn leaf(self, field: Field) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field)) + } + + pub fn variant( + self, + adt_def: &'tcx AdtDef, + variant_index: VariantIdx, + field: Field, + ) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) + } } /// Encodes the effect of a user-supplied type annotation on the @@ -2556,12 +2580,45 @@ impl<'tcx> UserTypeProjections<'tcx> { /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UserTypeProjection<'tcx> { - pub base: UserTypeAnnotation<'tcx>, + pub base: UserTypeAnnotationIndex, pub projs: Vec>, } impl<'tcx> Copy for ProjectionKind<'tcx> { } +impl<'tcx> UserTypeProjection<'tcx> { + pub(crate) fn index(mut self) -> Self { + self.projs.push(ProjectionElem::Index(())); + self + } + + pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self { + self.projs.push(ProjectionElem::Subslice { from, to }); + self + } + + pub(crate) fn deref(mut self) -> Self { + self.projs.push(ProjectionElem::Deref); + self + } + + pub(crate) fn leaf(mut self, field: Field) -> Self { + self.projs.push(ProjectionElem::Field(field, ())); + self + } + + pub(crate) fn variant( + mut self, + adt_def: &'tcx AdtDef, + variant_index: VariantIdx, + field: Field, + ) -> Self { + self.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); + self.projs.push(ProjectionElem::Field(field, ())); + self + } +} + CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { @@ -2970,6 +3027,7 @@ CloneTypeFoldableAndLiftImpls! { SourceScope, SourceScopeData, SourceScopeLocalData, + UserTypeAnnotationIndex, } BraceStructTypeFoldableImpl! { @@ -2983,6 +3041,7 @@ BraceStructTypeFoldableImpl! { generator_drop, generator_layout, local_decls, + user_type_annotations, arg_count, upvar_decls, spread_arg, diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index a20b8231f88a2..67f85fbc8679e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,4 +1,5 @@ use hir::def_id::DefId; +use infer::canonical::Canonical; use ty::subst::Substs; use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty}; use mir::*; @@ -219,9 +220,10 @@ macro_rules! make_mir_visitor { fn visit_user_type_annotation( &mut self, - ty: & $($mutability)* UserTypeAnnotation<'tcx>, + index: UserTypeAnnotationIndex, + ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>, ) { - self.super_user_type_annotation(ty); + self.super_user_type_annotation(index, ty); } fn visit_region(&mut self, @@ -307,6 +309,14 @@ macro_rules! make_mir_visitor { self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]); } + for index in mir.user_type_annotations.indices() { + let (span, annotation) = & $($mutability)* mir.user_type_annotations[index]; + self.visit_user_type_annotation( + index, annotation + ); + self.visit_span(span); + } + self.visit_span(&$($mutability)* mir.span); } @@ -865,18 +875,14 @@ macro_rules! make_mir_visitor { fn super_user_type_projection( &mut self, - ty: & $($mutability)* UserTypeProjection<'tcx>, + _ty: & $($mutability)* UserTypeProjection<'tcx>, ) { - let UserTypeProjection { - ref $($mutability)* base, - projs: _, // Note: Does not visit projection elems! - } = *ty; - self.visit_user_type_annotation(base); } fn super_user_type_annotation( &mut self, - _ty: & $($mutability)* UserTypeAnnotation<'tcx>, + _index: UserTypeAnnotationIndex, + _ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>, ) { } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e58c9d75a9db2..33409f9b4a74f 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1227,6 +1227,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "verify incr. comp. hashes of green query instances"), incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], "ignore spans during ICH computation -- used for testing"), + instrument_mcount: bool = (false, parse_bool, [TRACKED], + "insert function instrument code for mcount-based tracing"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 4fc9b87ceef20..5c977d5969e16 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -503,6 +503,9 @@ impl Session { pub fn profile_queries_and_keys(&self) -> bool { self.opts.debugging_opts.profile_queries_and_keys } + pub fn instrument_mcount(&self) -> bool { + self.opts.debugging_opts.instrument_mcount + } pub fn count_llvm_insns(&self) -> bool { self.opts.debugging_opts.count_llvm_insns } @@ -667,7 +670,11 @@ impl Session { } pub fn must_not_eliminate_frame_pointers(&self) -> bool { - if let Some(x) = self.opts.cg.force_frame_pointers { + // "mcount" function relies on stack pointer. + // See https://sourceware.org/binutils/docs/gprof/Implementation.html + if self.instrument_mcount() { + true + } else if let Some(x) = self.opts.cg.force_frame_pointers { x } else { !self.target.target.options.eliminate_frame_pointer diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index f96c4e9014b36..92004ece26d00 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -771,13 +771,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } &ty::Predicate::RegionOutlives(ref binder) => { - if select - .infcx() - .region_outlives_predicate(&dummy_cause, binder) - .is_err() - { - return false; - } + let () = select.infcx().region_outlives_predicate(&dummy_cause, binder); } &ty::Predicate::TypeOutlives(ref binder) => { match ( diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 980c98d2a2d50..b3d732ebcd7dc 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -4,6 +4,7 @@ //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html +use infer::CombinedSnapshot; use hir::def_id::{DefId, LOCAL_CRATE}; use syntax_pos::DUMMY_SP; use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; @@ -33,6 +34,17 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, pub intercrate_ambiguity_causes: Vec, + + /// True if the overlap might've been permitted before the shift + /// to universes. + pub involves_placeholder: bool, +} + +pub fn add_placeholder_note(err: &mut ::errors::DiagnosticBuilder<'_>) { + err.note(&format!( + "this behavior recently changed as a result of a bug fix; \ + see rust-lang/rust#56105 for details" + )); } /// If there are types that satisfy both impls, invokes `on_overlap` @@ -104,13 +116,22 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, ' /// Can both impl `a` and impl `b` be satisfied by a common type (including /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls. -fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, - a_def_id: DefId, - b_def_id: DefId) - -> Option> -{ +fn overlap<'cx, 'gcx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, +) -> Option> { debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); + selcx.infcx().probe(|snapshot| overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)) +} + +fn overlap_within_probe( + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, + a_def_id: DefId, + b_def_id: DefId, + snapshot: &CombinedSnapshot<'_, 'tcx>, +) -> Option> { // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with // fresh type variables, and hence we do our evaluations in an @@ -158,7 +179,13 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); - Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) + + let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) { + Some(true) => true, + _ => false, + }; + + Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) } pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0e63ef666c75a..21352ac1053a8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -728,12 +728,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) + // These errors should show up as region + // inference failures. + panic!("region outlives {:?} failed", predicate); } ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 556b97dc9bcf1..2e00d4d4b7c3b 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -282,7 +282,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, if data.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - if self.selcx.infcx().predicate_must_hold(&obligation) { + if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) { debug!("selecting trait `{:?}` at depth {} evaluated to holds", data, obligation.recursion_depth); return ProcessResult::Changed(vec![]) @@ -331,10 +331,8 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::RegionOutlives(ref binder) => { - match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) { - Ok(()) => ProcessResult::Changed(vec![]), - Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)), - } + let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder); + ProcessResult::Changed(vec![]) } ty::Predicate::TypeOutlives(ref binder) => { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 49bd04782b28e..b42d742b7f841 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -43,7 +43,8 @@ pub use self::FulfillmentErrorCode::*; pub use self::Vtable::*; pub use self::ObligationCauseCode::*; -pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult}; +pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; +pub use self::coherence::{OrphanCheckErr, OverlapResult}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::project::MismatchedProjectionTypes; pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type}; @@ -628,14 +629,14 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). -pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - span: Span) --> bool -{ - debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", +pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + span: Span, +) -> bool { + debug!("type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", ty, infcx.tcx.item_path_str(def_id)); @@ -650,7 +651,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx predicate: trait_ref.to_predicate(), }; - let result = infcx.predicate_must_hold(&obligation); + let result = infcx.predicate_must_hold_modulo_regions(&obligation); debug!("type_known_to_meet_ty={:?} bound={} => {:?}", ty, infcx.tcx.item_path_str(def_id), result); @@ -677,13 +678,13 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx // assume it is move; linear is always ok. match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { - debug!("type_known_to_meet_bound: ty={:?} bound={} success", + debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", ty, infcx.tcx.item_path_str(def_id)); true } Err(e) => { - debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}", + debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", ty, infcx.tcx.item_path_str(def_id), e); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1554afdeefdaf..31342c250e2bd 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -568,7 +568,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { self.infer_ctxt().enter(|ref infcx| { // the receiver is dispatchable iff the obligation holds - infcx.predicate_must_hold(&obligation) + infcx.predicate_must_hold_modulo_regions(&obligation) }) } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 952b37b89f2d4..732ca70dc78c5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -13,7 +13,7 @@ use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPoin use super::util; use hir::def_id::DefId; -use infer::{InferCtxt, InferOk}; +use infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use infer::type_variable::TypeVariableOrigin; use mir::interpret::ConstValue; use mir::interpret::{GlobalId}; @@ -192,28 +192,12 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( obligation); let infcx = selcx.infcx(); - infcx.commit_if_ok(|snapshot| { - let (placeholder_predicate, placeholder_map) = + infcx.commit_if_ok(|_| { + let (placeholder_predicate, _) = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); - let skol_obligation = obligation.with(placeholder_predicate); - let r = match project_and_unify_type(selcx, &skol_obligation) { - Ok(result) => { - let span = obligation.cause.span; - match infcx.leak_check(false, span, &placeholder_map, snapshot) { - Ok(()) => Ok(infcx.plug_leaks(placeholder_map, snapshot, result)), - Err(e) => { - debug!("poly_project_and_unify_type: leak check encountered error {:?}", e); - Err(MismatchedProjectionTypes { err: e }) - } - } - } - Err(e) => { - Err(e) - } - }; - - r + let placeholder_obligation = obligation.with(placeholder_predicate); + project_and_unify_type(selcx, &placeholder_obligation) }) } @@ -1443,17 +1427,25 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - poly_projection: ty::PolyProjectionPredicate<'tcx>) + poly_cache_entry: ty::PolyProjectionPredicate<'tcx>) -> Progress<'tcx> { let infcx = selcx.infcx(); - let cause = obligation.cause.clone(); + let cause = &obligation.cause; let param_env = obligation.param_env; - let trait_ref = obligation.predicate.trait_ref(infcx.tcx); - match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) { - Ok(InferOk { value: ty_match, obligations }) => { + + let (cache_entry, _) = + infcx.replace_bound_vars_with_fresh_vars( + cause.span, + LateBoundRegionConversionTime::HigherRankedType, + &poly_cache_entry); + + let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); + let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); + match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { + Ok(InferOk { value: _, obligations }) => { Progress { - ty: ty_match.value, + ty: cache_entry.ty, obligations, } } @@ -1463,7 +1455,7 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( "Failed to unify obligation `{:?}` \ with poly_projection `{:?}`: {:?}", obligation, - poly_projection, + poly_cache_entry, e); } } diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 4c1d65c46c56f..fdae7d833734e 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -16,11 +16,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// Evaluates whether the predicate can be satisfied in the given /// `ParamEnv`, and returns `false` if not certain. However, this is /// not entirely accurate if inference variables are involved. - pub fn predicate_must_hold( + /// + /// This version may conservatively fail when outlives obligations + /// are required. + pub fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, ) -> bool { - self.evaluate_obligation_no_overflow(obligation) == EvaluationResult::EvaluatedToOk + self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions() + } + + /// Evaluates whether the predicate can be satisfied in the given + /// `ParamEnv`, and returns `false` if not certain. However, this is + /// not entirely accurate if inference variables are involved. + /// + /// This version ignores all outlives constraints. + pub fn predicate_must_hold_modulo_regions( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool { + self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions() } /// Evaluate a given predicate, capturing overflow and propagating it back. diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index 365c1d67ef97a..b2f30564de93a 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -22,7 +22,7 @@ impl<'tcx> AscribeUserType<'tcx> { user_substs: UserSubsts<'tcx>, projs: &'tcx ty::List>, ) -> Self { - AscribeUserType { mir_ty, variance, def_id, user_substs, projs } + Self { mir_ty, variance, def_id, user_substs, projs } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index bd347764cc681..373ec2d5e490f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -29,7 +29,6 @@ use super::{ use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; -use infer; use infer::{InferCtxt, InferOk, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; @@ -45,7 +44,6 @@ use rustc_target::spec::abi::Abi; use std::cmp; use std::fmt; use std::iter; -use std::mem; use std::rc::Rc; use util::nodemap::{FxHashMap, FxHashSet}; @@ -328,7 +326,8 @@ enum BuiltinImplConditions<'tcx> { /// evaluations. /// /// The evaluation results are ordered: -/// - `EvaluatedToOk` implies `EvaluatedToAmbig` implies `EvaluatedToUnknown` +/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions` +/// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown` /// - `EvaluatedToErr` implies `EvaluatedToRecur` /// - the "union" of evaluation results is equal to their maximum - /// all the "potential success" candidates can potentially succeed, @@ -337,6 +336,8 @@ enum BuiltinImplConditions<'tcx> { pub enum EvaluationResult { /// Evaluation successful EvaluatedToOk, + /// Evaluation successful, but there were unevaluated region obligations + EvaluatedToOkModuloRegions, /// Evaluation is known to be ambiguous - it *might* hold for some /// assignment of inference variables, but it might not. /// @@ -400,9 +401,23 @@ pub enum EvaluationResult { } impl EvaluationResult { + /// True if this evaluation result is known to apply, even + /// considering outlives constraints. + pub fn must_apply_considering_regions(self) -> bool { + self == EvaluatedToOk + } + + /// True if this evaluation result is known to apply, ignoring + /// outlives constraints. + pub fn must_apply_modulo_regions(self) -> bool { + self <= EvaluatedToOkModuloRegions + } + pub fn may_apply(self) -> bool { match self { - EvaluatedToOk | EvaluatedToAmbig | EvaluatedToUnknown => true, + EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => { + true + } EvaluatedToErr | EvaluatedToRecur => false, } @@ -412,13 +427,14 @@ impl EvaluationResult { match self { EvaluatedToUnknown | EvaluatedToRecur => true, - EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr => false, + EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false, } } } impl_stable_hash_for!(enum self::EvaluationResult { EvaluatedToOk, + EvaluatedToOkModuloRegions, EvaluatedToAmbig, EvaluatedToUnknown, EvaluatedToRecur, @@ -531,33 +547,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx } - /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection - /// context's self. - fn in_snapshot(&mut self, f: F) -> R - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, - { - self.infcx.in_snapshot(|snapshot| f(self, snapshot)) - } - - /// Wraps a probe s.t. obligations collected during it are ignored and old obligations are - /// retained. - fn probe(&mut self, f: F) -> R - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, - { - self.infcx.probe(|snapshot| f(self, snapshot)) - } - - /// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if - /// the transaction fails and s.t. old obligations are retained. - fn commit_if_ok(&mut self, f: F) -> Result - where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result, - { - self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -639,11 +628,24 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, obligation: &PredicateObligation<'tcx>, ) -> Result { - self.probe(|this, _| { + self.evaluation_probe(|this| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) }) } + fn evaluation_probe( + &mut self, + op: impl FnOnce(&mut Self) -> Result, + ) -> Result { + self.infcx.probe(|snapshot| -> Result { + let result = op(self)?; + match self.infcx.region_constraints_added_in_snapshot(snapshot) { + None => Ok(result), + Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)), + } + }) + } + /// Evaluates the predicates in `predicates` recursively. Note that /// this applies projections in the predicates, and therefore /// is run within an inference probe. @@ -714,92 +716,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { None => Ok(EvaluatedToAmbig), }, - ty::Predicate::TypeOutlives(ref binder) => { - assert!(!binder.has_escaping_bound_vars()); - // Check if the type has higher-ranked vars. - if binder.skip_binder().0.has_escaping_bound_vars() { - // If so, this obligation is an error (for now). Eventually we should be - // able to support additional cases here, like `for<'a> &'a str: 'a`. - - // NOTE: this hack is implemented in both trait fulfillment and - // evaluation. If you fix it in one place, make sure you fix it - // in the other. - - // We don't want to allow this sort of reasoning in intercrate - // mode, for backwards-compatibility reasons. - if self.intercrate.is_some() { - Ok(EvaluatedToAmbig) - } else { - Ok(EvaluatedToErr) - } - } else { - // If the type has no late bound vars, then if we assign all - // the inference variables in it to be 'static, then the type - // will be 'static itself. - // - // Therefore, `staticize(T): 'a` holds for any `'a`, so this - // obligation is fulfilled. Because evaluation works with - // staticized types (yes I know this is involved with #21974), - // we are 100% OK here. - Ok(EvaluatedToOk) - } - } - - ty::Predicate::RegionOutlives(ref binder) => { - let ty::OutlivesPredicate(r_a, r_b) = binder.skip_binder(); - - if r_a == r_b { - // for<'a> 'a: 'a. OK - Ok(EvaluatedToOk) - } else if **r_a == ty::ReStatic { - // 'static: 'x always holds. - // - // This special case is handled somewhat inconsistently - if we - // have an inference variable that is supposed to be equal to - // `'static`, then we don't allow it to be equated to an LBR, - // but if we have a literal `'static`, then we *do*. - // - // This is actually consistent with how our region inference works. - // - // It would appear that this sort of inconsistency would - // cause "instability" problems with evaluation caching. However, - // evaluation caching is only for trait predicates, and when - // trait predicates create nested obligations, they contain - // inference variables for all the regions in the trait - the - // only way this codepath can be reached from trait predicate - // evaluation is when the user typed an explicit `where 'static: 'a` - // lifetime bound (in which case we want to return EvaluatedToOk). - // - // If we ever want to handle inference variables that might be - // equatable with ReStatic, we need to make sure we are not confused by - // technically-allowed-by-RFC-447-but-probably-should-not-be - // impls such as - // ```Rust - // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's - // ``` - Ok(EvaluatedToOk) - } else if r_a.is_late_bound() || r_b.is_late_bound() { - // There is no current way to prove `for<'a> 'a: 'x` - // unless `'a = 'x`, because there are no bounds involving - // lifetimes. - - // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x` - // to be `'static`. However, this is not currently done by type - // inference unless `'x` is literally ReStatic. See the comment - // above. - - // We don't want to allow this sort of reasoning in intercrate - // mode, for backwards-compatibility reasons. - if self.intercrate.is_some() { - Ok(EvaluatedToAmbig) - } else { - Ok(EvaluatedToErr) - } - } else { - // Relating 2 inference variable regions. These will - // always hold if our query is "staticized". - Ok(EvaluatedToOk) - } + ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => { + // we do not consider region relationships when + // evaluating trait matches + Ok(EvaluatedToOkModuloRegions) } ty::Predicate::ObjectSafe(trait_def_id) => { @@ -1013,6 +933,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); + // Subtle: when checking for a coinductive cycle, we do + // not compare using the "freshened trait refs" (which + // have erased regions) but rather the fully explicit + // trait refs. This is important because it's only a cycle + // if the regions match exactly. let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { @@ -1075,7 +1000,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate ); - let result = self.probe(|this, _| { + let result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { Ok(selection) => this.evaluate_predicates_recursively( @@ -1706,8 +1631,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => return, } - let result = self.probe(|this, snapshot| { - this.match_projection_obligation_against_definition_bounds(obligation, snapshot) + let result = self.infcx.probe(|_| { + self.match_projection_obligation_against_definition_bounds(obligation) }); if result { @@ -1718,16 +1643,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { let poly_trait_predicate = self.infcx() .resolve_type_vars_if_possible(&obligation.predicate); - let (skol_trait_predicate, placeholder_map) = self.infcx() + let (skol_trait_predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ - skol_trait_predicate={:?} placeholder_map={:?}", - skol_trait_predicate, placeholder_map + skol_trait_predicate={:?}", + skol_trait_predicate, ); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { @@ -1759,13 +1683,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates) .filter_to_traits() .find(|bound| { - self.probe(|this, _| { - this.match_projection( + self.infcx.probe(|_| { + self.match_projection( obligation, bound.clone(), skol_trait_predicate.trait_ref.clone(), - &placeholder_map, - snapshot, ) }) }); @@ -1783,12 +1705,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, bound, skol_trait_predicate.trait_ref.clone(), - &placeholder_map, - snapshot, ); - self.infcx.pop_placeholders(placeholder_map, snapshot); - assert!(result); true } @@ -1800,20 +1718,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, skol_trait_ref: ty::TraitRef<'tcx>, - placeholder_map: &infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); - if self.infcx + self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) - .is_err() - { - return false; - } - - self.infcx - .leak_check(false, obligation.cause.span, placeholder_map, snapshot) .is_ok() } @@ -1862,7 +1771,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result { - self.probe(move |this, _| { + self.evaluation_probe(|this| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { this.evaluate_predicates_recursively(stack.list(), obligations.iter()) @@ -2015,14 +1924,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.probe(|this, snapshot| { - if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot) + self.infcx.probe(|_| { + if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); - - // N.B., we can safely drop the placeholder map - // since we are in a probe. - mem::drop(placeholder_map); } }); }, @@ -2093,11 +1998,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.self_ty().skip_binder() ); - self.probe(|this, _snapshot| { + self.infcx.probe(|_snapshot| { // The code below doesn't care about regions, and the // self-ty here doesn't escape this probe, so just erase // any LBR. - let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); + let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { ty::Dynamic(ref data, ..) => { if data.auto_traits() @@ -2111,7 +2016,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - data.principal().with_self_ty(this.tcx(), self_ty) + data.principal().with_self_ty(self.tcx(), self_ty) } ty::Infer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -2131,11 +2036,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar`, // but `Foo` is declared as `trait Foo : Bar`. - let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref) + let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref) .filter(|upcast_trait_ref| { - this.probe(|this, _| { + self.infcx.probe(|_| { let upcast_trait_ref = upcast_trait_ref.clone(); - this.match_poly_trait_ref(obligation, upcast_trait_ref) + self.match_poly_trait_ref(obligation, upcast_trait_ref) .is_ok() }) }) @@ -2352,7 +2257,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // See if we can toss out `victim` based on specialization. // This requires us to know *for sure* that the `other` impl applies // i.e., EvaluatedToOk: - if other.evaluation == EvaluatedToOk { + if other.evaluation.must_apply_modulo_regions() { match victim.candidate { ImplCandidate(victim_def) => { let tcx = self.tcx().global_tcx(); @@ -2379,7 +2284,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ParamCandidate(ref cand) => { // Prefer these to a global where-clause bound // (see issue #50825) - is_global(cand) && other.evaluation == EvaluatedToOk + is_global(cand) && other.evaluation.must_apply_modulo_regions() } _ => false, } @@ -2680,20 +2585,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ - self.in_snapshot(|this, snapshot| { - let (skol_ty, placeholder_map) = this.infcx() + self.infcx.in_snapshot(|_| { + let (skol_ty, _) = self.infcx .replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations, } = project::normalize_with_depth( - this, + self, param_env, cause.clone(), recursion_depth, &skol_ty, ); - let skol_obligation = this.tcx().predicate_for_trait_def( + let skol_obligation = self.tcx().predicate_for_trait_def( param_env, cause.clone(), trait_def_id, @@ -2702,8 +2607,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &[], ); obligations.push(skol_obligation); - this.infcx() - .plug_leaks(placeholder_map, snapshot, obligations) + obligations }) }) .collect() @@ -2794,9 +2698,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.in_snapshot(|this, snapshot| { + self.infcx.in_snapshot(|_| { let result = - this.match_projection_obligation_against_definition_bounds(obligation, snapshot); + self.match_projection_obligation_against_definition_bounds(obligation); assert!(result); }) } @@ -2913,19 +2817,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { nested, ); - let trait_obligations: Vec> = self.in_snapshot(|this, snapshot| { + let trait_obligations: Vec> = self.infcx.in_snapshot(|_| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, placeholder_map) = this.infcx() + let (trait_ref, _) = self.infcx .replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); - this.impl_or_trait_obligations( + self.impl_or_trait_obligations( cause, obligation.recursion_depth + 1, obligation.param_env, trait_def_id, &trait_ref.substs, - placeholder_map, - snapshot, ) }); @@ -2950,18 +2852,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.in_snapshot(|this, snapshot| { - let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot); + self.infcx.in_snapshot(|_| { + let substs = self.rematch_impl(impl_def_id, obligation); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); - this.vtable_impl( + self.vtable_impl( impl_def_id, substs, cause, obligation.recursion_depth + 1, obligation.param_env, - placeholder_map, - snapshot, ) }) } @@ -2973,12 +2873,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - placeholder_map: infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> { debug!( - "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, placeholder_map={:?})", - impl_def_id, substs, recursion_depth, placeholder_map + "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})", + impl_def_id, substs, recursion_depth, ); let mut impl_obligations = self.impl_or_trait_obligations( @@ -2987,8 +2885,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { param_env, impl_def_id, &substs.value, - placeholder_map, - snapshot, ); debug!( @@ -3041,7 +2937,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // reported an ambiguity. (When we do find a match, also // record it for later.) let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while( - |&t| match self.commit_if_ok(|this, _| this.match_poly_trait_ref(obligation, t)) { + |&t| match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) { Ok(obligations) => { upcast_trait_ref = Some(t); nested.extend(obligations); @@ -3117,21 +3013,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, alias_def_id ); - self.in_snapshot(|this, snapshot| { - let (predicate, placeholder_map) = this.infcx() + self.infcx.in_snapshot(|_| { + let (predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let substs = trait_ref.substs; - let trait_obligations = this.impl_or_trait_obligations( + let trait_obligations = self.impl_or_trait_obligations( obligation.cause.clone(), obligation.recursion_depth, obligation.param_env, trait_def_id, &substs, - placeholder_map, - snapshot, ); debug!( @@ -3341,10 +3235,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ); tcx.mk_existential_predicates(iter) }); - let new_trait = tcx.mk_dynamic(existential_predicates, r_b); + let source_trait = tcx.mk_dynamic(existential_predicates, r_b); let InferOk { obligations, .. } = self.infcx .at(&obligation.cause, obligation.param_env) - .eq(target, new_trait) + .sup(target, source_trait) .map_err(|_| Unimplemented)?; nested.extend(obligations); @@ -3546,13 +3440,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, - ) -> ( - Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::PlaceholderMap<'tcx>, - ) { - match self.match_impl(impl_def_id, obligation, snapshot) { - Ok((substs, placeholder_map)) => (substs, placeholder_map), + ) -> Normalized<'tcx, &'tcx Substs<'tcx>> { + match self.match_impl(impl_def_id, obligation) { + Ok(substs) => substs, Err(()) => { bug!( "Impl {:?} was matchable against {:?} but now is not", @@ -3567,14 +3457,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut self, impl_def_id: DefId, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, - ) -> Result< - ( - Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::PlaceholderMap<'tcx>, - ), - (), - > { + ) -> Result>, ()> { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); // Before we create the substitutions and everything, first @@ -3584,7 +3467,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } - let (skol_obligation, placeholder_map) = self.infcx() + let (skol_obligation, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; @@ -3616,22 +3499,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = - self.infcx - .leak_check(false, obligation.cause.span, &placeholder_map, snapshot) - { - debug!("match_impl: failed leak check due to `{}`", e); - return Err(()); - } - debug!("match_impl: success impl_substs={:?}", impl_substs); - Ok(( - Normalized { - value: impl_substs, - obligations: nested_obligations, - }, - placeholder_map, - )) + Ok(Normalized { + value: impl_substs, + obligations: nested_obligations, + }) } fn fast_reject_trait_refs( @@ -3787,8 +3659,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, def_id: DefId, // of impl or trait substs: &Substs<'tcx>, // for impl or trait - placeholder_map: infer::PlaceholderMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> Vec> { debug!("impl_or_trait_obligations(def_id={:?})", def_id); let tcx = self.tcx(); @@ -3850,8 +3720,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut seen = FxHashSet::default(); predicates.retain(|i| seen.insert(i.clone())); } - self.infcx() - .plug_leaks(placeholder_map, snapshot, predicates) + + predicates } } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f5d68ddb5bd46..63f52a34dfa70 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -15,6 +15,7 @@ use hir::def_id::DefId; use infer::{InferCtxt, InferOk}; use lint; use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; +use traits::coherence; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax_pos::DUMMY_SP; @@ -32,6 +33,7 @@ pub struct OverlapError { pub trait_desc: String, pub self_desc: Option, pub intercrate_ambiguity_causes: Vec, + pub involves_placeholder: bool, } /// Given a subst for the requested impl, translate it to a subst @@ -370,6 +372,10 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + coherence::add_placeholder_note(&mut err); + } + err.emit(); } } else { diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index fd68917e53991..db3547b2b7479 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> Children { None }, intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, + involves_placeholder: overlap.involves_placeholder, } }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ea69d466ba6c5..32348e2e5046d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,7 +14,7 @@ use hir::map as hir_map; use hir::map::DefPathHash; use lint::{self, Lint}; use ich::{StableHashingContext, NodeIdHashingMode}; -use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; +use infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use infer::outlives::free_region_map::FreeRegionMap; use middle::cstore::CrateStoreDyn; use middle::cstore::EncodedMetadata; @@ -23,7 +23,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret, ProjectionKind}; use mir::interpret::Allocation; -use ty::subst::{CanonicalUserSubsts, Kind, Substs, Subst}; +use ty::subst::{Kind, Substs, Subst}; use ty::ReprOptions; use traits; use traits::{Clause, Clauses, GoalKind, Goal, Goals}; @@ -38,8 +38,8 @@ use ty::GenericParamDefKind; use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; use ty::query; use ty::steal::Steal; -use ty::BindingMode; -use ty::CanonicalTy; +use ty::subst::{UserSubsts, UnpackedKind}; +use ty::{BoundVar, BindingMode}; use ty::CanonicalPolyFnSig; use util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; @@ -49,7 +49,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableHasher, StableHasherResult, StableVec}; use arena::{TypedArena, SyncDroplessArena}; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal}; use std::any::Any; use std::borrow::Borrow; @@ -342,26 +342,21 @@ pub struct TypeckTables<'tcx> { /// other items. node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, - /// Stores the canonicalized types provided by the user. See also - /// `AscribeUserType` statement in MIR. - user_provided_tys: ItemLocalMap>, + /// This will either store the canonicalized types provided by the user + /// or the substitutions that the user explicitly gave (if any) attached + /// to `id`. These will not include any inferred values. The canonical form + /// is used to capture things like `_` or other unspecified values. + /// + /// For example, if the user wrote `foo.collect::>()`, then the + /// canonical substitutions would include only `for { Vec }`. + /// + /// See also `AscribeUserType` statement in MIR. + user_provided_types: ItemLocalMap>, /// Stores the canonicalized types provided by the user. See also /// `AscribeUserType` statement in MIR. pub user_provided_sigs: DefIdMap>, - /// Stores the substitutions that the user explicitly gave (if any) - /// attached to `id`. These will not include any inferred - /// values. The canonical form is used to capture things like `_` - /// or other unspecified values. - /// - /// Example: - /// - /// If the user wrote `foo.collect::>()`, then the - /// canonical substitutions would include only `for { Vec - /// }`. - user_substs: ItemLocalMap>, - adjustments: ItemLocalMap>>, /// Stores the actual binding mode for all instances of hir::BindingAnnotation. @@ -432,11 +427,10 @@ impl<'tcx> TypeckTables<'tcx> { local_id_root, type_dependent_defs: Default::default(), field_indices: Default::default(), - user_provided_tys: Default::default(), + user_provided_types: Default::default(), user_provided_sigs: Default::default(), node_types: Default::default(), node_substs: Default::default(), - user_substs: Default::default(), adjustments: Default::default(), pat_binding_modes: Default::default(), pat_adjustments: Default::default(), @@ -491,17 +485,21 @@ impl<'tcx> TypeckTables<'tcx> { } } - pub fn user_provided_tys(&self) -> LocalTableInContext<'_, CanonicalTy<'tcx>> { + pub fn user_provided_types( + &self + ) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> { LocalTableInContext { local_id_root: self.local_id_root, - data: &self.user_provided_tys + data: &self.user_provided_types } } - pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalTy<'tcx>> { + pub fn user_provided_types_mut( + &mut self + ) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> { LocalTableInContextMut { local_id_root: self.local_id_root, - data: &mut self.user_provided_tys + data: &mut self.user_provided_types } } @@ -551,18 +549,6 @@ impl<'tcx> TypeckTables<'tcx> { self.node_substs.get(&id.local_id).cloned() } - pub fn user_substs_mut(&mut self) -> LocalTableInContextMut<'_, CanonicalUserSubsts<'tcx>> { - LocalTableInContextMut { - local_id_root: self.local_id_root, - data: &mut self.user_substs - } - } - - pub fn user_substs(&self, id: hir::HirId) -> Option> { - validate_hir_id_for_typeck_tables(self.local_id_root, id, false); - self.user_substs.get(&id.local_id).cloned() - } - // Returns the type of a pattern as a monotype. Like @expr_ty, this function // doesn't provide type parameter substitutions. pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { @@ -739,11 +725,10 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { local_id_root, ref type_dependent_defs, ref field_indices, - ref user_provided_tys, + ref user_provided_types, ref user_provided_sigs, ref node_types, ref node_substs, - ref user_substs, ref adjustments, ref pat_binding_modes, ref pat_adjustments, @@ -763,11 +748,10 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { type_dependent_defs.hash_stable(hcx, hasher); field_indices.hash_stable(hcx, hasher); - user_provided_tys.hash_stable(hcx, hasher); + user_provided_types.hash_stable(hcx, hasher); user_provided_sigs.hash_stable(hcx, hasher); node_types.hash_stable(hcx, hasher); node_substs.hash_stable(hcx, hasher); - user_substs.hash_stable(hcx, hasher); adjustments.hash_stable(hcx, hasher); pat_binding_modes.hash_stable(hcx, hasher); pat_adjustments.hash_stable(hcx, hasher); @@ -805,6 +789,84 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { } } +newtype_index! { + pub struct UserTypeAnnotationIndex { + DEBUG_FORMAT = "UserTypeAnnotation({})", + const START_INDEX = 0, + } +} + +/// Mapping of type annotation indices to canonical user type annotations. +pub type CanonicalUserTypeAnnotations<'tcx> = + IndexVec)>; + +/// Canonicalized user type annotation. +pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>; + +impl CanonicalUserTypeAnnotation<'gcx> { + /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`, + /// i.e. each thing is mapped to a canonical variable with the same index. + pub fn is_identity(&self) -> bool { + match self.value { + UserTypeAnnotation::Ty(_) => false, + UserTypeAnnotation::TypeOf(_, user_substs) => { + if user_substs.user_self_ty.is_some() { + return false; + } + + user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { + match kind.unpack() { + UnpackedKind::Type(ty) => match ty.sty { + ty::Bound(debruijn, b) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(debruijn, ty::INNERMOST); + cvar == b.var + } + _ => false, + }, + + UnpackedKind::Lifetime(r) => match r { + ty::ReLateBound(debruijn, br) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(*debruijn, ty::INNERMOST); + cvar == br.assert_bound_var() + } + _ => false, + }, + } + }) + }, + } + } +} + +/// A user-given type annotation attached to a constant. These arise +/// from constants that are named via paths, like `Foo::::new` and +/// so forth. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +pub enum UserTypeAnnotation<'tcx> { + Ty(Ty<'tcx>), + + /// The canonical type is the result of `type_of(def_id)` with the + /// given substitutions applied. + TypeOf(DefId, UserSubsts<'tcx>), +} + +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> { + (UserTypeAnnotation::Ty)(ty), + (UserTypeAnnotation::TypeOf)(def, substs), + } +} + +EnumLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> { + type Lifted = UserTypeAnnotation<'tcx>; + (UserTypeAnnotation::Ty)(ty), + (UserTypeAnnotation::TypeOf)(def, substs), + } +} + impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index c491fdd9957e8..76e102d88d7ce 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -1,5 +1,5 @@ use hir::def_id::DefId; -use ty::{self, BoundRegion, Region, Ty, TyCtxt}; +use ty::{self, Region, Ty, TyCtxt}; use std::borrow::Cow; use std::fmt; use rustc_target::spec::abi; @@ -9,7 +9,7 @@ use syntax_pos::Span; use hir; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ExpectedFound { pub expected: T, pub found: T, @@ -27,8 +27,7 @@ pub enum TypeError<'tcx> { ArgCount, RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), - RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), - RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), + RegionsPlaceholderMismatch, Sorts(ExpectedFound>), IntMismatch(ExpectedFound), @@ -102,17 +101,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsDoesNotOutlive(..) => { write!(f, "lifetime mismatch") } - RegionsInsufficientlyPolymorphic(br, _) => { - write!(f, - "expected bound lifetime parameter{}{}, found concrete lifetime", - if br.is_named() { " " } else { "" }, - br) - } - RegionsOverlyPolymorphic(br, _) => { - write!(f, - "expected concrete lifetime, found bound lifetime parameter{}{}", - if br.is_named() { " " } else { "" }, - br) + RegionsPlaceholderMismatch => { + write!(f, "one type is more general than the other") } Sorts(values) => ty::tls::with(|tcx| { report_maybe_different(f, &values.expected.sort_string(tcx), @@ -200,8 +190,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), - ty::Infer(ty::IntVar(_)) => "integral variable".into(), - ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), + ty::Infer(ty::IntVar(_)) => "integer".into(), + ty::Infer(ty::FloatVar(_)) => "floating-point number".into(), ty::Placeholder(..) => "placeholder type".into(), ty::Bound(..) => "bound type".into(), ty::Infer(ty::FreshTy(_)) => "fresh type".into(), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a5331cbbdb0e5..171c53b7b20ba 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,7 +1,7 @@ use session::{self, DataTypeKind}; use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; -use syntax::ast::{self, IntTy, UintTy}; +use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; use syntax_pos::DUMMY_SP; @@ -1228,7 +1228,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let adt_kind = adt_def.adt_kind(); let adt_packed = adt_def.repr.packed(); - let build_variant_info = |n: Option, + let build_variant_info = |n: Option, flds: &[ast::Name], layout: TyLayout<'tcx>| { let mut min_size = Size::ZERO; @@ -1273,7 +1273,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { match layout.variants { Variants::Single { index } => { debug!("print-type-size `{:#?}` variant {}", - layout, adt_def.variants[index].name); + layout, adt_def.variants[index].ident); if !adt_def.variants.is_empty() { let variant_def = &adt_def.variants[index]; let fields: Vec<_> = @@ -1281,7 +1281,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { record(adt_kind.into(), adt_packed, None, - vec![build_variant_info(Some(variant_def.name), + vec![build_variant_info(Some(variant_def.ident), &fields, layout)]); } else { @@ -1299,7 +1299,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { adt_def.variants.iter_enumerated().map(|(i, variant_def)| { let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); - build_variant_info(Some(variant_def.name), + build_variant_info(Some(variant_def.ident), &fields, layout.for_variant(self, i)) }) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fd8a7db1b4760..d40dd830e9fb9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -73,6 +73,10 @@ pub use self::binding::BindingMode::*; pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local}; pub use self::context::{Lift, TypeckTables, CtxtInterners}; +pub use self::context::{ + UserTypeAnnotationIndex, UserTypeAnnotation, CanonicalUserTypeAnnotation, + CanonicalUserTypeAnnotations, +}; pub use self::instance::{Instance, InstanceDef}; @@ -1780,7 +1784,7 @@ pub struct VariantDef { /// The variant's `DefId`. If this is a tuple-like struct, /// this is the `DefId` of the struct's ctor. pub did: DefId, - pub name: Name, // struct's name if this is a struct + pub ident: Ident, // struct's name if this is a struct pub discr: VariantDiscr, pub fields: Vec, pub ctor_kind: CtorKind, @@ -1804,7 +1808,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { /// remove this hack and use the constructor DefId everywhere. pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, did: DefId, - name: Name, + ident: Ident, discr: VariantDiscr, fields: Vec, adt_kind: AdtKind, @@ -1812,7 +1816,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { attribute_def_id: DefId) -> Self { - debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, name, discr, + debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr, fields, adt_kind, ctor_kind, attribute_def_id); let mut flags = VariantFlags::NO_VARIANT_FLAGS; if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") { @@ -1821,7 +1825,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { } VariantDef { did, - name, + ident, discr, fields, ctor_kind, @@ -1837,7 +1841,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { impl_stable_hash_for!(struct VariantDef { did, - name, + ident -> (ident.name), discr, fields, ctor_kind, @@ -1978,8 +1982,6 @@ impl_stable_hash_for!(struct ReprFlags { bits }); - - /// Represents the repr options provided by the user, #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 22bd1cd90a754..4d026b97233ee 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -26,8 +26,8 @@ use session::config::OutputFilenames; use traits::{self, Vtable}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, - CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, - CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, + CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, + CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution, }; use traits::query::method_autoderef::MethodAutoderefStepsResult; @@ -382,7 +382,7 @@ define_queries! { <'tcx> /// might want to use `reveal_all()` method to change modes. [] fn param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>, - /// Trait selection queries. These are best used by invoking `ty.moves_by_default()`, + /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. [] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, [] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 5d23ee0994a06..6887f480f72e0 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -503,37 +503,48 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If -Zincremental-verify-ich is specified, re-hash results from // the cache and make sure that they have the expected fingerprint. - if self.sess.opts.debugging_opts.incremental_verify_ich { - use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; - use ich::Fingerprint; + if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) { + self.incremental_verify_ich::(&result, dep_node, dep_node_index); + } - assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == - self.dep_graph.prev_fingerprint_of(dep_node), - "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { + self.dep_graph.mark_loaded_from_cache(dep_node_index, true); + } - debug!("BEGIN verify_ich({:?})", dep_node); - let mut hcx = self.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); + job.complete(&result, dep_node_index); - result.hash_stable(&mut hcx, &mut hasher); + Ok(result) + } - let new_hash: Fingerprint = hasher.finish(); - debug!("END verify_ich({:?})", dep_node); + #[inline(never)] + #[cold] + fn incremental_verify_ich>( + self, + result: &Q::Value, + dep_node: &DepNode, + dep_node_index: DepNodeIndex, + ) { + use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; + use ich::Fingerprint; - let old_hash = self.dep_graph.fingerprint_of(dep_node_index); + assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == + self.dep_graph.prev_fingerprint_of(dep_node), + "Fingerprint for green query instance not loaded \ + from cache: {:?}", dep_node); - assert!(new_hash == old_hash, "Found unstable fingerprints \ - for {:?}", dep_node); - } + debug!("BEGIN verify_ich({:?})", dep_node); + let mut hcx = self.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); - if self.sess.opts.debugging_opts.query_dep_graph { - self.dep_graph.mark_loaded_from_cache(dep_node_index, true); - } + result.hash_stable(&mut hcx, &mut hasher); - job.complete(&result, dep_node_index); + let new_hash: Fingerprint = hasher.finish(); + debug!("END verify_ich({:?})", dep_node); - Ok(result) + let old_hash = self.dep_graph.fingerprint_of(dep_node_index); + + assert!(new_hash == old_hash, "Found unstable fingerprints \ + for {:?}", dep_node); } fn force_query_with_job>( @@ -578,7 +589,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ((result, dep_node_index), diagnostics) = res; - if self.sess.opts.debugging_opts.query_dep_graph { + if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { self.dep_graph.mark_loaded_from_cache(dep_node_index, false); } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 4755adc4cd10d..f9b43f42d5298 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -434,12 +434,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsDoesNotOutlive(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)) } - RegionsInsufficientlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) - } - RegionsOverlyPolymorphic(a, b) => { - return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b)) - } + RegionsPlaceholderMismatch => RegionsPlaceholderMismatch, IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), Traits(x) => Traits(x), @@ -1006,8 +1001,7 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::FixedArraySize)(x), (ty::error::TypeError::ArgCount), (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), - (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), - (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), + (ty::error::TypeError::RegionsPlaceholderMismatch), (ty::error::TypeError::IntMismatch)(x), (ty::error::TypeError::FloatMismatch)(x), (ty::error::TypeError::Traits)(x), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f7adb83f8eb18..a2720bdf385cd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1396,6 +1396,13 @@ impl RegionKind { } } + pub fn is_placeholder(&self) -> bool { + match *self { + ty::RePlaceholder(..) => true, + _ => false, + } + } + pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool { match *self { ty::ReLateBound(debruijn, _) => debruijn >= index, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 560e80abb9cbd..64e7af815b4bf 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -2,12 +2,11 @@ use hir::def_id::DefId; use infer::canonical::Canonical; -use ty::{self, BoundVar, Lift, List, Ty, TyCtxt}; +use ty::{self, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; -use rustc_data_structures::indexed_vec::Idx; use smallvec::SmallVec; use core::intrinsics; @@ -559,43 +558,6 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>; -impl CanonicalUserSubsts<'tcx> { - /// True if this represents a substitution like - /// - /// ```text - /// [?0, ?1, ?2] - /// ``` - /// - /// i.e., each thing is mapped to a canonical variable with the same index. - pub fn is_identity(&self) -> bool { - if self.value.user_self_ty.is_some() { - return false; - } - - self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { - match kind.unpack() { - UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(debruijn, b) => { - // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(debruijn, ty::INNERMOST); - cvar == b.var - } - _ => false, - }, - - UnpackedKind::Lifetime(r) => match r { - ty::ReLateBound(debruijn, br) => { - // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(*debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() - } - _ => false, - }, - } - }) - } -} - /// Stores the user-given substs to reach some fully qualified path /// (e.g., `::Item` or `::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index b2e2955619e06..ac062a2378611 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -203,7 +203,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { let cause = ObligationCause { span, ..ObligationCause::dummy() }; let ctx = traits::FulfillmentContext::new(); match traits::fully_normalize(&infcx, ctx, cause, self, &ty) { - Ok(ty) => if infcx.type_moves_by_default(self, ty, span) { + Ok(ty) => if !infcx.type_is_copy_modulo_regions(self, ty, span) { infringing.push(field); } Err(errors) => { @@ -621,14 +621,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'tcx> ty::TyS<'tcx> { - pub fn moves_by_default(&'tcx self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - span: Span) - -> bool { - !tcx.at(span).is_copy_raw(param_env.and(self)) + /// Checks whether values of this type `T` are *moved* or *copied* + /// when referenced -- this amounts to a check for whether `T: + /// Copy`, but note that we **don't** consider lifetimes when + /// doing this check. This means that we may generate MIR which + /// does copies even when the type actually doesn't satisfy the + /// full requirements for the `Copy` trait (cc #29149) -- this + /// winds up being reported as an error during NLL borrow check. + pub fn is_copy_modulo_regions(&'tcx self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + span: Span) + -> bool { + tcx.at(span).is_copy_raw(param_env.and(self)) } + /// Checks whether values of this type `T` have a size known at + /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored + /// for the purposes of this check, so it can be an + /// over-approximation in generic contexts, where one can have + /// strange rules like `>::Bar: Sized` that + /// actually carry lifetime requirements. pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>)-> bool @@ -636,6 +649,13 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tcx_at.is_sized_raw(param_env.and(self)) } + /// Checks whether values of this type `T` implement the `Freeze` + /// trait -- frozen types are those that do not contain a + /// `UnsafeCell` anywhere. This is a language concept used to + /// distinguish "true immutability", which is relevant to + /// optimization as well as the rules around static values. Note + /// that the `Freeze` trait is not exposed to end users and is + /// effectively an implementation detail. pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -658,6 +678,19 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tcx.needs_drop_raw(param_env.and(self)) } + pub fn same_type(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + match (&a.sty, &b.sty) { + (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { + if did_a != did_b { + return false; + } + + substs_a.types().zip(substs_b.types()).all(|(a, b)| Self::same_type(a, b)) + } + _ => a == b, + } + } + /// Check whether a type is representable. This means it cannot contain unboxed /// structural recursion. This check is needed for structs and enums. pub fn is_representable(&'tcx self, @@ -730,19 +763,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } - fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.sty, &b.sty) { - (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { - if did_a != did_b { - return false; - } - - substs_a.types().zip(substs_b.types()).all(|(a, b)| same_type(a, b)) - } - _ => a == b, - } - } - // Does the type `ty` directly (without indirection through a pointer) // contain any types on stack `seen`? fn is_type_structurally_recursive<'a, 'tcx>( @@ -807,7 +827,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // struct Foo { Option> } for &seen_type in iter { - if same_type(ty, seen_type) { + if ty::TyS::same_type(ty, seen_type) { debug!("ContainsRecursive: {:?} contains {:?}", seen_type, ty); @@ -851,11 +871,13 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -865,11 +887,13 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -879,11 +903,13 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem); tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound(&infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP)) + .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( + &infcx, + param_env, + ty, + trait_def_id, + DUMMY_SP, + )) } fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -921,11 +947,11 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `ManuallyDrop` doesn't have a destructor regardless of field types. ty::Adt(def, _) if Some(def.did) == tcx.lang_items().manually_drop() => false, - // Issue #22536: We first query type_moves_by_default. It sees a + // Issue #22536: We first query `is_copy_modulo_regions`. It sees a // normalized version of the type, and therefore will definitely // know whether the type implements Copy (and thus needs no // cleanup/drop/zeroing) ... - _ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false, + _ if ty.is_copy_modulo_regions(tcx, param_env, DUMMY_SP) => false, // ... (issue #22536 continued) but as an optimization, still use // prior logic of asking for the structural "may drop". diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index f4a998fb9905a..aacc63c47de61 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -289,6 +289,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.out.extend(obligations); } + ty::FnDef(did, substs) => { + let obligations = self.nominal_obligations(did, substs); + self.out.extend(obligations); + } + ty::Ref(r, rty, _) => { // WfReference if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { @@ -349,7 +354,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } } - ty::FnDef(..) | ty::FnPtr(_) => { + ty::FnPtr(_) => { // let the loop iterate into the argument/return // types appearing in the fn signature } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d5e6bb9a2e2a5..79405b124001d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; +use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; use std::cell::Cell; @@ -21,17 +21,163 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; use hir; +/// The "region highlights" are used to control region printing during +/// specific error messages. When a "region highlight" is enabled, it +/// gives an alternate way to print specific regions. For now, we +/// always print those regions using a number, so something like `'0`. +/// +/// Regions not selected by the region highlight mode are presently +/// unaffected. +#[derive(Copy, Clone, Default)] +pub struct RegionHighlightMode { + /// If enabled, when we see the selected region, use `"'N"` + /// instead of the ordinary behavior. + highlight_regions: [Option<(ty::RegionKind, usize)>; 3], + + /// If enabled, when printing a "free region" that originated from + /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily + /// have names print as normal. + /// + /// This is used when you have a signature like `fn foo(x: &u32, + /// y: &'a u32)` and we want to give a name to the region of the + /// reference `x`. + highlight_bound_region: Option<(ty::BoundRegion, usize)>, +} + thread_local! { /// Mechanism for highlighting of specific regions for display in NLL region inference errors. /// Contains region to highlight and counter for number to use when highlighting. - static HIGHLIGHT_REGION_FOR_REGIONVID: Cell> = Cell::new(None) + static REGION_HIGHLIGHT_MODE: Cell = + Cell::new(RegionHighlightMode::default()) } -thread_local! { - /// Mechanism for highlighting of specific regions for display in NLL's 'borrow does not live - /// long enough' errors. Contains a region to highlight and a counter to use. - static HIGHLIGHT_REGION_FOR_BOUND_REGION: Cell> = - Cell::new(None) +impl RegionHighlightMode { + /// Read and return current region highlight settings (accesses thread-local state).a + pub fn get() -> Self { + REGION_HIGHLIGHT_MODE.with(|c| c.get()) + } + + /// Internal helper to update current settings during the execution of `op`. + fn set( + old_mode: Self, + new_mode: Self, + op: impl FnOnce() -> R, + ) -> R { + REGION_HIGHLIGHT_MODE.with(|c| { + c.set(new_mode); + let result = op(); + c.set(old_mode); + result + }) + } + + /// If `region` and `number` are both `Some`, invoke + /// `highlighting_region`. Otherwise, just invoke `op` directly. + pub fn maybe_highlighting_region( + region: Option>, + number: Option, + op: impl FnOnce() -> R, + ) -> R { + if let Some(k) = region { + if let Some(n) = number { + return Self::highlighting_region(k, n, op); + } + } + + op() + } + + /// During the execution of `op`, highlight the region inference + /// vairable `vid` as `'N`. We can only highlight one region vid + /// at a time. + pub fn highlighting_region( + region: ty::Region<'_>, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + let old_mode = Self::get(); + let mut new_mode = old_mode; + let first_avail_slot = new_mode.highlight_regions.iter_mut() + .filter(|s| s.is_none()) + .next() + .unwrap_or_else(|| { + panic!( + "can only highlight {} placeholders at a time", + old_mode.highlight_regions.len(), + ) + }); + *first_avail_slot = Some((*region, number)); + Self::set(old_mode, new_mode, op) + } + + /// Convenience wrapper for `highlighting_region` + pub fn highlighting_region_vid( + vid: ty::RegionVid, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + Self::highlighting_region(&ty::ReVar(vid), number, op) + } + + /// Returns true if any placeholders are highlighted. + fn any_region_vids_highlighted(&self) -> bool { + Self::get() + .highlight_regions + .iter() + .any(|h| match h { + Some((ty::ReVar(_), _)) => true, + _ => false, + }) + } + + /// Returns `Some(n)` with the number to use for the given region, + /// if any. + fn region_highlighted(&self, region: ty::Region<'_>) -> Option { + Self::get() + .highlight_regions + .iter() + .filter_map(|h| match h { + Some((r, n)) if r == region => Some(*n), + _ => None, + }) + .next() + } + + /// During the execution of `op`, highlight the given bound + /// region. We can only highlight one bound region at a time. See + /// the field `highlight_bound_region` for more detailed notes. + pub fn highlighting_bound_region( + br: ty::BoundRegion, + number: usize, + op: impl FnOnce() -> R, + ) -> R { + let old_mode = Self::get(); + assert!(old_mode.highlight_bound_region.is_none()); + Self::set( + old_mode, + Self { + highlight_bound_region: Some((br, number)), + ..old_mode + }, + op, + ) + } + + /// Returns true if any placeholders are highlighted. + pub fn any_placeholders_highlighted(&self) -> bool { + Self::get() + .highlight_regions + .iter() + .any(|h| match h { + Some((ty::RePlaceholder(_), _)) => true, + _ => false, + }) + } + + /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. + pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option { + self.region_highlighted(&ty::RePlaceholder(p)) + } } macro_rules! gen_display_debug_body { @@ -553,42 +699,6 @@ pub fn parameterized(f: &mut F, PrintContext::new().parameterized(f, substs, did, projections) } -fn get_highlight_region_for_regionvid() -> Option<(RegionVid, usize)> { - HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| hr.get()) -} - -pub fn with_highlight_region_for_regionvid( - r: RegionVid, - counter: usize, - op: impl FnOnce() -> R -) -> R { - HIGHLIGHT_REGION_FOR_REGIONVID.with(|hr| { - assert_eq!(hr.get(), None); - hr.set(Some((r, counter))); - let r = op(); - hr.set(None); - r - }) -} - -fn get_highlight_region_for_bound_region() -> Option<(ty::BoundRegion, usize)> { - HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| hr.get()) -} - -pub fn with_highlight_region_for_bound_region( - r: ty::BoundRegion, - counter: usize, - op: impl Fn() -> R -) -> R { - HIGHLIGHT_REGION_FOR_BOUND_REGION.with(|hr| { - assert_eq!(hr.get(), None); - hr.set(Some((r, counter))); - let r = op(); - hr.set(None); - r - }) -} - impl<'a, T: Print> Print for &'a T { fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { (*self).print(f, cx) @@ -709,6 +819,9 @@ define_print! { define_print! { ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { + display { + cx.parameterized(f, self.substs, self.def_id, &[]) + } debug { ty::tls::with(|tcx| { let dummy_self = tcx.mk_infer(ty::FreshTy(0)); @@ -737,7 +850,7 @@ define_print! { return self.print_debug(f, cx); } - if let Some((region, counter)) = get_highlight_region_for_bound_region() { + if let Some((region, counter)) = RegionHighlightMode::get().highlight_bound_region { if *self == region { return match *self { BrNamed(_, name) => write!(f, "{}", name), @@ -765,13 +878,37 @@ define_print! { } } +define_print! { + () ty::PlaceholderRegion, (self, f, cx) { + display { + if cx.is_verbose { + return self.print_debug(f, cx); + } + + let highlight = RegionHighlightMode::get(); + if let Some(counter) = highlight.placeholder_highlight(*self) { + write!(f, "'{}", counter) + } else if highlight.any_placeholders_highlighted() { + write!(f, "'_") + } else { + write!(f, "{}", self.name) + } + } + } +} + define_print! { () ty::RegionKind, (self, f, cx) { display { - if cx.is_verbose || get_highlight_region_for_regionvid().is_some() { + if cx.is_verbose { return self.print_debug(f, cx); } + // Watch out for region highlights. + if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { + return write!(f, "'{:?}", n); + } + // These printouts are concise. They do not contain all the information // the user might want to diagnose an error, but there is basically no way // to fit that into a short string. Hence the recommendation to use @@ -781,10 +918,12 @@ define_print! { write!(f, "{}", data.name) } ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { write!(f, "{}", br) } + ty::RePlaceholder(p) => { + write!(f, "{}", p) + } ty::ReScope(scope) if cx.identify_regions => { match scope.data { region::ScopeData::Node => @@ -803,11 +942,16 @@ define_print! { ), } } - ty::ReVar(region_vid) if cx.identify_regions => { - write!(f, "'{}rv", region_vid.index()) + ty::ReVar(region_vid) => { + if RegionHighlightMode::get().any_region_vids_highlighted() { + write!(f, "{:?}", region_vid) + } else if cx.identify_regions { + write!(f, "'{}rv", region_vid.index()) + } else { + Ok(()) + } } ty::ReScope(_) | - ty::ReVar(_) | ty::ReErased => Ok(()), ty::ReStatic => write!(f, "'static"), ty::ReEmpty => write!(f, "'"), @@ -936,13 +1080,10 @@ impl fmt::Debug for ty::FloatVid { impl fmt::Debug for ty::RegionVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some((region, counter)) = get_highlight_region_for_regionvid() { - debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter); - return if *self == region { - write!(f, "'{:?}", counter) - } else { - write!(f, "'_") - } + if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) { + return write!(f, "'{:?}", counter); + } else if RegionHighlightMode::get().any_region_vids_highlighted() { + return write!(f, "'_"); } write!(f, "'_#{}r", self.index()) diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index a05c56e3629a3..6c47e8784e025 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -3,7 +3,7 @@ > WARNING: This README is more or less obsolete, and will be removed > soon! The new system is described in the [rustc guide]. -[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +[rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html This pass has the job of enforcing memory safety. This is a subtle topic. This docs aim to explain both the practice and the theory diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index acd1c4afd2e63..226b03c99c043 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -78,6 +78,18 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) } } +/// Tell LLVM what instrument function to insert. +#[inline] +pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + if cx.sess().instrument_mcount() { + // Similar to `clang -pg` behavior. Handled by the + // `post-inline-ee-instrument` LLVM pass. + llvm::AddFunctionAttrStringValue( + llfn, llvm::AttributePlace::Function, + const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount")); + } +} + pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes @@ -174,6 +186,7 @@ pub fn from_fn_attrs( } set_frame_pointer_elimination(cx, llfn); + set_instrument_function(cx, llfn); set_probestack(cx, llfn); if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3be784ccc04b0..0fd04e9d20393 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1215,7 +1215,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { name: if fallback { String::new() } else { - adt.variants[index].name.as_str().to_string() + adt.variants[index].ident.as_str().to_string() }, type_metadata: variant_type_metadata, offset: Size::ZERO, @@ -1255,7 +1255,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { name: if fallback { String::new() } else { - adt.variants[i].name.as_str().to_string() + adt.variants[i].ident.as_str().to_string() }, type_metadata: variant_type_metadata, offset: Size::ZERO, @@ -1321,7 +1321,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.layout, self.layout.fields.offset(0), self.layout.field(cx, 0).size); - name.push_str(&adt.variants[*niche_variants.start()].name.as_str()); + name.push_str(&adt.variants[*niche_variants.start()].ident.as_str()); // Create the (singleton) list of descriptions of union members. vec![ @@ -1365,7 +1365,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { }; MemberDescription { - name: adt.variants[i].name.as_str().to_string(), + name: adt.variants[i].ident.as_str().to_string(), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1433,7 +1433,7 @@ fn describe_enum_variant( containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { - let variant_name = variant.name.as_str(); + let variant_name = variant.ident.as_str(); let unique_type_id = debug_context(cx).type_map .borrow_mut() .get_unique_type_id_of_enum_variant( @@ -1527,7 +1527,7 @@ fn prepare_enum_metadata( let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) .map(|((_, discr), v)| { - let name = SmallCStr::new(&v.name.as_str()); + let name = SmallCStr::new(&v.ident.as_str()); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index bac2294bd31c7..97128c2d2a2ce 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -60,7 +60,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, = (&layout.ty.sty, &layout.variants) { if def.is_enum() && !def.variants.is_empty() { - write!(&mut name, "::{}", def.variants[index].name).unwrap(); + write!(&mut name, "::{}", def.variants[index].ident).unwrap(); } } Some(name) diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index a8cc401ac38ee..9c027f110eb4e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -7,7 +7,6 @@ use errors::{DiagnosticBuilder, Level}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::type_variable::TypeVariableOrigin; use rustc::infer::{self, InferOk, InferResult, SuppressRegionErrors}; use rustc::middle::region; use rustc::session::config::{OutputFilenames, OutputTypes}; @@ -26,7 +25,6 @@ use syntax::ast; use syntax::feature_gate::UnstableFeatures; use syntax::source_map::{FileName, FilePathMapping, SourceMap}; use syntax::symbol::Symbol; -use syntax_pos::DUMMY_SP; use std::path::PathBuf; use std::sync::mpsc; @@ -261,7 +259,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { assert!(idx < names.len()); for item in &m.item_ids { let item = this.infcx.tcx.hir().expect_item(item.id); - if item.name.to_string() == names[idx] { + if item.ident.to_string() == names[idx] { return search(this, item, idx + 1, names); } } @@ -431,17 +429,6 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } } } - - /// Checks that `t1 <: t2` is false (this may register additional - /// region checks). - pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub(t1, t2) { - Err(_) => {} - Ok(_) => { - panic!("unexpected success computing sub({:?},{:?})", t1, t2); - } - } - } } #[test] @@ -470,25 +457,6 @@ fn contravariant_region_ptr_err() { }) } -#[test] -fn sub_free_bound_false() { - //! Test that: - //! - //! fn(&'a isize) <: for<'b> fn(&'b isize) - //! - //! *does not* hold. - - test_env(EMPTY_SOURCE_STR, errors(&[]), |mut env| { - env.create_simple_region_hierarchy(); - let t_rptr_free1 = env.t_rptr_free(1); - let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub( - env.t_fn(&[t_rptr_free1], env.tcx().types.isize), - env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), - ); - }) -} - #[test] fn sub_bound_free_true() { //! Test that: @@ -508,25 +476,6 @@ fn sub_bound_free_true() { }) } -#[test] -fn sub_free_bound_false_infer() { - //! Test that: - //! - //! fn(_#1) <: for<'b> fn(&'b isize) - //! - //! does NOT hold for any instantiation of `_#1`. - - test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { - let t_infer1 = env.infcx - .next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP)); - let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub( - env.t_fn(&[t_infer1], env.tcx().types.isize), - env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), - ); - }) -} - /// Test substituting a bound region into a function, which introduces another level of binding. /// This requires adjusting the Debruijn index. #[test] diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index cd4cbcc13a6f2..27b65b4ec48a4 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -540,7 +540,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { return; } let param_env = ty::ParamEnv::empty(); - if !ty.moves_by_default(cx.tcx, param_env, item.span) { + if ty.is_copy_modulo_regions(cx.tcx, param_env, item.span) { return; } if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() { diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index e425d2cdae9a7..2694a04b94ce4 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemKind::Mod(_) = it.node { - self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span)); + self.check_snake_case(cx, "module", &it.ident.as_str(), Some(it.span)); } } @@ -354,10 +354,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { if attr::find_by_name(&it.attrs, "no_mangle").is_some() { return; } - NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.name, it.span); + NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.ident.name, + it.span); } hir::ItemKind::Const(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span); + NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident.name, + it.span); } _ => {} } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 65e1b9ff7628b..642681a73a8a0 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -837,7 +837,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let bytes = variant_layout.size.bytes().saturating_sub(discr_size); debug!("- variant `{}` is {} bytes large", - variant.node.name, + variant.node.ident, bytes); bytes }) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 687753bd8de08..dc8db5be5820a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -553,7 +553,7 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef::new( tcx, def_id, - self.item_name(index).as_symbol(), + Ident::from_interned_str(self.item_name(index)), data.discr, item.children.decode(self).map(|index| { let f = self.entry(index); diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 5044e351962ed..f0234c48c3eca 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ either = "1.5.0" graphviz = { path = "../libgraphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.5.0" +polonius-engine = "0.6.2" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index b072e464a2998..83cd28bbdc58c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -12,7 +12,7 @@ use rustc::mir::{ TerminatorKind, VarBindingForm, }; use rustc::ty::{self, DefIdTree}; -use rustc::util::ppaux::with_highlight_region_for_bound_region; +use rustc::util::ppaux::RegionHighlightMode; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -181,38 +181,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - if let Some(ty) = self.retrieve_type_for_place(used_place) { - let needs_note = match ty.sty { - ty::Closure(id, _) => { - let tables = self.infcx.tcx.typeck_tables_of(id); - let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); - let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); + let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let needs_note = match ty.sty { + ty::Closure(id, _) => { + let tables = self.infcx.tcx.typeck_tables_of(id); + let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - tables.closure_kind_origins().get(hir_id).is_none() - } - _ => true, + tables.closure_kind_origins().get(hir_id).is_none() + } + _ => true, + }; + + if needs_note { + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + + let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let note_msg = match self.describe_place_with_options( + place, + IncludingDowncast(true), + ) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), }; - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; - - if let Some(ty) = self.retrieve_type_for_place(place) { - let note_msg = match self.describe_place_with_options( - place, - IncludingDowncast(true), - ) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); - } - } + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); } if let Some((_, mut old_err)) = self.move_error_reported @@ -1558,7 +1556,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )?; buf.push_str("["); if self.append_local_to_string(index, buf).is_err() { - buf.push_str(".."); + buf.push_str("_"); } buf.push_str("]"); } @@ -1663,22 +1661,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Retrieve type of a place for the current MIR representation - fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { - match place { - Place::Local(local) => { - let local = &self.mir.local_decls[*local]; - Some(local.ty) - } - Place::Promoted(ref prom) => Some(prom.1), - Place::Static(ref st) => Some(st.ty), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(_, ty) => Some(ty), - _ => None, - }, - } - } - /// Check if a place is a thread-local static. pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool { if let Place::Static(statik) = place { @@ -2195,7 +2177,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, - ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()), + ) => RegionHighlightMode::highlighting_bound_region(*br, counter, || ty.to_string()), _ => ty.to_string(), } } @@ -2207,7 +2189,11 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::TyKind::Ref(region, _, _) => match region { ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { - with_highlight_region_for_bound_region(*br, counter, || region.to_string()) + RegionHighlightMode::highlighting_bound_region( + *br, + counter, + || region.to_string(), + ) } _ => region.to_string(), }, diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 76b516246f92a..112b39952559b 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -56,10 +56,14 @@ struct InvalidationGenerator<'cx, 'tcx: 'cx, 'gcx: 'tcx> { /// Visits the whole MIR and generates invalidates() facts /// Most of the code implementing this was stolen from borrow_check/mod.rs impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { - fn visit_statement(&mut self, - block: BasicBlock, - statement: &Statement<'tcx>, - location: Location) { + fn visit_statement( + &mut self, + block: BasicBlock, + statement: &Statement<'tcx>, + location: Location, + ) { + self.check_activations(location); + match statement.kind { StatementKind::Assign(ref lhs, ref rhs) => { self.consume_rvalue( @@ -148,6 +152,8 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> { terminator: &Terminator<'tcx>, location: Location ) { + self.check_activations(location); + match terminator.kind { TerminatorKind::SwitchInt { ref discr, @@ -471,5 +477,41 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> { let lidx = self.location_table.start_index(l); self.all_facts.invalidates.push((lidx, b)); } + + fn check_activations( + &mut self, + location: Location, + ) { + if !self.tcx.two_phase_borrows() { + return; + } + + // Two-phase borrow support: For each activation that is newly + // generated at this statement, check if it interferes with + // another borrow. + for &borrow_index in self.borrow_set.activations_at_location(location) { + let borrow = &self.borrow_set[borrow_index]; + + // only mutable borrows should be 2-phase + assert!(match borrow.kind { + BorrowKind::Shared | BorrowKind::Shallow => false, + BorrowKind::Unique | BorrowKind::Mut { .. } => true, + }); + + self.access_place( + ContextKind::Activation.new(location), + &borrow.borrowed_place, + ( + Deep, + Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), + ), + LocalMutationIsAllowed::No, + ); + + // We do not need to call `check_if_path_or_subpath_is_moved` + // again, as we already called it when we made the + // initial reservation. + } + } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index c5eabbbefa9a4..a092c3b8ecde2 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -230,13 +230,14 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( // Before the CFG, dump out the values for each region variable. PassWhere::BeforeCFG => { regioncx.dump_mir(out)?; + writeln!(out, "|")?; if let Some(closure_region_requirements) = closure_region_requirements { - writeln!(out, "|")?; writeln!(out, "| Free Region Constraints")?; for_each_region_constraint(closure_region_requirements, &mut |msg| { writeln!(out, "| {}", msg) })?; + writeln!(out, "|")?; } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 963d4ab3a5466..bff8015511242 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -8,7 +8,7 @@ use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; -use rustc::util::ppaux::with_highlight_region_for_regionvid; +use rustc::util::ppaux::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; @@ -396,7 +396,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_ty: Ty<'tcx>, counter: &mut usize, ) -> Option { - let type_name = with_highlight_region_for_regionvid(needle_fr, *counter, || { + let type_name = RegionHighlightMode::highlighting_region_vid(needle_fr, *counter, || { infcx.extract_type_name(&argument_ty) }); @@ -673,8 +673,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { return None; } - let type_name = with_highlight_region_for_regionvid( - fr, *counter, || infcx.extract_type_name(&return_ty)); + let type_name = RegionHighlightMode::highlighting_region_vid( + fr, *counter, || infcx.extract_type_name(&return_ty), + ); let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir"); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 673ee4ec017ac..55af7399aab8f 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,6 +1,10 @@ +use rustc::infer::canonical::Canonical; use rustc::ty::subst::Substs; -use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{Location, Mir, UserTypeAnnotation}; +use rustc::ty::{ + self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, UserTypeAnnotation, + UserTypeAnnotationIndex, +}; +use rustc::mir::{Location, Mir}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -55,7 +59,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { debug!("visit_ty: ty={:?}", ty); } - fn visit_user_type_annotation(&mut self, _ty: &mut UserTypeAnnotation<'tcx>) { + fn visit_user_type_annotation( + &mut self, + _index: UserTypeAnnotationIndex, + _ty: &mut Canonical<'tcx, UserTypeAnnotation<'tcx>>, + ) { // User type annotations represent the types that the user // wrote in the progarm. We don't want to erase the regions // from these types: rather, we want to add them as diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6d2fb54587ea3..b3e1237a45087 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -36,7 +36,10 @@ use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; -use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; +use rustc::ty::{ + self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserTypeAnnotation, + UserTypeAnnotationIndex, +}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::ty::layout::VariantIdx; @@ -272,19 +275,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_constant(constant, location); self.sanitize_type(constant, constant.ty); - if let Some(user_ty) = constant.user_ty { + if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( constant.ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty, projs: vec![], }, + &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { + let annotation = self.cx.instantiated_type_annotations[&annotation_index]; span_mirbug!( self, constant, "bad constant user type {:?} vs {:?}: {:?}", - user_ty, + annotation, constant.ty, terr, ); @@ -303,8 +307,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_type(local_decl, local_decl.ty); for (user_ty, span) in local_decl.user_ty.projections_and_spans() { + let ty = if !local_decl.is_nonref_binding() { + // If we have a binding of the form `let ref x: T = ..` then remove the outermost + // reference so we can check the type annotation for the remaining type. + if let ty::Ref(_, rty, _) = local_decl.ty.sty { + rty + } else { + bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); + } + } else { + local_decl.ty + }; + if let Err(terr) = self.cx.relate_type_and_user_type( - local_decl.ty, + ty, ty::Variance::Invariant, user_ty, Locations::All(*span), @@ -487,13 +503,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]), }; - // In order to have a Copy operand, the type T of the value must be Copy. Note that we - // prove that T: Copy, rather than using the type_moves_by_default test. This is - // important because type_moves_by_default ignores the resulting region obligations and - // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored - // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds - // fully apply: in effect, the rule is that if a value of some type could implement - // Copy, then it must. + // In order to have a Copy operand, the type T of the + // value must be Copy. Note that we prove that T: Copy, + // rather than using the `is_copy_modulo_regions` + // test. This is important because + // `is_copy_modulo_regions` ignores the resulting region + // obligations and assumes they pass. This can result in + // bounds from Copy impls being unsoundly ignored (e.g., + // #29149). Note that we decide to use Copy before knowing + // whether the bounds fully apply: in effect, the rule is + // that if a value of some type could implement Copy, then + // it must. self.cx.prove_trait_ref( trait_ref, location.to_locations(), @@ -715,6 +735,15 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>, + /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create + /// an "instantiated" version at the beginning of type check, which replaces each + /// canonical variable with a fresh inference variable. These instantiated versions are + /// stored either in this field or in user_substs, depending on the kind of user-type + /// annotation. They are then referenced by the code which has the job of enforcing these + /// annotations. Part of the reason for this setup is that it allows us to enforce basic + /// WF criteria on the types even if the code that referenced them is dead + /// code (see #54943). + instantiated_type_annotations: FxHashMap>, } struct BorrowCheckContext<'a, 'tcx: 'a> { @@ -860,7 +889,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>, ) -> Self { - TypeChecker { + let mut checker = Self { infcx, last_span: DUMMY_SP, mir, @@ -871,7 +900,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, + instantiated_type_annotations: Default::default(), + }; + checker.instantiate_user_type_annotations(); + checker + } + + /// Instantiate canonical types from user type annotations in the `Mir` into the + /// `TypeChecker`. Used when relating user type annotations and when checking if + /// annotations are well-formed. + fn instantiate_user_type_annotations(&mut self) { + debug!( + "instantiate_user_type_annotations: user_type_annotations={:?}", + self.mir.user_type_annotations + ); + for annotation_index in self.mir.user_type_annotations.indices() { + let (span, canonical_annotation) = &self.mir.user_type_annotations[annotation_index]; + let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( + *span, &canonical_annotation + ); + match annotation { + UserTypeAnnotation::Ty(ref mut ty) => + *ty = self.normalize(ty, Locations::All(*span)), + _ => {}, + } + self.instantiated_type_annotations.insert(annotation_index, annotation); } + debug!( + "instantiate_user_type_annotations: instantiated_type_annotations={:?}", + self.instantiated_type_annotations, + ); } /// Given some operation `op` that manipulates types, proves @@ -1003,18 +1061,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - match user_ty.base { - UserTypeAnnotation::Ty(canonical_ty) => { - let (ty, _) = self.infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty); - + let type_annotation = self.instantiated_type_annotations[&user_ty.base]; + match type_annotation { + UserTypeAnnotation::Ty(ty) => { // The `TypeRelating` code assumes that "unresolved inference // variables" appear in the "a" side, so flip `Contravariant` // ambient variance to get the right relationship. let v1 = ty::Contravariant.xform(v); - let tcx = self.infcx.tcx; - let ty = self.normalize(ty, locations); // We need to follow any provided projetions into the type. // @@ -1048,13 +1102,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.relate_types(ty, v1, a, locations, category)?; } } - UserTypeAnnotation::TypeOf(def_id, canonical_substs) => { - let ( - user_substs, - _, - ) = self.infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs); - + UserTypeAnnotation::TypeOf(def_id, user_substs) => { let projs = self.infcx.tcx.intern_projs(&user_ty.projs); self.fully_perform_op( locations, @@ -1225,19 +1273,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } - if let Some(user_ty) = self.rvalue_user_ty(rv) { + if let Some(annotation_index) = self.rvalue_user_ty(rv) { if let Err(terr) = self.relate_type_and_user_type( rv_ty, ty::Variance::Invariant, - &UserTypeProjection { base: user_ty, projs: vec![], }, + &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), ConstraintCategory::Boring, ) { + let annotation = self.instantiated_type_annotations[&annotation_index]; span_mirbug!( self, stmt, "bad user type on rvalue ({:?} = {:?}): {:?}", - user_ty, + annotation, rv_ty, terr ); @@ -1282,21 +1331,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); }; } - StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => { + StatementKind::AscribeUserType(ref place, variance, box ref projection) => { let place_ty = place.ty(mir, tcx).to_ty(tcx); if let Err(terr) = self.relate_type_and_user_type( place_ty, variance, - c_ty, + projection, Locations::All(stmt.source_info.span), ConstraintCategory::TypeAnnotation, ) { + let annotation = self.instantiated_type_annotations[&projection.base]; span_mirbug!( self, stmt, - "bad type assert ({:?} <: {:?}): {:?}", + "bad type assert ({:?} <: {:?} with projections {:?}): {:?}", place_ty, - c_ty, + annotation, + projection.projs, terr ); } @@ -1405,7 +1456,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.check_call_dest(mir, term, &sig, destination, term_location); self.prove_predicates( - sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)), + sig.inputs_and_output.iter().map(|ty| ty::Predicate::WellFormed(ty)), term_location.to_locations(), ConstraintCategory::Boring, ); @@ -1955,7 +2006,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { /// If this rvalue supports a user-given type annotation, then /// extract and return it. This represents the final type of the /// rvalue and will be unified with the inferred type. - fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option> { + fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option { match rvalue { Rvalue::Use(_) | Rvalue::Repeat(..) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ad4e5a50dcd14..f3d89a7a02515 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -141,9 +141,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { None, remainder_span, lint_level, slice::from_ref(&pattern), ArmHasGuard(false), None); + debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_bindings( &pattern, - &PatternTypeProjections::none(), + UserTypeProjections::none(), &mut |this, _, _, _, node, span, _, _| { this.storage_live_binding(block, node, span, OutsideGuard); this.schedule_drop_for_binding(node, span, OutsideGuard); diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a5fbe566a4a73..a431bfc61b37a 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -29,11 +29,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { lint_level: _, value, } => this.as_constant(value), - ExprKind::Literal { literal, user_ty } => Constant { - span, - ty, - user_ty, - literal, + ExprKind::Literal { literal, user_ty } => { + let user_ty = user_ty.map(|ty| { + this.canonical_user_type_annotations.push((span, ty)) + }); + Constant { + span, + ty, + user_ty, + literal, + } }, _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index d651b6bdca01f..3ed00d5797907 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -133,6 +133,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::PlaceTypeAscription { source, user_ty } => { let place = unpack!(block = this.as_place(block, source)); if let Some(user_ty) = user_ty { + let annotation_index = this.canonical_user_type_annotations.push( + (source_info.span, user_ty) + ); this.cfg.push( block, Statement { @@ -140,7 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( place.clone(), Variance::Invariant, - box UserTypeProjection { base: user_ty, projs: vec![], }, + box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); @@ -153,6 +156,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block = this.as_temp(block, source.temp_lifetime, source, mutability) ); if let Some(user_ty) = user_ty { + let annotation_index = this.canonical_user_type_annotations.push( + (source_info.span, user_ty) + ); this.cfg.push( block, Statement { @@ -160,7 +166,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( Place::Local(temp.clone()), Variance::Invariant, - box UserTypeProjection { base: user_ty, projs: vec![], }, + box UserTypeProjection { base: annotation_index, projs: vec![], }, ), }, ); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2f0e06cd4da29..7dcac05e702a3 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -331,6 +331,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .collect() }; + let user_ty = user_ty.map(|ty| { + this.canonical_user_type_annotations.push((expr_span, ty)) + }); let adt = box AggregateKind::Adt( adt_def, variant_index, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 86dbf1422738a..fe5bc6e19db65 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -8,7 +8,6 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard}; use build::{BlockAnd, BlockAndExtension, Builder}; use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use hair::*; -use hair::pattern::PatternTypeProjections; use rustc::mir::*; use rustc::ty::{self, Ty}; use rustc::ty::layout::VariantIdx; @@ -302,6 +301,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let ty_source_info = self.source_info(user_ty_span); + let user_ty = box pat_ascription_ty.user_ty( + &mut self.canonical_user_type_annotations, ty_source_info.span + ); self.cfg.push( block, Statement { @@ -309,7 +311,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( place, ty::Variance::Invariant, - box pat_ascription_ty.user_ty(), + user_ty, ), }, ); @@ -406,9 +408,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let mut scope = self.source_scope; let num_patterns = patterns.len(); + debug!("declare_bindings: patterns={:?}", patterns); self.visit_bindings( &patterns[0], - &PatternTypeProjections::none(), + UserTypeProjections::none(), &mut |this, mutability, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { visibility_scope = @@ -484,7 +487,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub(super) fn visit_bindings( &mut self, pattern: &Pattern<'tcx>, - pattern_user_ty: &PatternTypeProjections<'tcx>, + pattern_user_ty: UserTypeProjections<'tcx>, f: &mut impl FnMut( &mut Self, Mutability, @@ -493,9 +496,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { NodeId, Span, Ty<'tcx>, - &PatternTypeProjections<'tcx>, + UserTypeProjections<'tcx>, ), ) { + debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty); match *pattern.kind { PatternKind::Binding { mutability, @@ -506,19 +510,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ref subpattern, .. } => { - let pattern_ref_binding; // sidestep temp lifetime limitations. - let binding_user_ty = match mode { - BindingMode::ByValue => { pattern_user_ty } - BindingMode::ByRef(..) => { - // If this is a `ref` binding (e.g., `let ref - // x: T = ..`), then the type of `x` is not - // `T` but rather `&T`. - pattern_ref_binding = pattern_user_ty.ref_binding(); - &pattern_ref_binding - } - }; - - f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty); + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); if let Some(subpattern) = subpattern.as_ref() { self.visit_bindings(subpattern, pattern_user_ty, f); } @@ -536,18 +528,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let from = u32::try_from(prefix.len()).unwrap(); let to = u32::try_from(suffix.len()).unwrap(); for subpattern in prefix { - self.visit_bindings(subpattern, &pattern_user_ty.index(), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); } for subpattern in slice { - self.visit_bindings(subpattern, &pattern_user_ty.subslice(from, to), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f); } for subpattern in suffix { - self.visit_bindings(subpattern, &pattern_user_ty.index(), f); + self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f); } } PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {} PatternKind::Deref { ref subpattern } => { - self.visit_bindings(subpattern, &pattern_user_ty.deref(), f); + self.visit_bindings(subpattern, pattern_user_ty.deref(), f); } PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => { // This corresponds to something like @@ -555,22 +547,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // ``` // let A::<'a>(_): A<'static> = ...; // ``` - let subpattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span); - self.visit_bindings(subpattern, &subpattern_user_ty, f) + let annotation = (user_ty_span, user_ty.base); + let projection = UserTypeProjection { + base: self.canonical_user_type_annotations.push(annotation), + projs: user_ty.projs.clone(), + }; + let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span); + self.visit_bindings(subpattern, subpattern_user_ty, f) } PatternKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field); - self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); + let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); + debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty); + self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } PatternKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = pattern_user_ty.variant( + let subpattern_user_ty = pattern_user_ty.clone().variant( adt_def, variant_index, subpattern.field); - self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); + self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } } @@ -1314,6 +1312,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ascription.user_ty, ); + let user_ty = box ascription.user_ty.clone().user_ty( + &mut self.canonical_user_type_annotations, source_info.span + ); self.cfg.push( block, Statement { @@ -1321,7 +1322,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::AscribeUserType( ascription.source.clone(), ty::Variance::Covariant, - box ascription.user_ty.clone().user_ty(), + user_ty, ), }, ); @@ -1468,7 +1469,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { num_patterns: usize, var_id: NodeId, var_ty: Ty<'tcx>, - user_var_ty: &PatternTypeProjections<'tcx>, + user_ty: UserTypeProjections<'tcx>, has_guard: ArmHasGuard, opt_match_place: Option<(Option>, Span)>, pat_span: Span, @@ -1484,10 +1485,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()), BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()), }; + debug!("declare_binding: user_ty={:?}", user_ty); let local = LocalDecl::<'tcx> { mutability, ty: var_ty, - user_ty: user_var_ty.clone().user_ty(), + user_ty, name: Some(name), source_info, visibility_scope, diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 472f05a101f9e..5b20d412f0dd5 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { let tcx = self.hir.tcx(); let ty = place.ty(&self.local_decls, tcx).to_ty(tcx); - if self.hir.type_moves_by_default(ty, DUMMY_SP) { + if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) { Operand::Move(place) } else { Operand::Copy(place) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a700963749f67..8acdecf6fa248 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -379,6 +379,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// (A match binding can have two locals; the 2nd is for the arm's guard.) var_indices: NodeMap, local_decls: IndexVec>, + canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, upvar_decls: Vec, unit_temp: Option>, @@ -812,6 +813,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { LocalDecl::new_return_place(return_ty, return_span), 1, ), + canonical_user_type_annotations: IndexVec::new(), upvar_decls, var_indices: Default::default(), unit_temp: None, @@ -845,6 +847,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { IndexVec::new(), yield_ty, self.local_decls, + self.canonical_user_type_annotations, self.arg_count, self.upvar_decls, self.fn_span, diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 91568f7ff6b58..e73cc40c8c6e4 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -78,12 +78,13 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let mut pattern = cx.pattern_from_hir(&local.pat); if let Some(ty) = &local.ty { - if let Some(&user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) { + if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) { + debug!("mirror_stmts: user_ty={:?}", user_ty); pattern = Pattern { ty: pattern.ty, span: pattern.span, kind: Box::new(PatternKind::AscribeUserType { - user_ty: PatternTypeProjection::from_canonical_ty(user_ty), + user_ty: PatternTypeProjection::from_user_type(user_ty), user_ty_span: ty.span, subpattern: pattern }) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 23cfd18ef5d4c..293058a0f26f5 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -11,7 +11,7 @@ use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; use rustc::hir::def_id::LocalDefId; -use rustc::mir::{BorrowKind}; +use rustc::mir::BorrowKind; use syntax_pos::Span; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -283,9 +283,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; if let Some((adt_def, index)) = adt_data { let substs = cx.tables().node_substs(fun.hir_id); - - let user_ty = cx.tables().user_substs(fun.hir_id) - .map(|user_substs| UserTypeAnnotation::TypeOf(adt_def.did, user_substs)); + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(fun.hir_id) + .map(|u_ty| *u_ty) + .map(|mut u_ty| { + if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut u_ty.value { + *did = adt_def.did; + } + u_ty + }); + debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); let field_refs = args.iter() .enumerate() @@ -464,11 +471,14 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::Adt(adt, substs) => { match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); + debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); ExprKind::Adt { adt_def: adt, variant_index: VariantIdx::new(0), substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), + user_ty, fields: field_refs(cx, fields), base: base.as_ref().map(|base| { FruInfo { @@ -481,20 +491,24 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } AdtKind::Enum => { - let def = match *qpath { - hir::QPath::Resolved(_, ref path) => path.def, - hir::QPath::TypeRelative(..) => Def::Err, - }; + let def = cx.tables().qpath_def(qpath, expr.hir_id); match def { Def::Variant(variant_id) => { assert!(base.is_none()); let index = adt.variant_index_with_id(variant_id); + let user_provided_types = cx.tables().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id) + .map(|u_ty| *u_ty); + debug!( + "make_mirror_unadjusted: (variant) user_ty={:?}", + user_ty + ); ExprKind::Adt { adt_def: adt, variant_index: index, substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), + user_ty, fields: field_refs(cx, fields), base: None, } @@ -638,8 +652,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprKind::Cast(ref source, ref cast_ty) => { // Check for a user-given type annotation on this `cast` - let user_ty = cx.tables.user_provided_tys().get(cast_ty.hir_id) - .map(|&t| UserTypeAnnotation::Ty(t)); + let user_provided_types = cx.tables.user_provided_types(); + let user_ty = user_provided_types.get(cast_ty.hir_id); debug!( "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}", @@ -745,20 +759,20 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, span: expr.span, kind: cast, }; + debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); ExprKind::ValueTypeAscription { source: cast_expr.to_ref(), - user_ty: Some(user_ty), + user_ty: Some(*user_ty), } } else { cast } } hir::ExprKind::Type(ref source, ref ty) => { - let user_provided_tys = cx.tables.user_provided_tys(); - let user_ty = user_provided_tys - .get(ty.hir_id) - .map(|&c_ty| UserTypeAnnotation::Ty(c_ty)); + let user_provided_types = cx.tables.user_provided_types(); + let user_ty = user_provided_types.get(ty.hir_id).map(|u_ty| *u_ty); + debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); if source.is_place_expr() { ExprKind::PlaceTypeAscription { source: source.to_ref(), @@ -795,8 +809,9 @@ fn user_substs_applied_to_def( cx: &mut Cx<'a, 'gcx, 'tcx>, hir_id: hir::HirId, def: &Def, -) -> Option> { - match def { +) -> Option> { + debug!("user_substs_applied_to_def: def={:?}", def); + let user_provided_type = match def { // A reference to something callable -- e.g., a fn, method, or // a tuple-struct or tuple-variant. This has the type of a // `Fn` but with the user-given substitutions. @@ -805,8 +820,7 @@ fn user_substs_applied_to_def( Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) | Def::Const(_) | - Def::AssociatedConst(_) => - Some(UserTypeAnnotation::TypeOf(def.def_id(), cx.tables().user_substs(hir_id)?)), + Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty), // A unit struct/variant which is used as a value (e.g., // `None`). This has the type of the enum/struct that defines @@ -822,7 +836,9 @@ fn user_substs_applied_to_def( _ => bug!("user_substs_applied_to_def: unexpected def {:?} at {:?}", def, hir_id) - } + }; + debug!("user_substs_applied_to_def: user_provided_type={:?}", user_provided_type); + user_provided_type } fn method_callee<'a, 'gcx, 'tcx>( @@ -842,6 +858,7 @@ fn method_callee<'a, 'gcx, 'tcx>( span_bug!(expr.span, "no type-dependent def for method callee") }); let user_ty = user_substs_applied_to_def(cx, expr.hir_id, def); + debug!("method_callee: user_ty={:?}", user_ty); (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty) } }; @@ -909,6 +926,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::VariantCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => { let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); + debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { literal: ty::Const::zero_sized( cx.tcx, @@ -921,6 +939,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => { let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); + debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { literal: ty::Const::unevaluated( cx.tcx, @@ -934,6 +953,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::StructCtor(def_id, CtorKind::Const) | Def::VariantCtor(def_id, CtorKind::Const) => { + let user_provided_types = cx.tables.user_provided_types(); + let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); + debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); match cx.tables().node_id_to_type(expr.hir_id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. @@ -942,7 +964,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, adt_def, variant_index: adt_def.variant_index_with_id(def_id), substs, - user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt_def), + user_ty: user_provided_type, fields: vec![], base: None, } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 60c8022a374be..07f3c38c62c52 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -223,8 +223,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.check_overflow } - pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool { - self.infcx.type_moves_by_default(self.param_env, ty, span) + pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { + self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index bcca501e600ac..b56e3d4e77395 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -4,11 +4,12 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use rustc::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp}; +use rustc::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc::hir::def_id::DefId; +use rustc::infer::canonical::Canonical; use rustc::middle::region; use rustc::ty::subst::Substs; -use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; +use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, UserTypeAnnotation}; use rustc::ty::layout::VariantIdx; use rustc::hir; use syntax::ast; @@ -20,7 +21,7 @@ mod constant; pub mod pattern; pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern}; -pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections}; +pub(crate) use self::pattern::PatternTypeProjection; mod util; @@ -265,7 +266,7 @@ pub enum ExprKind<'tcx> { /// Optional user-given substs: for something like `let x = /// Bar:: { ... }`. - user_ty: Option>, + user_ty: Option>>, fields: Vec>, base: Option> @@ -273,12 +274,12 @@ pub enum ExprKind<'tcx> { PlaceTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option>, + user_ty: Option>>, }, ValueTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option>, + user_ty: Option>>, }, Closure { closure_id: DefId, @@ -288,7 +289,7 @@ pub enum ExprKind<'tcx> { }, Literal { literal: &'tcx Const<'tcx>, - user_ty: Option>, + user_ty: Option>>, }, InlineAsm { asm: &'tcx hir::InlineAsm, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 50d861b674cef..c104af7a7d81b 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -306,7 +306,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor, pat: &Pat) { let pat_ty = cx.tables.pat_ty(p); if let ty::Adt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { - variant.name == ident.name && variant.ctor_kind == CtorKind::Const + variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { let ty_path = cx.tcx.item_path_str(edef.did); let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, @@ -545,7 +545,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, match bm { ty::BindByValue(..) => { let pat_ty = cx.tables.node_id_to_type(p.hir_id); - if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { + if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p), span_vec); } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 92da0563d8091..10d2d7bc1b18b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,9 +12,10 @@ use hair::util::UserAnnotatedTyHelpers; use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; -use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections}; +use rustc::mir::{ProjectionElem, UserTypeProjection}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift}; +use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; @@ -58,113 +59,29 @@ pub struct Pattern<'tcx> { #[derive(Clone, Debug)] -pub(crate) struct PatternTypeProjections<'tcx> { - contents: Vec<(PatternTypeProjection<'tcx>, Span)>, +pub struct PatternTypeProjection<'tcx> { + pub base: CanonicalUserTypeAnnotation<'tcx>, + pub projs: Vec>, } -impl<'tcx> PatternTypeProjections<'tcx> { - pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> { - UserTypeProjections::from_projections( - self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span))) - } - - pub(crate) fn none() -> Self { - PatternTypeProjections { contents: vec![] } - } - - pub(crate) fn ref_binding(&self) -> Self { - // FIXME(#55401): ignore for now - PatternTypeProjections { contents: vec![] } - } - - fn map_projs(&self, - mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>) - -> Self - { - PatternTypeProjections { - contents: self.contents - .iter() - .map(|(proj, span)| (f(proj), *span)) - .collect(), } - } - - pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) } - - pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to)) - } - - pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) } - - pub(crate) fn leaf(&self, field: Field) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field)) - } - - pub(crate) fn variant(&self, - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - field: Field) -> Self { - self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) - } - - pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self { - let mut new = self.clone(); - new.contents.push((user_ty.clone(), sp)); - new - } -} - -#[derive(Clone, Debug)] -pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>); - impl<'tcx> PatternTypeProjection<'tcx> { - pub(crate) fn index(&self) -> Self { - let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Index(())); - new - } - - pub(crate) fn subslice(&self, from: u32, to: u32) -> Self { - let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Subslice { from, to }); - new - } - - pub(crate) fn deref(&self) -> Self { - let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Deref); - new - } - - pub(crate) fn leaf(&self, field: Field) -> Self { - let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Field(field, ())); - new - } - - pub(crate) fn variant(&self, - adt_def: &'tcx AdtDef, - variant_index: VariantIdx, - field: Field) -> Self { - let mut new = self.clone(); - new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); - new.0.projs.push(ProjectionElem::Field(field, ())); - new - } - - pub(crate) fn from_canonical_ty(c_ty: ty::CanonicalTy<'tcx>) -> Self { - Self::from_user_type(UserTypeAnnotation::Ty(c_ty)) - } - - pub(crate) fn from_user_type(u_ty: UserTypeAnnotation<'tcx>) -> Self { - Self::from_user_type_proj(UserTypeProjection { base: u_ty, projs: vec![], }) + pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self { + Self { + base: user_annotation, + projs: Vec::new(), + } } - pub(crate) fn from_user_type_proj(u_ty: UserTypeProjection<'tcx>) -> Self { - PatternTypeProjection(u_ty) + pub(crate) fn user_ty( + self, + annotations: &mut CanonicalUserTypeAnnotations<'tcx>, + span: Span, + ) -> UserTypeProjection<'tcx> { + UserTypeProjection { + base: annotations.push((span, self.base)), + projs: self.projs + } } - - pub(crate) fn user_ty(self) -> UserTypeProjection<'tcx> { self.0 } } #[derive(Clone, Debug)] @@ -280,7 +197,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { let mut start_or_continue = || if first { first = false; "" } else { ", " }; if let Some(variant) = variant { - write!(f, "{}", variant.name)?; + write!(f, "{}", variant.ident)?; // Only for Adt we can have `S {...}`, // which we handle separately here. @@ -788,18 +705,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { - let subpattern = Pattern { - span, - ty, - kind: Box::new(kind), - }; - - debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span); - - let pat_ty = PatternTypeProjection::from_user_type(user_ty); + debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span); kind = PatternKind::AscribeUserType { - subpattern, - user_ty: pat_ty, + subpattern: Pattern { + span, + ty, + kind: Box::new(kind), + }, + user_ty: PatternTypeProjection::from_user_type(user_ty), user_ty_span: span, }; } @@ -837,7 +750,28 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; match self.tcx.at(span).const_eval(self.param_env.and(cid)) { Ok(value) => { - return self.const_to_pat(instance, value, id, span) + let pattern = self.const_to_pat(instance, value, id, span); + if !is_associated_const { + return pattern; + } + + let user_provided_types = self.tables().user_provided_types(); + return if let Some(u_ty) = user_provided_types.get(id) { + let user_ty = PatternTypeProjection::from_user_type(*u_ty); + Pattern { + span, + kind: Box::new( + PatternKind::AscribeUserType { + subpattern: pattern, + user_ty, + user_ty_span: span, + } + ), + ty: value.ty, + } + } else { + pattern + } }, Err(_) => { self.tcx.sess.span_err( @@ -927,7 +861,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { id: hir::HirId, span: Span, ) -> Pattern<'tcx> { - debug!("const_to_pat: cv={:#?}", cv); + debug!("const_to_pat: cv={:#?} id={:?}", cv, id); let adt_subpattern = |i, variant_opt| { let field = Field::new(i); let val = const_field( @@ -945,6 +879,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } }).collect::>() }; + debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span); let kind = match cv.ty.sty { ty::Float(_) => { let id = self.tcx.hir().hir_to_node_id(id); diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index 050fb8b846ee0..f0f8263b64de5 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -1,37 +1,31 @@ use rustc::hir; -use rustc::mir::UserTypeAnnotation; -use rustc::ty::{self, AdtDef, TyCtxt}; +use rustc::ty::{self, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotation}; crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>; fn tables(&self) -> &ty::TypeckTables<'tcx>; - fn user_substs_applied_to_adt( - &self, - hir_id: hir::HirId, - adt_def: &'tcx AdtDef, - ) -> Option> { - let user_substs = self.tables().user_substs(hir_id)?; - Some(UserTypeAnnotation::TypeOf(adt_def.did, user_substs)) - } - /// Looks up the type associated with this hir-id and applies the /// user-given substitutions; the hir-id must map to a suitable /// type. fn user_substs_applied_to_ty_of_hir_id( &self, hir_id: hir::HirId, - ) -> Option> { - let user_substs = self.tables().user_substs(hir_id)?; + ) -> Option> { + let user_provided_types = self.tables().user_provided_types(); + let mut user_ty = *user_provided_types.get(hir_id)?; + debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); match &self.tables().node_id_to_type(hir_id).sty { - ty::Adt(adt_def, _) => Some(UserTypeAnnotation::TypeOf(adt_def.did, user_substs)), - ty::FnDef(def_id, _) => Some(UserTypeAnnotation::TypeOf(*def_id, user_substs)), - sty => bug!( - "sty: {:?} should not have user-substs {:?} recorded ", - sty, - user_substs - ), + ty::Adt(adt_def, ..) => { + if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut user_ty.value { + *did = adt_def.did; + } + Some(user_ty) + } + ty::FnDef(..) => Some(user_ty), + sty => + bug!("sty: {:?} should not have user provided type {:?} recorded ", sty, user_ty), } } } diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 1242c41a3562b..26d526a6f5ff8 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -76,7 +76,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { type MemoryExtra: Default; /// Extra data stored in every allocation. - type AllocExtra: AllocationExtra; + type AllocExtra: AllocationExtra + 'static; /// Memory's allocation map type MemoryMap: diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 5e006e20e4785..a5fb44587400a 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -246,7 +246,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> variant_id: VariantIdx, new_op: OpTy<'tcx, M::PointerTag> ) -> EvalResult<'tcx> { - let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name; + let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].ident.name; self.visit_elem(new_op, PathElem::Variant(name)) } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1029611cecd56..2aa44cc181a56 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -207,6 +207,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::new(), None, local_decls_for_sig(&sig, span), + IndexVec::new(), sig.inputs().len(), vec![], span, @@ -309,7 +310,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("build_clone_shim(def_id={:?})", def_id); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span); + let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span); let dest = Place::Local(RETURN_PLACE); let src = Place::Local(Local::new(1+0)).deref(); @@ -376,6 +377,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { IndexVec::new(), None, self.local_decls, + IndexVec::new(), self.sig.inputs().len(), vec![], self.span, @@ -825,6 +827,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, IndexVec::new(), None, local_decls, + IndexVec::new(), sig.inputs().len(), vec![], span, @@ -903,6 +906,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, IndexVec::new(), None, local_decls, + IndexVec::new(), sig.inputs().len(), vec![], span, diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 0b0845ef945d0..eb151b56bed65 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -224,8 +224,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { "non-field projection {:?} from union?", place) }; - if elem_ty.moves_by_default(self.tcx, self.param_env, - self.source_info.span) { + if !elem_ty.is_copy_modulo_regions( + self.tcx, + self.param_env, + self.source_info.span, + ) { self.require_unsafe( "assignment to non-`Copy` union field", "the previous content of the field will be dropped, which \ diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7e6554ae3d478..1602fc35a2c95 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -400,6 +400,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, IndexVec::new(), None, initial_locals, + IndexVec::new(), 0, vec![], mir.span, diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 35b367855ad28..6353eab6f6553 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -142,6 +142,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( } writeln!(file, "")?; extra_data(PassWhere::BeforeCFG, &mut file)?; + write_user_type_annotations(mir, &mut file)?; write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?; extra_data(PassWhere::AfterCFG, &mut file)?; }; @@ -618,6 +619,19 @@ fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { Ok(()) } +fn write_user_type_annotations(mir: &Mir, w: &mut dyn Write) -> io::Result<()> { + if !mir.user_type_annotations.is_empty() { + writeln!(w, "| User Type Annotations")?; + } + for (index, (span, annotation)) in mir.user_type_annotations.iter_enumerated() { + writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation, span)?; + } + if !mir.user_type_annotations.is_empty() { + writeln!(w, "|")?; + } + Ok(()) +} + pub fn dump_mir_def_ids(tcx: TyCtxt, single: Option) -> Vec { if let Some(i) = single { vec![i] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 67b6b2d04506d..c6626c1551f4a 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -20,22 +20,279 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind}; +use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; -use rustc::ty::subst::UnpackedKind; +use rustc::ty::subst::Substs; use rustc::util::nodemap::NodeSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax::ast::{self, CRATE_NODE_ID, Ident}; +use syntax::attr; use syntax::symbol::keywords; use syntax_pos::Span; -use std::cmp; -use std::mem::replace; +use std::{cmp, fmt, mem}; +use std::marker::PhantomData; mod diagnostics; +//////////////////////////////////////////////////////////////////////////////// +/// Generic infrastructure used to implement specific visitors below. +//////////////////////////////////////////////////////////////////////////////// + +/// Implemented to visit all `DefId`s in a type. +/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. +/// The idea is to visit "all components of a type", as documented in +/// https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type +/// Default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings. +/// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait def-ids +/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits +/// in `impl Trait`, see individual commits in `DefIdVisitorSkeleton::visit_ty`. +trait DefIdVisitor<'a, 'tcx: 'a> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; + fn recurse_into_assoc_tys(&self) -> bool { true } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool; + + /// Not overridden, but used to actually visit types and traits. + fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'a, 'tcx, Self> { + DefIdVisitorSkeleton { + def_id_visitor: self, + visited_opaque_tys: Default::default(), + dummy: Default::default(), + } + } + fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool { + ty_fragment.visit_with(&mut self.skeleton()) + } + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + self.skeleton().visit_trait(trait_ref) + } + fn visit_predicates(&mut self, predicates: Lrc>) -> bool { + self.skeleton().visit_predicates(predicates) + } +} + +struct DefIdVisitorSkeleton<'v, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + def_id_visitor: &'v mut V, + visited_opaque_tys: FxHashSet, + dummy: PhantomData>, +} + +impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + let TraitRef { def_id, substs } = trait_ref; + self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || substs.visit_with(self) + } + + fn visit_predicates(&mut self, predicates: Lrc>) -> bool { + let ty::GenericPredicates { parent: _, predicates } = &*predicates; + for (predicate, _span) in predicates { + match predicate { + ty::Predicate::Trait(poly_predicate) => { + let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); + if self.visit_trait(trait_ref) { + return true; + } + } + ty::Predicate::Projection(poly_predicate) => { + let ty::ProjectionPredicate { projection_ty, ty } = + *poly_predicate.skip_binder(); + if ty.visit_with(self) { + return true; + } + if self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx())) { + return true; + } + } + ty::Predicate::TypeOutlives(poly_predicate) => { + let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); + if ty.visit_with(self) { + return true; + } + } + ty::Predicate::RegionOutlives(..) => {}, + _ => bug!("unexpected predicate: {:?}", predicate), + } + } + false + } +} + +impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + let tcx = self.def_id_visitor.tcx(); + // Substs are not visited here because they are visited below in `super_visit_with`. + match ty.sty { + ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | + ty::Foreign(def_id) | + ty::FnDef(def_id, ..) | + ty::Closure(def_id, ..) | + ty::Generator(def_id, ..) => { + if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + return true; + } + // Default type visitor doesn't visit signatures of fn types. + // Something like `fn() -> Priv {my_func}` is considered a private type even if + // `my_func` is public, so we need to visit signatures. + if let ty::FnDef(..) = ty.sty { + if tcx.fn_sig(def_id).visit_with(self) { + return true; + } + } + // Inherent static methods don't have self type in substs. + // Something like `fn() {my_method}` type of the method + // `impl Pub { pub fn my_method() {} }` is considered a private type, + // so we need to visit the self type additionally. + if let Some(assoc_item) = tcx.opt_associated_item(def_id) { + if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if tcx.type_of(impl_def_id).visit_with(self) { + return true; + } + } + } + } + ty::Projection(proj) | ty::UnnormalizedProjection(proj) => { + if !self.def_id_visitor.recurse_into_assoc_tys() { + // Visitors searching for minimal visibility/reachability want to + // conservatively approximate associated types like `::Alias` + // as visible/reachable even if both `Type` and `Trait` are private. + // Ideally, associated types should be substituted in the same way as + // free type aliases, but this isn't done yet. + return false; + } + // This will also visit substs, so we don't need to recurse. + return self.visit_trait(proj.trait_ref(tcx)); + } + ty::Dynamic(predicates, ..) => { + for predicate in *predicates.skip_binder() { + let trait_ref = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref, + ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx), + ty::ExistentialPredicate::AutoTrait(def_id) => + ty::ExistentialTraitRef { def_id, substs: Substs::empty() }, + }; + let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref; + if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) { + return true; + } + } + } + ty::Opaque(def_id, ..) => { + // Skip repeated `Opaque`s to avoid infinite recursion. + if self.visited_opaque_tys.insert(def_id) { + // Default type visitor doesn't visit traits in `impl Trait`. + // Something like `impl PrivTr` is considered a private type, + // so we need to visit the traits additionally. + if self.visit_predicates(tcx.predicates_of(def_id)) { + return true; + } + } + } + // These types don't have their own def-ids (but may have subcomponents + // with def-ids that should be visited recursively). + ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | + ty::Float(..) | ty::Str | ty::Never | + ty::Array(..) | ty::Slice(..) | ty::Tuple(..) | + ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) | + ty::Param(..) | ty::Error | ty::GeneratorWitness(..) => {} + ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => + bug!("unexpected type: {:?}", ty), + } + + ty.super_visit_with(self) + } +} + +fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> (ty::Visibility, Span, &'static str) { + match tcx.hir().as_local_node_id(def_id) { + Some(node_id) => { + let vis = match tcx.hir().get(node_id) { + Node::Item(item) => &item.vis, + Node::ForeignItem(foreign_item) => &foreign_item.vis, + Node::TraitItem(..) | Node::Variant(..) => { + return def_id_visibility(tcx, tcx.hir().get_parent_did(node_id)); + } + Node::ImplItem(impl_item) => { + match tcx.hir().get(tcx.hir().get_parent(node_id)) { + Node::Item(item) => match &item.node { + hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis, + hir::ItemKind::Impl(.., Some(trait_ref), _, _) + => return def_id_visibility(tcx, trait_ref.path.def.def_id()), + kind => bug!("unexpected item kind: {:?}", kind), + } + node => bug!("unexpected node kind: {:?}", node), + } + } + Node::StructCtor(vdata) => { + let struct_node_id = tcx.hir().get_parent(node_id); + let item = match tcx.hir().get(struct_node_id) { + Node::Item(item) => item, + node => bug!("unexpected node kind: {:?}", node), + }; + let (mut ctor_vis, mut span, mut descr) = + (ty::Visibility::from_hir(&item.vis, struct_node_id, tcx), + item.vis.span, item.vis.node.descr()); + for field in vdata.fields() { + let field_vis = ty::Visibility::from_hir(&field.vis, node_id, tcx); + if ctor_vis.is_at_least(field_vis, tcx) { + ctor_vis = field_vis; + span = field.vis.span; + descr = field.vis.node.descr(); + } + } + + // If the structure is marked as non_exhaustive then lower the + // visibility to within the crate. + if ctor_vis == ty::Visibility::Public { + let adt_def = tcx.adt_def(tcx.hir().get_parent_did(node_id)); + if adt_def.non_enum_variant().is_field_list_non_exhaustive() { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span; + descr = "crate-visible"; + } + } + + return (ctor_vis, span, descr); + } + Node::Expr(expr) => { + return (ty::Visibility::Restricted(tcx.hir().get_module_parent(expr.id)), + expr.span, "private") + } + node => bug!("unexpected node kind: {:?}", node) + }; + (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr()) + } + None => { + let vis = tcx.visibility(def_id); + let descr = if vis == ty::Visibility::Public { "public" } else { "private" }; + (vis, tcx.def_span(def_id), descr) + } + } +} + +// Set the correct `TypeckTables` for the given `item_id` (or an empty table if +// there is no `TypeckTables` for the item). +fn item_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + node_id: ast::NodeId, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir().local_def_id(node_id); + if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables } +} + +fn min<'a, 'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::Visibility { + if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } +} + //////////////////////////////////////////////////////////////////////////////// /// Visitor used to determine if pub(restricted) is used anywhere in the crate. /// @@ -56,6 +313,59 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { } } +//////////////////////////////////////////////////////////////////////////////// +/// Visitor used to determine impl visibility and reachability. +//////////////////////////////////////////////////////////////////////////////// + +struct FindMin<'a, 'tcx, VL: VisibilityLike> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels, + min: VL, +} + +impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, VL> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn recurse_into_assoc_tys(&self) -> bool { false } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + self.min = VL::new_min(self, def_id); + false + } +} + +trait VisibilityLike: Sized { + const MAX: Self; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self; + + // Returns an over-approximation (`recurse_into_assoc_tys` = false) of visibility due to + // associated types for which we can't determine visibility precisely. + fn of_impl<'a, 'tcx>(node_id: ast::NodeId, tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels) -> Self { + let mut find = FindMin { tcx, access_levels, min: Self::MAX }; + let def_id = tcx.hir().local_def_id(node_id); + find.visit(tcx.type_of(def_id)); + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + find.visit_trait(trait_ref); + } + find.min + } +} +impl VisibilityLike for ty::Visibility { + const MAX: Self = ty::Visibility::Public; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx) + } +} +impl VisibilityLike for Option { + const MAX: Self = Some(AccessLevel::Public); + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + cmp::min(if let Some(node_id) = find.tcx.hir().as_local_node_id(def_id) { + find.access_levels.map.get(&node_id).cloned() + } else { + Self::MAX + }, find.min) + } +} + //////////////////////////////////////////////////////////////////////////////// /// The embargo visitor, used to determine the exports of the ast //////////////////////////////////////////////////////////////////////////////// @@ -78,30 +388,6 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { } impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { - fn item_ty_level(&self, item_def_id: DefId) -> Option { - let ty_def_id = match self.tcx.type_of(item_def_id).sty { - ty::Adt(adt, _) => adt.did, - ty::Foreign(did) => did, - ty::Dynamic(ref obj, ..) => obj.principal().def_id(), - ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id, - _ => return Some(AccessLevel::Public) - }; - if let Some(node_id) = self.tcx.hir().as_local_node_id(ty_def_id) { - self.get(node_id) - } else { - Some(AccessLevel::Public) - } - } - - fn impl_trait_level(&self, impl_def_id: DefId) -> Option { - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) { - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - return self.get(node_id); - } - } - Some(AccessLevel::Public) - } - fn get(&self, id: ast::NodeId) -> Option { self.access_levels.map.get(&id).cloned() } @@ -119,10 +405,10 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { } } - fn reach<'b>(&'b mut self, item_id: ast::NodeId) - -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { + fn reach(&mut self, item_id: ast::NodeId, access_level: Option) + -> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { - access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), + access_level: cmp::min(access_level, Some(AccessLevel::Reachable)), item_def_id: self.tcx.hir().local_def_id(item_id), ev: self, } @@ -138,15 +424,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { - // Impls inherit level from their types and traits. - hir::ItemKind::Impl(..) => { - let def_id = self.tcx.hir().local_def_id(item.id); - cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id)) - } + hir::ItemKind::Impl(..) => + Option::::of_impl(item.id, self.tcx, &self.access_levels), // Foreign modules inherit level from parents. - hir::ItemKind::ForeignMod(..) => { - self.prev_level - } + hir::ItemKind::ForeignMod(..) => self.prev_level, // Other `pub` items inherit levels from parents. hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | @@ -171,18 +452,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { - if impl_item_ref.vis.node.is_pub() { + if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() { self.update(impl_item_ref.id.node_id, item_level); } } } - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - for impl_item_ref in impl_item_refs { - self.update(impl_item_ref.id.node_id, item_level); - } - } hir::ItemKind::Trait(.., ref trait_item_refs) => { for trait_item_ref in trait_item_refs { self.update(trait_item_ref.id.node_id, item_level); @@ -205,15 +481,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - // Impl trait return types mark their parent function. - // It (and its children) are revisited if the change applies. - hir::ItemKind::Existential(ref ty_data) => { - if let Some(impl_trait_fn) = ty_data.impl_trait_fn { - if let Some(node_id) = self.tcx.hir().as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); - } - } - } + hir::ItemKind::Existential(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -225,10 +493,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } - // Store this node's access level here to propagate the correct - // reachability level through interfaces and children. - let orig_level = replace(&mut self.prev_level, item_level); - // Mark all items in interfaces of reachable items as reachable. match item.node { // The interface is empty. @@ -239,26 +503,26 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - if item_level.is_some() { - // Reach the (potentially private) type and the API being exposed. - self.reach(item.id).ty().predicates(); - } + hir::ItemKind::Existential(..) => { + // FIXME: This is some serious pessimization intended to workaround deficiencies + // in the reachability pass (`middle/reachable.rs`). Types are marked as link-time + // reachable if they are returned via `impl Trait`, even from private functions. + let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); + self.reach(item.id, exist_level).generics().predicates().ty(); } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | - hir::ItemKind::Existential(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().ty(); + self.reach(item.id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., ref trait_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { - let mut reach = self.reach(trait_item_ref.id.node_id); + let mut reach = self.reach(trait_item_ref.id.node_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == hir::AssociatedItemKind::Type && @@ -272,18 +536,19 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } } // Visit everything except for private impl items. - hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref impl_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().impl_trait_ref(); + self.reach(item.id, item_level).generics().predicates(); for impl_item_ref in impl_item_refs { - let id = impl_item_ref.id.node_id; - if trait_ref.is_some() || self.get(id).is_some() { - self.reach(id).generics().predicates().ty(); + let impl_item_level = self.get(impl_item_ref.id.node_id); + if impl_item_level.is_some() { + self.reach(impl_item_ref.id.node_id, impl_item_level) + .generics().predicates().ty(); } } } @@ -292,24 +557,27 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } for variant in &def.variants { - if self.get(variant.node.data.id()).is_some() { + let variant_level = self.get(variant.node.data.id()); + if variant_level.is_some() { for field in variant.node.data.fields() { - self.reach(field.id).ty(); + self.reach(field.id, variant_level).ty(); } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.update(item.id, Some(AccessLevel::Reachable)); + self.update(item.id, variant_level); } } } // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod(ref foreign_mod) => { for foreign_item in &foreign_mod.items { - if self.get(foreign_item.id).is_some() { - self.reach(foreign_item.id).generics().predicates().ty(); + let foreign_item_level = self.get(foreign_item.id); + if foreign_item_level.is_some() { + self.reach(foreign_item.id, foreign_item_level) + .generics().predicates().ty(); } } } @@ -317,29 +585,28 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for field in struct_def.fields() { - if self.get(field.id).is_some() { - self.reach(field.id).ty(); + let field_level = self.get(field.id); + if field_level.is_some() { + self.reach(field.id, field_level).ty(); } } } } } + let orig_level = mem::replace(&mut self.prev_level, item_level); intravisit::walk_item(self, item); - self.prev_level = orig_level; } fn visit_block(&mut self, b: &'tcx hir::Block) { - let orig_level = replace(&mut self.prev_level, None); - // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, // constant, type, field, etc., in which this block resides. + let orig_level = mem::replace(&mut self.prev_level, None); intravisit::walk_block(self, b); - self.prev_level = orig_level; } @@ -410,13 +677,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } -impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { +impl<'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.ev.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.ev.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -426,73 +693,23 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - let predicates = self.ev.tcx.predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.ev.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.ev.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.ev.tcx.fn_sig(def_id).visit_with(self); - } - } - self - } - - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } + self.visit(self.ev.tcx.type_of(self.item_def_id)); self } - - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir().expect_item(node_id); - self.ev.update(item.id, self.access_level); - } - } } -impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => Some(proj.item_def_id), - ty::FnDef(def_id, ..) | - ty::Closure(def_id, ..) | - ty::Generator(def_id, ..) | - ty::Opaque(def_id, _) => Some(def_id), - _ => None - }; - - if let Some(def_id) = ty_def_id { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { - self.ev.update(node_id, self.access_level); - } +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.ev.tcx } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { + self.ev.update(node_id, self.access_level); } - - ty.super_visit_with(self) + false } } @@ -528,22 +745,6 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -// Set the correct `TypeckTables` for the given `item_id` (or an empty table if -// there is no `TypeckTables` for the item). -fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - tables: &mut &'a ty::TypeckTables<'tcx>, - empty_tables: &'a ty::TypeckTables<'tcx>) - -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(item_id); - - if tcx.has_typeck_tables(def_id) { - replace(tables, tcx.typeck_tables_of(def_id)) - } else { - replace(tables, empty_tables) - } -} - impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. @@ -552,28 +753,31 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; } fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = replace(&mut self.current_item, item.id); - let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); + let orig_current_item = mem::replace(&mut self.current_item, item.id); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.current_item = orig_current_item; self.tables = orig_tables; } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } @@ -644,73 +848,22 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { in_body: bool, span: Span, empty_tables: &'a ty::TypeckTables<'tcx>, - visited_opaque_tys: FxHashSet } impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { - fn def_id_visibility(&self, did: DefId) -> ty::Visibility { - match self.tcx.hir().as_local_node_id(did) { - Some(node_id) => { - let vis = match self.tcx.hir().get(node_id) { - Node::Item(item) => &item.vis, - Node::ForeignItem(foreign_item) => &foreign_item.vis, - Node::ImplItem(impl_item) => &impl_item.vis, - Node::TraitItem(..) | - Node::Variant(..) => { - return self.def_id_visibility(self.tcx.hir().get_parent_did(node_id)); - } - Node::StructCtor(vdata) => { - let struct_node_id = self.tcx.hir().get_parent(node_id); - let struct_vis = match self.tcx.hir().get(struct_node_id) { - Node::Item(item) => &item.vis, - node => bug!("unexpected node kind: {:?}", node), - }; - let mut ctor_vis - = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx); - for field in vdata.fields() { - let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx); - if ctor_vis.is_at_least(field_vis, self.tcx) { - ctor_vis = field_vis; - } - } - - // If the structure is marked as non_exhaustive then lower the - // visibility to within the crate. - let struct_def_id = self.tcx.hir().get_parent_did(node_id); - let adt_def = self.tcx.adt_def(struct_def_id); - if adt_def.non_enum_variant().is_field_list_non_exhaustive() - && ctor_vis == ty::Visibility::Public - { - ctor_vis = ty::Visibility::Restricted( - DefId::local(CRATE_DEF_INDEX)); - } - - return ctor_vis; - } - node => bug!("unexpected node kind: {:?}", node) - }; - ty::Visibility::from_hir(vis, node_id, self.tcx) - } - None => self.tcx.visibility(did), - } - } - fn item_is_accessible(&self, did: DefId) -> bool { - self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx) + def_id_visibility(self.tcx, did).0.is_accessible_from(self.current_item, self.tcx) } // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - if self.tables.node_id_to_type(id).visit_with(self) { - return true; - } - if self.tables.node_substs(id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(id)) || self.visit(self.tables.node_substs(id)) { return true; } if let Some(adjustments) = self.tables.adjustments().get(id) { for adjustment in adjustments { - if adjustment.target.visit_with(self) { + if self.visit(adjustment.target) { return true; } } @@ -718,14 +871,12 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { false } - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + let is_error = !self.item_is_accessible(def_id); + if is_error { + self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr)); } - - trait_ref.super_visit_with(self) + is_error } } @@ -737,8 +888,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); - let orig_in_body = replace(&mut self.in_body, true); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_in_body = mem::replace(&mut self.in_body, true); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; @@ -749,14 +900,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { self.span = hir_ty.span; if self.in_body { // Types in bodies. - if self.tables.node_id_to_type(hir_ty.hir_id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(hir_ty.hir_id)) { return; } } else { // Types in signatures. // FIXME: This is very ineffective. Ideally each HIR type should be converted // into a semantic type only once and the result should be cached somehow. - if rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) { + if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) { return; } } @@ -771,12 +922,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // The traits' privacy in bodies is already checked as a part of trait object types. let (principal, projections) = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); - if self.check_trait_ref(*principal.skip_binder()) { + if self.visit_trait(*principal.skip_binder()) { return; } for (poly_predicate, _) in projections { let tcx = self.tcx; - if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { + if self.visit(poly_predicate.skip_binder().ty) || + self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { return; } } @@ -802,8 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Method calls have to be checked specially. self.span = span; if let Some(def) = self.tables.type_dependent_defs().get(expr.hir_id) { - let def_id = def.def_id(); - if self.tcx.type_of(def_id).visit_with(self) { + if self.visit(self.tcx.type_of(def.def_id())) { return; } } else { @@ -827,7 +978,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { let def = match *qpath { hir::QPath::Resolved(_, ref path) => match path.def { Def::Method(..) | Def::AssociatedConst(..) | - Def::AssociatedTy(..) | Def::Static(..) => Some(path.def), + Def::AssociatedTy(..) | Def::AssociatedExistential(..) | + Def::Static(..) => Some(path.def), _ => None, } hir::QPath::TypeRelative(..) => { @@ -874,13 +1026,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = self.current_item; - let orig_tables = update_tables(self.tcx, - item.id, - &mut self.tables, - self.empty_tables); - let orig_in_body = replace(&mut self.in_body, false); - self.current_item = self.tcx.hir().local_def_id(item.id); + let orig_current_item = + mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); + let orig_in_body = mem::replace(&mut self.in_body, false); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -888,108 +1038,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } } -impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | - ty::FnDef(def_id, ..) | - ty::Foreign(def_id) => { - if !self.item_is_accessible(def_id) { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - if let ty::FnDef(..) = ty.sty { - if self.tcx.fn_sig(def_id).visit_with(self) { - return true; - } - } - // Inherent static methods don't have self type in substs, - // we have to check it additionally. - if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { - if let ty::ImplContainer(impl_def_id) = assoc_item.container { - if self.tcx.type_of(impl_def_id).visit_with(self) { - return true; - } - } - } - } - ty::Dynamic(ref predicates, ..) => { - let is_private = predicates.skip_binder().iter().any(|predicate| { - let def_id = match *predicate { - ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => - proj.trait_ref(self.tcx).def_id, - ty::ExistentialPredicate::AutoTrait(def_id) => def_id, - }; - !self.item_is_accessible(def_id) - }); - if is_private { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - } - ty::Projection(ref proj) => { - let tcx = self.tcx; - if self.check_trait_ref(proj.trait_ref(tcx)) { - return true; - } - } - ty::Opaque(def_id, ..) => { - for (predicate, _) in &self.tcx.predicates_of(def_id).predicates { - let trait_ref = match *predicate { - ty::Predicate::Trait(ref poly_trait_predicate) => { - Some(poly_trait_predicate.skip_binder().trait_ref) - } - ty::Predicate::Projection(ref poly_projection_predicate) => { - if poly_projection_predicate.skip_binder().ty.visit_with(self) { - return true; - } - Some(poly_projection_predicate.skip_binder() - .projection_ty.trait_ref(self.tcx)) - } - ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => None, - _ => bug!("unexpected predicate: {:?}", predicate), - }; - if let Some(trait_ref) = trait_ref { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - for subst in trait_ref.substs.iter() { - // Skip repeated `Opaque`s to avoid infinite recursion. - if let UnpackedKind::Type(ty) = subst.unpack() { - if let ty::Opaque(def_id, ..) = ty.sty { - if !self.visited_opaque_tys.insert(def_id) { - continue; - } - } - } - if subst.visit_with(self) { - return true; - } - } - } - } - } - _ => {} - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for TypePrivacyVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1283,13 +1349,13 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } for predicate in &generics.where_clause.predicates { match predicate { - &hir::WherePredicate::BoundPredicate(ref bound_pred) => { + hir::WherePredicate::BoundPredicate(bound_pred) => { for bound in bound_pred.bounds.iter() { self.check_generic_bound(bound) } } - &hir::WherePredicate::RegionPredicate(_) => {} - &hir::WherePredicate::EqPredicate(ref eq_pred) => { + hir::WherePredicate::RegionPredicate(_) => {} + hir::WherePredicate::EqPredicate(eq_pred) => { self.visit_ty(&eq_pred.rhs_ty); } } @@ -1349,8 +1415,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> { span: Span, /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, - /// The visibility of the least visible component that has been visited. - min_visibility: ty::Visibility, has_pub_restricted: bool, has_old_errors: bool, in_assoc_ty: bool, @@ -1362,7 +1426,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -1378,132 +1442,47 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { // consider the ones that the user wrote. This is important // for the inferred outlives rules; see // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`. - let predicates = self.tcx.explicit_predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.tcx.fn_sig(def_id).visit_with(self); - } - } + self.visit(self.tcx.type_of(self.item_def_id)); self } - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } - self - } + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + let node_id = match self.tcx.hir().as_local_node_id(def_id) { + Some(node_id) => node_id, + None => return false, + }; - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir().expect_item(node_id); - let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - struct_span_err!(self.tcx.sess, self.span, E0445, - "private trait `{}` in public interface", trait_ref) - .span_label(self.span, format!( - "can't leak private trait")) - .emit(); + let (vis, vis_span, vis_descr) = def_id_visibility(self.tcx, def_id); + if !vis.is_at_least(self.required_visibility, self.tcx) { + let msg = format!("{} {} `{}` in public interface", vis_descr, kind, descr); + if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { + let mut err = if kind == "trait" { + struct_span_err!(self.tcx.sess, self.span, E0445, "{}", msg) } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); - } + struct_span_err!(self.tcx.sess, self.span, E0446, "{}", msg) + }; + err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind)); + err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr)); + err.emit(); + } else { + let err_code = if kind == "trait" { "E0445" } else { "E0446" }; + self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span, + &format!("{} (error {})", msg, err_code)); } } + false } } -impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => { - if self.required_visibility == ty::Visibility::Invisible { - // Conservatively approximate the whole type alias as public without - // recursing into its components when determining impl publicity. - // For example, `impl ::Alias {...}` may be a public impl - // even if both `Type` and `Trait` are private. - // Ideally, associated types should be substituted in the same way as - // free type aliases, but this isn't done yet. - return false; - } - let trait_ref = proj.trait_ref(self.tcx); - Some(trait_ref.def_id) - } - _ => None - }; - - if let Some(def_id) = ty_def_id { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - let hir_vis = match self.tcx.hir().find(node_id) { - Some(Node::Item(item)) => &item.vis, - Some(Node::ForeignItem(item)) => &item.vis, - _ => bug!("expected item of foreign item"), - }; - - let vis = ty::Visibility::from_hir(hir_vis, node_id, self.tcx); - - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - let vis_adj = match hir_vis.node { - hir::VisibilityKind::Crate(_) => "crate-visible", - hir::VisibilityKind::Restricted { .. } => "restricted", - _ => "private" - }; - - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - let mut err = struct_span_err!(self.tcx.sess, self.span, E0446, - "{} type `{}` in public interface", vis_adj, ty); - err.span_label(self.span, format!("can't leak {} type", vis_adj)); - err.span_label(hir_vis.span, format!("`{}` declared as {}", ty, vis_adj)); - err.emit(); - } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("{} type `{}` in public \ - interface (error E0446)", vis_adj, ty)); - } - } - } - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1511,7 +1490,6 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, has_pub_restricted: bool, old_error_set: &'a NodeSet, - inner_visibility: ty::Visibility, } impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { @@ -1544,7 +1522,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { tcx: self.tcx, item_def_id: self.tcx.hir().local_def_id(item_id), span: self.tcx.hir().span(item_id), - min_visibility: ty::Visibility::Public, required_visibility, has_pub_restricted: self.has_pub_restricted, has_old_errors, @@ -1560,10 +1537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> fn visit_item(&mut self, item: &'tcx hir::Item) { let tcx = self.tcx; - let min = |vis1: ty::Visibility, vis2| { - if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } - }; - let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx); match item.node { @@ -1575,23 +1548,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemKind::Use(..) => {} // No subitems. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - // Check the traits being exposed, as they're separate, - // e.g., `impl Iterator` has two predicates, - // `X: Iterator` and `::Item == T`, - // where `X` is the `impl Iterator` itself, - // stored in `predicates_of`, not in the `Ty` itself. - self.check(item.id, item_visibility).predicates(); - } // Subitems of these items have inherited publicity. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Ty(..) => { + hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { self.check(item.id, item_visibility).generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = item_visibility; - intravisit::walk_item(self, item); } hir::ItemKind::Trait(.., ref trait_item_refs) => { self.check(item.id, item_visibility).generics().predicates(); @@ -1635,56 +1595,30 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> for field in struct_def.fields() { let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx); - self.check(field.id, min(item_visibility, field_visibility)).ty(); + self.check(field.id, min(item_visibility, field_visibility, tcx)).ty(); } } // An inherent impl is public when its type is public // Subitems of inherent impls have their own publicity. - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { - let ty_vis = - self.check(item.id, ty::Visibility::Invisible).ty().min_visibility; - self.check(item.id, ty_vis).generics().predicates(); - - for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx); - let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis)); - check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; - check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = impl_item_vis; - intravisit::walk_impl_item(self, impl_item); - } - } // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - let vis = self.check(item.id, ty::Visibility::Invisible) - .ty().impl_trait_ref().min_visibility; - self.check(item.id, vis).generics().predicates(); + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default()); + self.check(item.id, impl_vis).generics().predicates(); for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let mut check = self.check(impl_item.id, vis); + let impl_item = tcx.hir().impl_item(impl_item_ref.id); + let impl_item_vis = if trait_ref.is_none() { + min(ty::Visibility::from_hir(&impl_item.vis, item.id, tcx), impl_vis, tcx) + } else { + impl_vis + }; + let mut check = self.check(impl_item.id, impl_item_vis); check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = vis; - intravisit::walk_impl_item(self, impl_item); } } } } - - fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { - // Handled in `visit_item` above. - } - - // Don't recurse into expressions in array sizes or const initializers. - fn visit_expr(&mut self, _: &'tcx hir::Expr) {} - // Don't recurse into patterns in function arguments. - fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } pub fn provide(providers: &mut Providers) { @@ -1724,7 +1658,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_body: false, span: krate.span, empty_tables: &empty_tables, - visited_opaque_tys: FxHashSet::default() }; intravisit::walk_crate(&mut visitor, krate); @@ -1770,7 +1703,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, has_pub_restricted, old_error_set: &visitor.old_error_set, - inner_visibility: ty::Visibility::Public, }; krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 21fb29974c880..a452bbf0c9d54 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -42,6 +42,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Module(self.0), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, @@ -53,6 +54,7 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(self.0, false), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, @@ -66,6 +68,7 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(self.0, true), + ambiguity: None, vis: self.1, span: self.2, expansion: self.3, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0db6dbafb6cc6..cf949b62a634e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1014,11 +1014,11 @@ enum ModuleOrUniformRoot<'a> { CurrentScope, } -impl<'a> PartialEq for ModuleOrUniformRoot<'a> { - fn eq(&self, other: &Self) -> bool { - match (*self, *other) { +impl ModuleOrUniformRoot<'_> { + fn same_def(lhs: Self, rhs: Self) -> bool { + match (lhs, rhs) { (ModuleOrUniformRoot::Module(lhs), - ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), + ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(), (ModuleOrUniformRoot::CrateRootAndExternPrelude, ModuleOrUniformRoot::CrateRootAndExternPrelude) | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | @@ -1191,6 +1191,7 @@ impl<'a> fmt::Debug for ModuleData<'a> { #[derive(Clone, Debug)] pub struct NameBinding<'a> { kind: NameBindingKind<'a>, + ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, expansion: Mark, span: Span, vis: ty::Visibility, @@ -1215,11 +1216,6 @@ enum NameBindingKind<'a> { directive: &'a ImportDirective<'a>, used: Cell, }, - Ambiguity { - kind: AmbiguityKind, - b1: &'a NameBinding<'a>, - b2: &'a NameBinding<'a>, - } } struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>); @@ -1309,15 +1305,13 @@ impl<'a> NameBinding<'a> { NameBindingKind::Def(def, _) => def, NameBindingKind::Module(module) => module.def().unwrap(), NameBindingKind::Import { binding, .. } => binding.def(), - NameBindingKind::Ambiguity { .. } => Def::Err, } } - fn def_ignoring_ambiguity(&self) -> Def { - match self.kind { - NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(), - NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(), - _ => self.def(), + fn is_ambiguity(&self) -> bool { + self.ambiguity.is_some() || match self.kind { + NameBindingKind::Import { binding, .. } => binding.is_ambiguity(), + _ => false, } } @@ -1362,7 +1356,6 @@ impl<'a> NameBinding<'a> { fn is_glob_import(&self) -> bool { match self.kind { NameBindingKind::Import { directive, .. } => directive.is_glob(), - NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(), _ => false, } } @@ -1382,7 +1375,7 @@ impl<'a> NameBinding<'a> { } fn macro_kind(&self) -> Option { - match self.def_ignoring_ambiguity() { + match self.def() { Def::Macro(_, kind) => Some(kind), Def::NonMacroAttr(..) => Some(MacroKind::Attr), _ => None, @@ -1893,6 +1886,7 @@ impl<'a> Resolver<'a> { arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Err, false), + ambiguity: None, expansion: Mark::root(), span: DUMMY_SP, vis: ty::Visibility::Public, @@ -1963,33 +1957,30 @@ impl<'a> Resolver<'a> { fn record_use(&mut self, ident: Ident, ns: Namespace, used_binding: &'a NameBinding<'a>, is_lexical_scope: bool) { - match used_binding.kind { - NameBindingKind::Import { directive, binding, ref used } if !used.get() => { - // Avoid marking `extern crate` items that refer to a name from extern prelude, - // but not introduce it, as used if they are accessed from lexical scope. - if is_lexical_scope { - if let Some(entry) = self.extern_prelude.get(&ident.modern()) { - if let Some(crate_item) = entry.extern_crate_item { - if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { - return; - } + if let Some((b2, kind)) = used_binding.ambiguity { + self.ambiguity_errors.push(AmbiguityError { + kind, ident, b1: used_binding, b2, + misc1: AmbiguityErrorMisc::None, + misc2: AmbiguityErrorMisc::None, + }); + } + if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind { + // Avoid marking `extern crate` items that refer to a name from extern prelude, + // but not introduce it, as used if they are accessed from lexical scope. + if is_lexical_scope { + if let Some(entry) = self.extern_prelude.get(&ident.modern()) { + if let Some(crate_item) = entry.extern_crate_item { + if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { + return; } } } - used.set(true); - directive.used.set(true); - self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(directive.id, ident); - self.record_use(ident, ns, binding, false); - } - NameBindingKind::Ambiguity { kind, b1, b2 } => { - self.ambiguity_errors.push(AmbiguityError { - kind, ident, b1, b2, - misc1: AmbiguityErrorMisc::None, - misc2: AmbiguityErrorMisc::None, - }); } - _ => {} + used.set(true); + directive.used.set(true); + self.used_imports.insert((directive.id, ns)); + self.add_to_glob_map(directive.id, ident); + self.record_use(ident, ns, binding, false); } } @@ -3925,8 +3916,11 @@ impl<'a> Resolver<'a> { }); if let Some(candidate) = candidates.get(0) { format!("did you mean `{}`?", candidate.path) - } else { + } else if !ident.is_reserved() { format!("maybe a missing `extern crate {};`?", ident) + } else { + // the parser will already have complained about the keyword being used + return PathResult::NonModule(err_path_resolution()); } } else if i == 0 { format!("use of undeclared type or module `{}`", ident) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5f6ef934c1aa3..e5e6c7a994b7a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -175,6 +175,7 @@ impl<'a> base::Resolver for Resolver<'a> { self.macro_map.insert(def_id, ext); let binding = self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Macro(def_id, kind), false), + ambiguity: None, span: DUMMY_SP, vis: ty::Visibility::Public, expansion: Mark::root(), @@ -304,7 +305,7 @@ impl<'a> Resolver<'a> { let features = self.session.features_untracked(); if attr_kind == NonMacroAttrKind::Custom { assert!(path.segments.len() == 1); - let name = path.segments[0].ident.name.as_str(); + let name = path.segments[0].ident.as_str(); if name.starts_with("rustc_") { if !features.rustc_attrs { let msg = "unless otherwise specified, attributes with the prefix \ @@ -389,7 +390,7 @@ impl<'a> Resolver<'a> { .push((path[0].ident, kind, parent_scope.clone(), binding.ok())); } - binding.map(|binding| binding.def_ignoring_ambiguity()) + binding.map(|binding| binding.def()) } } @@ -929,7 +930,7 @@ impl<'a> Resolver<'a> { let def = path_res.base_def(); check_consistency(self, &path, path_span, kind, initial_def, def); } - path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => { + path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => { let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res { (span, msg) } else { @@ -950,9 +951,9 @@ impl<'a> Resolver<'a> { Ok(binding) => { let initial_def = initial_binding.map(|initial_binding| { self.record_use(ident, MacroNS, initial_binding, false); - initial_binding.def_ignoring_ambiguity() + initial_binding.def() }); - let def = binding.def_ignoring_ambiguity(); + let def = binding.def(); let seg = Segment::from_ident(ident); check_consistency(self, &[seg], ident.span, kind, initial_def, def); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9a7b8c24993c6..c84dbd2974624 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -223,11 +223,6 @@ impl<'a> Resolver<'a> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { - if let Some(blacklisted_binding) = this.blacklisted_binding { - if ptr::eq(binding, blacklisted_binding) { - return Err((Determined, Weak::No)); - } - } // `extern crate` are always usable for backwards compatibility, see issue #37020, // remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`. let usable = this.is_accessible(binding.vis) || binding.is_extern_crate(); @@ -235,7 +230,18 @@ impl<'a> Resolver<'a> { }; if record_used { - return resolution.binding.ok_or((Determined, Weak::No)).and_then(|binding| { + return resolution.binding.and_then(|binding| { + // If the primary binding is blacklisted, search further and return the shadowed + // glob binding if it exists. What we really want here is having two separate + // scopes in a module - one for non-globs and one for globs, but until that's done + // use this hack to avoid inconsistent resolution ICEs during import validation. + if let Some(blacklisted_binding) = self.blacklisted_binding { + if ptr::eq(binding, blacklisted_binding) { + return resolution.shadowed_glob; + } + } + Some(binding) + }).ok_or((Determined, Weak::No)).and_then(|binding| { if self.last_import_segment && check_usable(self, binding).is_err() { Err((Determined, Weak::No)) } else { @@ -439,6 +445,7 @@ impl<'a> Resolver<'a> { directive, used: Cell::new(false), }, + ambiguity: None, span: directive.span, vis, expansion: directive.parent_scope.expansion, @@ -466,6 +473,10 @@ impl<'a> Resolver<'a> { self.set_binding_parent_module(binding, module); self.update_resolution(module, ident, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { + if binding.def() == Def::Err { + // Do not override real bindings with `Def::Err`s from error recovery. + return Ok(()); + } match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { if binding.def() != old_binding.def() { @@ -488,8 +499,8 @@ impl<'a> Resolver<'a> { nonglob_binding, glob_binding)); } else { resolution.binding = Some(nonglob_binding); - resolution.shadowed_glob = Some(glob_binding); } + resolution.shadowed_glob = Some(glob_binding); } (false, false) => { if let (&NameBindingKind::Def(_, true), &NameBindingKind::Def(_, true)) = @@ -517,13 +528,15 @@ impl<'a> Resolver<'a> { }) } - fn ambiguity(&self, kind: AmbiguityKind, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>) - -> &'a NameBinding<'a> { + fn ambiguity(&self, kind: AmbiguityKind, + primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>) + -> &'a NameBinding<'a> { self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Ambiguity { kind, b1, b2 }, - vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis }, - span: b1.span, - expansion: Mark::root(), + kind: primary_binding.kind.clone(), + ambiguity: Some((secondary_binding, kind)), + vis: primary_binding.vis, + span: primary_binding.span, + expansion: primary_binding.expansion, }) } @@ -842,7 +855,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. if let Some(initial_module) = directive.imported_module.get() { - if module != initial_module && no_ambiguity { + if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { span_bug!(directive.span, "inconsistent resolution for an import"); } } else { @@ -952,9 +965,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { directive.module_path.is_empty()); } } - initial_binding.def_ignoring_ambiguity() + initial_binding.def() }); - let def = binding.def_ignoring_ambiguity(); + let def = binding.def(); if let Ok(initial_def) = initial_def { if def != initial_def && this.ambiguity_errors.is_empty() { span_bug!(directive.span, "inconsistent resolution for an import"); @@ -1191,10 +1204,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => continue, }; - // Filter away "empty import canaries". - let is_non_canary_import = - binding.is_import() && binding.vis != ty::Visibility::Invisible; - if is_non_canary_import || binding.is_macro_def() { + // Filter away "empty import canaries" and ambiguous imports. + let is_good_import = binding.is_import() && !binding.is_ambiguity() && + binding.vis != ty::Visibility::Invisible; + if is_good_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { if let Some(def_id) = def.opt_def_id() { diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index d38ce3478d93d..52fcb5b80f4ae 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -14,7 +14,7 @@ use rustc::traits::{ Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt, }; use rustc::ty::query::Providers; -use rustc::ty::subst::{Kind, Subst, UserSelfTy, UserSubsts}; +use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy}; use rustc::ty::{ FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, }; @@ -44,28 +44,16 @@ fn type_op_ascribe_user_type<'tcx>( tcx.infer_ctxt() .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { let ( - param_env, - AscribeUserType { - mir_ty, - variance, - def_id, - user_substs, - projs, - }, + param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs } ) = key.into_parts(); debug!( - "type_op_ascribe_user_type(\ - mir_ty={:?}, variance={:?}, def_id={:?}, user_substs={:?}, projs={:?}\ - )", - mir_ty, variance, def_id, user_substs, projs, + "type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \ + user_substs={:?} projs={:?}", + mir_ty, variance, def_id, user_substs, projs ); - let mut cx = AscribeUserTypeCx { - infcx, - param_env, - fulfill_cx, - }; + let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; cx.relate_mir_and_user_ty(mir_ty, variance, def_id, user_substs, projs)?; Ok(()) @@ -130,10 +118,9 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { projs: &[ProjectionKind<'tcx>], ) -> Result<(), NoSolution> { let UserSubsts { - substs, user_self_ty, + substs, } = user_substs; - let tcx = self.tcx(); let ty = tcx.type_of(def_id); @@ -171,20 +158,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.relate(mir_ty, variance, ty)?; } - if let Some(UserSelfTy { - impl_def_id, - self_ty, - }) = user_self_ty - { - let impl_self_ty = self.tcx().type_of(impl_def_id); - let impl_self_ty = self.subst(impl_self_ty, &substs); - let impl_self_ty = self.normalize(impl_self_ty); - - self.relate(self_ty, Variance::Invariant, impl_self_ty)?; - - self.prove_predicate(Predicate::WellFormed(impl_self_ty)); - } - // Prove the predicates coming along with `def_id`. // // Also, normalize the `instantiated_predicates` @@ -198,6 +171,19 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.prove_predicate(instantiated_predicate); } + if let Some(UserSelfTy { + impl_def_id, + self_ty, + }) = user_self_ty { + let impl_self_ty = self.tcx().type_of(impl_def_id); + let impl_self_ty = self.subst(impl_self_ty, &substs); + let impl_self_ty = self.normalize(impl_self_ty); + + self.relate(self_ty, Variance::Invariant, impl_self_ty)?; + + self.prove_predicate(Predicate::WellFormed(impl_self_ty)); + } + // In addition to proving the predicates, we have to // prove that `ty` is well-formed -- this is because // the WF of `ty` is predicated on the substs being @@ -210,7 +196,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { // type were ill-formed but did not appear in `ty`, // which...could happen with normalization... self.prove_predicate(Predicate::WellFormed(ty)); - Ok(()) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 736b416dd4f21..1db7141917f98 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -31,6 +31,12 @@ use std::collections::BTreeSet; use std::iter; use std::slice; +use super::{check_type_alias_enum_variants_enabled}; +use rustc_data_structures::fx::FxHashSet; + +#[derive(Debug)] +pub struct PathSeg(pub DefId, pub usize); + pub trait AstConv<'gcx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -563,7 +569,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let has_self = generic_params.has_self; let (_, potential_assoc_types) = Self::check_generic_arg_count( - self.tcx(), + tcx, span, &generic_params, &generic_args, @@ -588,7 +594,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let substs = Self::create_substs_for_generic_args( - self.tcx(), + tcx, def_id, &[][..], self_ty.is_some(), @@ -1290,7 +1296,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // item is declared. let bound = match (&ty.sty, ty_path_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { - // `Self` in an impl of a trait -- we have a concrete `self` type and a + // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. let trait_ref = match tcx.impl_trait_ref(impl_def_id) { Some(trait_ref) => trait_ref, @@ -1317,13 +1323,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => { let ty_str = ty.to_string(); - // Incorrect enum variant + // Incorrect enum variant. let mut err = tcx.sess.struct_span_err( span, &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), ); - // Check if it was a typo - let input = adt_def.variants.iter().map(|variant| &variant.name); + // Check if it was a typo. + let input = adt_def.variants.iter().map(|variant| &variant.ident.name); if let Some(suggested_name) = find_best_match_for_name( input, &assoc_name.as_str(), @@ -1342,7 +1348,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { return (tcx.types.err, Def::Err); } _ => { - // Don't print TyErr to the user. + // Check if we have an enum variant. + match ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::Variant(variant_def.did); + tcx.check_stability(def.def_id(), Some(ref_id), span); + return (ty, def); + } + }, + _ => (), + } + + // Don't print `TyErr` to the user. if !ty.references_error() { self.report_ambiguous_associated_type(span, &ty.to_string(), @@ -1358,8 +1381,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident - }) - .expect("missing associated type"); + }).expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound); let ty = self.normalize_ty(span, ty); @@ -1410,7 +1432,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } - pub fn prohibit_generics<'a, T: IntoIterator>(&self, segments: T) { + pub fn prohibit_generics<'a, T: IntoIterator>( + &self, segments: T) -> bool { + let mut has_err = false; for segment in segments { segment.with_generic_args(|generic_args| { let (mut err_for_lt, mut err_for_ty) = (false, false); @@ -1419,32 +1443,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { hir::GenericArg::Lifetime(lt) => { if err_for_lt { continue } err_for_lt = true; + has_err = true; (struct_span_err!(self.tcx().sess, lt.span, E0110, - "lifetime parameters are not allowed on this type"), + "lifetime arguments are not allowed on this entity"), lt.span, "lifetime") } hir::GenericArg::Type(ty) => { if err_for_ty { continue } err_for_ty = true; + has_err = true; (struct_span_err!(self.tcx().sess, ty.span, E0109, - "type parameters are not allowed on this type"), + "type arguments are not allowed on this entity"), ty.span, "type") } }; - span_err.span_label(span, format!("{} parameter not allowed", kind)) + span_err.span_label(span, format!("{} argument not allowed", kind)) .emit(); if err_for_lt && err_for_ty { break; } } for binding in &generic_args.bindings { + has_err = true; Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); break; } }) } + has_err } pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) { @@ -1453,6 +1481,134 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { err.span_label(span, "associated type not allowed here").emit(); } + pub fn def_ids_for_path_segments(&self, + segments: &[hir::PathSegment], + self_ty: Option>, + def: Def) + -> Vec { + // We need to extract the type parameters supplied by the user in + // the path `path`. Due to the current setup, this is a bit of a + // tricky-process; the problem is that resolve only tells us the + // end-point of the path resolution, and not the intermediate steps. + // Luckily, we can (at least for now) deduce the intermediate steps + // just from the end-point. + // + // There are basically five cases to consider: + // + // 1. Reference to a constructor of a struct: + // + // struct Foo(...) + // + // In this case, the parameters are declared in the type space. + // + // 2. Reference to a constructor of an enum variant: + // + // enum E { Foo(...) } + // + // In this case, the parameters are defined in the type space, + // but may be specified either on the type or the variant. + // + // 3. Reference to a fn item or a free constant: + // + // fn foo() { } + // + // In this case, the path will again always have the form + // `a::b::foo::` where only the final segment should have + // type parameters. However, in this case, those parameters are + // declared on a value, and hence are in the `FnSpace`. + // + // 4. Reference to a method or an associated constant: + // + // impl SomeStruct { + // fn foo(...) + // } + // + // Here we can have a path like + // `a::b::SomeStruct::::foo::`, in which case parameters + // may appear in two places. The penultimate segment, + // `SomeStruct::`, contains parameters in TypeSpace, and the + // final segment, `foo::` contains parameters in fn space. + // + // 5. Reference to a local variable + // + // Local variables can't have any type parameters. + // + // The first step then is to categorize the segments appropriately. + + let tcx = self.tcx(); + + assert!(!segments.is_empty()); + let last = segments.len() - 1; + + let mut path_segs = vec![]; + + match def { + // Case 1. Reference to a struct constructor. + Def::StructCtor(def_id, ..) | + Def::SelfCtor(.., def_id) => { + // Everything but the final segment should have no + // parameters at all. + let generics = tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + let generics_def_id = generics.parent.unwrap_or(def_id); + path_segs.push(PathSeg(generics_def_id, last)); + } + + // Case 2. Reference to a variant constructor. + Def::Variant(def_id) | + Def::VariantCtor(def_id, ..) => { + let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap()); + let (generics_def_id, index) = if let Some(adt_def) = adt_def { + debug_assert!(adt_def.is_enum()); + (adt_def.did, last) + } else if last >= 1 && segments[last - 1].args.is_some() { + // Everything but the penultimate segment should have no + // parameters at all. + let enum_def_id = tcx.parent_def_id(def_id).unwrap(); + (enum_def_id, last - 1) + } else { + // FIXME: lint here recommending `Enum::<...>::Variant` form + // instead of `Enum::Variant::<...>` form. + + // Everything but the final segment should have no + // parameters at all. + let generics = tcx.generics_of(def_id); + // Variant and struct constructors use the + // generics of their parent type definition. + (generics.parent.unwrap_or(def_id), last) + }; + path_segs.push(PathSeg(generics_def_id, index)); + } + + // Case 3. Reference to a top-level value. + Def::Fn(def_id) | + Def::Const(def_id) | + Def::Static(def_id, _) => { + path_segs.push(PathSeg(def_id, last)); + } + + // Case 4. Reference to a method or associated const. + Def::Method(def_id) | + Def::AssociatedConst(def_id) => { + if segments.len() >= 2 { + let generics = tcx.generics_of(def_id); + path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); + } + path_segs.push(PathSeg(def_id, last)); + } + + // Case 5. Local variable, no generics. + Def::Local(..) | Def::Upvar(..) => {} + + _ => bug!("unexpected definition: {:?}", def), + } + + debug!("path_segs = {:?}", path_segs); + + path_segs + } + // Check a type `Path` and convert it to a `Ty`. pub fn def_to_ty(&self, opt_self_ty: Option>, @@ -1483,14 +1639,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { self.prohibit_generics(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, did, path.segments.last().unwrap()) } - Def::Variant(did) if permit_variants => { + Def::Variant(_) if permit_variants => { // Convert "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. assert_eq!(opt_self_ty, None); - self.prohibit_generics(path.segments.split_last().unwrap().1); - self.ast_path_to_ty(span, - tcx.parent_def_id(did).unwrap(), - path.segments.last().unwrap()) + + let path_segs = self.def_ids_for_path_segments(&path.segments, None, path.def); + let generic_segs: FxHashSet<_> = + path_segs.iter().map(|PathSeg(_, index)| index).collect(); + self.prohibit_generics(path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !generic_segs.contains(&index) { + Some(seg) + } else { + None + } + })); + + let PathSeg(def_id, index) = path_segs.last().unwrap(); + self.ast_path_to_ty(span, *def_id, &path.segments[*index]) } Def::TyParam(did) => { assert_eq!(opt_self_ty, None); @@ -1504,25 +1670,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.mk_ty_param(index, tcx.hir().name(node_id).as_interned_str()) } Def::SelfTy(_, Some(def_id)) => { - // `Self` in impl (we know the concrete type) - + // `Self` in impl (we know the concrete type). assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - tcx.at(span).type_of(def_id) } Def::SelfTy(Some(_), None) => { - // `Self` in trait + // `Self` in trait. assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); tcx.mk_self_type() } Def::AssociatedTy(def_id) => { - self.prohibit_generics(&path.segments[..path.segments.len()-2]); + debug_assert!(path.segments.len() >= 2); + self.prohibit_generics(&path.segments[..path.segments.len() - 2]); self.qpath_to_ty(span, opt_self_ty, def_id, - &path.segments[path.segments.len()-2], + &path.segments[path.segments.len() - 2], path.segments.last().unwrap()) } Def::PrimTy(prim_ty) => { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f227c529cb035..b66c383edb51e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -17,6 +17,8 @@ use util::nodemap::FxHashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::cmp; +use super::report_unexpected_variant_def; + impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// The `is_arg` argument indicates whether this pattern is the /// *outermost* pattern in an argument (e.g., in `fn foo(&x: @@ -273,7 +275,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { PatKind::Tuple(ref elements, ddpos) => { let mut expected_len = elements.len(); if ddpos.is_some() { - // Require known type only when `..` is present + // Require known type only when `..` is present. if let ty::Tuple(ref tys) = self.structurally_resolved_type(pat.span, expected).sty { expected_len = tys.len(); @@ -282,8 +284,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let max_len = cmp::max(expected_len, elements.len()); let element_tys_iter = (0..max_len).map(|_| self.next_ty_var( - // FIXME: MiscVariable for now, obtaining the span and name information - // from all tuple elements isn't trivial. + // FIXME: `MiscVariable` for now -- obtaining the span and name information + // from all tuple elements isn't trivial. TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); @@ -736,12 +738,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); expected: Ty<'tcx>) -> Ty<'tcx> { let tcx = self.tcx; - let report_unexpected_def = |def: Def| { - span_err!(tcx.sess, pat.span, E0533, - "expected unit struct/variant or constant, found {} `{}`", - def.kind_name(), - hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); - }; // Resolve the path and check the definition for errors. let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span); @@ -751,7 +747,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); return tcx.types.err; } Def::Method(..) => { - report_unexpected_def(def); + report_unexpected_variant_def(tcx, &def, pat.span, qpath); + return tcx.types.err; + } + Def::VariantCtor(_, CtorKind::Fictive) => { + report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } Def::VariantCtor(_, CtorKind::Const) | @@ -952,7 +952,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); if plural == "" { let input = unmentioned_fields.iter().map(|field| &field.name); let suggested_name = - find_best_match_for_name(input, &ident.name.as_str(), None); + find_best_match_for_name(input, &ident.as_str(), None); if let Some(suggested_name) = suggested_name { err.span_suggestion(*span, "did you mean", suggested_name.to_string()); // we don't want to throw `E0027` in case we have thrown `E0026` for them diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6ad707e3d2c78..9d418704f487d 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return Err(ErrorReported); } - if self.type_is_known_to_be_sized(t, span) { + if self.type_is_known_to_be_sized_modulo_regions(t, span) { return Ok(Some(PointerKind::Thin)); } @@ -397,7 +397,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { self.expr_ty, self.cast_ty); - if !fcx.type_is_known_to_be_sized(self.cast_ty, self.span) { + if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages @@ -618,8 +618,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool { + fn type_is_known_to_be_sized_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); - traits::type_known_to_meet_bound(self, self.param_env, ty, lang_item, span) + traits::type_known_to_meet_bound_modulo_regions(self, self.param_env, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 84ca77663a6ab..7a788f2de7f2f 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -353,9 +353,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Maybe add `*`? Only if `T: Copy`. _ => { - if !self.infcx.type_moves_by_default(self.param_env, - checked, - sp) { + if self.infcx.type_is_copy_modulo_regions(self.param_env, + checked, + sp) { // do not suggest if the span comes from a macro (#52783) if let (Ok(code), true) = (cm.span_to_snippet(sp), sp == expr.span) { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index c80990a0704bd..a36b21921436e 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -71,7 +71,7 @@ fn equate_intrinsic_type<'a, 'tcx>( pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); - let name = it.name.as_str(); + let name = it.ident.as_str(); let mk_va_list_ty = || { tcx.lang_items().va_list().map(|did| { @@ -393,7 +393,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let def_id = tcx.hir().local_def_id(it.id); let i_n_tps = tcx.generics_of(def_id).own_counts().types; - let name = it.name.as_str(); + let name = it.ident.as_str(); let (n_tps, inputs, output) = match &*name { "simd_eq" | "simd_ne" | "simd_lt" | "simd_le" | "simd_gt" | "simd_ge" => { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 2bc1dfaf04e37..1758f76252456 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -1,4 +1,4 @@ -//! Method lookup: the secret sauce of Rust. See the [rustc guide] chapter. +//! Method lookup: the secret sauce of Rust. See the [rustc guide] for more information. //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html @@ -8,7 +8,7 @@ mod suggest; pub use self::MethodError::*; pub use self::CandidateSource::*; -pub use self::suggest::TraitInfo; +pub use self::suggest::{SelfSource, TraitInfo}; use check::FnCtxt; use namespace::Namespace; @@ -25,6 +25,7 @@ use rustc::infer::{self, InferOk}; use syntax::ast; use syntax_pos::Span; +use crate::{check_type_alias_enum_variants_enabled}; use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { @@ -356,27 +357,59 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) } - pub fn resolve_ufcs(&self, - span: Span, - method_name: ast::Ident, - self_ty: Ty<'tcx>, - expr_id: ast::NodeId) - -> Result> { + pub fn resolve_ufcs( + &self, + span: Span, + method_name: ast::Ident, + self_ty: Ty<'tcx>, + expr_id: ast::NodeId + ) -> Result> { + debug!( + "resolve_ufcs: method_name={:?} self_ty={:?} expr_id={:?}", + method_name, self_ty, expr_id, + ); + + let tcx = self.tcx; + let mode = probe::Mode::Path; - let pick = self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope)?; + match self.probe_for_name(span, mode, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope) { + Ok(pick) => { + debug!("resolve_ufcs: pick={:?}", pick); + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); + } - if let Some(import_id) = pick.import_id { - let import_def_id = self.tcx.hir().local_def_id(import_id); - debug!("used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); - } + let def = pick.item.def(); + debug!("resolve_ufcs: def={:?}", def); + tcx.check_stability(def.def_id(), Some(expr_id), span); - let def = pick.item.def(); - self.tcx.check_stability(def.def_id(), Some(expr_id), span); + Ok(def) + } + Err(err) => { + // Check if we have an enum variant. + match self_ty.sty { + ty::Adt(adt_def, _) if adt_def.is_enum() => { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); + } + }, + _ => (), + } - Ok(def) + Err(err) + } + } } /// Find item with name `item_name` defined in impl/trait `def_id` diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index c4a908d56f351..98c425655d2d3 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -6,7 +6,7 @@ use errors::{Applicability, DiagnosticBuilder}; use middle::lang_items::FnOnceTraitLangItem; use namespace::Namespace; use rustc_data_structures::sync::Lrc; -use rustc::hir::{self, Node}; +use rustc::hir::{self, ExprKind, Node, QPath}; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::hir::map as hir_map; @@ -60,13 +60,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn report_method_error(&self, - span: Span, - rcvr_ty: Ty<'tcx>, - item_name: ast::Ident, - rcvr_expr: Option<&hir::Expr>, - error: MethodError<'tcx>, - args: Option<&'gcx [hir::Expr]>) { + pub fn report_method_error<'b>(&self, + span: Span, + rcvr_ty: Ty<'tcx>, + item_name: ast::Ident, + source: SelfSource<'b>, + error: MethodError<'tcx>, + args: Option<&'gcx [hir::Expr]>) { // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return; @@ -185,7 +185,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "method" } else if actual.is_enum() { if let Adt(ref adt_def, _) = actual.sty { - let names = adt_def.variants.iter().map(|s| &s.name); + let names = adt_def.variants.iter().map(|s| &s.ident.name); suggestion = find_best_match_for_name(names, &item_name.as_str(), None); @@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .filter_map(|info| self.associated_item(info.def_id, item_name, Namespace::Value) ); - if let (true, false, Some(expr), Some(_)) = (actual.is_numeric(), - actual.has_concrete_skeleton(), - rcvr_expr, - candidates.next()) { + if let (true, false, SelfSource::MethodCall(expr), Some(_)) = + (actual.is_numeric(), + actual.has_concrete_skeleton(), + source, + candidates.next()) { let mut err = struct_span_err!( tcx.sess, span, @@ -231,7 +232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "f32" }; match expr.node { - hir::ExprKind::Lit(ref lit) => { + ExprKind::Lit(ref lit) => { // numeric literal let snippet = tcx.sess.source_map().span_to_snippet(lit.span) .unwrap_or_else(|_| "".to_owned()); @@ -247,9 +248,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MaybeIncorrect, ); } - hir::ExprKind::Path(ref qpath) => { + ExprKind::Path(ref qpath) => { // local binding - if let &hir::QPath::Resolved(_, ref path) = &qpath { + if let &QPath::Resolved(_, ref path) = &qpath { if let hir::def::Def::Local(node_id) = path.def { let span = tcx.hir().span(node_id); let snippet = tcx.sess.source_map().span_to_snippet(span) @@ -294,7 +295,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { let mut err = struct_span_err!( tcx.sess, - span, + item_name.span, E0599, "no {} named `{}` found for type `{}` in the current scope", item_kind, @@ -302,7 +303,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_str ); if let Some(suggestion) = suggestion { - err.note(&format!("did you mean `{}::{}`?", ty_str, suggestion)); + // enum variant + err.help(&format!("did you mean `{}`?", suggestion)); } err } @@ -326,7 +328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { for (ty, _) in self.autoderef(span, rcvr_ty) { if let ty::Adt(def, substs) = ty.sty { if !def.is_enum() { @@ -377,10 +379,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) { report_function!(expr.span, expr_string); - } else if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = + } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.node { if let Some(segment) = path.segments.last() { @@ -396,7 +398,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.span_label(span, "this is an associated function, not a method"); } if static_sources.len() == 1 { - if let Some(expr) = rcvr_expr { + if let SelfSource::MethodCall(expr) = source { err.span_suggestion_with_applicability(expr.span.to(span), "use associated function syntax instead", format!("{}::{}", @@ -433,7 +435,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span, rcvr_ty, item_name, - rcvr_expr, + source, out_of_scope_traits); } @@ -571,18 +573,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - fn suggest_traits_to_import(&self, - err: &mut DiagnosticBuilder, - span: Span, - rcvr_ty: Ty<'tcx>, - item_name: ast::Ident, - rcvr_expr: Option<&hir::Expr>, - valid_out_of_scope_traits: Vec) { + fn suggest_traits_to_import<'b>(&self, + err: &mut DiagnosticBuilder, + span: Span, + rcvr_ty: Ty<'tcx>, + item_name: ast::Ident, + source: SelfSource<'b>, + valid_out_of_scope_traits: Vec) { if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; } - let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr); + let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source); // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are @@ -643,7 +645,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_derefs_to_local(&self, span: Span, rcvr_ty: Ty<'tcx>, - rcvr_expr: Option<&hir::Expr>) -> bool { + source: SelfSource) -> bool { fn is_local(ty: Ty) -> bool { match ty.sty { ty::Adt(def, _) => def.did.is_local(), @@ -663,7 +665,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This occurs for UFCS desugaring of `T::method`, where there is no // receiver expression for the method call, and thus no autoderef. - if rcvr_expr.is_none() { + if let SelfSource::QPath(_) = source { return is_local(self.resolve_type_vars_with_obligations(rcvr_ty)); } @@ -671,6 +673,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } +#[derive(Copy, Clone)] +pub enum SelfSource<'a> { + QPath(&'a hir::Ty), + MethodCall(&'a hir::Expr /* rcvr */), +} + #[derive(Copy, Clone)] pub struct TraitInfo { pub def_id: DefId, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b3c24be108da7..d78d7273a36e6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -83,10 +83,10 @@ mod generator_interior; mod intrinsic; mod op; -use astconv::AstConv; +use astconv::{AstConv, PathSeg}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; -use rustc::hir::{self, GenericArg, ItemKind, Node, PatKind}; -use rustc::hir::def::Def; +use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath}; +use rustc::hir::def::{CtorKind, Def}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -101,14 +101,15 @@ use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; -use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, - UserSelfTy, UserSubsts}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, RegionKind, Visibility, - ToPolyTraitRef, ToPredicate}; +use rustc::ty::{ + self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility, + ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation +}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; +use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts}; use rustc::ty::util::{Representability, IntTypeExt, Discr}; use rustc::ty::layout::VariantIdx; use syntax_pos::{self, BytePos, Span, MultiSpan}; @@ -142,7 +143,7 @@ use self::autoderef::Autoderef; use self::callee::DeferredCallResolution; use self::coercion::{CoerceMany, DynamicCoerceMany}; pub use self::compare_method::{compare_impl_method, compare_const_impl}; -use self::method::MethodCallee; +use self::method::{MethodCallee, SelfSource}; use self::TupleArgumentsFlag::*; /// The type of a local binding, including the revealed type for anon types. @@ -507,9 +508,6 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> { } } -#[derive(Debug)] -struct PathSeg(DefId, usize); - pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { body_id: ast::NodeId, @@ -977,10 +975,12 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { o_ty }; - let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty); + let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation( + &UserTypeAnnotation::Ty(revealed_ty) + ); debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}", ty.hir_id, o_ty, revealed_ty, c_ty); - self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty); + self.fcx.tables.borrow_mut().user_provided_types_mut().insert(ty.hir_id, c_ty); Some(LocalTy { decl_ty: o_ty, revealed_ty }) }, @@ -1327,7 +1327,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite } hir::ItemKind::Fn(..) => {} // entirely within check_item_body hir::ItemKind::Impl(.., ref impl_item_refs) => { - debug!("ItemKind::Impl {} with id {}", it.name, it.id); + debug!("ItemKind::Impl {} with id {}", it.ident, it.id); let impl_def_id = tcx.hir().local_def_id(it.id); if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { check_impl_items_against_trait( @@ -1864,6 +1864,16 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, check_representable(tcx, sp, def_id); } +fn report_unexpected_variant_def<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + def: &Def, + span: Span, + qpath: &QPath) { + span_err!(tcx.sess, span, E0533, + "expected unit struct/variant or constant, found {} `{}`", + def.kind_name(), + hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false))); +} + impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } @@ -2101,8 +2111,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tables.borrow_mut().field_indices_mut().insert(hir_id, index); } - // The NodeId and the ItemLocalId must identify the same item. We just pass - // both of them for consistency checking. pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { @@ -2131,23 +2139,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !method.substs.is_noop() { let method_generics = self.tcx.generics_of(method.def_id); if !method_generics.params.is_empty() { - let user_substs = self.infcx.probe(|_| { - let just_method_substs = Substs::for_item(self.tcx, method.def_id, |param, _| { - let i = param.index as usize; - if i < method_generics.parent_count { - self.infcx.var_for_def(DUMMY_SP, param) - } else { - method.substs[i] - } - }); - self.infcx.canonicalize_user_type_annotation(&UserSubsts { - substs: just_method_substs, + let user_type_annotation = self.infcx.probe(|_| { + let user_substs = UserSubsts { + substs: Substs::for_item(self.tcx, method.def_id, |param, _| { + let i = param.index as usize; + if i < method_generics.parent_count { + self.infcx.var_for_def(DUMMY_SP, param) + } else { + method.substs[i] + } + }), user_self_ty: None, // not relevant here - }) + }; + + self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf( + method.def_id, + user_substs, + )) }); - debug!("write_method_call: user_substs = {:?}", user_substs); - self.write_user_substs(hir_id, user_substs); + debug!("write_method_call: user_type_annotation={:?}", user_type_annotation); + self.write_user_type_annotation(hir_id, user_type_annotation); } } } @@ -2170,41 +2182,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// This should be invoked **before any unifications have /// occurred**, so that annotations like `Vec<_>` are preserved /// properly. - pub fn write_user_substs_from_substs( + pub fn write_user_type_annotation_from_substs( &self, hir_id: hir::HirId, + def_id: DefId, substs: &'tcx Substs<'tcx>, user_self_ty: Option>, ) { debug!( - "write_user_substs_from_substs({:?}, {:?}) in fcx {}", - hir_id, - substs, - self.tag(), + "write_user_type_annotation_from_substs: hir_id={:?} def_id={:?} substs={:?} \ + user_self_ty={:?} in fcx {}", + hir_id, def_id, substs, user_self_ty, self.tag(), ); if !substs.is_noop() { - let user_substs = self.infcx.canonicalize_user_type_annotation(&UserSubsts { - substs, - user_self_ty, - }); - debug!("instantiate_value_path: user_substs = {:?}", user_substs); - self.write_user_substs(hir_id, user_substs); + let canonicalized = self.infcx.canonicalize_user_type_annotation( + &UserTypeAnnotation::TypeOf(def_id, UserSubsts { + substs, + user_self_ty, + }) + ); + debug!("write_user_type_annotation_from_substs: canonicalized={:?}", canonicalized); + self.write_user_type_annotation(hir_id, canonicalized); } } - pub fn write_user_substs(&self, hir_id: hir::HirId, substs: CanonicalUserSubsts<'tcx>) { + pub fn write_user_type_annotation( + &self, + hir_id: hir::HirId, + canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>, + ) { debug!( - "write_user_substs({:?}, {:?}) in fcx {}", - hir_id, - substs, - self.tag(), + "write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}", + hir_id, canonical_user_type_annotation, self.tag(), ); - if !substs.is_identity() { - self.tables.borrow_mut().user_substs_mut().insert(hir_id, substs); + if !canonical_user_type_annotation.is_identity() { + self.tables.borrow_mut().user_provided_types_mut().insert( + hir_id, canonical_user_type_annotation + ); } else { - debug!("write_user_substs: skipping identity substs"); + debug!("write_user_type_annotation: skipping identity substs"); } } @@ -2370,6 +2388,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); + debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); // If the type given by the user has free regions, save it for // later, since NLL would like to enforce those. Also pass in @@ -2379,8 +2398,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // although I have my doubts). Other sorts of things are // already sufficiently enforced with erased regions. =) if ty.has_free_regions() || ty.has_projections() { - let c_ty = self.infcx.canonicalize_response(&ty); - self.tables.borrow_mut().user_provided_tys_mut().insert(ast_ty.hir_id, c_ty); + let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty)); + debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty); + self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); } ty @@ -2947,7 +2967,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let is_closure = match arg.node { - hir::ExprKind::Closure(..) => true, + ExprKind::Closure(..) => true, _ => false }; @@ -3097,8 +3117,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { - // Add help to type error if this is an `if` condition with an assignment - if let (ExpectIfCondition, &hir::ExprKind::Assign(ref lhs, ref rhs)) + // Add help to type error if this is an `if` condition with an assignment. + if let (ExpectIfCondition, &ExprKind::Assign(ref lhs, ref rhs)) = (expected, &expr.node) { let msg = "try comparing for equality"; @@ -3244,7 +3264,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.report_method_error(span, rcvr_t, segment.ident, - Some(rcvr), + SelfSource::MethodCall(rcvr), error, Some(args)); } @@ -3415,8 +3435,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(suggested_field_name) = Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![]) { - err.span_label(field.span, - format!("did you mean `{}`?", suggested_field_name)); + err.span_suggestion_with_applicability( + field.span, + "a field with a similar name exists", + suggested_field_name.to_string(), + Applicability::MaybeIncorrect, + ); } else { err.span_label(field.span, "unknown field"); let struct_variant_def = def.non_enum_variant(); @@ -3529,7 +3553,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Adt(adt, ..) if adt.is_enum() => { struct_span_err!(self.tcx.sess, field.ident.span, E0559, "{} `{}::{}` has no field named `{}`", - kind_name, actual, variant.name, field.ident) + kind_name, actual, variant.ident, field.ident) } _ => { struct_span_err!(self.tcx.sess, field.ident.span, E0560, @@ -3543,15 +3567,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field_name) = Self::suggest_field_name(variant, &field.ident.as_str(), skip_fields.collect()) { - err.span_label(field.ident.span, - format!("field does not exist - did you mean `{}`?", field_name)); + err.span_suggestion_with_applicability( + field.ident.span, + "a field with a similar name exists", + field_name.to_string(), + Applicability::MaybeIncorrect, + ); } else { match ty.sty { ty::Adt(adt, ..) => { if adt.is_enum() { err.span_label(field.ident.span, format!("`{}::{}` does not have this field", - ty, variant.name)); + ty, variant.ident)); } else { err.span_label(field.ident.span, format!("`{}` does not have this field", ty)); @@ -3691,12 +3719,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_struct_path(&self, - qpath: &hir::QPath, + qpath: &QPath, node_id: ast::NodeId) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> { let path_span = match *qpath { - hir::QPath::Resolved(_, ref path) => path.span, - hir::QPath::TypeRelative(ref qself, _) => qself.span + QPath::Resolved(_, ref path) => path.span, + QPath::TypeRelative(ref qself, _) => qself.span }; let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, node_id); let variant = match def { @@ -3727,7 +3755,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some((variant, did, substs)) = variant { debug!("check_struct_path: did={:?} substs={:?}", did, substs); let hir_id = self.tcx.hir().node_to_hir_id(node_id); - self.write_user_substs_from_substs(hir_id, substs, None); + self.write_user_type_annotation_from_substs(hir_id, did, substs, None); // Check bounds on type arguments used in the path. let bounds = self.instantiate_bounds(path_span, did, substs); @@ -3749,7 +3777,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_struct(&self, expr: &hir::Expr, expected: Expectation<'tcx>, - qpath: &hir::QPath, + qpath: &QPath, fields: &'gcx [hir::Field], base_expr: &'gcx Option>) -> Ty<'tcx> { @@ -3763,8 +3791,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let path_span = match *qpath { - hir::QPath::Resolved(_, ref path) => path.span, - hir::QPath::TypeRelative(ref qself, _) => qself.span + QPath::Resolved(_, ref path) => path.span, + QPath::TypeRelative(ref qself, _) => qself.span }; // Prohibit struct expressions when non-exhaustive flag is set. @@ -3836,9 +3864,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Warn for non-block expressions with diverging children. match expr.node { - hir::ExprKind::Block(..) | - hir::ExprKind::Loop(..) | hir::ExprKind::While(..) | - hir::ExprKind::If(..) | hir::ExprKind::Match(..) => {} + ExprKind::Block(..) | + ExprKind::Loop(..) | ExprKind::While(..) | + ExprKind::If(..) | ExprKind::Match(..) => {} _ => self.warn_if_unreachable(expr.id, expr.span, "expression") } @@ -3879,7 +3907,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let id = expr.id; match expr.node { - hir::ExprKind::Box(ref subexpr) => { + ExprKind::Box(ref subexpr) => { let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| { match ty.sty { ty::Adt(def, _) if def.is_box() @@ -3891,16 +3919,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_box(referent_ty) } - hir::ExprKind::Lit(ref lit) => { + ExprKind::Lit(ref lit) => { self.check_lit(&lit, expected) } - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + ExprKind::Binary(op, ref lhs, ref rhs) => { self.check_binop(expr, op, lhs, rhs) } - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + ExprKind::AssignOp(op, ref lhs, ref rhs) => { self.check_binop_assign(expr, op, lhs, rhs) } - hir::ExprKind::Unary(unop, ref oprnd) => { + ExprKind::Unary(unop, ref oprnd) => { let expected_inner = match unop { hir::UnNot | hir::UnNeg => { expected @@ -3968,7 +3996,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } oprnd_t } - hir::ExprKind::AddrOf(mutbl, ref oprnd) => { + ExprKind::AddrOf(mutbl, ref oprnd) => { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { match ty.sty { ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { @@ -4008,13 +4036,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_ref(region, tm) } } - hir::ExprKind::Path(ref qpath) => { + ExprKind::Path(ref qpath) => { let (def, opt_ty, segs) = self.resolve_ty_and_def_ufcs(qpath, expr.id, expr.span); - let ty = if def != Def::Err { - self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0 - } else { - self.set_tainted_by_errors(); - tcx.types.err + let ty = match def { + Def::Err => { + self.set_tainted_by_errors(); + tcx.types.err + } + Def::VariantCtor(_, CtorKind::Fictive) => { + report_unexpected_variant_def(tcx, &def, expr.span, qpath); + tcx.types.err + } + _ => self.instantiate_value_path(segs, opt_ty, def, expr.span, id).0, }; if let ty::FnDef(..) = ty.sty { @@ -4061,13 +4094,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - hir::ExprKind::InlineAsm(_, ref outputs, ref inputs) => { + ExprKind::InlineAsm(_, ref outputs, ref inputs) => { for expr in outputs.iter().chain(inputs.iter()) { self.check_expr(expr); } tcx.mk_unit() } - hir::ExprKind::Break(destination, ref expr_opt) => { + ExprKind::Break(destination, ref expr_opt) => { if let Ok(target_id) = destination.target_id { let (e_ty, cause); if let Some(ref e) = *expr_opt { @@ -4140,7 +4173,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // ... except when we try to 'break rust;'. // ICE this expression in particular (see #43162). - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = e.node { + if let ExprKind::Path(QPath::Resolved(_, ref path)) = e.node { if path.segments.len() == 1 && path.segments[0].ident.name == "rust" { fatally_break_rust(self.tcx.sess); } @@ -4151,7 +4184,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - hir::ExprKind::Continue(destination) => { + ExprKind::Continue(destination) => { if destination.target_id.is_ok() { tcx.types.never } else { @@ -4159,7 +4192,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err } } - hir::ExprKind::Ret(ref expr_opt) => { + ExprKind::Ret(ref expr_opt) => { if self.ret_coercion.is_none() { struct_span_err!(self.tcx.sess, expr.span, E0572, "return statement outside of function body").emit(); @@ -4191,7 +4224,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.types.never } - hir::ExprKind::Assign(ref lhs, ref rhs) => { + ExprKind::Assign(ref lhs, ref rhs) => { let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty); @@ -4221,11 +4254,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_unit() } } - hir::ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { + ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => { self.check_then_else(&cond, then_expr, opt_else_expr.as_ref().map(|e| &**e), expr.span, expected) } - hir::ExprKind::While(ref cond, ref body, _) => { + ExprKind::While(ref cond, ref body, _) => { let ctxt = BreakableCtxt { // cannot use break with a value from a while loop coerce: None, @@ -4249,7 +4282,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_unit() } - hir::ExprKind::Loop(ref body, _, source) => { + ExprKind::Loop(ref body, _, source) => { let coerce = match source { // you can only use break with a value from a normal `loop { }` hir::LoopSource::Loop => { @@ -4289,22 +4322,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.mk_unit()) } - hir::ExprKind::Match(ref discrim, ref arms, match_src) => { + ExprKind::Match(ref discrim, ref arms, match_src) => { self.check_match(expr, &discrim, arms, expected, match_src) } - hir::ExprKind::Closure(capture, ref decl, body_id, _, gen) => { + ExprKind::Closure(capture, ref decl, body_id, _, gen) => { self.check_expr_closure(expr, capture, &decl, body_id, gen, expected) } - hir::ExprKind::Block(ref body, _) => { + ExprKind::Block(ref body, _) => { self.check_block_with_expected(&body, expected) } - hir::ExprKind::Call(ref callee, ref args) => { + ExprKind::Call(ref callee, ref args) => { self.check_call(expr, &callee, args, expected) } - hir::ExprKind::MethodCall(ref segment, span, ref args) => { + ExprKind::MethodCall(ref segment, span, ref args) => { self.check_method_call(expr, segment, span, args, expected, needs) } - hir::ExprKind::Cast(ref e, ref t) => { + ExprKind::Cast(ref e, ref t) => { // Find the type of `e`. Supply hints based on the type we are casting to, // if appropriate. let t_cast = self.to_ty_saving_user_provided_ty(t); @@ -4329,12 +4362,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - hir::ExprKind::Type(ref e, ref t) => { + ExprKind::Type(ref e, ref t) => { let ty = self.to_ty_saving_user_provided_ty(&t); self.check_expr_eq_type(&e, ty); ty } - hir::ExprKind::Array(ref args) => { + ExprKind::Array(ref args) => { let uty = expected.to_option(self).and_then(|uty| { match uty.sty { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), @@ -4358,7 +4391,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; tcx.mk_array(element_ty, args.len() as u64) } - hir::ExprKind::Repeat(ref element, ref count) => { + ExprKind::Repeat(ref element, ref count) => { let count_def_id = tcx.hir().local_def_id(count.id); let param_env = ty::ParamEnv::empty(); let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); @@ -4414,7 +4447,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.types.err } } - hir::ExprKind::Tup(ref elts) => { + ExprKind::Tup(ref elts) => { let flds = expected.only_has_type(self).and_then(|ty| { let ty = self.resolve_type_vars_with_obligations(ty); match ty.sty { @@ -4444,13 +4477,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tuple } } - hir::ExprKind::Struct(ref qpath, ref fields, ref base_expr) => { + ExprKind::Struct(ref qpath, ref fields, ref base_expr) => { self.check_expr_struct(expr, expected, qpath, fields, base_expr) } - hir::ExprKind::Field(ref base, field) => { + ExprKind::Field(ref base, field) => { self.check_field(expr, needs, &base, field) } - hir::ExprKind::Index(ref base, ref idx) => { + ExprKind::Index(ref base, ref idx) => { let base_t = self.check_expr_with_needs(&base, needs); let idx_t = self.check_expr(&idx); @@ -4476,7 +4509,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: - if let hir::ExprKind::Lit(ref lit) = idx.node { + if let ExprKind::Lit(ref lit) = idx.node { if let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node { let snip = tcx.sess.source_map().span_to_snippet(base.span); @@ -4501,7 +4534,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } - hir::ExprKind::Yield(ref value) => { + ExprKind::Yield(ref value) => { match self.yield_ty { Some(ty) => { self.check_expr_coercable_to_type(&value, ty); @@ -4522,21 +4555,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary. // The newly resolved definition is written into `type_dependent_defs`. fn finish_resolving_struct_path(&self, - qpath: &hir::QPath, + qpath: &QPath, path_span: Span, node_id: ast::NodeId) -> (Def, Ty<'tcx>) { match *qpath { - hir::QPath::Resolved(ref maybe_qself, ref path) => { + QPath::Resolved(ref maybe_qself, ref path) => { let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself)); let ty = AstConv::def_to_ty(self, self_ty, path, true); (path.def, ty) } - hir::QPath::TypeRelative(ref qself, ref segment) => { + QPath::TypeRelative(ref qself, ref segment) => { let ty = self.to_ty(qself); - let def = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.node { + let def = if let hir::TyKind::Path(QPath::Resolved(_, ref path)) = qself.node { path.def } else { Def::Err @@ -4556,19 +4589,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Resolve associated value path into a base type and associated constant or method definition. // The newly resolved definition is written into `type_dependent_defs`. pub fn resolve_ty_and_def_ufcs<'b>(&self, - qpath: &'b hir::QPath, + qpath: &'b QPath, node_id: ast::NodeId, span: Span) -> (Def, Option>, &'b [hir::PathSegment]) { - let (ty, item_segment) = match *qpath { - hir::QPath::Resolved(ref opt_qself, ref path) => { + debug!("resolve_ty_and_def_ufcs: qpath={:?} node_id={:?} span={:?}", qpath, node_id, span); + let (ty, qself, item_segment) = match *qpath { + QPath::Resolved(ref opt_qself, ref path) => { return (path.def, opt_qself.as_ref().map(|qself| self.to_ty(qself)), &path.segments[..]); } - hir::QPath::TypeRelative(ref qself, ref segment) => { - (self.to_ty(qself), segment) + QPath::TypeRelative(ref qself, ref segment) => { + (self.to_ty(qself), qself, segment) } }; let hir_id = self.tcx.hir().node_to_hir_id(node_id); @@ -4586,7 +4620,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => Def::Err, }; if item_name.name != keywords::Invalid.name() { - self.report_method_error(span, ty, item_name, None, error, None); + self.report_method_error(span, + ty, + item_name, + SelfSource::QPath(qself), + error, + None); } def } @@ -4601,7 +4640,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { local: &'gcx hir::Local, init: &'gcx hir::Expr) -> Ty<'tcx> { - // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed + // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed // for #42640 (default match binding modes). // // See #44848. @@ -4646,7 +4685,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { - // Don't do all the complex logic below for DeclItem. + // Don't do all the complex logic below for `DeclItem`. match stmt.node { hir::StmtKind::Decl(ref decl, _) => { if let hir::DeclKind::Item(_) = decl.node { @@ -4658,7 +4697,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement"); - // Hide the outer diverging and has_errors flags. + // Hide the outer diverging and `has_errors` flags. let old_diverges = self.diverges.get(); let old_has_errors = self.has_errors.get(); self.diverges.set(Diverges::Maybe); @@ -4670,11 +4709,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::DeclKind::Local(ref l) => { self.check_decl_local(&l); } - hir::DeclKind::Item(_) => {/* ignore for now */} + // Ignore for now. + hir::DeclKind::Item(_) => () } } hir::StmtKind::Expr(ref expr, _) => { - // Check with expected type of () + // Check with expected type of `()`. self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); } hir::StmtKind::Semi(ref expr, _) => { @@ -4682,7 +4722,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - // Combine the diverging and has_error flags. + // Combine the diverging and `has_error` flags. self.diverges.set(self.diverges.get() | old_diverges); self.has_errors.set(self.has_errors.get() | old_has_errors); } @@ -4811,13 +4851,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let parent = self.tcx.hir().get(fn_id); if let Node::Item(&hir::Item { - name, node: hir::ItemKind::Fn(ref decl, ..), .. + ident, node: hir::ItemKind::Fn(ref decl, ..), .. }) = parent { decl.clone().and_then(|decl| { // This is less than ideal, it will not suggest a return type span on any // method called `main`, regardless of whether it is actually the entry point, // but it will still present it as the reason for the expected type. - Some((decl, name != Symbol::intern("main"))) + Some((decl, ident.name != Symbol::intern("main"))) }) } else if let Node::TraitItem(&hir::TraitItem { node: hir::TraitItemKind::Method(hir::MethodSig { @@ -4928,13 +4968,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `BlockTailExpression` only relevant if the tail expr would be // useful on its own. match expression.node { - hir::ExprKind::Call(..) | - hir::ExprKind::MethodCall(..) | - hir::ExprKind::If(..) | - hir::ExprKind::While(..) | - hir::ExprKind::Loop(..) | - hir::ExprKind::Match(..) | - hir::ExprKind::Block(..) => { + ExprKind::Call(..) | + ExprKind::MethodCall(..) | + ExprKind::If(..) | + ExprKind::While(..) | + ExprKind::Loop(..) | + ExprKind::Match(..) | + ExprKind::Block(..) => { let sp = self.tcx.sess.source_map().next_point(cause_span); err.span_suggestion_with_applicability( sp, @@ -5038,101 +5078,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MachineApplicable); } - fn def_ids_for_path_segments(&self, - segments: &[hir::PathSegment], - def: Def) - -> Vec { - // We need to extract the type parameters supplied by the user in - // the path `path`. Due to the current setup, this is a bit of a - // tricky-process; the problem is that resolve only tells us the - // end-point of the path resolution, and not the intermediate steps. - // Luckily, we can (at least for now) deduce the intermediate steps - // just from the end-point. - // - // There are basically four cases to consider: - // - // 1. Reference to a constructor of enum variant or struct: - // - // struct Foo(...) - // enum E { Foo(...) } - // - // In these cases, the parameters are declared in the type - // space. - // - // 2. Reference to a fn item or a free constant: - // - // fn foo() { } - // - // In this case, the path will again always have the form - // `a::b::foo::` where only the final segment should have - // type parameters. However, in this case, those parameters are - // declared on a value, and hence are in the `FnSpace`. - // - // 3. Reference to a method or an associated constant: - // - // impl SomeStruct { - // fn foo(...) - // } - // - // Here we can have a path like - // `a::b::SomeStruct::::foo::`, in which case parameters - // may appear in two places. The penultimate segment, - // `SomeStruct::`, contains parameters in TypeSpace, and the - // final segment, `foo::` contains parameters in fn space. - // - // 4. Reference to a local variable - // - // Local variables can't have any type parameters. - // - // The first step then is to categorize the segments appropriately. - - assert!(!segments.is_empty()); - let last = segments.len() - 1; - - let mut path_segs = vec![]; - - match def { - // Case 1. Reference to a struct/variant constructor. - Def::StructCtor(def_id, ..) | - Def::VariantCtor(def_id, ..) | - Def::SelfCtor(.., def_id) => { - // Everything but the final segment should have no - // parameters at all. - let generics = self.tcx.generics_of(def_id); - // Variant and struct constructors use the - // generics of their parent type definition. - let generics_def_id = generics.parent.unwrap_or(def_id); - path_segs.push(PathSeg(generics_def_id, last)); - } - - // Case 2. Reference to a top-level value. - Def::Fn(def_id) | - Def::Const(def_id) | - Def::Static(def_id, _) => { - path_segs.push(PathSeg(def_id, last)); - } - - // Case 3. Reference to a method or associated const. - Def::Method(def_id) | - Def::AssociatedConst(def_id) => { - if segments.len() >= 2 { - let generics = self.tcx.generics_of(def_id); - path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); - } - path_segs.push(PathSeg(def_id, last)); - } - - // Case 4. Local variable, no generics. - Def::Local(..) | Def::Upvar(..) => {} - - _ => bug!("unexpected definition: {:?}", def), - } - - debug!("path_segs = {:?}", path_segs); - - path_segs - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, @@ -5150,16 +5095,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { node_id, ); - let path_segs = self.def_ids_for_path_segments(segments, def); + let tcx = self.tcx; + + let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def); let mut user_self_ty = None; + let mut is_alias_variant_ctor = false; match def { + Def::VariantCtor(_, _) => { + if let Some(self_ty) = self_ty { + let adt_def = self_ty.ty_adt_def().unwrap(); + user_self_ty = Some(UserSelfTy { + impl_def_id: adt_def.did, + self_ty, + }); + is_alias_variant_ctor = true; + } + } Def::Method(def_id) | Def::AssociatedConst(def_id) => { - let container = self.tcx.associated_item(def_id).container; + let container = tcx.associated_item(def_id).container; + debug!("instantiate_value_path: def={:?} container={:?}", def, container); match container { ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(self.tcx, span, trait_did) + callee::check_legal_trait_for_method_call(tcx, span, trait_did) } ty::ImplContainer(impl_def_id) => { if segments.len() == 1 { @@ -5185,21 +5144,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let generic_segs = path_segs.iter().map(|PathSeg(_, index)| index) - .collect::>(); - AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| { - if !generic_segs.contains(&index) { + let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); + let generics_has_err = AstConv::prohibit_generics( + self, segments.iter().enumerate().filter_map(|(index, seg)| { + if !generic_segs.contains(&index) || is_alias_variant_ctor { Some(seg) } else { None } })); + if generics_has_err { + // Don't try to infer type parameters when prohibited generic arguments were given. + user_self_ty = None; + } match def { Def::Local(nid) | Def::Upvar(nid, ..) => { let ty = self.local_ty(span, nid).decl_ty; let ty = self.normalize_associated_types_in(span, &ty); - self.write_ty(self.tcx.hir().node_to_hir_id(node_id), ty); + self.write_ty(tcx.hir().node_to_hir_id(node_id), ty); return (ty, def); } _ => {} @@ -5215,13 +5178,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut infer_args_for_err = FxHashSet::default(); for &PathSeg(def_id, index) in &path_segs { let seg = &segments[index]; - let generics = self.tcx.generics_of(def_id); + let generics = tcx.generics_of(def_id); // Argument-position `impl Trait` is treated as a normal generic // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. let suppress_errors = AstConv::check_generic_arg_count_for_call( - self.tcx, + tcx, span, &generics, &seg, @@ -5234,7 +5197,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let has_self = path_segs.last().map(|PathSeg(def_id, _)| { - self.tcx.generics_of(*def_id).has_self + tcx.generics_of(*def_id).has_self }).unwrap_or(false); let mut new_def = def; @@ -5247,28 +5210,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); new_def = Def::StructCtor(variant.did, variant.ctor_kind); - (variant.did, self.tcx.type_of(variant.did)) + (variant.did, tcx.type_of(variant.did)) } _ => { - let mut err = self.tcx.sess.struct_span_err(span, + let mut err = tcx.sess.struct_span_err(span, "the `Self` constructor can only be used with tuple or unit structs"); if let Some(adt_def) = adt_def { match adt_def.adt_kind() { AdtKind::Enum => { - err.note("did you mean to use one of the enum's variants?"); + err.help("did you mean to use one of the enum's variants?"); }, AdtKind::Struct | AdtKind::Union => { - err.span_label( + err.span_suggestion_with_applicability( span, - format!("did you mean `Self {{ /* fields */ }}`?"), + "use curly brackets", + String::from("Self { /* fields */ }"), + Applicability::HasPlaceholders, ); } } } err.emit(); - (impl_def_id, self.tcx.types.err) + (impl_def_id, tcx.types.err) } } } @@ -5277,13 +5242,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. - let ty = self.tcx.type_of(def_id); + let ty = tcx.type_of(def_id); (def_id, ty) } }; let substs = AstConv::create_substs_for_generic_args( - self.tcx, + tcx, def_id, &[][..], has_self, @@ -5329,10 +5294,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If we have a default, then we it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. - let default = self.tcx.type_of(param.def_id); + let default = tcx.type_of(param.def_id); self.normalize_ty( span, - default.subst_spanned(self.tcx, substs.unwrap(), Some(span)) + default.subst_spanned(tcx, substs.unwrap(), Some(span)) ).into() } else { // If no type arguments were provided, we have to infer them. @@ -5349,8 +5314,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!ty.has_escaping_bound_vars()); // First, store the "user substs" for later. - let hir_id = self.tcx.hir().node_to_hir_id(node_id); - self.write_user_substs_from_substs(hir_id, substs, user_self_ty); + let hir_id = tcx.hir().node_to_hir_id(node_id); + self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty); // Add all the obligations that are required, substituting and // normalized appropriately. @@ -5365,10 +5330,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { // In the case of `Foo::method` and `>::method`, if `method` - // is inherent, there is no `Self` parameter, instead, the impl needs + // is inherent, there is no `Self` parameter; instead, the impl needs // type parameters, which we can infer by unifying the provided `Self` // with the substituted impl type. - let ty = self.tcx.type_of(impl_def_id); + // This also occurs for an enum variant on a type alias. + let ty = tcx.type_of(impl_def_id); let impl_ty = self.instantiate_type_scheme(span, &substs, &ty); match self.at(&self.misc(span), self.param_env).sup(impl_ty, self_ty) { @@ -5405,7 +5371,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If our calling expression is indeed the function itself, we're good! // If not, generate an error that this can only be called directly. if let Node::Expr(expr) = self.tcx.hir().get(self.tcx.hir().get_parent_node(node_id)) { - if let hir::ExprKind::Call(ref callee, ..) = expr.node { + if let ExprKind::Call(ref callee, ..) = expr.node { if callee.id == node_id { return } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 8cf97970a1556..7c871601af308 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -262,9 +262,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { - !self.infcx.type_moves_by_default(self.param_env, - rty, - lhs_expr.span) && + self.infcx.type_is_copy_modulo_regions(self.param_env, + rty, + lhs_expr.span) && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)) @@ -334,9 +334,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut suggested_deref = false; if let Ref(_, mut rty, _) = lhs_ty.sty { if { - !self.infcx.type_moves_by_default(self.param_env, - rty, - lhs_expr.span) && + self.infcx.type_is_copy_modulo_regions(self.param_env, + rty, + lhs_expr.span) && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 65539d3b10709..53e44d53e6a9b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -873,7 +873,7 @@ fn receiver_is_valid<'fcx, 'tcx, 'gcx>( trait_ref.to_predicate() ); - if !fcx.predicate_must_hold(&obligation) { + if !fcx.predicate_must_hold_modulo_regions(&obligation) { debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait", receiver_ty); return false diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8bd9b097d2df1..38de936a027ff 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -3,6 +3,7 @@ // substitutions. use check::FnCtxt; +use errors::DiagnosticBuilder; use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -357,7 +358,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); let common_local_id_root = fcx_tables.local_id_root.unwrap(); - for (&local_id, c_ty) in fcx_tables.user_provided_tys().iter() { + let mut errors_buffer = Vec::new(); + for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { let hir_id = hir::HirId { owner: common_local_id_root.index, local_id, @@ -374,8 +376,30 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }; self.tables - .user_provided_tys_mut() + .user_provided_types_mut() .insert(hir_id, c_ty.clone()); + + if let ty::UserTypeAnnotation::TypeOf(_, user_substs) = c_ty.value { + if self.rustc_dump_user_substs { + // This is a unit-testing mechanism. + let node_id = self.tcx().hir().hir_to_node_id(hir_id); + let span = self.tcx().hir().span(node_id); + // We need to buffer the errors in order to guarantee a consistent + // order when emitting them. + let err = self.tcx().sess.struct_span_err( + span, + &format!("user substs: {:?}", user_substs) + ); + err.buffer(&mut errors_buffer); + } + } + } + + if !errors_buffer.is_empty() { + errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + for diag in errors_buffer.drain(..) { + DiagnosticBuilder::new_diagnostic(self.tcx().sess.diagnostic(), diag).emit(); + } } } @@ -573,22 +597,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { assert!(!substs.needs_infer() && !substs.has_placeholders()); self.tables.node_substs_mut().insert(hir_id, substs); } - - // Copy over any user-substs - if let Some(user_substs) = self.fcx.tables.borrow().user_substs(hir_id) { - let user_substs = self.tcx().lift_to_global(&user_substs).unwrap(); - self.tables.user_substs_mut().insert(hir_id, user_substs); - - // Unit-testing mechanism: - if self.rustc_dump_user_substs { - let node_id = self.tcx().hir().hir_to_node_id(hir_id); - let span = self.tcx().hir().span(node_id); - self.tcx().sess.span_err( - span, - &format!("user substs: {:?}", user_substs), - ); - } - } } fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 740e64b1895e8..bf767726ef715 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -154,7 +154,7 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { // If the extern crate isn't in the extern prelude, // there is no way it can be written as an `use`. - let orig_name = extern_crate.orig_name.unwrap_or(item.name); + let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name); if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) { continue; } @@ -173,8 +173,8 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { visibility_qualified(&item.vis, "use") ); let base_replacement = match extern_crate.orig_name { - Some(orig_name) => format!("use {} as {};", orig_name, item.name), - None => format!("use {};", item.name), + Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name), + None => format!("use {};", item.ident.name), }; let replacement = visibility_qualified(&item.vis, base_replacement); tcx.struct_span_lint_node(lint, id, extern_crate.span, msg) @@ -219,7 +219,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> { def_id: extern_crate_def_id, span: item.span, orig_name, - warn_if_unused: !item.name.as_str().starts_with('_'), + warn_if_unused: !item.ident.as_str().starts_with('_'), } ); } diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index e568320ba8e73..8d27a77b29c6c 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -73,6 +73,10 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { cause.add_intercrate_ambiguity_hint(&mut err); } + if overlap.involves_placeholder { + traits::add_placeholder_note(&mut err); + } + err.emit(); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 54dfc57bac674..9fc2f11b19738 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -33,7 +33,7 @@ use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; -use syntax::ast::MetaItemKind; +use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, list_contains_name, mark_used}; use syntax::source_map::Spanned; use syntax::feature_gate; @@ -385,7 +385,7 @@ fn is_param<'a, 'tcx>( fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { let it = tcx.hir().expect_item(item_id); - debug!("convert: item {} with id {}", it.name, it.id); + debug!("convert: item {} with id {}", it.ident, it.id); let def_id = tcx.hir().local_def_id(item_id); match it.node { // These don't define types. @@ -533,7 +533,7 @@ fn convert_enum_variant_types<'a, 'tcx>( format!("overflowed on value after {}", prev_discr.unwrap()), ).note(&format!( "explicitly set `{} = {}` if that is desired outcome", - variant.node.name, wrapped_discr + variant.node.ident, wrapped_discr )) .emit(); None @@ -556,7 +556,7 @@ fn convert_enum_variant_types<'a, 'tcx>( fn convert_variant<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, - name: ast::Name, + ident: Ident, discr: ty::VariantDiscr, def: &hir::VariantData, adt_kind: ty::AdtKind, @@ -593,12 +593,13 @@ fn convert_variant<'a, 'tcx>( .collect(); ty::VariantDef::new(tcx, did, - name, + ident, discr, fields, adt_kind, CtorKind::from_hir(def), - attribute_def_id) + attribute_def_id + ) } fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef { @@ -628,7 +629,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad }; distance_from_explicit += 1; - convert_variant(tcx, did, v.node.name, discr, &v.node.data, AdtKind::Enum, + convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum, did) }) .collect(), @@ -646,7 +647,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad std::iter::once(convert_variant( tcx, ctor_id.unwrap_or(def_id), - item.name, + item.ident, ty::VariantDiscr::Relative(0), def, AdtKind::Struct, @@ -659,7 +660,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad std::iter::once(convert_variant( tcx, def_id, - item.name, + item.ident, ty::VariantDiscr::Relative(0), def, AdtKind::Union, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 425b428ecf2db..5910a8b3110d0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1291,7 +1291,7 @@ You tried to give a type parameter to a type which doesn't need it. Erroneous code example: ```compile_fail,E0109 -type X = u32; // error: type parameters are not allowed on this type +type X = u32; // error: type arguments are not allowed on this entity ``` Please check that you used the correct type and recheck its definition. Perhaps diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index cba07ab3602c5..c55a1258ce955 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -111,6 +111,7 @@ use rustc::infer::InferOk; use rustc::lint; use rustc::middle; use rustc::session; +use rustc::session::config::nightly_options; use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; @@ -129,6 +130,22 @@ pub struct TypeAndSubsts<'tcx> { ty: Ty<'tcx>, } +fn check_type_alias_enum_variants_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + span: Span) { + if !tcx.features().type_alias_enum_variants { + let mut err = tcx.sess.struct_span_err( + span, + "enum variants on type aliases are experimental" + ); + if nightly_options::is_nightly_build() { + help!(&mut err, + "add `#![feature(type_alias_enum_variants)]` to the \ + crate attributes to enable"); + } + err.emit(); + } +} + fn require_c_abi_if_variadic(tcx: TyCtxt, decl: &hir::FnDecl, abi: Abi, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 54d3e640ec585..38b2452b420e9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2967,7 +2967,7 @@ impl<'tcx> Clean for ty::VariantDef { } }; Item { - name: Some(self.name.clean(cx)), + name: Some(self.ident.clean(cx)), attrs: inline::load_attrs(cx, self.did), source: cx.tcx.def_span(self.did).clean(cx), visibility: Some(Inherited), @@ -3183,13 +3183,22 @@ fn qpath_to_string(p: &hir::QPath) -> String { s } +impl Clean for Ident { + #[inline] + fn clean(&self, cx: &DocContext) -> String { + self.name.clean(cx) + } +} + impl Clean for ast::Name { + #[inline] fn clean(&self, _: &DocContext) -> String { self.to_string() } } impl Clean for InternedString { + #[inline] fn clean(&self, _: &DocContext) -> String { self.to_string() } @@ -3616,7 +3625,7 @@ impl Clean for hir::ForeignItem { }; Item { - name: Some(self.name.clean(cx)), + name: Some(self.ident.clean(cx)), attrs: self.attrs.clean(cx), source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), @@ -3951,7 +3960,7 @@ pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option { for item_id in mem::replace(&mut items, HirVec::new()).iter() { let item = tcx.hir().expect_item(item_id.id); - if item.name == *segment { + if item.ident.name == *segment { if path_it.peek().is_none() { return Some(tcx.hir().local_def_id(item_id.id)) } diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index c7af41ac969ce..3e1114f9c9ce8 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": 2015, - "sourceType": "module" + "sourceType": "script" }, "rules": { "linebreak-style": [ @@ -16,6 +16,10 @@ module.exports = { "semi": [ "error", "always" + ], + "no-constant-condition": [ + "error", + { "checkLoops": false } ] } }; diff --git a/src/librustdoc/html/static/down-arrow.svg b/src/librustdoc/html/static/down-arrow.svg index a2d9a37dde091..c0f59f0c36fce 100644 --- a/src/librustdoc/html/static/down-arrow.svg +++ b/src/librustdoc/html/static/down-arrow.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 75b0f5df0d8b3..e376462d6e3cf 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,9 +1,12 @@ // From rust: /* global ALIASES, currentCrate, rootPath */ +// From DOM global ids: +/* global help */ + // Local js definitions: /* global addClass, getCurrentValue, hasClass */ -/* global isHidden onEach, removeClass, updateLocalStorage */ +/* global isHidden, onEachLazy, removeClass, updateLocalStorage */ if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { @@ -13,7 +16,7 @@ if (!String.prototype.startsWith) { } if (!String.prototype.endsWith) { String.prototype.endsWith = function(suffix, length) { - var l = length || this.length; + let l = length || this.length; return this.indexOf(suffix, l - suffix.length) !== -1; }; } @@ -44,7 +47,7 @@ if (!DOMTokenList.prototype.remove) { // This mapping table should match the discriminants of // `rustdoc::html::item_type::ItemType` type in Rust. - var itemTypes = ["mod", + let itemTypes = ["mod", "externcrate", "import", "struct", @@ -70,21 +73,19 @@ if (!DOMTokenList.prototype.remove) { "attr", "derive"]; - var search_input = document.getElementsByClassName("search-input")[0]; + let search_input = document.getElementsByClassName("search-input")[0]; // On the search screen, so you remain on the last tab you opened. // // 0 for "In Names" // 1 for "In Parameters" // 2 for "In Return Types" - var currentTab = 0; - - var themesWidth = null; + let currentTab = 0; - var titleBeforeSearch = document.title; + let titleBeforeSearch = document.title; function getPageId() { - var id = document.location.href.split("#")[1]; + let id = document.location.href.split("#")[1]; if (id) { return id.split("?")[0].split("&")[0]; } @@ -92,57 +93,57 @@ if (!DOMTokenList.prototype.remove) { } function showSidebar() { - var elems = document.getElementsByClassName("sidebar-elems")[0]; + let elems = document.getElementsByClassName("sidebar-elems")[0]; if (elems) { addClass(elems, "show-it"); } - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; if (sidebar) { addClass(sidebar, "mobile"); - var filler = document.getElementById("sidebar-filler"); + let filler = document.getElementById("sidebar-filler"); if (!filler) { - var div = document.createElement("div"); + let div = document.createElement("div"); div.id = "sidebar-filler"; sidebar.appendChild(div); } } - var themePicker = document.getElementsByClassName("theme-picker"); + let themePicker = document.getElementsByClassName("theme-picker"); if (themePicker && themePicker.length > 0) { themePicker[0].style.display = "none"; } } function hideSidebar() { - var elems = document.getElementsByClassName("sidebar-elems")[0]; + let elems = document.getElementsByClassName("sidebar-elems")[0]; if (elems) { removeClass(elems, "show-it"); } - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; removeClass(sidebar, "mobile"); - var filler = document.getElementById("sidebar-filler"); + let filler = document.getElementById("sidebar-filler"); if (filler) { filler.remove(); } document.getElementsByTagName("body")[0].style.marginTop = ""; - var themePicker = document.getElementsByClassName("theme-picker"); + let themePicker = document.getElementsByClassName("theme-picker"); if (themePicker && themePicker.length > 0) { themePicker[0].style.display = null; } } // used for special search precedence - var TY_PRIMITIVE = itemTypes.indexOf("primitive"); - var TY_KEYWORD = itemTypes.indexOf("keyword"); + let TY_PRIMITIVE = itemTypes.indexOf("primitive"); + let TY_KEYWORD = itemTypes.indexOf("keyword"); onEachLazy(document.getElementsByClassName("js-only"), function(e) { removeClass(e, "js-only"); }); function getQueryStringParams() { - var params = {}; + let params = {}; window.location.search.substring(1).split("&"). map(function(s) { - var pair = s.split("="); + let pair = s.split("="); params[decodeURIComponent(pair[0])] = typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]); }); @@ -154,14 +155,14 @@ if (!DOMTokenList.prototype.remove) { window.history && typeof window.history.pushState === "function"; } - var main = document.getElementById("main"); + let main = document.getElementById("main"); function highlightSourceLines(ev) { // If we're in mobile mode, we should add the sidebar in any case. hideSidebar(); - var elem; - var search = document.getElementById("search"); - var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); + let elem; + let search = document.getElementById("search"); + let i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { from = parseInt(match[1], 10); to = Math.min(50000, parseInt(match[2] || match[1], 10)); @@ -171,7 +172,7 @@ if (!DOMTokenList.prototype.remove) { return; } if (ev === null) { - var x = document.getElementById(from); + let x = document.getElementById(from); if (x) { x.scrollIntoView(); } @@ -187,7 +188,7 @@ if (!DOMTokenList.prototype.remove) { } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { addClass(search, "hidden"); removeClass(main, "hidden"); - var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); + let hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); if (browserSupportsHistoryApi()) { history.replaceState(hash, "", "?search=#" + hash); } @@ -199,15 +200,15 @@ if (!DOMTokenList.prototype.remove) { } function expandSection(id) { - var elem = document.getElementById(id); + let elem = document.getElementById(id); if (elem && isHidden(elem)) { - var h3 = elem.parentNode.previousElementSibling; + let h3 = elem.parentNode.previousElementSibling; if (h3 && h3.tagName !== "H3") { h3 = h3.previousElementSibling; // skip div.docblock } if (h3) { - var collapses = h3.getElementsByClassName("collapse-toggle"); + let collapses = h3.getElementsByClassName("collapse-toggle"); if (collapses.length > 0) { // The element is not visible, we need to make it appear! collapseDocs(collapses[0], "show"); @@ -234,7 +235,7 @@ if (!DOMTokenList.prototype.remove) { return ev.key; } - var c = ev.charCode || ev.keyCode; + let c = ev.charCode || ev.keyCode; if (c == 27) { return "Escape"; } @@ -257,7 +258,7 @@ if (!DOMTokenList.prototype.remove) { function handleEscape(ev, help) { hideModal(); - var search = document.getElementById("search"); + let search = document.getElementById("search"); if (hasClass(help, "hidden") === false) { displayHelp(false, ev); } else if (hasClass(search, "hidden") === false) { @@ -275,7 +276,7 @@ if (!DOMTokenList.prototype.remove) { return; } - var help = document.getElementById("help"); + let help = document.getElementById("help"); if (document.activeElement.tagName === "INPUT") { switch (getVirtualKey(ev)) { case "Escape": @@ -330,9 +331,9 @@ if (!DOMTokenList.prototype.remove) { } else if (hasClass(ev.target.parentNode, "collapse-toggle")) { collapseDocs(ev.target.parentNode, "toggle"); } else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) { - var prev_id = 0; + let prev_id = 0; - var set_fragment = function(name) { + let set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, "#" + name); window.hashchange(); @@ -341,11 +342,11 @@ if (!DOMTokenList.prototype.remove) { } }; - var cur_id = parseInt(ev.target.id, 10); + let cur_id = parseInt(ev.target.id, 10); if (ev.shiftKey && prev_id) { if (prev_id > cur_id) { - var tmp = prev_id; + let tmp = prev_id; prev_id = cur_id; cur_id = tmp; } @@ -362,23 +363,23 @@ if (!DOMTokenList.prototype.remove) { } else { // Making a collapsed element visible on onhashchange seems // too late - var a = findParentElement(ev.target, "A"); + let a = findParentElement(ev.target, "A"); if (a && a.hash) { expandSection(a.hash.replace(/^#/, "")); } } }; - var x = document.getElementsByClassName("version-selector"); + let x = document.getElementsByClassName("version-selector"); if (x.length > 0) { x[0].onchange = function() { - var i, match, + let i, match, url = document.location.href, stripped = "", len = rootPath.match(/\.\.\//g).length + 1; for (i = 0; i < len; ++i) { - match = url.match(/\/[^\/]*$/); + match = url.match(/\/[^/]*$/); if (i < len - 1) { stripped = match[0] + stripped; } @@ -398,14 +399,14 @@ if (!DOMTokenList.prototype.remove) { * This code is an unmodified version of the code written by Marco de Wit * and was found at http://stackoverflow.com/a/18514751/745719 */ - var levenshtein_row2 = []; + let levenshtein_row2 = []; function levenshtein(s1, s2) { if (s1 === s2) { return 0; } - var s1_len = s1.length, s2_len = s2.length; + let s1_len = s1.length, s2_len = s2.length; if (s1_len && s2_len) { - var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2; + let i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2; while (i1 < s1_len) { row[i1] = ++i1; } @@ -427,14 +428,14 @@ if (!DOMTokenList.prototype.remove) { } function initSearch(rawSearchIndex) { - var currentResults, index, searchIndex; - var MAX_LEV_DISTANCE = 3; - var MAX_RESULTS = 200; - var GENERICS_DATA = 1; - var NAME = 0; - var INPUTS_DATA = 0; - var OUTPUT_DATA = 1; - var params = getQueryStringParams(); + let currentResults, index, searchIndex; + let MAX_LEV_DISTANCE = 3; + let MAX_RESULTS = 200; + let GENERICS_DATA = 1; + let NAME = 0; + let INPUTS_DATA = 0; + let OUTPUT_DATA = 1; + let params = getQueryStringParams(); // Populate search bar with query string search term when provided, // but only if the input bar is empty. This avoid the obnoxious issue @@ -454,8 +455,8 @@ if (!DOMTokenList.prototype.remove) { */ function execQuery(query, searchWords, filterCrates) { function itemTypeFromName(typename) { - var length = itemTypes.length; - for (var i = 0; i < length; ++i) { + let length = itemTypes.length; + for (let i = 0; i < length; ++i) { if (itemTypes[i] === typename) { return i; } @@ -463,14 +464,14 @@ if (!DOMTokenList.prototype.remove) { return -1; } - var valLower = query.query.toLowerCase(), + let valLower = query.query.toLowerCase(), val = valLower, typeFilter = itemTypeFromName(query.type), results = {}, results_in_args = {}, results_returned = {}, split = valLower.split("::"); - var length = split.length; - for (var z = 0; z < length; ++z) { + let length = split.length; + for (let z = 0; z < length; ++z) { if (split[z] === "") { split.splice(z, 1); z -= 1; @@ -478,14 +479,14 @@ if (!DOMTokenList.prototype.remove) { } function transformResults(results, isType) { - var out = []; - var length = results.length; - for (var i = 0; i < length; ++i) { + let out = []; + let length = results.length; + for (let i = 0; i < length; ++i) { if (results[i].id > -1) { - var obj = searchIndex[results[i].id]; + let obj = searchIndex[results[i].id]; obj.lev = results[i].lev; if (isType !== true || obj.type) { - var res = buildHrefAndPath(obj); + let res = buildHrefAndPath(obj); obj.displayPath = pathSplitter(res[0]); obj.fullPath = obj.displayPath + obj.name; // To be sure than it some items aren't considered as duplicate. @@ -502,15 +503,15 @@ if (!DOMTokenList.prototype.remove) { } function sortResults(results, isType) { - var ar = []; - for (var entry in results) { + let ar = []; + for (let entry in results) { if (results.hasOwnProperty(entry)) { ar.push(results[entry]); } } results = ar; - var i; - var nresults = results.length; + let i; + let nresults = results.length; for (i = 0; i < nresults; ++i) { results[i].word = searchWords[results[i].id]; results[i].item = searchIndex[results[i].id] || {}; @@ -521,7 +522,7 @@ if (!DOMTokenList.prototype.remove) { } results.sort(function(aaa, bbb) { - var a, b; + let a, b; // Sort by non levenshtein results and then levenshtein results by the distance // (less changes required to match means higher rankings) @@ -587,15 +588,15 @@ if (!DOMTokenList.prototype.remove) { return 0; }); - var length = results.length; + let length = results.length; for (i = 0; i < length; ++i) { - var result = results[i]; + let result = results[i]; // this validation does not make sense when searching by types if (result.dontValidate) { continue; } - var name = result.item.name.toLowerCase(), + let name = result.item.name.toLowerCase(), path = result.item.path.toLowerCase(), parent = result.item.parent; @@ -611,7 +612,7 @@ if (!DOMTokenList.prototype.remove) { function extractGenerics(val) { val = val.toLowerCase(); if (val.indexOf("<") !== -1) { - var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">")); + let values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">")); return { name: val.substring(0, val.indexOf("<")), generics: values.split(/\s*,\s*/), @@ -626,21 +627,19 @@ if (!DOMTokenList.prototype.remove) { function checkGenerics(obj, val) { // The names match, but we need to be sure that all generics kinda // match as well. - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (val.generics.length > 0) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length >= val.generics.length) { - var elems = obj[GENERICS_DATA].slice(0); - var total = 0; - var done = 0; + let elems = obj[GENERICS_DATA].slice(0); // We need to find the type that matches the most to remove it in order // to move forward. - var vlength = val.generics.length; - for (var y = 0; y < vlength; ++y) { - var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; - var elength = elems.length; - for (var x = 0; x < elength; ++x) { - var tmp_lev = levenshtein(elems[x], val.generics[y]); + let vlength = val.generics.length; + for (let y = 0; y < vlength; ++y) { + let lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; + let elength = elems.length; + for (let x = 0; x < elength; ++x) { + let tmp_lev = levenshtein(elems[x], val.generics[y]); if (tmp_lev < lev.lev) { lev.lev = tmp_lev; lev.pos = x; @@ -649,8 +648,6 @@ if (!DOMTokenList.prototype.remove) { if (lev.pos !== -1) { elems.splice(lev.pos, 1); lev_distance = Math.min(lev.lev, lev_distance); - total += lev.lev; - done += 1; } else { return MAX_LEV_DISTANCE + 1; } @@ -663,17 +660,17 @@ if (!DOMTokenList.prototype.remove) { // Check for type name and type generics (if any). function checkType(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; - var x; + let lev_distance = MAX_LEV_DISTANCE + 1; + let x; if (obj[NAME] === val.name) { if (literalSearch === true) { if (val.generics && val.generics.length !== 0) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length >= val.generics.length) { - var elems = obj[GENERICS_DATA].slice(0); - var allFound = true; + let elems = obj[GENERICS_DATA].slice(0); + let allFound = true; - for (var y = 0; allFound === true && y < val.generics.length; ++y) { + for (let y = 0; allFound === true && y < val.generics.length; ++y) { allFound = false; for (x = 0; allFound === false && x < elems.length; ++x) { allFound = elems[x] === val.generics[y]; @@ -694,7 +691,7 @@ if (!DOMTokenList.prototype.remove) { // If the type has generics but don't match, then it won't return at this point. // Otherwise, `checkGenerics` will return 0 and it'll return. if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) { - var tmp_lev = checkGenerics(obj, val); + let tmp_lev = checkGenerics(obj, val); if (tmp_lev <= MAX_LEV_DISTANCE) { return tmp_lev; } @@ -705,7 +702,7 @@ if (!DOMTokenList.prototype.remove) { // Names didn't match so let's check if one of the generic types could. if (literalSearch === true) { if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { - var length = obj[GENERICS_DATA].length; + let length = obj[GENERICS_DATA].length; for (x = 0; x < length; ++x) { if (obj[GENERICS_DATA][x] === val.name) { return true; @@ -719,7 +716,7 @@ if (!DOMTokenList.prototype.remove) { lev_distance = Math.min(checkGenerics(obj, val), lev_distance); } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) { // We can check if the type we're looking for is inside the generics! - var olength = obj[GENERICS_DATA].length; + let olength = obj[GENERICS_DATA].length; for (x = 0; x < olength; ++x) { lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name), lev_distance); @@ -731,13 +728,13 @@ if (!DOMTokenList.prototype.remove) { } function findArg(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) { - var length = obj.type[INPUTS_DATA].length; - for (var i = 0; i < length; i++) { - var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); + let length = obj.type[INPUTS_DATA].length; + for (let i = 0; i < length; i++) { + let tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -751,10 +748,10 @@ if (!DOMTokenList.prototype.remove) { } function checkReturned(obj, val, literalSearch) { - var lev_distance = MAX_LEV_DISTANCE + 1; + let lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type.length > OUTPUT_DATA) { - var tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch); + let tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch); if (literalSearch === true && tmp === true) { return true; } @@ -770,26 +767,26 @@ if (!DOMTokenList.prototype.remove) { if (contains.length === 0) { return 0; } - var ret_lev = MAX_LEV_DISTANCE + 1; - var path = ty.path.split("::"); + let ret_lev = MAX_LEV_DISTANCE + 1; + let path = ty.path.split("::"); if (ty.parent && ty.parent.name) { path.push(ty.parent.name.toLowerCase()); } - var length = path.length; - var clength = contains.length; + let length = path.length; + let clength = contains.length; if (clength > length) { return MAX_LEV_DISTANCE + 1; } - for (var i = 0; i < length; ++i) { + for (let i = 0; i < length; ++i) { if (i + clength > length) { break; } - var lev_total = 0; - var aborted = false; - for (var x = 0; x < clength; ++x) { - var lev = levenshtein(path[i + x], contains[x]); + let lev_total = 0; + let aborted = false; + for (let x = 0; x < clength; ++x) { + let lev = levenshtein(path[i + x], contains[x]); if (lev > MAX_LEV_DISTANCE) { aborted = true; break; @@ -811,7 +808,7 @@ if (!DOMTokenList.prototype.remove) { if (filter === type) return true; // Match related items - var name = itemTypes[type]; + let name = itemTypes[type]; switch (itemTypes[filter]) { case "constant": return (name == "associatedconstant"); @@ -833,12 +830,12 @@ if (!DOMTokenList.prototype.remove) { } // quoted values mean literal search - var nSearchWords = searchWords.length; - var i; - var ty; - var fullId; - var returned; - var in_args; + let nSearchWords = searchWords.length; + let i; + let ty; + let fullId; + let returned; + let in_args; if ((val.charAt(0) === "\"" || val.charAt(0) === "'") && val.charAt(val.length - 1) === val.charAt(0)) { @@ -890,21 +887,21 @@ if (!DOMTokenList.prototype.remove) { query.search = val; // searching by type } else if (val.search("->") > -1) { - var trimmer = function(s) { return s.trim(); }; - var parts = val.split("->").map(trimmer); - var input = parts[0]; + let trimmer = function(s) { return s.trim(); }; + let parts = val.split("->").map(trimmer); + let input = parts[0]; // sort inputs so that order does not matter - var inputs = input.split(",").map(trimmer).sort(); + let inputs = input.split(",").map(trimmer).sort(); for (i = 0; i < inputs.length; ++i) { inputs[i] = extractGenerics(inputs[i]); } - var output = extractGenerics(parts[1]); + let output = extractGenerics(parts[1]); for (i = 0; i < nSearchWords; ++i) { if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) { continue; } - var type = searchIndex[i].type; + let type = searchIndex[i].type; ty = searchIndex[i]; if (!type) { continue; @@ -912,17 +909,16 @@ if (!DOMTokenList.prototype.remove) { fullId = generateId(ty); // allow searching for void (no output) functions as well - var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : ""; returned = checkReturned(ty, output, true); if (output.name === "*" || returned === true) { in_args = false; - var module = false; + let module = false; if (input === "*") { module = true; } else { - var allFound = true; - for (var it = 0; allFound === true && it < inputs.length; it++) { + let allFound = true; + for (let it = 0; allFound === true && it < inputs.length; it++) { allFound = checkType(type, inputs[it], true); } in_args = allFound; @@ -959,12 +955,12 @@ if (!DOMTokenList.prototype.remove) { query.output = val; query.search = val; // gather matching search results up to a certain maximum - val = val.replace(/\_/g, ""); + val = val.replace(/_/g, ""); - var valGenerics = extractGenerics(val); + let valGenerics = extractGenerics(val); - var paths = valLower.split("::"); - var j; + let paths = valLower.split("::"); + let j; for (j = 0; j < paths.length; ++j) { if (paths[j] === "") { paths.splice(j, 1); @@ -972,17 +968,15 @@ if (!DOMTokenList.prototype.remove) { } } val = paths[paths.length - 1]; - var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1); + let contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1); for (j = 0; j < nSearchWords; ++j) { - var lev; - var lev_distance; + let lev; ty = searchIndex[j]; if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) { continue; } - var lev_distance; - var lev_add = 0; + let lev_add = 0; if (paths.length > 1) { lev = checkPath(contains, paths[paths.length - 1], ty); if (lev > MAX_LEV_DISTANCE) { @@ -994,7 +988,7 @@ if (!DOMTokenList.prototype.remove) { returned = MAX_LEV_DISTANCE + 1; in_args = MAX_LEV_DISTANCE + 1; - var index = -1; + let index = -1; // we want lev results to go lower than others lev = MAX_LEV_DISTANCE + 1; fullId = generateId(ty); @@ -1072,19 +1066,19 @@ if (!DOMTokenList.prototype.remove) { } } - var ret = { + let ret = { "in_args": sortResults(results_in_args, true), "returned": sortResults(results_returned, true), "others": sortResults(results), }; if (ALIASES && ALIASES[window.currentCrate] && ALIASES[window.currentCrate][query.raw]) { - var aliases = ALIASES[window.currentCrate][query.raw]; + let aliases = ALIASES[window.currentCrate][query.raw]; for (i = 0; i < aliases.length; ++i) { aliases[i].is_alias = true; aliases[i].alias = query.raw; aliases[i].path = aliases[i].p; - var res = buildHrefAndPath(aliases[i]); + let res = buildHrefAndPath(aliases[i]); aliases[i].displayPath = pathSplitter(res[0]); aliases[i].fullPath = aliases[i].displayPath + aliases[i].name; aliases[i].href = res[1]; @@ -1113,7 +1107,7 @@ if (!DOMTokenList.prototype.remove) { * @return {[boolean]} [Whether the result is valid or not] */ function validateResult(name, path, keys, parent) { - for (var i = 0; i < keys.length; ++i) { + for (let i = 0; i < keys.length; ++i) { // each check is for validation so we negate the conditions and invalidate if (!( // check for an exact name match @@ -1132,7 +1126,7 @@ if (!DOMTokenList.prototype.remove) { } function getQuery(raw) { - var matches, type, query; + let matches, type, query; query = raw; matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i); @@ -1150,15 +1144,15 @@ if (!DOMTokenList.prototype.remove) { } function initSearchNav() { - var hoverTimeout; + let hoverTimeout; - var click_func = function(e) { - var el = e.target; + let click_func = function(e) { + let el = e.target; // to retrieve the real "owner" of the event. while (el.tagName !== "TR") { el = el.parentNode; } - var dst = e.target.getElementsByTagName("a"); + let dst = e.target.getElementsByTagName("a"); if (dst.length < 1) { return; } @@ -1169,8 +1163,8 @@ if (!DOMTokenList.prototype.remove) { document.location.href = dst.href; } }; - var mouseover_func = function(e) { - var el = e.target; + let mouseover_func = function(e) { + let el = e.target; // to retrieve the real "owner" of the event. while (el.tagName !== "TR") { el = el.parentNode; @@ -1195,9 +1189,9 @@ if (!DOMTokenList.prototype.remove) { search_input.onkeydown = function(e) { // "actives" references the currently highlighted item in each search tab. // Each array in "actives" represents a tab. - var actives = [[], [], []]; + let actives = [[], [], []]; // "current" is used to know which tab we're looking into. - var current = 0; + let current = 0; onEachLazy(document.getElementsByClassName("search-results"), function(e) { onEachLazy(e.getElementsByClassName("highlighted"), function(e) { actives[current].push(e); @@ -1215,9 +1209,9 @@ if (!DOMTokenList.prototype.remove) { removeClass(actives[currentTab][0], "highlighted"); } else if (e.which === 40) { // down if (!actives[currentTab].length) { - var results = document.getElementsByClassName("search-results"); + let results = document.getElementsByClassName("search-results"); if (results.length > 0) { - var res = results[currentTab].getElementsByClassName("result"); + let res = results[currentTab].getElementsByClassName("result"); if (res.length > 0) { addClass(res[0], "highlighted"); } @@ -1251,10 +1245,10 @@ if (!DOMTokenList.prototype.remove) { } function buildHrefAndPath(item) { - var displayPath; - var href; - var type = itemTypes[item.ty]; - var name = item.name; + let displayPath; + let href; + let type = itemTypes[item.ty]; + let name = item.name; if (type === "mod") { displayPath = item.path + "::"; @@ -1268,9 +1262,9 @@ if (!DOMTokenList.prototype.remove) { displayPath = ""; href = rootPath + name + "/index.html"; } else if (item.parent !== undefined) { - var myparent = item.parent; - var anchor = "#" + type + "." + name; - var parentType = itemTypes[myparent.ty]; + let myparent = item.parent; + let anchor = "#" + type + "." + name; + let parentType = itemTypes[myparent.ty]; if (parentType === "primitive") { displayPath = myparent.name + "::"; } else { @@ -1289,13 +1283,13 @@ if (!DOMTokenList.prototype.remove) { } function escape(content) { - var h1 = document.createElement("h1"); + let h1 = document.createElement("h1"); h1.textContent = content; return h1.innerHTML; } function pathSplitter(path) { - var tmp = "" + path.replace(/::/g, "::"); + let tmp = "" + path.replace(/::/g, "::"); if (tmp.endsWith("")) { return tmp.slice(0, tmp.length - 6); } @@ -1303,19 +1297,19 @@ if (!DOMTokenList.prototype.remove) { } function addTab(array, query, display) { - var extraStyle = ""; + let extraStyle = ""; if (display === false) { extraStyle = " style=\"display: none;\""; } - var output = ""; - var duplicates = {}; - var length = 0; + let output = ""; + let duplicates = {}; + let length = 0; if (array.length > 0) { output = ""; array.forEach(function(item) { - var name, type; + let name, type; name = item.name; type = itemTypes[item.ty]; @@ -1369,22 +1363,22 @@ if (!DOMTokenList.prototype.remove) { function showResults(results) { if (results.others.length === 1 && getCurrentValue("rustdoc-go-to-only-result") === "true") { - var elem = document.createElement("a"); + let elem = document.createElement("a"); elem.href = results.others[0].href; elem.style.display = "none"; // For firefox, we need the element to be in the DOM so it can be clicked. document.body.appendChild(elem); elem.click(); } - var query = getQuery(search_input.value); + let query = getQuery(search_input.value); currentResults = query.id; - var ret_others = addTab(results.others, query); - var ret_in_args = addTab(results.in_args, query, false); - var ret_returned = addTab(results.returned, query, false); + let ret_others = addTab(results.others, query); + let ret_in_args = addTab(results.in_args, query, false); + let ret_returned = addTab(results.returned, query, false); - var output = "

Results for " + escape(query.query) + + let output = "

Results for " + escape(query.query) + (query.type ? " (type: " + escape(query.type) + ")" : "") + "

" + "
" + makeTabHeader(0, "In Names", ret_others[1]) + @@ -1394,20 +1388,20 @@ if (!DOMTokenList.prototype.remove) { ret_others[0] + ret_in_args[0] + ret_returned[0] + "
"; addClass(main, "hidden"); - var search = document.getElementById("search"); + let search = document.getElementById("search"); removeClass(search, "hidden"); search.innerHTML = output; - var tds = search.getElementsByTagName("td"); - var td_width = 0; + let tds = search.getElementsByTagName("td"); + let td_width = 0; if (tds.length > 0) { td_width = tds[0].offsetWidth; } - var width = search.offsetWidth - 40 - td_width; + let width = search.offsetWidth - 40 - td_width; onEachLazy(search.getElementsByClassName("desc"), function(e) { e.style.width = width + "px"; }); initSearchNav(); - var elems = document.getElementById("titles").childNodes; + let elems = document.getElementById("titles").childNodes; elems[0].onclick = function() { printTab(0); }; elems[1].onclick = function() { printTab(1); }; elems[2].onclick = function() { printTab(2); }; @@ -1416,9 +1410,9 @@ if (!DOMTokenList.prototype.remove) { function execSearch(query, searchWords, filterCrates) { function getSmallest(arrays, positions, notDuplicates) { - var start = null; + let start = null; - for (var it = 0; it < positions.length; ++it) { + for (let it = 0; it < positions.length; ++it) { if (arrays[it].length > positions[it] && (start === null || start > arrays[it][positions[it]].lev) && !notDuplicates[arrays[it][positions[it]].fullPath]) { @@ -1429,15 +1423,15 @@ if (!DOMTokenList.prototype.remove) { } function mergeArrays(arrays) { - var ret = []; - var positions = []; - var notDuplicates = {}; + let ret = []; + let positions = []; + let notDuplicates = {}; - for (var x = 0; x < arrays.length; ++x) { + for (let x = 0; x < arrays.length; ++x) { positions.push(0); } while (ret.length < MAX_RESULTS) { - var smallest = getSmallest(arrays, positions, notDuplicates); + let smallest = getSmallest(arrays, positions, notDuplicates); if (smallest === null) { break; @@ -1455,17 +1449,17 @@ if (!DOMTokenList.prototype.remove) { return ret; } - var queries = query.raw.split(","); - var results = { + let queries = query.raw.split(","); + let results = { "in_args": [], "returned": [], "others": [], }; - for (var i = 0; i < queries.length; ++i) { + for (let i = 0; i < queries.length; ++i) { query = queries[i].trim(); if (query.length !== 0) { - var tmp = execQuery(getQuery(query), searchWords, filterCrates); + let tmp = execQuery(getQuery(query), searchWords, filterCrates); results.in_args.push(tmp.in_args); results.returned.push(tmp.returned); @@ -1488,7 +1482,7 @@ if (!DOMTokenList.prototype.remove) { } function getFilterCrates() { - var elem = document.getElementById("crate-search"); + let elem = document.getElementById("crate-search"); if (elem && elem.value !== "All crates" && rawSearchIndex.hasOwnProperty(elem.value)) { return elem.value; @@ -1497,8 +1491,8 @@ if (!DOMTokenList.prototype.remove) { } function search(e, forced) { - var params = getQueryStringParams(); - var query = getQuery(search_input.value.trim()); + let params = getQueryStringParams(); + let query = getQuery(search_input.value.trim()); if (e) { e.preventDefault(); @@ -1527,16 +1521,16 @@ if (!DOMTokenList.prototype.remove) { } } - var filterCrates = getFilterCrates(); + let filterCrates = getFilterCrates(); showResults(execSearch(query, index, filterCrates), filterCrates); } function buildIndex(rawSearchIndex) { searchIndex = []; - var searchWords = []; - var i; + let searchWords = []; + let i; - for (var crate in rawSearchIndex) { + for (let crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } searchWords.push(crate); @@ -1555,13 +1549,13 @@ if (!DOMTokenList.prototype.remove) { // (String) description, // (Number | null) the parent path index to `paths`] // (Object | null) the type of the function (if any) - var items = rawSearchIndex[crate].items; + let items = rawSearchIndex[crate].items; // an array of [(Number) item type, // (String) name] - var paths = rawSearchIndex[crate].paths; + let paths = rawSearchIndex[crate].paths; // convert `paths` into an object form - var len = paths.length; + let len = paths.length; for (i = 0; i < len; ++i) { paths[i] = {ty: paths[i][0], name: paths[i][1]}; } @@ -1574,15 +1568,15 @@ if (!DOMTokenList.prototype.remove) { // all other search operations have access to this cached data for // faster analysis operations len = items.length; - var lastPath = ""; + let lastPath = ""; for (i = 0; i < len; ++i) { - var rawRow = items[i]; - var row = {crate: crate, ty: rawRow[0], name: rawRow[1], + let rawRow = items[i]; + let row = {crate: crate, ty: rawRow[0], name: rawRow[1], path: rawRow[2] || lastPath, desc: rawRow[3], parent: paths[rawRow[4]], type: rawRow[5]}; searchIndex.push(row); if (typeof row.name === "string") { - var word = row.name.toLowerCase(); + let word = row.name.toLowerCase(); searchWords.push(word); } else { searchWords.push(""); @@ -1594,8 +1588,8 @@ if (!DOMTokenList.prototype.remove) { } function startSearch() { - var searchTimeout; - var callback = function() { + let searchTimeout; + let callback = function() { clearTimeout(searchTimeout); if (search_input.value.length === 0) { if (browserSupportsHistoryApi()) { @@ -1604,7 +1598,7 @@ if (!DOMTokenList.prototype.remove) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + let search_c = document.getElementById("search"); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -1619,7 +1613,7 @@ if (!DOMTokenList.prototype.remove) { clearTimeout(searchTimeout); search(); }; - search_input.onchange = function(e) { + search_input.onchange = function() { // Do NOT e.preventDefault() here. It will prevent pasting. clearTimeout(searchTimeout); // zero-timeout necessary here because at the time of event handler execution the @@ -1629,7 +1623,7 @@ if (!DOMTokenList.prototype.remove) { }; search_input.onpaste = search_input.onchange; - var selectCrate = document.getElementById('crate-search'); + let selectCrate = document.getElementById('crate-search'); if (selectCrate) { selectCrate.onchange = function() { search(undefined, true); @@ -1640,17 +1634,17 @@ if (!DOMTokenList.prototype.remove) { // history. if (browserSupportsHistoryApi()) { // Store the previous so we can revert back to it later. - var previousTitle = document.title; + let previousTitle = document.title; - window.onpopstate = function(e) { - var params = getQueryStringParams(); + window.onpopstate = function() { + let params = getQueryStringParams(); // When browsing back from search results the main page // visibility must be reset. if (!params.search) { if (hasClass(main, "content")) { removeClass(main, "hidden"); } - var search_c = document.getElementById("search"); + let search_c = document.getElementById("search"); if (hasClass(search_c, "content")) { addClass(search_c, "hidden"); } @@ -1687,34 +1681,34 @@ if (!DOMTokenList.prototype.remove) { // Draw a convenient sidebar of known crates if we have a listing if (rootPath === "../" || rootPath === "./") { - var sidebar = document.getElementsByClassName("sidebar-elems")[0]; + let sidebar = document.getElementsByClassName("sidebar-elems")[0]; if (sidebar) { - var div = document.createElement("div"); + let div = document.createElement("div"); div.className = "block crate"; div.innerHTML = "<h3>Crates</h3>"; - var ul = document.createElement("ul"); + let ul = document.createElement("ul"); div.appendChild(ul); - var crates = []; - for (var crate in rawSearchIndex) { + let crates = []; + for (let crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } crates.push(crate); } crates.sort(); - for (var i = 0; i < crates.length; ++i) { - var klass = "crate"; + for (let i = 0; i < crates.length; ++i) { + let klass = "crate"; if (rootPath !== "./" && crates[i] === window.currentCrate) { klass += " current"; } - var link = document.createElement("a"); + let link = document.createElement("a"); link.href = rootPath + crates[i] + "/index.html"; link.title = rawSearchIndex[crates[i]].doc; link.className = klass; link.textContent = crates[i]; - var li = document.createElement("li"); + let li = document.createElement("li"); li.appendChild(link); ul.appendChild(li); } @@ -1727,44 +1721,44 @@ if (!DOMTokenList.prototype.remove) { // delayed sidebar rendering. function initSidebarItems(items) { - var sidebar = document.getElementsByClassName("sidebar-elems")[0]; - var current = window.sidebarCurrent; + let sidebar = document.getElementsByClassName("sidebar-elems")[0]; + let current = window.sidebarCurrent; function block(shortty, longty) { - var filtered = items[shortty]; + let filtered = items[shortty]; if (!filtered) { return; } - var div = document.createElement("div"); + let div = document.createElement("div"); div.className = "block " + shortty; - var h3 = document.createElement("h3"); + let h3 = document.createElement("h3"); h3.textContent = longty; div.appendChild(h3); - var ul = document.createElement("ul"); + let ul = document.createElement("ul"); - var length = filtered.length; - for (var i = 0; i < length; ++i) { - var item = filtered[i]; - var name = item[0]; - var desc = item[1]; // can be null + let length = filtered.length; + for (let i = 0; i < length; ++i) { + let item = filtered[i]; + let name = item[0]; + let desc = item[1]; // can be null - var klass = shortty; + let klass = shortty; if (name === current.name && shortty === current.ty) { klass += " current"; } - var path; + let path; if (shortty === "mod") { path = name + "/index.html"; } else { path = shortty + "." + name + ".html"; } - var link = document.createElement("a"); + let link = document.createElement("a"); link.href = current.relpath + path; link.title = desc; link.className = klass; link.textContent = name; - var li = document.createElement("li"); + let li = document.createElement("li"); li.appendChild(link); ul.appendChild(li); } @@ -1792,25 +1786,25 @@ if (!DOMTokenList.prototype.remove) { window.initSidebarItems = initSidebarItems; window.register_implementors = function(imp) { - var implementors = document.getElementById("implementors-list"); - var synthetic_implementors = document.getElementById("synthetic-implementors-list"); + let implementors = document.getElementById("implementors-list"); + let synthetic_implementors = document.getElementById("synthetic-implementors-list"); - var libs = Object.getOwnPropertyNames(imp); - var llength = libs.length; - for (var i = 0; i < llength; ++i) { + let libs = Object.getOwnPropertyNames(imp); + let llength = libs.length; + for (let i = 0; i < llength; ++i) { if (libs[i] === currentCrate) { continue; } - var structs = imp[libs[i]]; + let structs = imp[libs[i]]; - var slength = structs.length; + let slength = structs.length; struct_loop: - for (var j = 0; j < slength; ++j) { - var struct = structs[j]; + for (let j = 0; j < slength; ++j) { + let struct = structs[j]; - var list = struct.synthetic ? synthetic_implementors : implementors; + let list = struct.synthetic ? synthetic_implementors : implementors; if (struct.synthetic) { - var stlength = struct.types.length; - for (var k = 0; k < stlength; k++) { + let stlength = struct.types.length; + for (let k = 0; k < stlength; k++) { if (window.inlined_types.has(struct.types[k])) { continue struct_loop; } @@ -1818,18 +1812,18 @@ if (!DOMTokenList.prototype.remove) { } } - var code = document.createElement("code"); + let code = document.createElement("code"); code.innerHTML = struct.text; - var x = code.getElementsByTagName("a"); - var xlength = x.length; - for (var it = 0; it < xlength; it++) { - var href = x[it].getAttribute("href"); + let x = code.getElementsByTagName("a"); + let xlength = x.length; + for (let it = 0; it < xlength; it++) { + let href = x[it].getAttribute("href"); if (href && href.indexOf("http") !== 0) { x[it].setAttribute("href", rootPath + href); } } - var display = document.createElement("h3"); + let display = document.createElement("h3"); addClass(display, "impl"); display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" + "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" + @@ -1854,9 +1848,9 @@ if (!DOMTokenList.prototype.remove) { function onEveryMatchingChild(elem, className, func) { if (elem && className && func) { - var length = elem.childNodes.length; - var nodes = elem.childNodes; - for (var i = 0; i < length; ++i) { + let length = elem.childNodes.length; + let nodes = elem.childNodes; + for (let i = 0; i < length; ++i) { if (hasClass(nodes[i], className)) { func(nodes[i]); } else { @@ -1867,7 +1861,7 @@ if (!DOMTokenList.prototype.remove) { } function toggleAllDocs(pageId, fromAutoCollapse) { - var innerToggle = document.getElementById("toggle-all-docs"); + let innerToggle = document.getElementById("toggle-all-docs"); if (!innerToggle) { return; } @@ -1920,7 +1914,7 @@ if (!DOMTokenList.prototype.remove) { function implHider(addOrRemove) { return function(n) { - var is_method = hasClass(n, "method"); + let is_method = hasClass(n, "method"); if (is_method || hasClass(n, "type")) { if (is_method === true) { if (addOrRemove) { @@ -1929,7 +1923,7 @@ if (!DOMTokenList.prototype.remove) { removeClass(n, "hidden-by-impl-hider"); } } - var ns = n.nextElementSibling; + let ns = n.nextElementSibling; while (true) { if (ns && ( hasClass(ns, "docblock") || @@ -1948,8 +1942,8 @@ if (!DOMTokenList.prototype.remove) { }; } - var relatedDoc; - var action = mode; + let relatedDoc; + let action = mode; if (hasClass(toggle.parentNode, "impl") === false) { relatedDoc = toggle.parentNode.nextElementSibling; if (hasClass(relatedDoc, "stability")) { @@ -1976,9 +1970,9 @@ if (!DOMTokenList.prototype.remove) { } else { // we are collapsing the impl block - var parentElem = toggle.parentNode; + let parentElem = toggle.parentNode; relatedDoc = parentElem; - var docblock = relatedDoc.nextElementSibling; + let docblock = relatedDoc.nextElementSibling; while (hasClass(relatedDoc, "impl-items") === false) { relatedDoc = relatedDoc.nextElementSibling; @@ -2017,7 +2011,7 @@ if (!DOMTokenList.prototype.remove) { function collapser(e, collapse) { // inherent impl ids are like "impl" or impl-<number>'. // they will never be hidden by default. - var n = e.parentElement; + let n = e.parentElement; if (n.id.match(/^impl(?:-\d+)?$/) === null) { // Automatically minimize all non-inherent impls if (collapse || hasClass(n, "impl")) { @@ -2030,7 +2024,7 @@ if (!DOMTokenList.prototype.remove) { if (collapse) { toggleAllDocs(pageId, true); } else if (getCurrentValue("rustdoc-trait-implementations") !== "false") { - var impl_list = document.getElementById("implementations-list"); + let impl_list = document.getElementById("implementations-list"); if (impl_list !== null) { onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) { @@ -2040,7 +2034,7 @@ if (!DOMTokenList.prototype.remove) { } } - var toggles = document.getElementById("toggle-all-docs"); + let toggles = document.getElementById("toggle-all-docs"); if (toggles) { toggles.onclick = toggleAllDocs; } @@ -2050,7 +2044,7 @@ if (!DOMTokenList.prototype.remove) { } function createSimpleToggle(sectionIsCollapsed) { - var toggle = document.createElement("a"); + let toggle = document.createElement("a"); toggle.href = "javascript:void(0)"; toggle.className = "collapse-toggle"; toggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(sectionIsCollapsed) + @@ -2058,10 +2052,10 @@ if (!DOMTokenList.prototype.remove) { return toggle; } - var toggle = createSimpleToggle(false); + let toggle = createSimpleToggle(false); - var func = function(e) { - var next = e.nextElementSibling; + let func = function(e) { + let next = e.nextElementSibling; if (!next) { return; } @@ -2072,8 +2066,8 @@ if (!DOMTokenList.prototype.remove) { } }; - var funcImpl = function(e) { - var next = e.nextElementSibling; + let funcImpl = function(e) { + let next = e.nextElementSibling; if (next && hasClass(next, "docblock")) { next = next.nextElementSibling; } @@ -2088,7 +2082,7 @@ if (!DOMTokenList.prototype.remove) { onEachLazy(document.getElementsByClassName("method"), func); onEachLazy(document.getElementsByClassName("associatedconstant"), func); onEachLazy(document.getElementsByClassName("impl"), funcImpl); - var impl_call = function() {}; + let impl_call = function() {}; if (getCurrentValue("rustdoc-method-docs") !== "false") { impl_call = function(e, newToggle, pageId) { if (e.id.match(/^impl(?:-\d+)?$/) === null) { @@ -2099,8 +2093,8 @@ if (!DOMTokenList.prototype.remove) { } }; } - var pageId = getPageId(); - var newToggle = document.createElement("a"); + let pageId = getPageId(); + let newToggle = document.createElement("a"); newToggle.href = "javascript:void(0)"; newToggle.className = "collapse-toggle hidden-default collapsed"; newToggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) + @@ -2130,11 +2124,11 @@ if (!DOMTokenList.prototype.remove) { } onEachLazy(document.getElementsByClassName("impl-items"), function(e) { onEachLazy(e.getElementsByClassName("associatedconstant"), func); - var hiddenElems = e.getElementsByClassName("hidden"); - var needToggle = false; + let hiddenElems = e.getElementsByClassName("hidden"); + let needToggle = false; - var hlength = hiddenElems.length; - for (var i = 0; i < hlength; ++i) { + let hlength = hiddenElems.length; + for (let i = 0; i < hlength; ++i) { if (hasClass(hiddenElems[i], "content") === false && hasClass(hiddenElems[i], "docblock") === false) { needToggle = true; @@ -2142,7 +2136,7 @@ if (!DOMTokenList.prototype.remove) { } } if (needToggle === true) { - var inner_toggle = newToggle.cloneNode(true); + let inner_toggle = newToggle.cloneNode(true); inner_toggle.onclick = toggleClicked; e.insertBefore(inner_toggle, e.firstChild); impl_call(e, inner_toggle, pageId); @@ -2150,7 +2144,7 @@ if (!DOMTokenList.prototype.remove) { }); function createToggle(otherMessage, fontSize, extraClass, show) { - var span = document.createElement("span"); + let span = document.createElement("span"); span.className = "toggle-label"; if (show) { span.style.display = "none"; @@ -2165,14 +2159,14 @@ if (!DOMTokenList.prototype.remove) { span.style.fontSize = fontSize; } - var mainToggle = toggle.cloneNode(true); + let mainToggle = toggle.cloneNode(true); mainToggle.appendChild(span); - var wrapper = document.createElement("div"); + let wrapper = document.createElement("div"); wrapper.className = "toggle-wrapper"; if (!show) { addClass(wrapper, "collapsed"); - var inner = mainToggle.getElementsByClassName("inner"); + let inner = mainToggle.getElementsByClassName("inner"); if (inner && inner.length > 0) { inner[0].innerHTML = "+"; } @@ -2184,31 +2178,12 @@ if (!DOMTokenList.prototype.remove) { return wrapper; } - var showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; + let showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; function buildToggleWrapper(e) { - if (hasClass(e, "autohide")) { - var wrap = e.previousElementSibling; - if (wrap && hasClass(wrap, "toggle-wrapper")) { - var inner_toggle = wrap.childNodes[0]; - var extra = e.childNodes[0].tagName === "H3"; - - e.style.display = "none"; - addClass(wrap, "collapsed"); - onEachLazy(inner_toggle.getElementsByClassName("inner"), function(e) { - e.innerHTML = labelForToggleButton(true); - }); - onEachLazy(inner_toggle.getElementsByClassName("toggle-label"), function(e) { - e.style.display = "inline-block"; - if (extra === true) { - i_e.innerHTML = " Show " + e.childNodes[0].innerHTML; - } - }); - } - } if (e.parentNode.id === "main") { - var otherMessage = ""; - var fontSize; - var extraClass; + let otherMessage = ""; + let fontSize; + let extraClass; if (hasClass(e, "type-decl")) { fontSize = "20px"; @@ -2252,7 +2227,7 @@ if (!DOMTokenList.prototype.remove) { if (nb === 0 || nb === 1 || nb === 2) { currentTab = nb; } - var nb_copy = nb; + let nb_copy = nb; onEachLazy(document.getElementById("titles").childNodes, function(elem) { if (nb_copy === 0) { addClass(elem, "selected"); @@ -2272,41 +2247,41 @@ if (!DOMTokenList.prototype.remove) { } function createToggleWrapper(tog) { - var span = document.createElement("span"); + let span = document.createElement("span"); span.className = "toggle-label"; span.style.display = "none"; span.innerHTML = " Expand attributes"; tog.appendChild(span); - var wrapper = document.createElement("div"); + let wrapper = document.createElement("div"); wrapper.className = "toggle-wrapper toggle-attributes"; wrapper.appendChild(tog); return wrapper; } // To avoid checking on "rustdoc-item-attributes" value on every loop... - var itemAttributesFunc = function() {}; + let itemAttributesFunc = function() {}; if (getCurrentValue("rustdoc-item-attributes") !== "false") { itemAttributesFunc = function(x) { collapseDocs(x.previousSibling.childNodes[0], "toggle"); }; } - var attributesToggle = createToggleWrapper(createSimpleToggle(false)); + let attributesToggle = createToggleWrapper(createSimpleToggle(false)); onEachLazy(main.getElementsByClassName("attributes"), function(i_e) { i_e.parentNode.insertBefore(attributesToggle.cloneNode(true), i_e); itemAttributesFunc(i_e); }); // To avoid checking on "rustdoc-line-numbers" value on every loop... - var lineNumbersFunc = function() {}; + let lineNumbersFunc = function() {}; if (getCurrentValue("rustdoc-line-numbers") === "true") { lineNumbersFunc = function(x) { - var count = x.textContent.split("\n").length; - var elems = []; - for (var i = 0; i < count; ++i) { + let count = x.textContent.split("\n").length; + let elems = []; + for (let i = 0; i < count; ++i) { elems.push(i + 1); } - var node = document.createElement("pre"); + let node = document.createElement("pre"); addClass(node, "line-number"); node.innerHTML = elems.join("\n"); x.parentNode.insertBefore(node, x); @@ -2314,17 +2289,17 @@ if (!DOMTokenList.prototype.remove) { } onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) { if (hasClass(e, "compile_fail")) { - e.addEventListener("mouseover", function(event) { + e.addEventListener("mouseover", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00"; }); - e.addEventListener("mouseout", function(event) { + e.addEventListener("mouseout", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = ""; }); } else if (hasClass(e, "ignore")) { - e.addEventListener("mouseover", function(event) { + e.addEventListener("mouseover", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200"; }); - e.addEventListener("mouseout", function(event) { + e.addEventListener("mouseout", function() { this.parentElement.previousElementSibling.childNodes[0].style.color = ""; }); } @@ -2332,7 +2307,7 @@ if (!DOMTokenList.prototype.remove) { }); function showModal(content) { - var modal = document.createElement("div"); + let modal = document.createElement("div"); modal.id = "important"; addClass(modal, "modal"); modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" + @@ -2344,7 +2319,7 @@ if (!DOMTokenList.prototype.remove) { } function hideModal() { - var modal = document.getElementById("important"); + let modal = document.getElementById("important"); if (modal) { modal.parentNode.removeChild(modal); } @@ -2374,18 +2349,18 @@ if (!DOMTokenList.prototype.remove) { }; } - var params = getQueryStringParams(); + let params = getQueryStringParams(); if (params && params.search) { addClass(main, "hidden"); - var search = document.getElementById("search"); + let search = document.getElementById("search"); removeClass(search, "hidden"); search.innerHTML = "<h3 style=\"text-align: center;\">Loading search results...</h3>"; } - var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; + let sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; if (sidebar_menu) { sidebar_menu.onclick = function() { - var sidebar = document.getElementsByClassName("sidebar")[0]; + let sidebar = document.getElementsByClassName("sidebar")[0]; if (hasClass(sidebar, "mobile") === true) { hideSidebar(); } else { @@ -2416,22 +2391,22 @@ if (!DOMTokenList.prototype.remove) { } function addSearchOptions(crates) { - var elem = document.getElementById('crate-search'); + let elem = document.getElementById('crate-search'); if (!elem) { return; } - var crates_text = []; + let crates_text = []; if (crates.length > 1) { - for (var crate in crates) { + for (let crate in crates) { if (crates.hasOwnProperty(crate)) { crates_text.push(crate); } } } crates_text.sort(function(a, b) { - var lower_a = a.toLowerCase(); - var lower_b = b.toLowerCase(); + let lower_a = a.toLowerCase(); + let lower_b = b.toLowerCase(); if (lower_a < lower_b) { return -1; @@ -2440,8 +2415,8 @@ if (!DOMTokenList.prototype.remove) { } return 0; }); - for (var i = 0; i < crates_text.length; ++i) { - var option = document.createElement("option"); + for (let i = 0; i < crates_text.length; ++i) { + let option = document.createElement("option"); option.value = crates_text[i]; option.innerText = crates_text[i]; elem.appendChild(option); diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js index c21db7371f3c3..e985c4f8ba24a 100644 --- a/src/librustdoc/html/static/settings.js +++ b/src/librustdoc/html/static/settings.js @@ -1,3 +1,6 @@ +// Local js definitions: +/* global getCurrentValue, updateLocalStorage */ + (function () { function changeSetting(settingName, isEnabled) { updateLocalStorage('rustdoc-' + settingName, isEnabled); @@ -8,14 +11,14 @@ } function setEvents() { - var elems = document.getElementsByClassName("slider"); + let elems = document.getElementsByClassName("slider"); if (!elems || elems.length === 0) { return; } - for (var i = 0; i < elems.length; ++i) { - var toggle = elems[i].previousElementSibling; - var settingId = toggle.id; - var settingValue = getSettingValue(settingId); + for (let i = 0; i < elems.length; ++i) { + let toggle = elems[i].previousElementSibling; + let settingId = toggle.id; + let settingValue = getSettingValue(settingId); if (settingValue !== null) { toggle.checked = settingValue === "true"; } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 0affe1c6812f5..2780cadb7a6d8 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -1,19 +1,22 @@ // From rust: /* global sourcesIndex */ +// From DOM global ids: +/* global search */ + // Local js definitions: /* global addClass, getCurrentValue, hasClass, removeClass, updateLocalStorage */ function getCurrentFilePath() { - var parts = window.location.pathname.split("/"); - var rootPathParts = window.rootPath.split("/"); + let parts = window.location.pathname.split("/"); + let rootPathParts = window.rootPath.split("/"); - for (var i = 0; i < rootPathParts.length; ++i) { + for (let i = 0; i < rootPathParts.length; ++i) { if (rootPathParts[i] === "..") { parts.pop(); } } - var file = window.location.pathname.substring(parts.join("/").length); + let file = window.location.pathname.substring(parts.join("/").length); if (file.startsWith("/")) { file = file.substring(1); } @@ -21,7 +24,7 @@ function getCurrentFilePath() { } function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { - var name = document.createElement("div"); + let name = document.createElement("div"); name.className = "name"; fullPath += elem["name"] + "/"; @@ -35,11 +38,11 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { }; name.innerText = elem["name"]; - var children = document.createElement("div"); + let children = document.createElement("div"); children.className = "children"; - var folders = document.createElement("div"); + let folders = document.createElement("div"); folders.className = "folders"; - for (var i = 0; i < elem.dirs.length; ++i) { + for (let i = 0; i < elem.dirs.length; ++i) { if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile, hasFoundFile) === true) { addClass(name, "expand"); @@ -48,10 +51,10 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { } children.appendChild(folders); - var files = document.createElement("div"); + let files = document.createElement("div"); files.className = "files"; - for (i = 0; i < elem.files.length; ++i) { - var file = document.createElement("a"); + for (let i = 0; i < elem.files.length; ++i) { + let file = document.createElement("a"); file.innerText = elem.files[i]; file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html"; if (hasFoundFile === false && @@ -70,8 +73,8 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { } function toggleSidebar() { - var sidebar = document.getElementById("source-sidebar"); - var child = this.children[0].children[0]; + let sidebar = document.getElementById("source-sidebar"); + let child = this.children[0].children[0]; if (child.innerText === ">") { sidebar.style.left = ""; this.style.left = ""; @@ -86,14 +89,14 @@ function toggleSidebar() { } function createSidebarToggle() { - var sidebarToggle = document.createElement("div"); + let sidebarToggle = document.createElement("div"); sidebarToggle.id = "sidebar-toggle"; sidebarToggle.onclick = toggleSidebar; - var inner1 = document.createElement("div"); + let inner1 = document.createElement("div"); inner1.style.position = "relative"; - var inner2 = document.createElement("div"); + let inner2 = document.createElement("div"); inner2.style.marginTop = "-2px"; if (getCurrentValue("rustdoc-source-sidebar-show") === "true") { inner2.innerText = "<"; @@ -111,21 +114,21 @@ function createSourceSidebar() { if (window.rootPath.endsWith("/") === false) { window.rootPath += "/"; } - var main = document.getElementById("main"); + let main = document.getElementById("main"); - var sidebarToggle = createSidebarToggle(); + let sidebarToggle = createSidebarToggle(); main.insertBefore(sidebarToggle, main.firstChild); - var sidebar = document.createElement("div"); + let sidebar = document.createElement("div"); sidebar.id = "source-sidebar"; if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") { sidebar.style.left = "-300px"; } - var currentFile = getCurrentFilePath(); - var hasFoundFile = false; + let currentFile = getCurrentFilePath(); + let hasFoundFile = false; - var title = document.createElement("div"); + let title = document.createElement("div"); title.className = "title"; title.innerText = "Files"; sidebar.appendChild(title); diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index d5dea247d28d1..00741619d2dd7 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -1,6 +1,9 @@ // From rust: /* global resourcesSuffix */ +// eslint doesn't understand the functions here are used elsewhere +/* eslint no-unused-vars: "off" */ + var currentTheme = document.getElementById("themeStyle"); var mainTheme = document.getElementById("mainThemeStyle"); @@ -30,15 +33,15 @@ function isHidden(elem) { function onEach(arr, func, reversed) { if (arr && arr.length > 0 && func) { - var length = arr.length; + let length = arr.length; if (reversed !== true) { - for (var i = 0; i < length; ++i) { + for (let i = 0; i < length; ++i) { if (func(arr[i]) === true) { return true; } } } else { - for (var i = length - 1; i >= 0; --i) { + for (let i = length - 1; i >= 0; --i) { if (func(arr[i]) === true) { return true; } @@ -89,15 +92,15 @@ function getCurrentValue(name) { } function switchTheme(styleElem, mainStyleElem, newTheme) { - var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; - var fullNewTheme = newTheme + resourcesSuffix + ".css"; - var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); + let fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; + let fullNewTheme = newTheme + resourcesSuffix + ".css"; + let newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme); if (styleElem.href === newHref) { return; } - var found = false; + let found = false; if (savedHref.length === 0) { onEachLazy(document.getElementsByTagName("link"), function(el) { savedHref.push(el.href); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index b8ec7e4bd32ab..fdc1c0616187a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -632,7 +632,7 @@ fn handle_variant(cx: &DocContext, def: Def) -> Result<(Def, Option<String>), () }; let parent_def = Def::Enum(parent); let variant = cx.tcx.expect_variant_def(def); - Ok((parent_def, Some(format!("{}.v", variant.name)))) + Ok((parent_def, Some(format!("{}.v", variant.ident.name)))) } const PRIMITIVES: &[(&str, Def)] = &[ diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4d870daac4d03..24bb00f411242 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -811,7 +811,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.node { self.map.node_to_pretty_string(ty.id) } else { - item.name.to_string() + item.ident.to_string() }; self.visit_testable(name, &item.attrs, |this| { @@ -832,7 +832,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { } fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem) { - self.visit_testable(item.name.to_string(), &item.attrs, |this| { + self.visit_testable(item.ident.to_string(), &item.attrs, |this| { intravisit::walk_foreign_item(this, item); }); } @@ -841,7 +841,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { v: &'hir hir::Variant, g: &'hir hir::Generics, item_id: ast::NodeId) { - self.visit_testable(v.node.name.to_string(), &v.node.attrs, |this| { + self.visit_testable(v.node.ident.to_string(), &v.node.attrs, |this| { intravisit::walk_variant(this, v, g, item_id); }); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ffdc048a30ece..953ab7c2565bf 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { Enum { name, variants: def.variants.iter().map(|v| Variant { - name: v.node.name, + name: v.node.ident.name, attrs: v.node.attrs.clone(), stab: self.stability(v.node.data.id()), depr: self.deprecation(v.node.data.id()), @@ -263,7 +263,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { fn maybe_inline_local(&mut self, id: ast::NodeId, def: Def, - renamed: Option<ast::Name>, + renamed: Option<ast::Ident>, glob: bool, om: &mut Module, please_inline: bool) -> bool { @@ -357,14 +357,14 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { om.foreigns.push(hir::ForeignMod { abi: tcx.hir().get_foreign_abi(it.id), items: vec![hir::ForeignItem { - name: renamed.unwrap_or(it.name), + ident: renamed.unwrap_or(it.ident), .. it.clone() }].into(), }); true } Node::MacroDef(def) if !glob => { - om.macros.push(self.visit_local_macro(def, renamed)); + om.macros.push(self.visit_local_macro(def, renamed.map(|i| i.name))); true } _ => false, @@ -374,9 +374,9 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { } pub fn visit_item(&mut self, item: &hir::Item, - renamed: Option<ast::Name>, om: &mut Module) { + renamed: Option<ast::Ident>, om: &mut Module) { debug!("Visiting item {:?}", item); - let name = renamed.unwrap_or(item.name); + let ident = renamed.unwrap_or(item.ident); if item.vis.node.is_pub() { let def_id = self.cx.tcx.hir().local_def_id(item.id); @@ -403,7 +403,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { om.extern_crates.push(ExternCrate { cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id) .unwrap_or(LOCAL_CRATE), - name, + name: ident.name, path: orig_name.map(|x|x.to_string()), vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -433,10 +433,10 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { _ => false, } }); - let name = if is_glob { None } else { Some(name) }; + let ident = if is_glob { None } else { Some(ident) }; if self.maybe_inline_local(item.id, path.def, - name, + ident, is_glob, om, please_inline) { @@ -445,7 +445,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { } om.imports.push(Import { - name, + name: ident.name, id: item.id, vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -460,21 +460,21 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { item.vis.clone(), item.id, m, - Some(name))); + Some(ident.name))); }, hir::ItemKind::Enum(ref ed, ref gen) => - om.enums.push(self.visit_enum_def(item, name, ed, gen)), + om.enums.push(self.visit_enum_def(item, ident.name, ed, gen)), hir::ItemKind::Struct(ref sd, ref gen) => - om.structs.push(self.visit_variant_data(item, name, sd, gen)), + om.structs.push(self.visit_variant_data(item, ident.name, sd, gen)), hir::ItemKind::Union(ref sd, ref gen) => - om.unions.push(self.visit_union_data(item, name, sd, gen)), + om.unions.push(self.visit_union_data(item, ident.name, sd, gen)), hir::ItemKind::Fn(ref fd, header, ref gen, body) => - self.visit_fn(om, item, name, &**fd, header, gen, body), + self.visit_fn(om, item, ident.name, &**fd, header, gen, body), hir::ItemKind::Ty(ref ty, ref gen) => { let t = Typedef { ty: ty.clone(), gen: gen.clone(), - name, + name: ident.name, id: item.id, attrs: item.attrs.clone(), whence: item.span, @@ -487,7 +487,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { hir::ItemKind::Existential(ref exist_ty) => { let t = Existential { exist_ty: exist_ty.clone(), - name, + name: ident.name, id: item.id, attrs: item.attrs.clone(), whence: item.span, @@ -503,7 +503,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { mutability: mut_.clone(), expr: exp.clone(), id: item.id, - name, + name: ident.name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -517,7 +517,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { type_: ty.clone(), expr: exp.clone(), id: item.id, - name, + name: ident.name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -533,7 +533,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { let t = Trait { is_auto, unsafety, - name, + name: ident.name, items, generics: gen.clone(), bounds: b.iter().cloned().collect(), diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5214f365a6476..92876f7f2d804 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -37,7 +37,7 @@ rustc_lsan = { path = "../librustc_lsan" } rustc_msan = { path = "../librustc_msan" } rustc_tsan = { path = "../librustc_tsan" } -[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))'.dependencies] +[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index aa4278a879981..d42e39f16e663 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -248,7 +248,6 @@ #![feature(const_cstr_unchecked)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] -#![cfg_attr(stage0, feature(duration_as_u128))] #![feature(exact_size_is_empty)] #![feature(external_doc)] #![feature(fixed_size_array)] @@ -303,9 +302,9 @@ #![feature(non_exhaustive)] #![feature(alloc_layout_extra)] #![feature(maybe_uninit)] -#![cfg_attr(target_env = "sgx", feature(global_asm, range_contains, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform, - min_const_unsafe_fn))] +#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), + feature(global_asm, range_contains, slice_index_methods, + decl_macro, coerce_unsized, sgx_platform))] #![default_lib_allocator] @@ -348,7 +347,7 @@ extern crate backtrace_sys; // testing gives test-std access to real-std lang items and globals. See #2912 #[cfg(test)] extern crate std as realstd; -#[cfg(target_env = "sgx")] +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] #[macro_use] #[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot // determine resolution for the macro `usercalls_asm`” diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 27e720533b2c9..7755d9339e6f5 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -302,7 +302,7 @@ mod prim_never { } /// ```text /// error: character literal may only contain one codepoint: 'é' /// let c = 'é'; -/// ^^^^ +/// ^^^ /// ``` /// /// Another implication of the 4-byte fixed size of a `char` is that diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index ecdf7e5668cd2..446c164965d6f 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1311,12 +1311,13 @@ impl<T> Receiver<T> { // Do an optimistic try_recv to avoid the performance impact of // Instant::now() in the full-channel case. match self.try_recv() { - Ok(result) - => Ok(result), - Err(TryRecvError::Disconnected) - => Err(RecvTimeoutError::Disconnected), - Err(TryRecvError::Empty) - => self.recv_deadline(Instant::now() + timeout) + Ok(result) => Ok(result), + Err(TryRecvError::Disconnected) => Err(RecvTimeoutError::Disconnected), + Err(TryRecvError::Empty) => match Instant::now().checked_add(timeout) { + Some(deadline) => self.recv_deadline(deadline), + // So far in the future that it's practically the same as waiting indefinitely. + None => self.recv().map_err(RecvTimeoutError::from), + }, } } @@ -2301,6 +2302,17 @@ mod tests { assert_eq!(recv_count, stress); } + #[test] + fn very_long_recv_timeout_wont_panic() { + let (tx, rx) = channel::<()>(); + let join_handle = thread::spawn(move || { + rx.recv_timeout(Duration::from_secs(u64::max_value())) + }); + thread::sleep(Duration::from_secs(1)); + assert!(tx.send(()).is_ok()); + assert_eq!(join_handle.join().unwrap(), Ok(())); + } + #[test] fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index de9e09bf7057e..f398a2a6225ce 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -38,7 +38,7 @@ cfg_if! { } else if #[cfg(target_arch = "wasm32")] { mod wasm; pub use self::wasm::*; - } else if #[cfg(target_env = "sgx")] { + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use self::sgx::*; } else { @@ -55,7 +55,9 @@ cfg_if! { if #[cfg(any(unix, target_os = "redox"))] { // On unix we'll document what's already available pub use self::ext as unix_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(any(target_os = "cloudabi", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] { // On CloudABI and wasm right now the module below doesn't compile // (missing things in `libc` which is empty) so just omit everything // with an empty module @@ -76,7 +78,9 @@ cfg_if! { // On windows we'll just be documenting what's already available #[allow(missing_docs)] pub use self::ext as windows_ext; - } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(any(target_os = "cloudabi", + target_arch = "wasm32", + all(target_vendor = "fortanix", target_env = "sgx")))] { // On CloudABI and wasm right now the shim below doesn't compile, so // just omit it #[unstable(issue = "0", feature = "std_internals")] diff --git a/src/libstd/sys/sgx/ext/arch.rs b/src/libstd/sys/sgx/ext/arch.rs index 377210f5d699c..ba6f9e622ad35 100644 --- a/src/libstd/sys/sgx/ext/arch.rs +++ b/src/libstd/sys/sgx/ext/arch.rs @@ -1,13 +1,3 @@ -// 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. - //! SGX-specific access to architectural features. //! //! The functionality in this module is further documented in the Intel diff --git a/src/libstd/sys/sgx/ext/io.rs b/src/libstd/sys/sgx/ext/io.rs index 55cc4c9ba1ffb..1eb269783c5ab 100644 --- a/src/libstd/sys/sgx/ext/io.rs +++ b/src/libstd/sys/sgx/ext/io.rs @@ -1,13 +1,3 @@ -// 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. - //! SGX-specific extensions to general I/O primitives //! //! SGX file descriptors behave differently from Unix file descriptors. See the diff --git a/src/libstd/sys/sgx/ext/mod.rs b/src/libstd/sys/sgx/ext/mod.rs index 8e505a23c422d..5489f6f56946e 100644 --- a/src/libstd/sys/sgx/ext/mod.rs +++ b/src/libstd/sys/sgx/ext/mod.rs @@ -1,13 +1,3 @@ -// 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. - #![unstable(feature = "sgx_platform", issue = "56975")] pub mod arch; diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 7d12e0f6ef085..855efbd3eb5d6 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -160,11 +160,6 @@ impl RawHandle { } } - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { - let mut me = self; - (&mut me).read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let mut amt = 0; let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index f331397db8cf3..a4f4bd22cd921 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -128,11 +128,6 @@ impl Stdin { // MemReader shouldn't error here since we just filled it utf8.read(buf) } - - pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { - let mut me = self; - (&mut me).read_to_end(buf) - } } #[unstable(reason = "not public", issue = "0", feature = "fd_read")] diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index ee3916b35f9c9..c18b603a6356c 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -51,7 +51,7 @@ cfg_if! { target_os = "l4re", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx"))] { + all(target_vendor = "fortanix", target_env = "sgx")))] { pub use sys::net; } else { pub mod net; diff --git a/src/libstd/time.rs b/src/libstd/time.rs index ffe604cd33bd8..eb67b718dbd3d 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -220,6 +220,12 @@ impl Instant { impl Add<Duration> for Instant { type Output = Instant; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { self.checked_add(other) .expect("overflow when adding duration to instant") @@ -387,6 +393,12 @@ impl SystemTime { impl Add<Duration> for SystemTime { type Output = SystemTime; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { self.checked_add(dur) .expect("overflow when adding duration to instant") diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7e8b7007b2289..2793754e1033a 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -995,7 +995,7 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str, -) -> Result<Spanned<(Symbol, ast::StrStyle)>, DiagnosticBuilder<'a>> { +) -> Result<Spanned<(Symbol, ast::StrStyle)>, Option<DiagnosticBuilder<'a>>> { // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. let expr = expr.map(|mut expr| { expr.span = expr.span.apply_mark(cx.current_expansion.mark); @@ -1007,16 +1007,17 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), - _ => cx.struct_span_err(l.span, err_msg) + _ => Some(cx.struct_span_err(l.span, err_msg)) }, - _ => cx.struct_span_err(expr.span, err_msg) + ast::ExprKind::Err => None, + _ => Some(cx.struct_span_err(expr.span, err_msg)) }) } pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) - .map_err(|mut err| err.emit()) + .map_err(|err| err.map(|mut err| err.emit())) .ok() .map(|s| s.node) } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 1101d7772b839..e63042a420824 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -86,7 +86,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T -> Box<dyn base::MacResult+'cx> { let file = match get_single_str_from_tts(cx, sp, tts, "include!") { Some(f) => f, - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), }; // The file will be added to the code map by the parser let path = res_rel_file(cx, sp, file); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 70df403d0c2ea..3f2122e24a642 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -111,7 +111,7 @@ declare_features! ( (active, concat_idents, "1.0.0", Some(29599), None), (active, link_args, "1.0.0", Some(29596), None), (active, log_syntax, "1.0.0", Some(29598), None), - (active, non_ascii_idents, "1.0.0", Some(28979), None), + (active, non_ascii_idents, "1.0.0", Some(55467), None), (active, plugin_registrar, "1.0.0", Some(29597), None), (active, thread_local, "1.0.0", Some(29594), None), (active, trace_macros, "1.0.0", Some(29598), None), @@ -471,11 +471,14 @@ declare_features! ( // Allows `const _: TYPE = VALUE`. (active, underscore_const_names, "1.31.0", Some(54912), None), - // `reason = ` in lint attributes and `expect` lint attribute + // Adds `reason` and `expect` lint attributes. (active, lint_reasons, "1.31.0", Some(54503), None), // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`. (active, extern_crate_self, "1.31.0", Some(56409), None), + + // Allows paths to enum variants on type aliases. + (active, type_alias_enum_variants, "1.31.0", Some(49683), None), ); declare_features! ( diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index d13de0029682e..ecb34e43c590c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -945,12 +945,36 @@ impl<'a> StringReader<'a> { self.scan_unicode_escape(delim) && !ascii_only } else { let span = self.mk_sp(start, self.pos); - self.sess.span_diagnostic - .struct_span_err(span, "incorrect unicode escape sequence") - .span_help(span, - "format of unicode escape sequences is \ - `\\u{…}`") - .emit(); + let mut suggestion = "\\u{".to_owned(); + let mut err = self.sess.span_diagnostic.struct_span_err( + span, + "incorrect unicode escape sequence", + ); + let mut i = 0; + while let (Some(ch), true) = (self.ch, i < 6) { + if ch.is_digit(16) { + suggestion.push(ch); + self.bump(); + i += 1; + } else { + break; + } + } + if i != 0 { + suggestion.push('}'); + err.span_suggestion_with_applicability( + self.mk_sp(start, self.pos), + "format of unicode escape sequences uses braces", + suggestion, + Applicability::MaybeIncorrect, + ); + } else { + err.span_help( + span, + "format of unicode escape sequences is `\\u{...}`", + ); + } + err.emit(); false }; if ascii_only { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 52da8a072c751..1e4a26b353759 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -798,6 +798,18 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(self.span, &format!("expected identifier, found {}", self.this_token_descr())); + if let token::Ident(ident, false) = &self.token { + if ident.is_reserved() && !ident.is_path_segment_keyword() && + ident.name != keywords::Underscore.name() + { + err.span_suggestion_with_applicability( + self.span, + "you can escape reserved keywords to use them as identifiers", + format!("r#{}", ident), + Applicability::MaybeIncorrect, + ); + } + } if let Some(token_descr) = self.token_descr() { err.span_label(self.span, format!("expected identifier, found {}", token_descr)); } else { @@ -1866,7 +1878,8 @@ impl<'a> Parser<'a> { let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment("a method argument's type"); let mut ty = self.parse_ty(); - if ty.is_ok() && self.token == token::Colon { + if ty.is_ok() && self.token != token::Comma && + self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, // so we are going to rollback and re-parse for recovery. ty = self.unexpected(); diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs index fd018885a26be..8f7f5deb091ac 100644 --- a/src/libsyntax_ext/compile_error.rs +++ b/src/libsyntax_ext/compile_error.rs @@ -10,7 +10,7 @@ pub fn expand_compile_error<'cx>(cx: &'cx mut ExtCtxt, tts: &[tokenstream::TokenTree]) -> Box<dyn base::MacResult + 'cx> { let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(v) => v, }; diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index a19c7e427e34c..807f190cb6a1a 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -18,6 +18,7 @@ pub fn expand_syntax_ext( }; let mut accumulator = String::new(); let mut missing_literal = vec![]; + let mut has_errors = false; for e in es { match e.node { ast::ExprKind::Lit(ref lit) => match lit.node { @@ -41,6 +42,9 @@ pub fn expand_syntax_ext( cx.span_err(e.span, "cannot concatenate a byte string literal"); } }, + ast::ExprKind::Err => { + has_errors = true; + } _ => { missing_literal.push(e.span); } @@ -50,6 +54,9 @@ pub fn expand_syntax_ext( let mut err = cx.struct_span_err(missing_literal, "expected a literal"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); + return base::DummyResult::expr(sp); + } else if has_errors { + return base::DummyResult::expr(sp); } let sp = sp.apply_mark(cx.current_expansion.mark); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 9c49a59678fdb..de96de4bdc2bc 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -24,7 +24,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, if tts.is_empty() { cx.span_err(sp, "concat_idents! takes 1 or more arguments."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } let mut res_str = String::new(); @@ -34,7 +34,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, TokenTree::Token(_, token::Comma) => {} _ => { cx.span_err(sp, "concat_idents! expecting comma."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } } } else { @@ -43,7 +43,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, res_str.push_str(&ident.as_str()), _ => { cx.span_err(sp, "concat_idents! requires ident args."); - return DummyResult::expr(sp); + return DummyResult::any(sp); } } } diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 33669c8bc37ec..16fb64a5f3912 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -79,7 +79,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); - cx.expr_usize(sp, 0) + return DummyResult::expr(sp); } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 9d29e2b0fb69a..c11f27f3ed589 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -748,18 +748,20 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, fmt } Ok(fmt) => fmt, - Err(mut err) => { - let sugg_fmt = match args.len() { - 0 => "{}".to_string(), - _ => format!("{}{{}}", "{} ".repeat(args.len())), - }; - err.span_suggestion_with_applicability( - fmt_sp.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{}\", ", sugg_fmt), - Applicability::MaybeIncorrect, - ); - err.emit(); + Err(err) => { + if let Some(mut err) = err { + let sugg_fmt = match args.len() { + 0 => "{}".to_string(), + _ => format!("{}{{}}", "{} ".repeat(args.len())), + }; + err.span_suggestion_with_applicability( + fmt_sp.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{}\", ", sugg_fmt), + Applicability::MaybeIncorrect, + ); + err.emit(); + } return DummyResult::raw_expr(sp, true); } }; @@ -806,12 +808,57 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } ('\\', Some((next_pos, 'n'))) | ('\\', Some((next_pos, 't'))) | + ('\\', Some((next_pos, '0'))) | ('\\', Some((next_pos, '\\'))) | ('\\', Some((next_pos, '\''))) | ('\\', Some((next_pos, '\"'))) => { skips.push(*next_pos); let _ = s.next(); } + ('\\', Some((_, 'x'))) if !is_raw => { + for _ in 0..3 { // consume `\xAB` literal + if let Some((pos, _)) = s.next() { + skips.push(pos); + } else { + break; + } + } + } + ('\\', Some((_, 'u'))) if !is_raw => { + if let Some((pos, _)) = s.next() { + skips.push(pos); + } + if let Some((next_pos, next_c)) = s.next() { + if next_c == '{' { + skips.push(next_pos); + let mut i = 0; // consume up to 6 hexanumeric chars + closing `}` + while let (Some((next_pos, c)), true) = (s.next(), i < 7) { + if c.is_digit(16) { + skips.push(next_pos); + } else if c == '}' { + skips.push(next_pos); + break; + } else { + break; + } + i += 1; + } + } else if next_c.is_digit(16) { + skips.push(next_pos); + // We suggest adding `{` and `}` when appropriate, accept it here as if + // it were correct + let mut i = 0; // consume up to 6 hexanumeric chars + while let (Some((next_pos, c)), _) = (s.next(), i < 6) { + if c.is_digit(16) { + skips.push(next_pos); + } else { + break; + } + i += 1; + } + } + } + } _ if eat_ws => { // `take_while(|c| c.is_whitespace())` eat_ws = false; } @@ -860,7 +907,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, } let arg_spans = parser.arg_places.iter() - .map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end)) + .map(|&(parse::SpanIndex(start), parse::SpanIndex(end))| { + fmt.span.from_inner_byte_pos(start, end) + }) .collect(); let mut cx = Context { @@ -954,13 +1003,18 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let mut diag = { if errs_len == 1 { let (sp, msg) = errs.into_iter().next().unwrap(); - cx.ecx.struct_span_err(sp, msg) + let mut diag = cx.ecx.struct_span_err(sp, msg); + diag.span_label(sp, msg); + diag } else { let mut diag = cx.ecx.struct_span_err( errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(), "multiple unused formatting arguments", ); diag.span_label(cx.fmtsp, "multiple missing formatting specifiers"); + for (sp, msg) in errs { + diag.span_label(sp, msg); + } diag } }; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 4e227745a793f..ec96ea067082f 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,6 +23,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(asm)] +#![feature(cfg_target_vendor)] #![feature(fnbox)] #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))] #![feature(nll)] @@ -1015,7 +1016,7 @@ fn use_color(opts: &TestOpts) -> bool { #[cfg(any(target_os = "cloudabi", target_os = "redox", all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx"))] + all(target_vendor = "fortanix", target_env = "sgx")))] fn stdout_isatty() -> bool { // FIXME: Implement isatty on Redox and SGX false @@ -1246,7 +1247,8 @@ fn get_concurrency() -> usize { 1 } - #[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))] + #[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_vendor = "fortanix", target_env = "sgx")))] fn num_cpus() -> usize { 1 } diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs new file mode 100644 index 0000000000000..efef4ab00aed2 --- /dev/null +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -0,0 +1,51 @@ +// Copyright 2014 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 + +#![feature(plugin_registrar)] +#![feature(box_syntax, rustc_private)] + +// Load rustc as a plugin to get macros. +#[macro_use] +extern crate rustc; +extern crate rustc_plugin; + +use rustc::hir; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc_plugin::Registry; + +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); + +struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(TEST_LINT, PLEASE_LINT) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + match &*it.ident.as_str() { + "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), + "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), + _ => {} + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_late_lint_pass(box Pass); + reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]); +} diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 3aa66527ca7e8..b6050f059c27b 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,TypeckTables,MirValidated")] + except="HirBody,TypeckTables,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index bb304ea12ca7f..88fd53d4ba59d 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -37,7 +37,7 @@ fn main() { // StorageLive(_4); // _4 = std::option::Option<std::boxed::Box<u32>>::None; // FakeRead(ForLet, _4); -// AscribeUserType(_4, o, UserTypeProjection { base: Ty(Canonical { max_universe: U0, variables: [], value: std::option::Option<std::boxed::Box<u32>> }), projs: [] }); +// AscribeUserType(_4, o, UserTypeProjection { base: UserTypeAnnotation(1), projs: [] }); // StorageLive(_5); // StorageLive(_6); // _6 = move _4; diff --git a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs index 647652d02734a..4801369cfd1a8 100644 --- a/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs +++ b/src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(dead_code)] +#![allow(dead_code, unreachable_patterns)] struct Foo; diff --git a/src/test/run-pass/coherence/coherence-subtyping.rs b/src/test/run-pass/coherence/coherence-subtyping.rs deleted file mode 100644 index b7aa57b5c31f7..0000000000000 --- a/src/test/run-pass/coherence/coherence-subtyping.rs +++ /dev/null @@ -1,39 +0,0 @@ -// run-pass -// Test that two distinct impls which match subtypes of one another -// yield coherence errors (or not) depending on the variance. - -trait Contravariant { - fn foo(&self) { } -} - -impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { -} - -impl Contravariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { -} - -/////////////////////////////////////////////////////////////////////////// - -trait Covariant { - fn foo(&self) { } -} - -impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { -} - -impl Covariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { -} - -/////////////////////////////////////////////////////////////////////////// - -trait Invariant { - fn foo(&self) { } -} - -impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { -} - -impl Invariant for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { -} - -fn main() { } diff --git a/src/test/run-pass/enum-variant-generic-args.rs b/src/test/run-pass/enum-variant-generic-args.rs new file mode 100644 index 0000000000000..0743f99897922 --- /dev/null +++ b/src/test/run-pass/enum-variant-generic-args.rs @@ -0,0 +1,42 @@ +#![feature(irrefutable_let_patterns)] +#![feature(type_alias_enum_variants)] + +#![allow(irrefutable_let_patterns)] + +#[allow(dead_code)] +enum Enum<T> { TSVariant(T), SVariant { v: T } } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +macro_rules! is_variant { + (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr)); + (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr)); + (@check $variant:ident, $matcher:tt, $expr:expr) => ( + assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false }, + "expr does not have correct type"); + ); +} + +fn main() { + // Tuple struct variant + + is_variant!(TSVariant, Enum::TSVariant(())); + is_variant!(TSVariant, Enum::TSVariant::<()>(())); + is_variant!(TSVariant, Enum::<()>::TSVariant(())); + + is_variant!(TSVariant, Alias::TSVariant(())); + is_variant!(TSVariant, Alias::<()>::TSVariant(())); + + is_variant!(TSVariant, AliasFixed::TSVariant(())); + + // Struct variant + + is_variant!(SVariant, Enum::SVariant { v: () }); + is_variant!(SVariant, Enum::SVariant::<()> { v: () }); + is_variant!(SVariant, Enum::<()>::SVariant { v: () }); + + is_variant!(SVariant, Alias::SVariant { v: () }); + is_variant!(SVariant, Alias::<()>::SVariant { v: () }); + + is_variant!(SVariant, AliasFixed::SVariant { v: () }); +} diff --git a/src/test/run-pass/type-alias-enum-variants-2.rs b/src/test/run-pass/type-alias-enum-variants-2.rs new file mode 100644 index 0000000000000..0cf413babcbf6 --- /dev/null +++ b/src/test/run-pass/type-alias-enum-variants-2.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_enum_variants)] + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type FooAlias = Foo; +type OptionAlias = Option<i32>; + +impl Foo { + fn foo() -> Self { + Self::Bar(3) + } +} + +fn main() { + let t = FooAlias::Bar(1); + assert_eq!(t, Foo::Bar(1)); + let t = FooAlias::Baz { i: 2 }; + assert_eq!(t, Foo::Baz { i: 2 }); + match t { + FooAlias::Bar(_i) => {} + FooAlias::Baz { i } => { assert_eq!(i, 2); } + } + assert_eq!(Foo::foo(), Foo::Bar(3)); + + assert_eq!(OptionAlias::Some(4), Option::Some(4)); +} diff --git a/src/test/run-pass/type-alias-enum-variants.rs b/src/test/run-pass/type-alias-enum-variants.rs new file mode 100644 index 0000000000000..0cf413babcbf6 --- /dev/null +++ b/src/test/run-pass/type-alias-enum-variants.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_enum_variants)] + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type FooAlias = Foo; +type OptionAlias = Option<i32>; + +impl Foo { + fn foo() -> Self { + Self::Bar(3) + } +} + +fn main() { + let t = FooAlias::Bar(1); + assert_eq!(t, Foo::Bar(1)); + let t = FooAlias::Baz { i: 2 }; + assert_eq!(t, Foo::Baz { i: 2 }); + match t { + FooAlias::Bar(_i) => {} + FooAlias::Baz { i } => { assert_eq!(i, 2); } + } + assert_eq!(Foo::foo(), Foo::Bar(3)); + + assert_eq!(OptionAlias::Some(4), Option::Some(4)); +} diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index 41aba1a007ad8..2d6cb1368d120 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -1,13 +1,3 @@ -// 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. - struct Wrapper<T>(T); trait MyTrait { diff --git a/src/test/rustfix/closure-immutable-outer-variable.fixed b/src/test/rustfix/closure-immutable-outer-variable.fixed index bddc2eab16dd8..05bbc13d714fa 100644 --- a/src/test/rustfix/closure-immutable-outer-variable.fixed +++ b/src/test/rustfix/closure-immutable-outer-variable.fixed @@ -1,13 +1,3 @@ -// 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. - // Point at the captured immutable outer variable fn foo(mut f: Box<FnMut()>) { diff --git a/src/test/rustfix/empty-no-fixes.fixed b/src/test/rustfix/empty-no-fixes.fixed index 39e19566d7652..3724a00ce7ce0 100644 --- a/src/test/rustfix/empty-no-fixes.fixed +++ b/src/test/rustfix/empty-no-fixes.fixed @@ -1,11 +1 @@ -// 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-flags:--crate-type lib diff --git a/src/test/rustfix/empty-no-fixes.rs.fixed b/src/test/rustfix/empty-no-fixes.rs.fixed index ee58e77825343..e30d3ae0965ae 100644 --- a/src/test/rustfix/empty-no-fixes.rs.fixed +++ b/src/test/rustfix/empty-no-fixes.rs.fixed @@ -1,12 +1,2 @@ -// 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-flags:--crate-type lib fn foo() {} diff --git a/src/test/rustfix/issue-45562.fixed b/src/test/rustfix/issue-45562.fixed index d7a27a11fc07a..955b2cbf899ba 100644 --- a/src/test/rustfix/issue-45562.fixed +++ b/src/test/rustfix/issue-45562.fixed @@ -1,13 +1,3 @@ -// 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_mangle] pub static RAH: usize = 5; fn main() {} diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed index d931f90cd0431..b4ae4dc1ab2f8 100644 --- a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed +++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -1,12 +1,2 @@ -// 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. - extern crate std as other_std; fn main() {} diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed index aaa04ef40042d..bedc8e15ace6e 100644 --- a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed +++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed @@ -1,13 +1,3 @@ -// 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. - #![allow(unused)] fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { diff --git a/src/test/rustfix/main-no-fixes.fixed b/src/test/rustfix/main-no-fixes.fixed index 3f07b46791d22..f328e4d9d04c3 100644 --- a/src/test/rustfix/main-no-fixes.fixed +++ b/src/test/rustfix/main-no-fixes.fixed @@ -1,11 +1 @@ -// 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. - fn main() {} diff --git a/src/test/rustfix/main-no-fixes.rs.fixed b/src/test/rustfix/main-no-fixes.rs.fixed index 3f07b46791d22..f328e4d9d04c3 100644 --- a/src/test/rustfix/main-no-fixes.rs.fixed +++ b/src/test/rustfix/main-no-fixes.rs.fixed @@ -1,11 +1 @@ -// 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. - fn main() {} diff --git a/src/test/rustfix/missing-comma-in-match.fixed b/src/test/rustfix/missing-comma-in-match.fixed index 621a4127bc293..d4696ab9547a6 100644 --- a/src/test/rustfix/missing-comma-in-match.fixed +++ b/src/test/rustfix/missing-comma-in-match.fixed @@ -1,13 +1,3 @@ -// 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. - fn main() { match &Some(3) { &None => 1, diff --git a/src/test/rustfix/str-as-char.fixed b/src/test/rustfix/str-as-char.fixed index 0ace6d96613d7..900fee94653c1 100644 --- a/src/test/rustfix/str-as-char.fixed +++ b/src/test/rustfix/str-as-char.fixed @@ -1,13 +1,3 @@ -// 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. - fn main() { println!("●●"); } diff --git a/src/test/rustfix/tuple-float-index.fixed b/src/test/rustfix/tuple-float-index.fixed index 9cb7537b42807..abb07962e894a 100644 --- a/src/test/rustfix/tuple-float-index.fixed +++ b/src/test/rustfix/tuple-float-index.fixed @@ -1,13 +1,3 @@ -// Copyright 2012 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-flags: -Z parse-only fn main () { diff --git a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs index 91d03d98a10b9..bca1d7a72b4ab 100644 --- a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs @@ -3,7 +3,7 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -// Load rustc as a plugin to get macros +// Load rustc as a plugin to get macros. #[macro_use] extern crate rustc; extern crate rustc_plugin; @@ -26,7 +26,7 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - match &*it.name.as_str() { + match &*it.ident.as_str() { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), _ => {} diff --git a/src/test/ui-fulldeps/lint-group-plugin.rs b/src/test/ui-fulldeps/lint-group-plugin.rs index 00c5a56a482c1..7a650afe5f8fa 100644 --- a/src/test/ui-fulldeps/lint-group-plugin.rs +++ b/src/test/ui-fulldeps/lint-group-plugin.rs @@ -1,6 +1,7 @@ // run-pass // aux-build:lint_group_plugin_test.rs // ignore-stage1 + #![feature(plugin)] #![plugin(lint_group_plugin_test)] #![allow(dead_code)] diff --git a/src/test/ui-fulldeps/lint-group-plugin.stderr b/src/test/ui-fulldeps/lint-group-plugin.stderr index 15cffedcc5d3c..b566048c75ee6 100644 --- a/src/test/ui-fulldeps/lint-group-plugin.stderr +++ b/src/test/ui-fulldeps/lint-group-plugin.stderr @@ -1,5 +1,5 @@ warning: item is named 'lintme' - --> $DIR/lint-group-plugin.rs:8:1 + --> $DIR/lint-group-plugin.rs:9:1 | LL | fn lintme() { } //~ WARNING item is named 'lintme' | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | fn lintme() { } //~ WARNING item is named 'lintme' = note: #[warn(test_lint)] on by default warning: item is named 'pleaselintme' - --> $DIR/lint-group-plugin.rs:9:1 + --> $DIR/lint-group-plugin.rs:10:1 | LL | fn pleaselintme() { } //~ WARNING item is named 'pleaselintme' | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/E0642.rs b/src/test/ui/E0642.rs index 8b74e5abe19df..cfbd362c1da19 100644 --- a/src/test/ui/E0642.rs +++ b/src/test/ui/E0642.rs @@ -6,6 +6,8 @@ trait T { fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies + fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies + fn f(&ident: &S) {} // ok fn g(&&ident: &&S) {} // ok fn h(mut ident: S) {} // ok diff --git a/src/test/ui/E0642.stderr b/src/test/ui/E0642.stderr index c3a230d5acf3c..4c82a6cbd21b4 100644 --- a/src/test/ui/E0642.stderr +++ b/src/test/ui/E0642.stderr @@ -18,6 +18,16 @@ help: give this argument a name or use an underscore to ignore it LL | fn bar(_: (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies | ^ -error: aborting due to 2 previous errors +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/E0642.rs:9:15 + | +LL | fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies + | ^^^^^^^^ +help: give this argument a name or use an underscore to ignore it + | +LL | fn method(_: S) {} //~ ERROR patterns aren't allowed in methods without bodies + | ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0642`. diff --git a/src/test/ui/as-ref.stderr b/src/test/ui/as-ref.stderr deleted file mode 100644 index 8ca54e8006cf3..0000000000000 --- a/src/test/ui/as-ref.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/as-ref.rs:6:27 - | -LL | opt.map(|arg| takes_ref(arg)); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:8:37 - | -LL | opt.and_then(|arg| Some(takes_ref(arg))); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:11:27 - | -LL | opt.map(|arg| takes_ref(arg)); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error[E0308]: mismatched types - --> $DIR/as-ref.rs:13:35 - | -LL | opt.and_then(|arg| Ok(takes_ref(arg))); - | - ^^^ expected &Foo, found struct `Foo` - | | - | help: consider using `as_ref` instead: `as_ref().` - | - = note: expected type `&Foo` - found type `Foo` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index cd60132efdd65..de172049872f5 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope - --> $DIR/associated-const-no-item.rs:5:16 + --> $DIR/associated-const-no-item.rs:5:23 | LL | const X: i32 = <i32>::ID; - | ^^^^^^^^^ associated item not found in `i32` + | -------^^ + | | + | associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `ID`, perhaps you need to implement it: diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index d0245a07e40bd..20fa1e7a48db1 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -77,23 +77,33 @@ fn tuple_four<T>() // not ok for tuple, two lifetimes, and lifetime matching is invariant } -pub fn main() { +pub fn call_foo() { foo::<IntStruct>(); foo::<UintStruct>(); //~ ERROR type mismatch +} +pub fn call_bar() { bar::<IntStruct>(); //~ ERROR type mismatch bar::<UintStruct>(); +} +pub fn call_tuple_one() { tuple_one::<Tuple>(); - //~^ ERROR E0277 - //~| ERROR type mismatch + //~^ ERROR not general enough +} +pub fn call_tuple_two() { tuple_two::<Tuple>(); - //~^ ERROR E0277 - //~| ERROR type mismatch + //~^ ERROR not general enough +} +pub fn call_tuple_three() { tuple_three::<Tuple>(); +} +pub fn call_tuple_four() { tuple_four::<Tuple>(); - //~^ ERROR E0277 + //~^ ERROR not general enough } + +fn main() { } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 5e04dc5f8c5d9..d3eaa894b5043 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -17,7 +17,7 @@ LL | | } | |_^ error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize` - --> $DIR/associated-types-eq-hr.rs:84:5 + --> $DIR/associated-types-eq-hr.rs:86:5 | LL | bar::<IntStruct>(); //~ ERROR type mismatch | ^^^^^^^^^^^^^^^^ expected isize, found usize @@ -34,93 +34,36 @@ LL | | // ok for UintStruct, but not IntStruct LL | | } | |_^ -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:87:5 - | -LL | tuple_one::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | -LL | / fn tuple_one<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ - -error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize` - --> $DIR/associated-types-eq-hr.rs:87:5 - | -LL | tuple_one::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_one` - --> $DIR/associated-types-eq-hr.rs:56:1 - | -LL | / fn tuple_one<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick first -LL | | } - | |_^ - -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied +error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:91:5 | -LL | tuple_two::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 +LL | tuple_one::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_two<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ + = note: Due to a where-clause on `tuple_one`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize` - --> $DIR/associated-types-eq-hr.rs:91:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 | LL | tuple_two::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime - | -note: required by `tuple_two` - --> $DIR/associated-types-eq-hr.rs:62:1 + | ^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_two<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize> -LL | | { -LL | | // not ok for tuple, two lifetimes and we pick second -LL | | } - | |_^ + = note: Due to a where-clause on `tuple_two`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied - --> $DIR/associated-types-eq-hr.rs:97:5 +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:105:5 | LL | tuple_four::<Tuple>(); - | ^^^^^^^^^^^^^^^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple` - | - = help: the following implementations were found: - <Tuple as TheTrait<(&'a isize, &'a isize)>> -note: required by `tuple_four` - --> $DIR/associated-types-eq-hr.rs:74:1 + | ^^^^^^^^^^^^^^^^^^^ | -LL | / fn tuple_four<T>() -LL | | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)> -LL | | { -LL | | // not ok for tuple, two lifetimes, and lifetime matching is invariant -LL | | } - | |_^ + = note: Due to a where-clause on `tuple_four`, + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors occurred: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index cc69e849fe144..e4704494e1492 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,17 +1,12 @@ -error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other | -note: required by `foo` - --> $DIR/higher-ranked-projection.rs:14:1 - | -LL | / fn foo<U, T>(_t: T) -LL | | where for<'a> &'a T: Mirror<Image=U> -LL | | {} - | |__^ + = note: expected type `Mirror` + found type `Mirror` error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index 632fe493e1f3f..db15ec51d87c6 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,8 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` -LL | | //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime +LL | | //[bad]~^ ERROR E0308 LL | | } | |_^ diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index be6300c418293..5b380c982f041 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,6 +23,5 @@ fn foo<U, T>(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _` - //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime + //[bad]~^ ERROR E0308 } diff --git a/src/test/ui/attr-bad-crate-attr.rc b/src/test/ui/attr-bad-crate-attr.rc index 4ab07f4fa9918..89ba26dfd6f4b 100644 --- a/src/test/ui/attr-bad-crate-attr.rc +++ b/src/test/ui/attr-bad-crate-attr.rc @@ -1,13 +1,3 @@ -// Copyright 2012 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. - // error-pattern: expected item #![attr = "val"] diff --git a/src/test/ui/bad/bad-const-type.rs b/src/test/ui/bad/bad-const-type.rs index b46f5933010de..8121929e09675 100644 --- a/src/test/ui/bad/bad-const-type.rs +++ b/src/test/ui/bad/bad-const-type.rs @@ -2,5 +2,5 @@ static i: String = 10; //~^ ERROR mismatched types //~| expected type `std::string::String` //~| found type `{integer}` -//~| expected struct `std::string::String`, found integral variable +//~| expected struct `std::string::String`, found integer fn main() { println!("{}", i); } diff --git a/src/test/ui/bad/bad-const-type.stderr b/src/test/ui/bad/bad-const-type.stderr index 694e692a5bec5..677dc72652e92 100644 --- a/src/test/ui/bad/bad-const-type.stderr +++ b/src/test/ui/bad/bad-const-type.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | static i: String = 10; | ^^ | | - | expected struct `std::string::String`, found integral variable + | expected struct `std::string::String`, found integer | help: try using a conversion method: `10.to_string()` | = note: expected type `std::string::String` diff --git a/src/test/ui/binop/binop-logic-int.stderr b/src/test/ui/binop/binop-logic-int.stderr index 9ca9e64211c82..b699b390b8bb1 100644 --- a/src/test/ui/binop/binop-logic-int.stderr +++ b/src/test/ui/binop/binop-logic-int.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/binop-logic-int.rs:1:21 | LL | fn main() { let x = 1 && 2; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/binop-logic-int.rs:1:26 | LL | fn main() { let x = 1 && 2; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index 05a623404493a..389b63c0adf93 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/blind-item-block-middle.rs:6:9 | LL | let bar = 5; - | ^^^ expected integral variable, found struct `foo::bar` + | ^^^ expected integer, found struct `foo::bar` | = note: expected type `{integer}` found type `foo::bar` diff --git a/src/test/ui/bogus-tag.rs b/src/test/ui/bogus-tag.rs index ca8db9b502b5b..c594385eec2d6 100644 --- a/src/test/ui/bogus-tag.rs +++ b/src/test/ui/bogus-tag.rs @@ -3,8 +3,8 @@ enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } fn main() { let red: Color = Color::Rgb(255, 0, 0); match red { - Color::Rgb(r, g, b) => { println!("rgb"); } - Color::Hsl(h, s, l) => { println!("hsl"); } - //~^ ERROR no variant + Color::Rgb(r, g, b) => { println!("rgb"); } + Color::Hsl(h, s, l) => { println!("hsl"); } + //~^ ERROR no variant } } diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index 1225abd2c8a16..3750df841720c 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -1,11 +1,11 @@ error[E0599]: no variant named `Hsl` found for type `Color` in the current scope - --> $DIR/bogus-tag.rs:7:7 + --> $DIR/bogus-tag.rs:7:16 | LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } | ---------- variant `Hsl` not found here ... -LL | Color::Hsl(h, s, l) => { println!("hsl"); } - | ^^^^^^^^^^^^^^^^^^^ variant not found in `Color` +LL | Color::Hsl(h, s, l) => { println!("hsl"); } + | -------^^^--------- variant not found in `Color` error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr index 410b94b34bcac..24467faa90ca9 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:261:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr index ab208ee20c5ef..279548f870fd0 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:261:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 00ce234d6d5f0..eb622ac10addf 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -260,7 +260,7 @@ fn main() { let x = &mut v; v[0].y; //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed - //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[_].y` because it was mutably borrowed //[mir]~| ERROR cannot use `*v` because it was mutably borrowed drop(x); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr index 93e2dd49f7bfa..25a9a11204430 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr @@ -5,6 +5,8 @@ LL | drop(x.b); | --- value moved here LL | drop(*x.b); //~ ERROR use of moved value: `*x.b` | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:14:10 @@ -13,6 +15,8 @@ LL | let y = A { a: 3, .. x }; | ---------------- value moved here LL | drop(*x.b); //~ ERROR use of moved value: `*x.b` | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `x.b` --> $DIR/borrowck-field-sensitivity.rs:20:13 diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr deleted file mode 100644 index 2e5477c573bbe..0000000000000 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.ast.nll.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:10:14 - | -LL | let [_, _x] = a; - | -- value moved here -LL | let [.., _y] = a; //[ast]~ ERROR [E0382] - | ^^ value used here after move - -error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:17:10 - | -LL | let [_x, _] = a; - | -- value moved here -LL | let [_y..] = a; //[ast]~ ERROR [E0382] - | ^^ value used here after move - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr index 2e5477c573bbe..f866ff9e9bae1 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr @@ -5,6 +5,8 @@ LL | let [_, _x] = a; | -- value moved here LL | let [.., _y] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array.rs:17:10 @@ -13,6 +15,8 @@ LL | let [_x, _] = a; | -- value moved here LL | let [_y..] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr index 9577a41bb182e..6dc2778892d2e 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.ast.nll.stderr @@ -1,11 +1,11 @@ -error[E0506]: cannot assign to `a[..]` because it is borrowed +error[E0506]: cannot assign to `a[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr index 0e4a3cd6c1b50..6eb9eac760f00 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr @@ -7,14 +7,14 @@ LL | [1, 2, ref tail..] => tail, LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed | ^^^^^^^^ assignment to borrowed `a[..]` occurs here -error[E0506]: cannot assign to `a[..]` because it is borrowed (Mir) +error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir) --> $DIR/borrowck-vec-pattern-move-tail.rs:16:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index 540f9333bc063..e14ecd90d56fb 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -15,7 +15,7 @@ fn main() { println!("t[0]: {}", t[0]); a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) - //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir) + //[cmp]~| ERROR cannot assign to `a[_]` because it is borrowed (Mir) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr index 6a3c051e34989..018a3173af1b0 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `vec[..]` because it is borrowed +error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:10:13 | LL | [box ref _a, _, _] => { - | ------ borrow of `vec[..]` occurs here + | ------ borrow of `vec[_]` occurs here LL | //~^ borrow of `vec[..]` occurs here LL | vec[0] = box 4; //~ ERROR cannot assign - | ^^^^^^ assignment to borrowed `vec[..]` occurs here + | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | //~^ assignment to borrowed `vec[..]` occurs here LL | _a.use_ref(); | -- borrow later used here -error[E0506]: cannot assign to `vec[..]` because it is borrowed +error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:23:13 | LL | &mut [ref _b..] => { - | ------ borrow of `vec[..]` occurs here + | ------ borrow of `vec[_]` occurs here LL | //~^ borrow of `vec[..]` occurs here LL | vec[0] = box 4; //~ ERROR cannot assign - | ^^^^^^ assignment to borrowed `vec[..]` occurs here + | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | //~^ assignment to borrowed `vec[..]` occurs here LL | _b.use_ref(); | -- borrow later used here diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr index 1fdde5e15f364..0e99e158eda02 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:129:27 diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index 1fdde5e15f364..0e99e158eda02 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:76:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:129:27 diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index 49ed97d71680b..d65b701307b43 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type_inference.rs:21:14 | LL | only_foo(x); //~ ERROR mismatched types - | ^ expected i32, found floating-point variable + | ^ expected i32, found floating-point number | = note: expected type `i32` found type `{float}` diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index 8c7d3cbad33c4..6977fd47a2e85 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -28,14 +28,14 @@ fn expect_free_supply_bound() { // Here, we are given a function whose region is bound at closure level, // but we expect one bound in the argument. Error results. with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - //~^ ERROR type mismatch in closure arguments + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { // Here, we are given a `fn(&u32)` but we expect a `fn(&'x // u32)`. In principle, this could be ok, but we demand equality. with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - //~^ ERROR type mismatch in closure arguments + //~^ ERROR mismatched types } fn expect_bound_supply_free_from_closure() { @@ -43,8 +43,9 @@ fn expect_bound_supply_free_from_closure() { // bound at the closure level, but we expect something bound at // the argument level. type Foo<'a> = fn(&'a u32); - with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {}); - //~^ ERROR type mismatch in closure arguments + with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + //~^ ERROR mismatched types + }); } fn expect_bound_supply_bound<'x>(x: &'x u32) { diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 9c85743106776..b1cfd6cef1022 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -36,58 +36,33 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the b LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:30:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:30:52 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `for<'a, 'r> fn(fn(&'a u32), &'r i32) -> _` - | -note: required by `with_closure_expecting_fn_with_free_region` - --> $DIR/expect-fn-supply-fn.rs:1:1 + | ^^^^^^^^ one type is more general than the other | -LL | / fn with_closure_expecting_fn_with_free_region<F>(_: F) -LL | | where F: for<'a> FnOnce(fn(&'a u32), &i32) -LL | | { -LL | | } - | |_^ + = note: expected type `fn(&u32)` + found type `for<'r> fn(&'r u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:37:53 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _` - | | - | expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _` + | ^^^^^^^^^^^ one type is more general than the other | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 - | -LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ + = note: expected type `for<'r> fn(&'r u32)` + found type `fn(&'x u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 - | -LL | with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _` - | | - | expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _` +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:46:53 | -note: required by `with_closure_expecting_fn_with_bound_region` - --> $DIR/expect-fn-supply-fn.rs:6:1 +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^^^^^^^ one type is more general than the other | -LL | / fn with_closure_expecting_fn_with_bound_region<F>(_: F) -LL | | where F: FnOnce(fn(&u32), &i32) -LL | | { -LL | | } - | |_^ + = note: expected type `for<'r> fn(&'r u32)` + found type `fn(&u32)` error: aborting due to 5 previous errors -Some errors occurred: E0308, E0631. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed index 80a5a45a30580..5c6358beb2487 100644 --- a/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed +++ b/src/test/ui/closures/closure-immutable-outer-variable.rs.fixed @@ -1,13 +1,3 @@ -// 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. - // Point at the captured immutable outer variable fn foo(mut f: Box<FnMut()>) { diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr index 0795765ef2d8e..72e7211de7a7f 100644 --- a/src/test/ui/coercion/coerce-to-bang.stderr +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:6:17 | LL | foo(return, 22, 44); - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:18:13 | LL | foo(22, 44, return); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 | LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 | LL | foo(a, b, c); //~ ERROR mismatched types - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 | LL | foo(a, b, c); //~ ERROR mismatched types - | ^ expected !, found integral variable + | ^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -47,7 +47,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:50:21 | LL | let x: [!; 2] = [return, 22]; //~ ERROR mismatched types - | ^^^^^^^^^^^^ expected !, found integral variable + | ^^^^^^^^^^^^ expected !, found integer | = note: expected type `[!; 2]` found type `[{integer}; 2]` @@ -56,7 +56,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:55:22 | LL | let x: [!; 2] = [22, return]; //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -65,7 +65,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:60:37 | LL | let x: (usize, !, usize) = (22, 44, 66); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -74,7 +74,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:65:41 | LL | let x: (usize, !, usize) = (return, 44, 66); - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` @@ -83,7 +83,7 @@ error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:76:37 | LL | let x: (usize, !, usize) = (22, 44, return); //~ ERROR mismatched types - | ^^ expected !, found integral variable + | ^^ expected !, found integer | = note: expected type `!` found type `{integer}` diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs new file mode 100644 index 0000000000000..fb9a7fbf7aba5 --- /dev/null +++ b/src/test/ui/coherence/coherence-subtyping.rs @@ -0,0 +1,15 @@ +// Test that two distinct impls which match subtypes of one another +// yield coherence errors (or not) depending on the variance. + +trait TheTrait { + fn foo(&self) { } +} + +impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { +} + +impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + //~^ ERROR +} + +fn main() { } diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr new file mode 100644 index 0000000000000..1fc5c39d5c9fd --- /dev/null +++ b/src/test/ui/coherence/coherence-subtyping.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`: + --> $DIR/coherence-subtyping.rs:11:1 + | +LL | impl TheTrait for for<'a,'b> fn(&'a u8, &'b u8) -> &'a u8 { + | --------------------------------------------------------- first implementation here +... +LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index d557d70a52f10..f0d5a558e3529 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -1,8 +1,8 @@ const X: usize = 42 && 39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR: [i32; X] = [99; 34]; @@ -10,9 +10,9 @@ const ARR: [i32; X] = [99; 34]; const X1: usize = 42 || 39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR1: [i32; X1] = [99; 47]; @@ -20,9 +20,9 @@ const ARR1: [i32; X1] = [99; 47]; const X2: usize = -42 || -39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR2: [i32; X2] = [99; 18446744073709551607]; @@ -30,9 +30,9 @@ const ARR2: [i32; X2] = [99; 18446744073709551607]; const X3: usize = -42 && -39; //~^ ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected usize, found bool const ARR3: [i32; X3] = [99; 6]; diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 8ac3f617a3670..7885eb446f0dd 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:1:18 | LL | const X: usize = 42 && 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:1:24 | LL | const X: usize = 42 && 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -32,7 +32,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:11:19 | LL | const X1: usize = 42 || 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -41,7 +41,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:11:25 | LL | const X1: usize = 42 || 39; - | ^^ expected bool, found integral variable + | ^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:21:19 | LL | const X2: usize = -42 || -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -71,7 +71,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:21:26 | LL | const X2: usize = -42 || -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -92,7 +92,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:31:19 | LL | const X3: usize = -42 && -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` @@ -101,7 +101,7 @@ error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:31:26 | LL | const X3: usize = -42 && -39; - | ^^^ expected bool, found integral variable + | ^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr index 78099ea9e7cca..33fff4a0f68ed 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/conversion-methods.stderr @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here | ^ | | - | expected struct `std::string::String`, found integral variable + | expected struct `std::string::String`, found integer | help: try using a conversion method: `2.to_string()` | = note: expected type `std::string::String` diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr index 86beb0f33f64a..92fd9f26777f1 100644 --- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr @@ -23,28 +23,36 @@ LL | &(u8,)::AssocItem => {} | ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem` error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope - --> $DIR/bad-assoc-pat.rs:3:9 + --> $DIR/bad-assoc-pat.rs:3:15 | LL | [u8]::AssocItem => {} - | ^^^^^^^^^^^^^^^ associated item not found in `[u8]` + | ------^^^^^^^^^ + | | + | associated item not found in `[u8]` error[E0599]: no associated item named `AssocItem` found for type `(u8, u8)` in the current scope - --> $DIR/bad-assoc-pat.rs:6:9 + --> $DIR/bad-assoc-pat.rs:6:19 | LL | (u8, u8)::AssocItem => {} - | ^^^^^^^^^^^^^^^^^^^ associated item not found in `(u8, u8)` + | ----------^^^^^^^^^ + | | + | associated item not found in `(u8, u8)` error[E0599]: no associated item named `AssocItem` found for type `_` in the current scope - --> $DIR/bad-assoc-pat.rs:9:9 + --> $DIR/bad-assoc-pat.rs:9:12 | LL | _::AssocItem => {} - | ^^^^^^^^^^^^ associated item not found in `_` + | ---^^^^^^^^^ + | | + | associated item not found in `_` error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope - --> $DIR/bad-assoc-pat.rs:14:10 + --> $DIR/bad-assoc-pat.rs:14:17 | LL | &(u8,)::AssocItem => {} - | ^^^^^^^^^^^^^^^^ associated item not found in `(u8,)` + | -------^^^^^^^^^ + | | + | associated item not found in `(u8,)` error: aborting due to 8 previous errors diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr index 41dc15c1b81e7..8273fad476462 100644 --- a/src/test/ui/did_you_mean/issue-36798.stderr +++ b/src/test/ui/did_you_mean/issue-36798.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:7:7 | LL | f.baz; //~ ERROR no field - | ^^^ did you mean `bar`? + | ^^^ help: a field with a similar name exists: `bar` error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr index 808ff1670da09..e5dd61c45d662 100644 --- a/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr +++ b/src/test/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `submodule::Demo` has no field named `inocently_mispellable --> $DIR/issue-42599_available_fields_note.rs:16:39 | LL | Self { secret_integer: 2, inocently_mispellable: () } - | ^^^^^^^^^^^^^^^^^^^^^ field does not exist - did you mean `innocently_misspellable`? + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` error[E0560]: struct `submodule::Demo` has no field named `egregiously_nonexistent_field` --> $DIR/issue-42599_available_fields_note.rs:21:39 @@ -16,7 +16,7 @@ error[E0609]: no field `inocently_mispellable` on type `submodule::Demo` --> $DIR/issue-42599_available_fields_note.rs:32:41 | LL | let innocent_field_misaccess = demo.inocently_mispellable; - | ^^^^^^^^^^^^^^^^^^^^^ did you mean `innocently_misspellable`? + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` error[E0609]: no field `egregiously_nonexistent_field` on type `submodule::Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 diff --git a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr index 9f09c9b53ccea..301704ec0c7ef 100644 --- a/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr +++ b/src/test/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let sixteen: f32 = 16; | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `16.0` | = note: expected type `f32` @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | let a_million_and_seventy: f64 = 1_000_070; | ^^^^^^^^^ | | - | expected f64, found integral variable + | expected f64, found integer | help: use a float literal: `1_000_070.0` | = note: expected type `f64` @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | let negative_nine: f32 = -9; | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `-9.0` | = note: expected type `f32` @@ -38,7 +38,7 @@ error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:15:30 | LL | let sixteen_again: f64 = 0x10; - | ^^^^ expected f64, found integral variable + | ^^^^ expected f64, found integer | = note: expected type `f64` found type `{integer}` @@ -47,7 +47,7 @@ error[E0308]: mismatched types --> $DIR/issue-53280-expected-float-found-integer-literal.rs:17:30 | LL | let and_once_more: f32 = 0o20; - | ^^^^ expected f32, found integral variable + | ^^^^ expected f32, found integer | = note: expected type `f32` found type `{integer}` diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr index 483192149b850..af4253779a4f5 100644 --- a/src/test/ui/dont-suggest-private-trait-method.stderr +++ b/src/test/ui/dont-suggest-private-trait-method.stderr @@ -1,11 +1,13 @@ error[E0599]: no function or associated item named `new` found for type `T` in the current scope - --> $DIR/dont-suggest-private-trait-method.rs:4:5 + --> $DIR/dont-suggest-private-trait-method.rs:4:8 | LL | struct T; | --------- function or associated item `new` not found for this ... LL | T::new(); - | ^^^^^^ function or associated item not found in `T` + | ---^^^ + | | + | function or associated item not found in `T` error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index 5dd7030c77ec6..af1ac19c837d5 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -5,6 +5,10 @@ LL | produces_async! {} //~ ERROR expected identifier, found reserved keywor | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +help: you can escape reserved keywords to use them as identifiers + | +LL | ( ) => ( pub fn r#async ( ) { } ) + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index bd49948eb9531..52399362482bc 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -3,12 +3,20 @@ error: expected identifier, found reserved keyword `async` | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31 diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index 44d0e78d06a46..d997c3d8a421a 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -5,6 +5,10 @@ LL | produces_async! {} //~ ERROR expected identifier, found reserved keywor | ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +help: you can escape reserved keywords to use them as identifiers + | +LL | ( ) => ( pub fn r#async ( ) { } ) + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 8e596f743d7f7..1621368870a52 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -3,12 +3,20 @@ error: expected identifier, found reserved keyword `async` | LL | let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | let mut r#async = 1; //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: expected identifier, found reserved keyword `async` --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 | LL | module::async(); //~ ERROR expected identifier, found reserved keyword `async` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | module::r#async(); //~ ERROR expected identifier, found reserved keyword `async` + | ^^^^^^^ error: no rules expected the token `r#async` --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31 diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index be613121fe88e..d3e1cebd26fe1 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -47,20 +47,24 @@ LL | let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1 | did you mean `XEmpty1 { /* fields */ }`? error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope - --> $DIR/empty-struct-braces-expr.rs:22:15 + --> $DIR/empty-struct-braces-expr.rs:22:19 | LL | let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type - | ^^^^^^^^^^ variant not found in `empty_struct::XE` + | ----^^^^^^ + | | + | variant not found in `empty_struct::XE` | - = note: did you mean `empty_struct::XE::XEmpty3`? + = help: did you mean `XEmpty3`? error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope - --> $DIR/empty-struct-braces-expr.rs:23:15 + --> $DIR/empty-struct-braces-expr.rs:23:19 | LL | let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type - | ^^^^^^^^^^ variant not found in `empty_struct::XE` + | ----^^^^^^ + | | + | variant not found in `empty_struct::XE` | - = note: did you mean `empty_struct::XE::XEmpty3`? + = help: did you mean `XEmpty3`? error: aborting due to 8 previous errors diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/enum-variant-generic-args.rs new file mode 100644 index 0000000000000..6eddd70964546 --- /dev/null +++ b/src/test/ui/enum-variant-generic-args.rs @@ -0,0 +1,73 @@ +#![feature(type_alias_enum_variants)] + +enum Enum<T> { TSVariant(T), SVariant { v: T } } +type Alias<T> = Enum<T>; +type AliasFixed = Enum<()>; + +impl<T> Enum<T> { + fn ts_variant() { + Self::TSVariant(()); + //~^ ERROR mismatched types [E0308] + Self::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + Self::<()>::TSVariant(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR mismatched types [E0308] + Self::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR type arguments are not allowed on this entity [E0109] + } + + fn s_variant() { + Self::SVariant { v: () }; + //~^ ERROR mismatched types [E0308] + Self::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR mismatched types [E0308] + Self::<()>::SVariant { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR mismatched types [E0308] + Self::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR type arguments are not allowed on this entity [E0109] + //~^^^ ERROR mismatched types [E0308] + } +} + +fn main() { + // Tuple struct variant + + Enum::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + + Alias::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + Alias::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + + AliasFixed::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + AliasFixed::<()>::TSVariant(()); + //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + AliasFixed::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + + // Struct variant + + Enum::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + + Alias::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + Alias::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + + AliasFixed::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + AliasFixed::<()>::SVariant { v: () }; + //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] + AliasFixed::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107] +} diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/enum-variant-generic-args.stderr new file mode 100644 index 0000000000000..4d3b576734643 --- /dev/null +++ b/src/test/ui/enum-variant-generic-args.stderr @@ -0,0 +1,190 @@ +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:9:25 + | +LL | Self::TSVariant(()); + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:11:27 + | +LL | Self::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:13:16 + | +LL | Self::<()>::TSVariant(()); + | ^^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:13:31 + | +LL | Self::<()>::TSVariant(()); + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:16:16 + | +LL | Self::<()>::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:16:33 + | +LL | Self::<()>::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:22:29 + | +LL | Self::SVariant { v: () }; + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:24:26 + | +LL | Self::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:24:35 + | +LL | Self::SVariant::<()> { v: () }; + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:27:16 + | +LL | Self::<()>::SVariant { v: () }; + | ^^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:27:35 + | +LL | Self::<()>::SVariant { v: () }; + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:30:16 + | +LL | Self::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:30:32 + | +LL | Self::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:30:41 + | +LL | Self::<()>::SVariant::<()> { v: () }; + | ^^ expected type parameter, found () + | + = note: expected type `T` + found type `()` + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:40:29 + | +LL | Enum::<()>::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:43:24 + | +LL | Alias::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:45:30 + | +LL | Alias::<()>::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:48:29 + | +LL | AliasFixed::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:50:18 + | +LL | AliasFixed::<()>::TSVariant(()); + | ^^ unexpected type argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:52:18 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | ^^ unexpected type argument + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:52:35 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:58:28 + | +LL | Enum::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:61:23 + | +LL | Alias::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:63:29 + | +LL | Alias::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:66:28 + | +LL | AliasFixed::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:68:18 + | +LL | AliasFixed::<()>::SVariant { v: () }; + | ^^ unexpected type argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/enum-variant-generic-args.rs:70:18 + | +LL | AliasFixed::<()>::SVariant::<()> { v: () }; + | ^^ unexpected type argument + +error[E0109]: type arguments are not allowed on this entity + --> $DIR/enum-variant-generic-args.rs:70:34 + | +LL | AliasFixed::<()>::SVariant::<()> { v: () }; + | ^^ type argument not allowed + +error: aborting due to 28 previous errors + +Some errors occurred: E0107, E0109, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/error-codes/E0070.stderr b/src/test/ui/error-codes/E0070.stderr index a6a8925d99142..4c1cfd858e6c5 100644 --- a/src/test/ui/error-codes/E0070.stderr +++ b/src/test/ui/error-codes/E0070.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/E0070.rs:8:25 | LL | some_other_func() = 4; //~ ERROR E0070 - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr index 447b106c6296b..a5508f9808576 100644 --- a/src/test/ui/error-codes/E0109.stderr +++ b/src/test/ui/error-codes/E0109.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/E0109.rs:1:14 | LL | type X = u32<i32>; //~ ERROR E0109 - | ^^^ type parameter not allowed + | ^^^ type argument not allowed error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0110.rs b/src/test/ui/error-codes/E0110.rs index 2de5da16ad76a..764b62b8dfecf 100644 --- a/src/test/ui/error-codes/E0110.rs +++ b/src/test/ui/error-codes/E0110.rs @@ -1,4 +1,3 @@ type X = u32<'static>; //~ ERROR E0110 -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index 609b8b58276ff..a644ac92cefbf 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -1,8 +1,8 @@ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/E0110.rs:1:14 | LL | type X = u32<'static>; //~ ERROR E0110 - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0445.rs b/src/test/ui/error-codes/E0445.rs index 570c37ef2ccbe..a9a3aee2500fb 100644 --- a/src/test/ui/error-codes/E0445.rs +++ b/src/test/ui/error-codes/E0445.rs @@ -4,12 +4,9 @@ trait Foo { pub trait Bar : Foo {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub struct Bar2<T: Foo>(pub T); //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub fn foo<T: Foo> (t: T) {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait fn main() {} diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr index 747e4daf74ec2..d0d6ebe16c7f7 100644 --- a/src/test/ui/error-codes/E0445.stderr +++ b/src/test/ui/error-codes/E0445.stderr @@ -5,13 +5,13 @@ LL | pub trait Bar : Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:8:1 + --> $DIR/E0445.rs:7:1 | LL | pub struct Bar2<T: Foo>(pub T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:11:1 + --> $DIR/E0445.rs:9:1 | LL | pub fn foo<T: Foo> (t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait diff --git a/src/test/ui/error-codes/E0512.stderr b/src/test/ui/error-codes/E0512.stderr index 5b07afc29190c..998f6403f0b29 100644 --- a/src/test/ui/error-codes/E0512.stderr +++ b/src/test/ui/error-codes/E0512.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/E0512.rs:4:23 | LL | unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 | ^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: u16 (16 bits) - = note: target type: u8 (8 bits) + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr index 5a7cddbf38210..85110889e9a7b 100644 --- a/src/test/ui/error-codes/E0599.stderr +++ b/src/test/ui/error-codes/E0599.stderr @@ -1,11 +1,11 @@ error[E0599]: no associated item named `NotEvenReal` found for type `Foo` in the current scope - --> $DIR/E0599.rs:4:15 + --> $DIR/E0599.rs:4:20 | LL | struct Foo; | ----------- associated item `NotEvenReal` not found for this ... LL | || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 - | ^^^^^^^^^^^^^^^^^^ associated item not found in `Foo` + | -----^^^^^^^^^^^-- associated item not found in `Foo` error: aborting due to previous error diff --git a/src/test/ui/error-codes/ex-E0612.stderr b/src/test/ui/error-codes/ex-E0612.stderr index e65e8bd814266..0f498d1643905 100644 --- a/src/test/ui/error-codes/ex-E0612.stderr +++ b/src/test/ui/error-codes/ex-E0612.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `1` on type `Foo` --> $DIR/ex-E0612.rs:5:6 | LL | y.1; //~ ERROR no field `1` on type `Foo` - | ^ did you mean `0`? + | ^ help: a field with a similar name exists: `0` error: aborting due to previous error diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs new file mode 100644 index 0000000000000..bd151c8a4e4e7 --- /dev/null +++ b/src/test/ui/extenv/issue-55897.rs @@ -0,0 +1,15 @@ +use prelude::*; //~ ERROR unresolved import `prelude` + +mod unresolved_env { + use env; + + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR cannot determine resolution for the macro `env` +} + +mod nonexistent_env { + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR environment variable `NON_EXISTENT` not defined +} + +fn main() {} diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr new file mode 100644 index 0000000000000..4d2e35dff4629 --- /dev/null +++ b/src/test/ui/extenv/issue-55897.stderr @@ -0,0 +1,23 @@ +error: environment variable `NON_EXISTENT` not defined + --> $DIR/issue-55897.rs:11:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0432]: unresolved import `prelude` + --> $DIR/issue-55897.rs:1:5 + | +LL | use prelude::*; //~ ERROR unresolved import `prelude` + | ^^^^^^^ did you mean `std::prelude`? + +error: cannot determine resolution for the macro `env` + --> $DIR/issue-55897.rs:6:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr index 452a3ecfacd84..5c441189ea7cb 100644 --- a/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_ascii_idents.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:1:22 | LL | extern crate core as bäz; //~ ERROR non-ascii idents @@ -6,7 +6,7 @@ LL | extern crate core as bäz; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:3:5 | LL | use föö::bar; //~ ERROR non-ascii idents @@ -14,7 +14,7 @@ LL | use föö::bar; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:5:5 | LL | mod föö { //~ ERROR non-ascii idents @@ -22,7 +22,7 @@ LL | mod föö { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:9:4 | LL | fn bär( //~ ERROR non-ascii idents @@ -30,7 +30,7 @@ LL | fn bär( //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:10:5 | LL | bäz: isize //~ ERROR non-ascii idents @@ -38,7 +38,7 @@ LL | bäz: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:12:9 | LL | let _ö: isize; //~ ERROR non-ascii idents @@ -46,7 +46,7 @@ LL | let _ö: isize; //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:15:10 | LL | (_ä, _) => {} //~ ERROR non-ascii idents @@ -54,7 +54,7 @@ LL | (_ä, _) => {} //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:19:8 | LL | struct Föö { //~ ERROR non-ascii idents @@ -62,7 +62,7 @@ LL | struct Föö { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:20:5 | LL | föö: isize //~ ERROR non-ascii idents @@ -70,7 +70,7 @@ LL | föö: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:23:6 | LL | enum Bär { //~ ERROR non-ascii idents @@ -78,7 +78,7 @@ LL | enum Bär { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:24:5 | LL | Bäz { //~ ERROR non-ascii idents @@ -86,7 +86,7 @@ LL | Bäz { //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:25:9 | LL | qüx: isize //~ ERROR non-ascii idents @@ -94,7 +94,7 @@ LL | qüx: isize //~ ERROR non-ascii idents | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/feature-gate-non_ascii_idents.rs:30:8 | LL | fn qüx(); //~ ERROR non-ascii idents diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs new file mode 100644 index 0000000000000..8997c1824ca6d --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs @@ -0,0 +1,29 @@ +// 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. + +enum Foo { + Bar(i32), + Baz { i: i32 }, +} + +type Alias = Foo; + +fn main() { + let t = Alias::Bar(0); + //~^ ERROR enum variants on type aliases are experimental + let t = Alias::Baz { i: 0 }; + //~^ ERROR enum variants on type aliases are experimental + match t { + Alias::Bar(_i) => {} + //~^ ERROR enum variants on type aliases are experimental + Alias::Baz { i: _i } => {} + //~^ ERROR enum variants on type aliases are experimental + } +} diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr new file mode 100644 index 0000000000000..cba643e18ca1a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr @@ -0,0 +1,34 @@ +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:19:13 + | +LL | let t = Alias::Bar(0); + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:21:13 + | +LL | let t = Alias::Baz { i: 0 }; + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:24:9 + | +LL | Alias::Bar(_i) => {} + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error: enum variants on type aliases are experimental + --> $DIR/feature-gate-type_alias_enum_variants.rs:26:9 + | +LL | Alias::Baz { i: _i } => {} + | ^^^^^^^^^^ + | + = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/float-literal-inference-restrictions.stderr index ea12c9caa77cc..a69c13507e6b2 100644 --- a/src/test/ui/float-literal-inference-restrictions.stderr +++ b/src/test/ui/float-literal-inference-restrictions.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let x: f32 = 1; //~ ERROR mismatched types | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `1.0` | = note: expected type `f32` diff --git a/src/test/ui/fmt/format-string-error-2.rs b/src/test/ui/fmt/format-string-error-2.rs index fd6e41ec6fca7..5c25ae502ff6d 100644 --- a/src/test/ui/fmt/format-string-error-2.rs +++ b/src/test/ui/fmt/format-string-error-2.rs @@ -67,4 +67,21 @@ raw { \n asdf} ", asdf=1); //~^^ ERROR invalid format string + println!("\t{}"); + //~^ ERROR 1 positional argument in format string + + // note: `\x7B` is `{` + println!("\x7B}\u{8} {", 1); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + + println!("\x7B}\u8 {", 1); + //~^ ERROR incorrect unicode escape sequence + //~| ERROR argument never used + + // note: raw strings don't escape `\xFF` and `\u{FF}` sequences + println!(r#"\x7B}\u{8} {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found + + println!(r#"\x7B}\u8 {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found } diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index 0b3f08c1fbe8d..baab8529940c5 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -1,3 +1,11 @@ +error: incorrect unicode escape sequence + --> $DIR/format-string-error-2.rs:77:20 + | +LL | println!("/x7B}/u8 {", 1); + | ^^- + | | + | help: format of unicode escape sequences uses braces: `/u{8}` + error: invalid format string: expected `'}'`, found `'a'` --> $DIR/format-string-error-2.rs:5:5 | @@ -133,5 +141,45 @@ LL | asdf} | = note: if you intended to print `{`, you can escape it using `{{` -error: aborting due to 13 previous errors +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-string-error-2.rs:70:17 + | +LL | println!("/t{}"); + | ^^ + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error-2.rs:74:27 + | +LL | println!("/x7B}/u{8} {", 1); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: argument never used + --> $DIR/format-string-error-2.rs:77:28 + | +LL | println!("/x7B}/u8 {", 1); + | ------------ ^ argument never used + | | + | formatting specifier missing + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:82:21 + | +LL | println!(r#"/x7B}/u{8} {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:85:21 + | +LL | println!(r#"/x7B}/u8 {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 19 previous errors diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs index 8fdcbbae8debf..7e5b884103ed2 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -6,5 +6,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `std::option::Option<usize>` //~| found type `{integer}` - //~| expected enum `std::option::Option`, found integral variable + //~| expected enum `std::option::Option`, found integer } diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr index d16cbcfe1d5f4..62ded3e255a44 100644 --- a/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr +++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | x = 5; | ^ | | - | expected enum `std::option::Option`, found integral variable + | expected enum `std::option::Option`, found integer | help: try using a variant of the expected type: `Some(5)` | = note: expected type `std::option::Option<usize>` diff --git a/src/test/ui/generator/auto-trait-regions.rs b/src/test/ui/generator/auto-trait-regions.rs index 2110e8a5407ba..46d7289943857 100644 --- a/src/test/ui/generator/auto-trait-regions.rs +++ b/src/test/ui/generator/auto-trait-regions.rs @@ -27,7 +27,8 @@ fn main() { yield; assert_foo(x); }; - assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied + assert_foo(gen); + //~^ ERROR implementation of `Foo` is not general enough // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); @@ -44,5 +45,6 @@ fn main() { yield; assert_foo(a); }; - assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied + assert_foo(gen); + //~^ ERROR not general enough } diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index a301dc2ff9a00..1b4dfe2df1c0c 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -1,37 +1,20 @@ -error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` +error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:30:5 | -LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied - | ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No` - | - = help: the following implementations were found: - <No as Foo> - = note: required because it appears within the type `OnlyFooIfStaticRef` - = note: required because it appears within the type `&OnlyFooIfStaticRef` - = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}` - = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:25:15: 29:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]` -note: required by `assert_foo` - --> $DIR/auto-trait-regions.rs:20:1 +LL | assert_foo(gen); + | ^^^^^^^^^^ | -LL | fn assert_foo<T: Foo>(f: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo` for any lifetime `'0` + = note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for the lifetime `'1` -error[E0279]: the requirement `for<'r, 's> 'r : 's` is not satisfied (`expected bound lifetime parameter, found concrete lifetime`) - --> $DIR/auto-trait-regions.rs:47:5 +error: implementation of `Foo` is not general enough + --> $DIR/auto-trait-regions.rs:48:5 | -LL | assert_foo(gen); //~ ERROR the requirement `for<'r, 's> 'r : 's` is not satisfied +LL | assert_foo(gen); | ^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'r, 's> Foo` for `A<'_, '_>` - = note: required because it appears within the type `for<'r, 's> {A<'r, 's>, ()}` - = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:42:15: 46:6 for<'r, 's> {A<'r, 's>, ()}]` -note: required by `assert_foo` - --> $DIR/auto-trait-regions.rs:20:1 - | -LL | fn assert_foo<T: Foo>(f: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1` + = note: but `A<'_, '2>` only implements `Foo` for the lifetime `'2` error: aborting due to 2 previous errors -Some errors occurred: E0277, E0279. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.stderr b/src/test/ui/generic/generic-arg-mismatch-recover.stderr index 1576b3c3915f9..37f6c61f06df3 100644 --- a/src/test/ui/generic/generic-arg-mismatch-recover.stderr +++ b/src/test/ui/generic/generic-arg-mismatch-recover.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/generic-arg-mismatch-recover.rs:6:33 | LL | Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments - | ^^ expected (), found integral variable + | ^^ expected (), found integer | = note: expected type `&'static ()` found type `&{integer}` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index 8e2b0b8c60045..bdfabdabbebb7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index dbb5018139076..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), -LL | | for<'a> fn(&'a u32, &'a u32)) } - | |__________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>` - found type `std::option::Option<for<'a> fn(&'a u32, &'a u32)>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index db9892b48a6f7..74b8c89b6e86f 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index e9fb73411bd39..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), -LL | | for<'a> fn(Co<'a>, Co<'a>)) } - | |______________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>` - found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index d0e80faa68e8b..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, -LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } - | |______________________________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>` - found type `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index 3605ecf4f8667..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -1,16 +1,14 @@ -error[E0308]: mismatched types - --> $DIR/hr-subtype.rs:39:26 +error: compilation successful + --> $DIR/hr-subtype.rs:96:1 | -LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a -... -LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, -LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } - | |______________________________________________________________________________________________- in this macro invocation - | - = note: expected type `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>` - found type `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>` +LL | / fn main() { +LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful +LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful +LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful +LL | | } + | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index fae6e9b5c89ca..8168941e2777c 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:39:26 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a + | ^^^^^^^^^^^ one type is more general than the other ... LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 5fcb63e17bf31..25b74d855bb48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -1,12 +1,12 @@ error: compilation successful - --> $DIR/hr-subtype.rs:100:1 + --> $DIR/hr-subtype.rs:96:1 | LL | / fn main() { LL | | //[bound_a_vs_bound_a]~^ ERROR compilation successful LL | | //[bound_a_vs_bound_b]~^^ ERROR compilation successful LL | | //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful -LL | | //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful -LL | | //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +... | +LL | | //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful LL | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index 4157953fb9068..ad4f39f840528 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -31,21 +31,17 @@ macro_rules! check { #[cfg($rev)] fn subtype<'x,'y:'x,'z:'y>() { gimme::<$t2>(None::<$t1>); - //[free_inv_x_vs_free_inv_y]~^ ERROR mismatched types + //[free_inv_x_vs_free_inv_y]~^ ERROR } #[cfg($rev)] fn supertype<'x,'y:'x,'z:'y>() { gimme::<$t1>(None::<$t2>); - //[bound_a_vs_free_x]~^ ERROR mismatched types - //[free_x_vs_free_y]~^^ ERROR mismatched types - //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR mismatched types - //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR mismatched types - //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR mismatched types - //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types - //[bound_co_a_b_vs_bound_co_a]~^^^^^^^ ERROR mismatched types - //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR mismatched types - //[bound_co_a_co_b_ret_contra_a]~^^^^^^^^^ ERROR mismatched types + //[bound_a_vs_free_x]~^ ERROR + //[free_x_vs_free_y]~^^ ERROR + //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR + //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR + //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR } } } @@ -103,4 +99,8 @@ fn main() { //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR compilation successful //[bound_co_a_vs_bound_co_b]~^^^^ ERROR compilation successful //[free_x_vs_free_x]~^^^^^ ERROR compilation successful +//[bound_a_b_vs_bound_a]~^^^^^^ ERROR compilation successful +//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR compilation successful +//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^ ERROR compilation successful +//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR compilation successful } diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.rs b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs new file mode 100644 index 0000000000000..a20d03c7747cd --- /dev/null +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.rs @@ -0,0 +1,24 @@ +// Regression test for #54302. +// +// We were incorrectly using the "evaluation cache" (which ignored +// region results) to conclude that `&'static str: Deserialize`, even +// though it would require that `for<'de> 'de: 'static`, which is +// clearly false. + +trait Deserialize<'de> {} + +trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {} + +// Based on this impl, `&'static str` only implements Deserialize<'static>. +// It does not implement for<'de> Deserialize<'de>. +impl<'de: 'a, 'a> Deserialize<'de> for &'a str {} + +fn main() { + fn assert_deserialize_owned<T: DeserializeOwned>() {} + assert_deserialize_owned::<&'static str>(); //~ ERROR + + // It correctly does not implement for<'de> Deserialize<'de>. + // fn assert_hrtb<T: for<'de> Deserialize<'de>>() {} + // assert_hrtb::<&'static str>(); +} diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr new file mode 100644 index 0000000000000..e82fa51524ef1 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -0,0 +1,11 @@ +error: implementation of `Deserialize` is not general enough + --> $DIR/hrtb-cache-issue-54302.rs:19:5 + | +LL | assert_deserialize_owned::<&'static str>(); //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` + = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs index 8953a847213d5..391303676d784 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.rs +++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs @@ -25,6 +25,6 @@ impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct } fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region -fn b() { want_foo2::<SomeStruct>(); } //~ ERROR E0277 +fn b() { want_foo2::<SomeStruct>(); } //~ ERROR fn main() { } diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index e2a99ea8472ba..2ee398e3dd3b2 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,20 +1,12 @@ -error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied +error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:28:10 | -LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` +LL | fn b() { want_foo2::<SomeStruct>(); } //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the following implementations were found: - <SomeStruct as Foo<(&'a isize, &'a isize)>> -note: required by `want_foo2` - --> $DIR/hrtb-conflate-regions.rs:8:1 - | -LL | / fn want_foo2<T>() -LL | | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> -LL | | { -LL | | } - | |_^ + = note: Due to a where-clause on `want_foo2`, + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` + = note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs new file mode 100644 index 0000000000000..828331cb950ed --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs @@ -0,0 +1,18 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +fn foo<'a>() -> fn(&'a u32) { + panic!() +} + +fn main() { + // Here, proving that `fn(&'a u32) <: for<'b> fn(&'b u32)`: + // + // - instantiates `'b` with a placeholder `!b`, + // - requires that `&!b u32 <: &'a u32` and hence that `!b: 'a`, + // - but we can never know this. + + let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr new file mode 100644 index 0000000000000..6301ed45ac277 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/hrtb-exists-forall-fn.rs:17:34 + | +LL | let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types + | ^^^^^ one type is more general than the other + | + = note: expected type `for<'b> fn(&'b u32)` + found type `fn(&u32)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs new file mode 100644 index 0000000000000..8801760056ecb --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -0,0 +1,35 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. +// +// compile-pass + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(&'b u32)>, +{ +} + +impl<'a> Trait<fn(&'a u32)> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(&?a u32) <: for<'b> fn(&'b u32)` :- + // - `&'!b u32 <: &?a u32` + // - `!'b: ?a` -- solveable if `?a` is inferred to `'empty` + // - `for<'b> fn(&'b u32) <: fn(&?a u32)` :- + // - `&?a u32 u32 <: &?b u32` + // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'empty`. + + foo::<()>(); +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs new file mode 100644 index 0000000000000..da1bb7cd5fd0b --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -0,0 +1,37 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. +// +// compile-pass + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(fn(&'b u32))>, +{ +} + +impl<'a> Trait<fn(fn(&'a u32))> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>` + // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :- + // - `fn(&!b u32) <: fn(&?a u32)` + // - `&?a u32 <: &!b u32` + // - `?a: !'b` -- solveable if `?a` is inferred to `'static` + // - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :- + // - `fn(&?a u32) <: fn(&?b u32)` + // - `&?b u32 <: &?a u32` + // - `?b: ?a` -- solveable if `?b` is inferred to `'static` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'static`. + + foo::<()>(); +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs new file mode 100644 index 0000000000000..da3f8ad1b8957 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -0,0 +1,29 @@ +// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +use std::cell::Cell; + +trait Trait<T> {} + +fn foo<T>() +where + T: Trait<for<'b> fn(Cell<&'b u32>)>, +{ +} + +impl<'a> Trait<fn(Cell<&'a u32>)> for () {} + +fn main() { + // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }` + // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` + // - This requires (among other things) instantiating `'b` universally, + // yielding `fn(&!b u32)`, in a fresh universe U1 + // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. + + foo::<()>(); //~ ERROR not general enough +} diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr new file mode 100644 index 0000000000000..6a61181e2407c --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -0,0 +1,12 @@ +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); //~ ERROR not general enough + | ^^^^^^^^^ + | + = note: Due to a where-clause on `foo`, + = note: `()` must implement `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` + = note: but `()` only implements `Trait<fn(std::cell::Cell<&'0 u32>)>` for some lifetime `'0` + +error: aborting due to previous error + diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs index 99001d7053c62..f9ae1429ee4a2 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.rs @@ -44,7 +44,7 @@ fn want_qux<B>(b: &B) where B : Qux { want_foo_for_any_tcx(b); - want_bar_for_any_ccx(b); //~ ERROR E0277 + want_bar_for_any_ccx(b); //~ ERROR } fn main() {} diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index d233ed475241a..0d7b5cbf82348 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -1,19 +1,12 @@ -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:5 | -LL | want_bar_for_any_ccx(b); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` +LL | want_bar_for_any_ccx(b); //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:31:1 - | -LL | / fn want_bar_for_any_ccx<B>(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | } - | |_^ + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'static>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs index f430a10d2a722..3d2d403462d8b 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.rs @@ -15,7 +15,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) where F : Foo<'x> { want_foo_for_some_tcx(f); - want_foo_for_any_tcx(f); //~ ERROR E0277 + want_foo_for_any_tcx(f); //~ ERROR E0308 } fn want_foo_for_any_tcx<F>(f: &F) @@ -32,7 +32,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_foo_for_any_tcx(b); want_bar_for_some_ccx(b); - want_bar_for_any_ccx(b); //~ ERROR E0277 + want_bar_for_any_ccx(b); //~ ERROR E0308 } fn want_bar_for_any_ccx<B>(b: &B) diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index fe485c5b259eb..31dbeec2a551b 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,40 +1,21 @@ -error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits.rs:18:5 | -LL | want_foo_for_any_tcx(f); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` +LL | want_foo_for_any_tcx(f); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound -note: required by `want_foo_for_any_tcx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 - | -LL | / fn want_foo_for_any_tcx<F>(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> -LL | | { -LL | | want_foo_for_some_tcx(f); -LL | | want_foo_for_any_tcx(f); -LL | | } - | |_^ + = note: expected type `for<'tcx> Foo<'tcx>` + found type `Foo<'x>` -error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-higher-ranker-supertraits.rs:35:5 | -LL | want_bar_for_any_ccx(b); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound -note: required by `want_bar_for_any_ccx` - --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 +LL | want_bar_for_any_ccx(b); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | -LL | / fn want_bar_for_any_ccx<B>(b: &B) -LL | | where B : for<'ccx> Bar<'ccx> -LL | | { -LL | | want_foo_for_some_tcx(b); -... | -LL | | want_bar_for_any_ccx(b); -LL | | } - | |_^ + = note: expected type `for<'ccx> Bar<'ccx>` + found type `Bar<'x>` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.rs b/src/test/ui/hrtb/hrtb-just-for-static.rs index c162c777c0bad..88d5ce8e64056 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.rs +++ b/src/test/ui/hrtb/hrtb-just-for-static.rs @@ -21,7 +21,13 @@ fn give_any() { struct StaticInt; impl Foo<&'static isize> for StaticInt { } fn give_static() { - want_hrtb::<StaticInt>() //~ ERROR `for<'a> StaticInt: Foo<&'a isize>` is not satisfied + want_hrtb::<StaticInt>() //~ ERROR +} + +// AnyInt implements Foo<&'a isize> for any 'a, so it is a match. +impl<'a> Foo<&'a isize> for &'a u32 { } +fn give_some<'a>() { + want_hrtb::<&'a u32>() //~ ERROR } fn main() { } diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 38865fac86ded..094c449802415 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -1,20 +1,22 @@ -error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied +error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | want_hrtb::<StaticInt>() //~ ERROR `for<'a> StaticInt: Foo<&'a isize>` is not satisfied - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt` +LL | want_hrtb::<StaticInt>() //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^ | - = help: the following implementations were found: - <StaticInt as Foo<&'static isize>> -note: required by `want_hrtb` - --> $DIR/hrtb-just-for-static.rs:8:1 + = note: Due to a where-clause on `want_hrtb`, + = note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0` + = note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1` + +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^ | -LL | / fn want_hrtb<T>() -LL | | where T : for<'a> Foo<&'a isize> -LL | | { -LL | | } - | |_^ + = note: Due to a where-clause on `want_hrtb`, + = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` + = note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 90e1773a3f62d..7bd89960e42e5 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs @@ -43,7 +43,7 @@ fn foo_hrtb_bar_not<'b,T>(mut t: T) // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // clause only specifies `T : Bar<&'b isize>`. - foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied + foo_hrtb_bar_not(&mut t); //~ ERROR E0308 } fn foo_hrtb_bar_hrtb<T>(mut t: T) diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 6cada7ac78f4b..ec3bf8a1a1be3 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -1,23 +1,12 @@ -error[E0277]: the trait bound `for<'a> T: Bar<&'a isize>` is not satisfied +error[E0308]: mismatched types --> $DIR/hrtb-perfect-forwarding.rs:46:5 | -LL | foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied - | ^^^^^^^^^^^^^^^^ the trait `for<'a> Bar<&'a isize>` is not implemented for `T` +LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308 + | ^^^^^^^^^^^^^^^^ one type is more general than the other | - = help: consider adding a `where for<'a> T: Bar<&'a isize>` bound - = note: required because of the requirements on the impl of `for<'a> Foo<&'a isize>` for `&mut T` -note: required by `foo_hrtb_bar_not` - --> $DIR/hrtb-perfect-forwarding.rs:39:1 - | -LL | / fn foo_hrtb_bar_not<'b,T>(mut t: T) -LL | | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> -LL | | { -LL | | // Not OK -- The forwarding impl for `Foo` requires that `Bar` also -... | -LL | | foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> T: Bar<&'a isize>` is not satisfied -LL | | } - | |_^ + = note: expected type `Foo<&'a isize>` + found type `Foo<&isize>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/if/if-let-arm-types.rs b/src/test/ui/if/if-let-arm-types.rs index ca115cc219e95..749c089ae9752 100644 --- a/src/test/ui/if/if-let-arm-types.rs +++ b/src/test/ui/if/if-let-arm-types.rs @@ -1,6 +1,6 @@ fn main() { if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types - //~^ expected (), found integral variable + //~^ expected (), found integer //~| expected type `()` //~| found type `{integer}` () diff --git a/src/test/ui/if/if-let-arm-types.stderr b/src/test/ui/if/if-let-arm-types.stderr index 23cf5a45af055..fcf9e4695f675 100644 --- a/src/test/ui/if/if-let-arm-types.stderr +++ b/src/test/ui/if/if-let-arm-types.stderr @@ -2,13 +2,13 @@ error[E0308]: `if let` arms have incompatible types --> $DIR/if-let-arm-types.rs:2:5 | LL | / if let Some(b) = None { //~ ERROR: `if let` arms have incompatible types -LL | | //~^ expected (), found integral variable +LL | | //~^ expected (), found integer LL | | //~| expected type `()` LL | | //~| found type `{integer}` ... | LL | | 1 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 3ae8669a7f244..d4153ac94acd1 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -16,7 +16,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:9:20 | LL | format!("{1}", 1); - | ----- ^ + | ----- ^ argument never used | | | formatting specifier missing @@ -80,15 +80,16 @@ error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:32:17 | LL | format!("", 1, 2); //~ ERROR: multiple unused formatting arguments - | -- ^ ^ - | | + | -- ^ ^ argument never used + | | | + | | argument never used | multiple missing formatting specifiers error: argument never used --> $DIR/ifmt-bad-arg.rs:33:22 | LL | format!("{}", 1, 2); //~ ERROR: argument never used - | ---- ^ + | ---- ^ argument never used | | | formatting specifier missing @@ -96,7 +97,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:34:20 | LL | format!("{1}", 1, 2); //~ ERROR: argument never used - | ----- ^ + | ----- ^ argument never used | | | formatting specifier missing @@ -104,7 +105,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:35:26 | LL | format!("{}", 1, foo=2); //~ ERROR: named argument never used - | ---- ^ + | ---- ^ named argument never used | | | formatting specifier missing @@ -112,7 +113,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:36:22 | LL | format!("{foo}", 1, foo=2); //~ ERROR: argument never used - | ------- ^ + | ------- ^ argument never used | | | formatting specifier missing @@ -120,7 +121,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:37:21 | LL | format!("", foo=2); //~ ERROR: named argument never used - | -- ^ + | -- ^ named argument never used | | | formatting specifier missing @@ -128,8 +129,9 @@ error: multiple unused formatting arguments --> $DIR/ifmt-bad-arg.rs:38:32 | LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments - | ------- ^ ^ - | | + | ------- ^ ^ named argument never used + | | | + | | named argument never used | multiple missing formatting specifiers error: duplicate argument named `foo` @@ -160,7 +162,7 @@ error: named argument never used --> $DIR/ifmt-bad-arg.rs:45:51 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ------------------- ^ + | ------------------- ^ named argument never used | | | formatting specifier missing @@ -194,7 +196,7 @@ error: argument never used --> $DIR/ifmt-bad-arg.rs:56:27 | LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used - | -- ^^^^^ + | -- ^^^^^ argument never used | | | help: format specifiers use curly braces: `{}` | diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issue-49376.rs index 4a45988e45d7f..13671b8dbf448 100644 --- a/src/test/ui/impl-trait/issue-49376.rs +++ b/src/test/ui/impl-trait/issue-49376.rs @@ -9,9 +9,11 @@ fn gen() -> impl PartialOrd + PartialEq + Debug { } struct Bar {} trait Foo<T = Self> {} +trait FooNested<T = Option<Self>> {} impl Foo for Bar {} +impl FooNested for Bar {} -fn foo() -> impl Foo { +fn foo() -> impl Foo + FooNested { Bar {} } diff --git a/src/test/ui/imports/auxiliary/glob-conflict.rs b/src/test/ui/imports/auxiliary/glob-conflict.rs index ac12ed9c81c77..c83db64c6437c 100644 --- a/src/test/ui/imports/auxiliary/glob-conflict.rs +++ b/src/test/ui/imports/auxiliary/glob-conflict.rs @@ -7,3 +7,7 @@ mod m2 { pub use m1::*; pub use m2::*; + +pub mod glob { + pub use *; +} diff --git a/src/test/ui/imports/duplicate.rs b/src/test/ui/imports/duplicate.rs index 95bb69043e9bf..db6538969ec71 100644 --- a/src/test/ui/imports/duplicate.rs +++ b/src/test/ui/imports/duplicate.rs @@ -33,11 +33,11 @@ mod g { fn main() { e::foo(); f::foo(); //~ ERROR `foo` is ambiguous - g::foo(); //~ ERROR `foo` is ambiguous + g::foo(); } mod ambiguous_module_errors { - pub mod m1 { pub use super::m1 as foo; } + pub mod m1 { pub use super::m1 as foo; pub fn bar() {} } pub mod m2 { pub use super::m2 as foo; } use self::m1::*; diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 3df2c5930e86e..acd66826fdfb7 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -50,25 +50,6 @@ LL | pub use b::*; | ^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) - --> $DIR/duplicate.rs:36:8 - | -LL | g::foo(); //~ ERROR `foo` is ambiguous - | ^^^ ambiguous name - | -note: `foo` could refer to the function imported here - --> $DIR/duplicate.rs:29:13 - | -LL | pub use a::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate -note: `foo` could also refer to the unresolved item imported here - --> $DIR/duplicate.rs:30:13 - | -LL | pub use f::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate - error[E0659]: `foo` is ambiguous (glob import vs glob import in the same module) --> $DIR/duplicate.rs:49:9 | @@ -88,7 +69,7 @@ LL | use self::m2::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors occurred: E0252, E0659. For more information about an error, try `rustc --explain E0252`. diff --git a/src/test/ui/imports/glob-conflict-cross-crate.rs b/src/test/ui/imports/glob-conflict-cross-crate.rs index e02148b19f786..c8b18525d8059 100644 --- a/src/test/ui/imports/glob-conflict-cross-crate.rs +++ b/src/test/ui/imports/glob-conflict-cross-crate.rs @@ -4,4 +4,5 @@ extern crate glob_conflict; fn main() { glob_conflict::f(); //~ ERROR cannot find function `f` in module `glob_conflict` + glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` } diff --git a/src/test/ui/imports/glob-conflict-cross-crate.stderr b/src/test/ui/imports/glob-conflict-cross-crate.stderr index f64637fd6f625..f5a82ef1b3b01 100644 --- a/src/test/ui/imports/glob-conflict-cross-crate.stderr +++ b/src/test/ui/imports/glob-conflict-cross-crate.stderr @@ -4,6 +4,12 @@ error[E0425]: cannot find function `f` in module `glob_conflict` LL | glob_conflict::f(); //~ ERROR cannot find function `f` in module `glob_conflict` | ^ not found in `glob_conflict` -error: aborting due to previous error +error[E0425]: cannot find function `f` in module `glob_conflict::glob` + --> $DIR/glob-conflict-cross-crate.rs:7:26 + | +LL | glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` + | ^ not found in `glob_conflict::glob` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr index 559979e5d51c3..210f6a4399635 100644 --- a/src/test/ui/imports/issue-56125.stderr +++ b/src/test/ui/imports/issue-56125.stderr @@ -42,12 +42,12 @@ LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous | = note: `issue_56125` could refer to an extern crate passed with `--extern` = help: use `::issue_56125` to refer to this extern crate unambiguously -note: `issue_56125` could also refer to the unresolved item imported here - --> $DIR/issue-56125.rs:19:9 +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:20:9 | -LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` - | ^^^^^^^^^^^^^^^^^^ - = help: use `self::issue_56125` to refer to this unresolved item unambiguously +LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous + | ^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously error: aborting due to 4 previous errors diff --git a/src/test/ui/imports/issue-57015.rs b/src/test/ui/imports/issue-57015.rs new file mode 100644 index 0000000000000..27688fd34f62f --- /dev/null +++ b/src/test/ui/imports/issue-57015.rs @@ -0,0 +1,13 @@ +mod glob_ok { + pub mod something { + pub mod something_else {} + } +} + +mod single_err {} + +use glob_ok::*; // glob_ok::something +use single_err::something; //~ ERROR unresolved import `single_err::something` +use something::something_else; + +fn main() {} diff --git a/src/test/ui/imports/issue-57015.stderr b/src/test/ui/imports/issue-57015.stderr new file mode 100644 index 0000000000000..b0fcf5bec6a77 --- /dev/null +++ b/src/test/ui/imports/issue-57015.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `single_err::something` + --> $DIR/issue-57015.rs:10:5 + | +LL | use single_err::something; //~ ERROR unresolved import `single_err::something` + | ^^^^^^^^^^^^^^^^^^^^^ no `something` in `single_err` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr index 42ee68073fbc5..40cb10ced16f5 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:20:32 | LL | exported!(); @@ -9,7 +9,7 @@ LL | () => ( struct Б; ) //~ ERROR non-ascii idents are not ful | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:36:24 | LL | panic!(); @@ -20,7 +20,7 @@ LL | () => ( struct Г; ) //~ ERROR non-ascii idents are not fully suppo | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/local-modularized-tricky-fail-2.rs:46:24 | LL | include!(); diff --git a/src/test/ui/integral-variable-unification-error.rs b/src/test/ui/integral-variable-unification-error.rs index 98a77e9c82f67..3eefcdea3d902 100644 --- a/src/test/ui/integral-variable-unification-error.rs +++ b/src/test/ui/integral-variable-unification-error.rs @@ -4,5 +4,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `{integer}` //~| found type `{float}` - //~| expected integral variable, found floating-point variable + //~| expected integer, found floating-point number } diff --git a/src/test/ui/integral-variable-unification-error.stderr b/src/test/ui/integral-variable-unification-error.stderr index 7670f7a0e8da7..262203b7b8e4d 100644 --- a/src/test/ui/integral-variable-unification-error.stderr +++ b/src/test/ui/integral-variable-unification-error.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/integral-variable-unification-error.rs:3:9 | LL | x = 5.0; - | ^^^ expected integral variable, found floating-point variable + | ^^^ expected integer, found floating-point number | = note: expected type `{integer}` found type `{float}` diff --git a/src/test/ui/invalid/invalid-path-in-const.stderr b/src/test/ui/invalid/invalid-path-in-const.stderr index 6541c92c691c8..13176b8b8fb15 100644 --- a/src/test/ui/invalid/invalid-path-in-const.stderr +++ b/src/test/ui/invalid/invalid-path-in-const.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `DOESNOTEXIST` found for type `u32` in the current scope - --> $DIR/invalid-path-in-const.rs:2:18 + --> $DIR/invalid-path-in-const.rs:2:23 | LL | fn f(a: [u8; u32::DOESNOTEXIST]) {} - | ^^^^^^^^^^^^^^^^^ associated item not found in `u32` + | -----^^^^^^^^^^^^ + | | + | associated item not found in `u32` error: aborting due to previous error diff --git a/src/test/ui/issue-54943-1.rs b/src/test/ui/issue-54943-1.rs new file mode 100644 index 0000000000000..7750e34036192 --- /dev/null +++ b/src/test/ui/issue-54943-1.rs @@ -0,0 +1,15 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/issue-54943-2.rs b/src/test/ui/issue-54943-2.rs new file mode 100644 index 0000000000000..f829c38c35d23 --- /dev/null +++ b/src/test/ui/issue-54943-2.rs @@ -0,0 +1,18 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. In particular, this test is in unreachable +// code as the initial fix for this ICE only worked if the code was reachable. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + return; + + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/issue-54943-3.rs b/src/test/ui/issue-54943-3.rs new file mode 100644 index 0000000000000..185077bd684a8 --- /dev/null +++ b/src/test/ui/issue-54943-3.rs @@ -0,0 +1,21 @@ +// compile-pass +// FIXME(#54943) This test targets the scenario where proving the WF requirements requires +// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring +// out the value of that `_` requires type-checking the surrounding code, but that code is dead, +// so our NLL region checker doesn't have access to it. This test should actually fail to compile. + +#![feature(nll)] +#![allow(warnings)] + +use std::fmt::Debug; + +fn foo<T: 'static + Debug>(_: T) { } + +fn bar<'a>() { + return; + + let _x = foo::<Vec<_>>(Vec::<&'a u32>::new()); + //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477] +} + +fn main() {} diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs new file mode 100644 index 0000000000000..c720f62797580 --- /dev/null +++ b/src/test/ui/issue-54943.rs @@ -0,0 +1,17 @@ +// compile-pass +// FIXME(#54943) This test targets the scenario where proving the WF requirements of a user +// type annotation requires checking dead code. This test should actually fail to compile. + +#![feature(nll)] +#![allow(warnings)] + +fn foo<T: 'static>() { } + +fn boo<'a>() { + return; + + let x = foo::<&'a u32>(); + //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477] +} + +fn main() {} diff --git a/src/test/ui/issue-55511.nll.stderr b/src/test/ui/issue-55511.nll.stderr new file mode 100644 index 0000000000000..bf3e58e8cdb19 --- /dev/null +++ b/src/test/ui/issue-55511.nll.stderr @@ -0,0 +1,15 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-55511.rs:13:28 + | +LL | let b = Some(Cell::new(&a)); + | ^^ borrowed value does not live long enough +... +LL | <() as Foo<'static>>::C => { } + | ----------------------- type annotation requires that `a` is borrowed for `'static` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issue-55511.rs b/src/test/ui/issue-55511.rs new file mode 100644 index 0000000000000..4b9475ba62718 --- /dev/null +++ b/src/test/ui/issue-55511.rs @@ -0,0 +1,19 @@ +use std::cell::Cell; + +trait Foo<'a> { + const C: Option<Cell<&'a u32>>; +} + +impl<'a, T> Foo<'a> for T { + const C: Option<Cell<&'a u32>> = None; +} + +fn main() { + let a = 22; + let b = Some(Cell::new(&a)); + //~^ ERROR `a` does not live long enough [E0597] + match b { + <() as Foo<'static>>::C => { } + _ => { } + } +} diff --git a/src/test/ui/issue-55511.stderr b/src/test/ui/issue-55511.stderr new file mode 100644 index 0000000000000..24668f045517a --- /dev/null +++ b/src/test/ui/issue-55511.stderr @@ -0,0 +1,14 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-55511.rs:13:29 + | +LL | let b = Some(Cell::new(&a)); + | ^ borrowed value does not live long enough +... +LL | } + | - borrowed value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs index 2277778040292..70b712c560830 100644 --- a/src/test/ui/issues/issue-11692-1.rs +++ b/src/test/ui/issues/issue-11692-1.rs @@ -1,5 +1,3 @@ fn main() { - print!(testo!()); - //~^ ERROR: format argument must be a string literal - //~| ERROR: cannot find macro `testo!` in this scope + print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope } diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr index f4cc825803a3b..57a6a999544cf 100644 --- a/src/test/ui/issues/issue-11692-1.stderr +++ b/src/test/ui/issues/issue-11692-1.stderr @@ -1,18 +1,8 @@ -error: format argument must be a string literal - --> $DIR/issue-11692-1.rs:2:12 - | -LL | print!(testo!()); - | ^^^^^^^^ -help: you might be missing a string literal to format with - | -LL | print!("{}", testo!()); - | ^^^^^ - error: cannot find macro `testo!` in this scope --> $DIR/issue-11692-1.rs:2:12 | -LL | print!(testo!()); +LL | print!(testo!()); //~ ERROR cannot find macro `testo!` in this scope | ^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs index 6103931657342..61be284d7320e 100644 --- a/src/test/ui/issues/issue-11692-2.rs +++ b/src/test/ui/issues/issue-11692-2.rs @@ -1,4 +1,3 @@ fn main() { concat!(test!()); //~ ERROR cannot find macro `test!` in this scope - //~| ERROR expected a literal } diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr index 848415435a78b..5d4467080f149 100644 --- a/src/test/ui/issues/issue-11692-2.stderr +++ b/src/test/ui/issues/issue-11692-2.stderr @@ -1,16 +1,8 @@ -error: expected a literal - --> $DIR/issue-11692-2.rs:2:13 - | -LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope - | ^^^^^^^ - | - = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` - error: cannot find macro `test!` in this scope --> $DIR/issue-11692-2.rs:2:13 | LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope | ^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/issues/issue-13407.stderr b/src/test/ui/issues/issue-13407.stderr index 90b5d22a28425..1f4c7dfb0da02 100644 --- a/src/test/ui/issues/issue-13407.stderr +++ b/src/test/ui/issues/issue-13407.stderr @@ -8,7 +8,7 @@ error[E0308]: mismatched types --> $DIR/issue-13407.rs:6:12 | LL | A::C = 1; - | ^ expected struct `A::C`, found integral variable + | ^ expected struct `A::C`, found integer | = note: expected type `A::C` found type `{integer}` diff --git a/src/test/ui/issues/issue-14091.stderr b/src/test/ui/issues/issue-14091.stderr index c7616e5ab4f41..24a076624edee 100644 --- a/src/test/ui/issues/issue-14091.stderr +++ b/src/test/ui/issues/issue-14091.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-14091.rs:2:5 | LL | assert!(1,1); - | ^^^^^^^^^^^^^ expected bool, found integral variable + | ^^^^^^^^^^^^^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/issues/issue-18389.stderr b/src/test/ui/issues/issue-18389.stderr index 9cbe8c05b7e3d..02ff6b6d5bff4 100644 --- a/src/test/ui/issues/issue-18389.stderr +++ b/src/test/ui/issues/issue-18389.stderr @@ -1,6 +1,9 @@ error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface --> $DIR/issue-18389.rs:7:1 | +LL | trait Private<P, R> { + | - `Private<<Self as Public>::P, <Self as Public>::R>` declared as private +... LL | / pub trait Public: Private< LL | | //~^ ERROR private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface LL | | <Self as Public>::P, diff --git a/src/test/ui/issues/issue-19991.rs b/src/test/ui/issues/issue-19991.rs index 349a1d77c2b7c..e9094ecc01589 100644 --- a/src/test/ui/issues/issue-19991.rs +++ b/src/test/ui/issues/issue-19991.rs @@ -5,7 +5,7 @@ fn main() { if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause //~| expected type `()` //~| found type `{integer}` - //~| expected (), found integral variable + //~| expected (), found integer 765 }; } diff --git a/src/test/ui/issues/issue-19991.stderr b/src/test/ui/issues/issue-19991.stderr index cf3d55e821091..ee5d363c4bd2b 100644 --- a/src/test/ui/issues/issue-19991.stderr +++ b/src/test/ui/issues/issue-19991.stderr @@ -4,10 +4,10 @@ error[E0317]: if may be missing an else clause LL | / if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause LL | | //~| expected type `()` LL | | //~| found type `{integer}` -LL | | //~| expected (), found integral variable +LL | | //~| expected (), found integer LL | | 765 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-21174.rs b/src/test/ui/issues/issue-21174.rs index 4f835cde641e7..07827425116af 100644 --- a/src/test/ui/issues/issue-21174.rs +++ b/src/test/ui/issues/issue-21174.rs @@ -5,7 +5,7 @@ trait Trait<'a> { fn foo<'a, T: Trait<'a>>(value: T::A) { let new: T::B = unsafe { std::mem::transmute(value) }; -//~^ ERROR: transmute called with types of different sizes +//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types } fn main() { } diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 5ff72aef550c3..5ac5a8665bc69 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-21174.rs:7:30 | LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: <T as Trait<'a>>::A (size can vary because of <T as Trait>::A) - = note: target type: <T as Trait<'a>>::B (size can vary because of <T as Trait>::B) + = note: source type: `<T as Trait<'a>>::A` (size can vary because of <T as Trait>::A) + = note: target type: `<T as Trait<'a>>::B` (size can vary because of <T as Trait>::B) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22706.rs b/src/test/ui/issues/issue-22706.rs index c19c2a4c7059b..413a0d9a4943a 100644 --- a/src/test/ui/issues/issue-22706.rs +++ b/src/test/ui/issues/issue-22706.rs @@ -1,3 +1,3 @@ fn is_copy<T: ::std::marker<i32>::Copy>() {} -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] fn main() {} diff --git a/src/test/ui/issues/issue-22706.stderr b/src/test/ui/issues/issue-22706.stderr index 57e62599b196f..a3cf716903d20 100644 --- a/src/test/ui/issues/issue-22706.stderr +++ b/src/test/ui/issues/issue-22706.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/issue-22706.rs:1:29 | LL | fn is_copy<T: ::std::marker<i32>::Copy>() {} - | ^^^ type parameter not allowed + | ^^^ type argument not allowed error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22872.rs b/src/test/ui/issues/issue-22872.rs index a6130d21b5d39..8ef4af15bd462 100644 --- a/src/test/ui/issues/issue-22872.rs +++ b/src/test/ui/issues/issue-22872.rs @@ -19,7 +19,6 @@ pub trait Process<'a> { fn push_process<P>(process: P) where P: Process<'static> { let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); //~^ ERROR is not an iterator -//~| ERROR is not satisfied } fn main() {} diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index 231080add9bd0..ebd096f1dde5a 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -1,23 +1,14 @@ -error[E0277]: the trait bound `for<'b> P: Process<'b>` is not satisfied +error[E0277]: `<P as Process<'_>>::Item` is not an iterator --> $DIR/issue-22872.rs:20:36 | LL | let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'b> Process<'b>` is not implemented for `P` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator | - = help: consider adding a `where for<'b> P: Process<'b>` bound + = help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item` + = help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` -error[E0277]: `<P as Process<'b>>::Item` is not an iterator - --> $DIR/issue-22872.rs:20:36 - | -LL | let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'b>>::Item` is not an iterator - | - = help: the trait `for<'b> std::iter::Iterator` is not implemented for `<P as Process<'b>>::Item` - = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>` - = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr index 58145a38026e4..97962adc2d286 100644 --- a/src/test/ui/issues/issue-22933-2.stderr +++ b/src/test/ui/issues/issue-22933-2.stderr @@ -1,11 +1,13 @@ error[E0599]: no variant named `PIE` found for type `Delicious` in the current scope - --> $DIR/issue-22933-2.rs:4:44 + --> $DIR/issue-22933-2.rs:4:55 | LL | enum Delicious { | -------------- variant `PIE` not found here ... LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, - | ^^^^^^^^^^^^^^ variant not found in `Delicious` + | -----------^^^ + | | + | variant not found in `Delicious` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22933-3.stderr b/src/test/ui/issues/issue-22933-3.stderr index 2ca1bd7401a20..aa0052f97013e 100644 --- a/src/test/ui/issues/issue-22933-3.stderr +++ b/src/test/ui/issues/issue-22933-3.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `MIN` found for type `u8` in the current scope - --> $DIR/issue-22933-3.rs:1:18 + --> $DIR/issue-22933-3.rs:1:22 | LL | const FOO: [u32; u8::MIN as usize] = []; - | ^^^^^^^ associated item not found in `u8` + | ----^^^ + | | + | associated item not found in `u8` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr index de4c8422b9ccb..98c4f867ad6a0 100644 --- a/src/test/ui/issues/issue-23173.stderr +++ b/src/test/ui/issues/issue-23173.stderr @@ -1,38 +1,46 @@ error[E0599]: no variant named `Homura` found for type `Token` in the current scope - --> $DIR/issue-23173.rs:9:16 + --> $DIR/issue-23173.rs:9:23 | LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } | ---------- variant `Homura` not found here ... LL | use_token(&Token::Homura); - | ^^^^^^^^^^^^^ variant not found in `Token` + | -------^^^^^^ + | | + | variant not found in `Token` error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:11:5 + --> $DIR/issue-23173.rs:11:13 | LL | struct Struct { | ------------- function or associated item `method` not found for this ... LL | Struct::method(); - | ^^^^^^^^^^^^^^ function or associated item not found in `Struct` + | --------^^^^^^ + | | + | function or associated item not found in `Struct` error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:13:5 + --> $DIR/issue-23173.rs:13:13 | LL | struct Struct { | ------------- function or associated item `method` not found for this ... LL | Struct::method; - | ^^^^^^^^^^^^^^ function or associated item not found in `Struct` + | --------^^^^^^ + | | + | function or associated item not found in `Struct` error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope - --> $DIR/issue-23173.rs:15:5 + --> $DIR/issue-23173.rs:15:13 | LL | struct Struct { | ------------- associated item `Assoc` not found for this ... LL | Struct::Assoc; - | ^^^^^^^^^^^^^ associated item not found in `Struct` + | --------^^^^^ + | | + | associated item not found in `Struct` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr index a058caf81bbe8..208d0cc499a80 100644 --- a/src/test/ui/issues/issue-23217.stderr +++ b/src/test/ui/issues/issue-23217.stderr @@ -1,12 +1,14 @@ error[E0599]: no variant named `A` found for type `SomeEnum` in the current scope - --> $DIR/issue-23217.rs:2:9 + --> $DIR/issue-23217.rs:2:19 | LL | pub enum SomeEnum { | ----------------- variant `A` not found here LL | B = SomeEnum::A, - | ^^^^^^^^^^^ variant not found in `SomeEnum` + | ----------^ + | | + | variant not found in `SomeEnum` | - = note: did you mean `SomeEnum::B`? + = help: did you mean `B`? error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index be393c5e4f509..8ea2bdb693d31 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -8,6 +8,8 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); LL | false } => { }, LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move + | + = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index f7d8d2af86208..146ebad6ce175 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -5,10 +5,12 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^^^^^^^^ associated type `Output` must be specified error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:4:17 + --> $DIR/issue-28344.rs:4:25 | LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^^^^^^^^^ function or associated item not found in `dyn std::ops::BitXor<_>` + | --------^^^^^ + | | + | function or associated item not found in `dyn std::ops::BitXor<_>` | = help: did you mean `bitxor`? @@ -19,10 +21,12 @@ LL | let g = BitXor::bitor; | ^^^^^^^^^^^^^ associated type `Output` must be specified error[E0599]: no function or associated item named `bitor` found for type `dyn std::ops::BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:8:13 + --> $DIR/issue-28344.rs:8:21 | LL | let g = BitXor::bitor; - | ^^^^^^^^^^^^^ function or associated item not found in `dyn std::ops::BitXor<_>` + | --------^^^^^ + | | + | function or associated item not found in `dyn std::ops::BitXor<_>` | = help: did you mean `bitxor`? diff --git a/src/test/ui/issues/issue-28433.stderr b/src/test/ui/issues/issue-28433.stderr index 97df6db2b5215..d3cba3aae7101 100644 --- a/src/test/ui/issues/issue-28433.stderr +++ b/src/test/ui/issues/issue-28433.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `pub` | LL | pub duck, | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#pub duck, + | ^^^^^ error: expected one of `(`, `,`, `=`, `{`, or `}`, found `duck` --> $DIR/issue-28433.rs:4:9 diff --git a/src/test/ui/issues/issue-28586.stderr b/src/test/ui/issues/issue-28586.stderr index 52af2f54653f3..eccb474c15eb6 100644 --- a/src/test/ui/issues/issue-28586.stderr +++ b/src/test/ui/issues/issue-28586.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `BYTES` found for type `usize` in the current scope - --> $DIR/issue-28586.rs:4:19 + --> $DIR/issue-28586.rs:4:26 | LL | impl Foo for [u8; usize::BYTES] {} - | ^^^^^^^^^^^^ associated item not found in `usize` + | -------^^^^^ + | | + | associated item not found in `usize` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28625.rs b/src/test/ui/issues/issue-28625.rs index 46cbb45e97bb6..15a6a63d5ef0b 100644 --- a/src/test/ui/issues/issue-28625.rs +++ b/src/test/ui/issues/issue-28625.rs @@ -9,7 +9,7 @@ struct ArrayPeano<T: Bar> { } fn foo<T>(a: &ArrayPeano<T>) -> &[T] where T: Bar { - unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes + unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes } impl Bar for () { diff --git a/src/test/ui/issues/issue-28625.stderr b/src/test/ui/issues/issue-28625.stderr index ae383b44511bd..36cb47944f234 100644 --- a/src/test/ui/issues/issue-28625.stderr +++ b/src/test/ui/issues/issue-28625.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-28625.rs:12:14 | -LL | unsafe { std::mem::transmute(a) } //~ ERROR transmute called with types of different sizes +LL | unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: &ArrayPeano<T> (N bits) - = note: target type: &[T] (N bits) + = note: source type: `&ArrayPeano<T>` (N bits) + = note: target type: `&[T]` (N bits) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr index f6362faab12b8..d5dbd5f64885c 100644 --- a/src/test/ui/issues/issue-28971.stderr +++ b/src/test/ui/issues/issue-28971.stderr @@ -1,13 +1,13 @@ error[E0599]: no variant named `Baz` found for type `Foo` in the current scope - --> $DIR/issue-28971.rs:9:13 + --> $DIR/issue-28971.rs:9:18 | LL | enum Foo { | -------- variant `Baz` not found here ... LL | Foo::Baz(..) => (), - | ^^^^^^^^^^^^ variant not found in `Foo` + | -----^^^---- variant not found in `Foo` | - = note: did you mean `Foo::Bar`? + = help: did you mean `Bar`? error: aborting due to previous error diff --git a/src/test/ui/issues/issue-30123.stderr b/src/test/ui/issues/issue-30123.stderr index 9729b13d57fe8..555bdb1236fe6 100644 --- a/src/test/ui/issues/issue-30123.stderr +++ b/src/test/ui/issues/issue-30123.stderr @@ -1,8 +1,10 @@ error[E0599]: no function or associated item named `new_undirected` found for type `issue_30123_aux::Graph<i32, i32>` in the current scope - --> $DIR/issue-30123.rs:7:14 + --> $DIR/issue-30123.rs:7:33 | LL | let ug = Graph::<i32, i32>::new_undirected(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>` + | -------------------^^^^^^^^^^^^^^ + | | + | function or associated item not found in `issue_30123_aux::Graph<i32, i32>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-32377.rs b/src/test/ui/issues/issue-32377.rs index 6f073bcce6108..555f6abd791ac 100644 --- a/src/test/ui/issues/issue-32377.rs +++ b/src/test/ui/issues/issue-32377.rs @@ -13,7 +13,7 @@ struct Bar<U: Foo> { fn foo<U: Foo>(x: [usize; 2]) -> Bar<U> { unsafe { mem::transmute(x) } - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/issues/issue-32377.stderr b/src/test/ui/issues/issue-32377.stderr index 72d94721d887f..5e870eb3e8d17 100644 --- a/src/test/ui/issues/issue-32377.stderr +++ b/src/test/ui/issues/issue-32377.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/issue-32377.rs:15:14 | LL | unsafe { mem::transmute(x) } | ^^^^^^^^^^^^^^ | - = note: source type: [usize; 2] (N bits) - = note: target type: Bar<U> (N bits) + = note: source type: `[usize; 2]` (N bits) + = note: target type: `Bar<U>` (N bits) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index 95d6c55c1ea50..716aa8a863292 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-33504.rs:7:13 | LL | let Test = 1; //~ ERROR mismatched types - | ^^^^ expected integral variable, found struct `Test` + | ^^^^ expected integer, found struct `Test` | = note: expected type `{integer}` found type `Test` diff --git a/src/test/ui/issues/issue-37665.stderr b/src/test/ui/issues/issue-37665.stderr index 0022ab73e1ad9..c3599fab68507 100644 --- a/src/test/ui/issues/issue-37665.stderr +++ b/src/test/ui/issues/issue-37665.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-37665.rs:10:17 | LL | let x: () = 0; //~ ERROR: mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr index 41da422c1b960..8c09436479564 100644 --- a/src/test/ui/issues/issue-38919.stderr +++ b/src/test/ui/issues/issue-38919.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `Item` found for type `T` in the current scope - --> $DIR/issue-38919.rs:2:5 + --> $DIR/issue-38919.rs:2:8 | LL | T::Item; //~ ERROR no associated item named `Item` found for type `T` in the current scope - | ^^^^^^^ associated item not found in `T` + | ---^^^^ + | | + | associated item not found in `T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr index 7653cadc6a777..e851e79faee06 100644 --- a/src/test/ui/issues/issue-39559.stderr +++ b/src/test/ui/issues/issue-39559.stderr @@ -1,8 +1,10 @@ error[E0599]: no function or associated item named `dim` found for type `D` in the current scope - --> $DIR/issue-39559.rs:14:18 + --> $DIR/issue-39559.rs:14:21 | LL | entries: [T; D::dim()], - | ^^^^^^ function or associated item not found in `D` + | ---^^^ + | | + | function or associated item not found in `D` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `dim`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-3973.stderr b/src/test/ui/issues/issue-3973.stderr index 0f9c15647492e..8e46d88018112 100644 --- a/src/test/ui/issues/issue-3973.stderr +++ b/src/test/ui/issues/issue-3973.stderr @@ -8,13 +8,15 @@ LL | | } | |_____^ not a member of trait `ToString_` error[E0599]: no function or associated item named `new` found for type `Point` in the current scope - --> $DIR/issue-3973.rs:22:13 + --> $DIR/issue-3973.rs:22:20 | LL | struct Point { | ------------ function or associated item `new` not found for this ... LL | let p = Point::new(0.0, 0.0); - | ^^^^^^^^^^ function or associated item not found in `Point` + | -------^^^ + | | + | function or associated item not found in `Point` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-40000.rs b/src/test/ui/issues/issue-40000.rs index 2d1e1d07a26ff..320992c0764cf 100644 --- a/src/test/ui/issues/issue-40000.rs +++ b/src/test/ui/issues/issue-40000.rs @@ -3,6 +3,5 @@ fn main() { fn foo(x: Box<Fn(&i32)>) {} let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>; - foo(bar); //~ ERROR mismatched types - //~| expected concrete lifetime, found bound lifetime parameter + foo(bar); //~ ERROR E0308 } diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 3ff5870348109..d7966cea52bb0 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -1,11 +1,11 @@ error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | -LL | foo(bar); //~ ERROR mismatched types - | ^^^ expected concrete lifetime, found bound lifetime parameter +LL | foo(bar); //~ ERROR E0308 + | ^^^ one type is more general than the other | - = note: expected type `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>` - found type `std::boxed::Box<dyn std::ops::Fn(_)>` + = note: expected type `dyn for<'r> std::ops::Fn(&'r i32)` + found type `dyn std::ops::Fn(&i32)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4201.rs b/src/test/ui/issues/issue-4201.rs index c9098c843f92f..2f1d6d2177e40 100644 --- a/src/test/ui/issues/issue-4201.rs +++ b/src/test/ui/issues/issue-4201.rs @@ -5,7 +5,7 @@ fn main() { //~^ ERROR if may be missing an else clause //~| expected type `()` //~| found type `{integer}` -//~| expected (), found integral variable +//~| expected (), found integer 1 }; } diff --git a/src/test/ui/issues/issue-4201.stderr b/src/test/ui/issues/issue-4201.stderr index ebeb870183e45..4f8ec96d53151 100644 --- a/src/test/ui/issues/issue-4201.stderr +++ b/src/test/ui/issues/issue-4201.stderr @@ -6,10 +6,10 @@ LL | } else if false { LL | | //~^ ERROR if may be missing an else clause LL | | //~| expected type `()` LL | | //~| found type `{integer}` -LL | | //~| expected (), found integral variable +LL | | //~| expected (), found integer LL | | 1 LL | | }; - | |_____^ expected (), found integral variable + | |_____^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/issues/issue-42344.nll.stderr b/src/test/ui/issues/issue-42344.nll.stderr index 046a45241cdd7..9770d26fb12d8 100644 --- a/src/test/ui/issues/issue-42344.nll.stderr +++ b/src/test/ui/issues/issue-42344.nll.stderr @@ -1,4 +1,4 @@ -error[E0596]: cannot borrow `*TAB[..]` as mutable, as `TAB` is an immutable static item +error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable static item --> $DIR/issue-42344.rs:4:5 | LL | TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389] diff --git a/src/test/ui/issues/issue-42880.stderr b/src/test/ui/issues/issue-42880.stderr index 7d8bae9cafc6f..36b9e8a1e8afa 100644 --- a/src/test/ui/issues/issue-42880.stderr +++ b/src/test/ui/issues/issue-42880.stderr @@ -1,8 +1,8 @@ error[E0599]: no associated item named `String` found for type `std::string::String` in the current scope - --> $DIR/issue-42880.rs:4:15 + --> $DIR/issue-42880.rs:4:22 | LL | let f = |&Value::String(_)| (); //~ ERROR no associated item named - | ^^^^^^^^^^^^^^^^ associated item not found in `std::string::String` + | -------^^^^^^--- associated item not found in `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-44406.stderr b/src/test/ui/issues/issue-44406.stderr index 45ea586373c3c..105dbb677dc02 100644 --- a/src/test/ui/issues/issue-44406.stderr +++ b/src/test/ui/issues/issue-44406.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `true` | LL | foo!(true); //~ ERROR expected type, found keyword | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | foo!(r#true); //~ ERROR expected type, found keyword + | ^^^^^^ error: expected type, found keyword `true` --> $DIR/issue-44406.rs:8:10 diff --git a/src/test/ui/issues/issue-46604.ast.nll.stderr b/src/test/ui/issues/issue-46604.ast.nll.stderr index ed23a69edb987..4f73a0f9d541d 100644 --- a/src/test/ui/issues/issue-46604.ast.nll.stderr +++ b/src/test/ui/issues/issue-46604.ast.nll.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:10:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr index ed23a69edb987..4f73a0f9d541d 100644 --- a/src/test/ui/issues/issue-46604.mir.stderr +++ b/src/test/ui/issues/issue-46604.mir.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:10:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr index 6e8d1ef2f7b9e..5e1b816defda3 100644 --- a/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr +++ b/src/test/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `00` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 | LL | let _condemned = justice.00; - | ^^ did you mean `0`? + | ^^ help: a field with a similar name exists: `0` error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index eac7e65064d49..39c649ba3e0e7 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; //~ ERROR struct `NonCopyable` has no field named `p` - | ^ field does not exist - did you mean `0`? + | ^ help: a field with a similar name exists: `0` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4968.rs b/src/test/ui/issues/issue-4968.rs index 3bf65c5ce8e6e..383b9ecd466fe 100644 --- a/src/test/ui/issues/issue-4968.rs +++ b/src/test/ui/issues/issue-4968.rs @@ -6,5 +6,5 @@ fn main() { //~^ ERROR mismatched types //~| expected type `{integer}` //~| found type `(isize, isize)` - //~| expected integral variable, found tuple + //~| expected integer, found tuple } diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 2f6b4b95882fc..a925783723b44 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-4968.rs:5:16 | LL | match 42 { A => () } - | ^ expected integral variable, found tuple + | ^ expected integer, found tuple | = note: expected type `{integer}` found type `(isize, isize)` diff --git a/src/test/ui/issues/issue-54302-cases.rs b/src/test/ui/issues/issue-54302-cases.rs index 0c852a2eb6321..faa116269ee96 100644 --- a/src/test/ui/issues/issue-54302-cases.rs +++ b/src/test/ui/issues/issue-54302-cases.rs @@ -61,25 +61,25 @@ impl<T> RefFoo<T> for T where for<'a> &'a T: Foo<'static, T> { fn coerce_lifetime1(a: &u32) -> &'static u32 { <u32 as RefFoo<u32>>::ref_foo(a) - //~^ ERROR the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied + //~^ ERROR not general enough } fn coerce_lifetime2(a: &i32) -> &'static i32 { <i32 as RefFoo<i32>>::ref_foo(a) - //~^ ERROR the requirement `for<'a> 'a : ` is not satisfied + //~^ ERROR not general enough } fn coerce_lifetime3(a: &u64) -> &'static u64 { <u64 as RefFoo<u64>>::ref_foo(a) - //~^ ERROR type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` + //~^ ERROR not general enough } fn coerce_lifetime4(a: &i64) -> &'static i64 { <i64 as RefFoo<i64>>::ref_foo(a) - //~^ ERROR type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` + //~^ ERROR not general enough } fn main() {} diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 0ed88463277d5..c1329d331a181 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -1,65 +1,38 @@ -error[E0277]: the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | LL | <u32 as RefFoo<u32>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo2<'_, u32>` is not implemented for `&'a u32` - | - = help: the following implementations were found: - <&'x u32 as Foo2<'x, u32>> - = note: required because of the requirements on the impl of `for<'a> Foo<'static, u32>` for `&'a u32` - = note: required because of the requirements on the impl of `RefFoo<u32>` for `u32` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'0 u32` must implement `Foo<'static, u32>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` -error[E0279]: the requirement `for<'a> 'a : ` is not satisfied (`expected bound lifetime parameter 'a, found concrete lifetime`) +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | LL | <i32 as RefFoo<i32>>::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i32>` for `&'a i32` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, i32>` for `&'a i32` - = note: required because of the requirements on the impl of `RefFoo<i32>` for `i32` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 - | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'0 i32` must implement `Foo<'static, i32>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` -error[E0271]: type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64` +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | LL | <u64 as RefFoo<u64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime - | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, u64>` for `&'a u64` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, u64>` for `&'a u64` - = note: required because of the requirements on the impl of `RefFoo<u64>` for `u64` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'0 u64` must implement `Foo<'static, u64>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` -error[E0271]: type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64` +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | LL | <i64 as RefFoo<i64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime - | - = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i64>` for `&'a i64` - = note: required because of the requirements on the impl of `for<'a> Foo<'static, i64>` for `&'a i64` - = note: required because of the requirements on the impl of `RefFoo<i64>` for `i64` -note: required by `RefFoo::ref_foo` - --> $DIR/issue-54302-cases.rs:51:5 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'0 i64` must implement `Foo<'static, i64>` for any lifetime `'0` + = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` error: aborting due to 4 previous errors -Some errors occurred: E0271, E0277, E0279. -For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/issues/issue-54302.rs b/src/test/ui/issues/issue-54302.rs index c681d37cdae00..1bfaebc3895d9 100644 --- a/src/test/ui/issues/issue-54302.rs +++ b/src/test/ui/issues/issue-54302.rs @@ -11,7 +11,7 @@ fn main() { // Then why does it implement DeserializeOwned? This compiles. fn assert_deserialize_owned<T: DeserializeOwned>() {} assert_deserialize_owned::<&'static str>(); - //~^ ERROR the requirement `for<'de> 'de : ` is not satisfied + //~^ ERROR not general enough // It correctly does not implement for<'de> Deserialize<'de>. //fn assert_hrtb<T: for<'de> Deserialize<'de>>() {} diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index 2d95aa2b156f2..1b255204b6ef7 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -1,17 +1,11 @@ -error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`) +error: implementation of `Deserialize` is not general enough --> $DIR/issue-54302.rs:13:5 | LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str` - = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str` -note: required by `main::assert_deserialize_owned` - --> $DIR/issue-54302.rs:12:5 - | -LL | fn assert_deserialize_owned<T: DeserializeOwned>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` + = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0279`. diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr index 9503183deb97c..7aaf8e4ac2f14 100644 --- a/src/test/ui/issues/issue-56199.stderr +++ b/src/test/ui/issues/issue-56199.stderr @@ -4,7 +4,7 @@ error: the `Self` constructor can only be used with tuple or unit structs LL | let _ = Self; | ^^^^ | - = note: did you mean to use one of the enum's variants? + = help: did you mean to use one of the enum's variants? error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:8:17 @@ -12,19 +12,19 @@ error: the `Self` constructor can only be used with tuple or unit structs LL | let _ = Self(); | ^^^^ | - = note: did you mean to use one of the enum's variants? + = help: did you mean to use one of the enum's variants? error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:15:17 | LL | let _ = Self; - | ^^^^ did you mean `Self { /* fields */ }`? + | ^^^^ help: use curly brackets: `Self { /* fields */ }` error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:17:17 | LL | let _ = Self(); - | ^^^^ did you mean `Self { /* fields */ }`? + | ^^^^ help: use curly brackets: `Self { /* fields */ }` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr index 21ecbf05dc72f..f9fdf23af9715 100644 --- a/src/test/ui/issues/issue-56835.stderr +++ b/src/test/ui/issues/issue-56835.stderr @@ -2,7 +2,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56835.rs:4:12 | LL | fn bar(Self(foo): Self) {} - | ^^^^^^^^^ did you mean `Self { /* fields */ }`? + | ^^^^^^^^^ help: use curly brackets: `Self { /* fields */ }` error[E0164]: expected tuple struct/variant, found self constructor `Self` --> $DIR/issue-56835.rs:4:12 diff --git a/src/test/ui/issues/issue-57198-pass.rs b/src/test/ui/issues/issue-57198-pass.rs new file mode 100644 index 0000000000000..3857def9824f8 --- /dev/null +++ b/src/test/ui/issues/issue-57198-pass.rs @@ -0,0 +1,9 @@ +// run-pass + +mod m { + pub fn r#for() {} +} + +fn main() { + m::r#for(); +} diff --git a/src/test/ui/issues/issue-57198.rs b/src/test/ui/issues/issue-57198.rs new file mode 100644 index 0000000000000..714a46cbc9f48 --- /dev/null +++ b/src/test/ui/issues/issue-57198.rs @@ -0,0 +1,8 @@ +mod m { + pub fn r#for() {} +} + +fn main() { + m::for(); + //~^ ERROR expected identifier, found keyword `for` +} diff --git a/src/test/ui/issues/issue-57198.stderr b/src/test/ui/issues/issue-57198.stderr new file mode 100644 index 0000000000000..2ab552ccbd3c8 --- /dev/null +++ b/src/test/ui/issues/issue-57198.stderr @@ -0,0 +1,12 @@ +error: expected identifier, found keyword `for` + --> $DIR/issue-57198.rs:6:8 + | +LL | m::for(); + | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | m::r#for(); + | ^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr index 169ce5429f5af..e30f04753762e 100644 --- a/src/test/ui/issues/issue-7950.stderr +++ b/src/test/ui/issues/issue-7950.stderr @@ -1,11 +1,13 @@ error[E0599]: no function or associated item named `bar` found for type `Foo` in the current scope - --> $DIR/issue-7950.rs:6:5 + --> $DIR/issue-7950.rs:6:10 | LL | struct Foo; | ----------- function or associated item `bar` not found for this ... LL | Foo::bar(); - | ^^^^^^^^ function or associated item not found in `Foo` + | -----^^^ + | | + | function or associated item not found in `Foo` error: aborting due to previous error diff --git a/src/test/ui/keyword/keyword-false-as-identifier.stderr b/src/test/ui/keyword/keyword-false-as-identifier.stderr index de5dfcfbe4360..6c8dffa7e22c6 100644 --- a/src/test/ui/keyword/keyword-false-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-false-as-identifier.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/keyword-false-as-identifier.rs:2:9 | LL | let false = 22; //~ error: mismatched types - | ^^^^^ expected integral variable, found bool + | ^^^^^ expected integer, found bool | = note: expected type `{integer}` found type `bool` diff --git a/src/test/ui/keyword/keyword-true-as-identifier.stderr b/src/test/ui/keyword/keyword-true-as-identifier.stderr index cc5c6fe45565f..e5d3938e54ac2 100644 --- a/src/test/ui/keyword/keyword-true-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-true-as-identifier.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/keyword-true-as-identifier.rs:2:9 | LL | let true = 22; //~ error: mismatched types - | ^^^^ expected integral variable, found bool + | ^^^^ expected integer, found bool | = note: expected type `{integer}` found type `bool` diff --git a/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master index a9bbfcfa26263..3f0444ec9c807 100644 --- a/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master +++ b/src/test/ui/kindck/kindck-send-unsafe.rs~rust-lang_master @@ -1,13 +1,3 @@ -// Copyright 2014 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. - fn assert_send<T:Send>() { } // unsafe ptrs are ok unless they point at unsendable things diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 7ac629b5dea19..51313033a02dd 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -9,10 +9,12 @@ LL | use T; | error[E0599]: no function or associated item named `f` found for type `Foo` in the current scope - --> $DIR/lexical-scopes.rs:10:5 + --> $DIR/lexical-scopes.rs:10:10 | LL | Foo::f(); //~ ERROR no function or associated item named `f` - | ^^^^^^ function or associated item not found in `Foo` + | -----^ + | | + | function or associated item not found in `Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr index 20efc1fab56b1..fa0a7ac002b2f 100644 --- a/src/test/ui/lifetime_starts_expressions.stderr +++ b/src/test/ui/lifetime_starts_expressions.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `loop` | LL | loop { break 'label: loop { break 'label 42; }; } | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | loop { break 'label: r#loop { break 'label 42; }; } + | ^^^^^^ error: expected type, found keyword `loop` --> $DIR/lifetime_starts_expressions.rs:6:26 diff --git a/src/test/ui/lint/lint-group-nonstandard-style.rs b/src/test/ui/lint/lint-group-nonstandard-style.rs index 1e99764df15be..0386daaa59b07 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.rs +++ b/src/test/ui/lint/lint-group-nonstandard-style.rs @@ -1,7 +1,3 @@ -// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT -// http://rust-lang.org/COPYRIGHT. -// - #![deny(nonstandard_style)] #![allow(dead_code)] diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index a6f751d15841d..d85ca7811d01e 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -1,63 +1,63 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` - --> $DIR/lint-group-nonstandard-style.rs:26:9 + --> $DIR/lint-group-nonstandard-style.rs:22:9 | LL | struct snake_case; //~ WARN should have a camel | ^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:22:17 + --> $DIR/lint-group-nonstandard-style.rs:18:17 | LL | #![warn(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)] error: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:8:1 + --> $DIR/lint-group-nonstandard-style.rs:4:1 | LL | fn CamelCase() {} //~ ERROR should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:5:9 + --> $DIR/lint-group-nonstandard-style.rs:1:9 | LL | #![deny(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)] error: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:16:9 + --> $DIR/lint-group-nonstandard-style.rs:12:9 | LL | fn CamelCase() {} //~ ERROR should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:14:14 + --> $DIR/lint-group-nonstandard-style.rs:10:14 | LL | #[forbid(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)] error: static variable `bad` should have an upper case name such as `BAD` - --> $DIR/lint-group-nonstandard-style.rs:18:9 + --> $DIR/lint-group-nonstandard-style.rs:14:9 | LL | static bad: isize = 1; //~ ERROR should have an upper | ^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:14:14 + --> $DIR/lint-group-nonstandard-style.rs:10:14 | LL | #[forbid(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ = note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)] warning: function `CamelCase` should have a snake case name such as `camel_case` - --> $DIR/lint-group-nonstandard-style.rs:24:9 + --> $DIR/lint-group-nonstandard-style.rs:20:9 | LL | fn CamelCase() {} //~ WARN should have a snake | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-group-nonstandard-style.rs:22:17 + --> $DIR/lint-group-nonstandard-style.rs:18:17 | LL | #![warn(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/not_found.rs b/src/test/ui/lint/not_found.rs index a3e301d6bd039..0b5a4eb785195 100644 --- a/src/test/ui/lint/not_found.rs +++ b/src/test/ui/lint/not_found.rs @@ -1,7 +1,3 @@ -// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT -// http://rust-lang.org/COPYRIGHT. -// - // compile-pass // this tests the `unknown_lint` lint, especially the suggestions diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 5ae7fb352d668..266cf10af8285 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -1,5 +1,5 @@ warning: unknown lint: `FOO_BAR` - --> $DIR/not_found.rs:10:9 + --> $DIR/not_found.rs:6:9 | LL | #[allow(FOO_BAR)] | ^^^^^^^ @@ -7,13 +7,13 @@ LL | #[allow(FOO_BAR)] = note: #[warn(unknown_lints)] on by default warning: unknown lint: `DEAD_CODE` - --> $DIR/not_found.rs:12:8 + --> $DIR/not_found.rs:8:8 | LL | #[warn(DEAD_CODE)] | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` - --> $DIR/not_found.rs:14:8 + --> $DIR/not_found.rs:10:8 | LL | #[deny(Warnings)] | ^^^^^^^^ help: did you mean: `warnings` diff --git a/src/test/ui/liveness/liveness-use-after-move.nll.stderr b/src/test/ui/liveness/liveness-use-after-move.nll.stderr index 01534d0c0f667..45fd43687f39b 100644 --- a/src/test/ui/liveness/liveness-use-after-move.nll.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.nll.stderr @@ -5,6 +5,8 @@ LL | let y = x; | - value moved here LL | println!("{}", *x); //~ ERROR use of moved value: `*x` | ^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/loops/loop-break-value.stderr b/src/test/ui/loops/loop-break-value.stderr index 8fc4ec94366a5..3e009c007e08d 100644 --- a/src/test/ui/loops/loop-break-value.stderr +++ b/src/test/ui/loops/loop-break-value.stderr @@ -91,7 +91,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:11:19 | LL | break 123; //~ ERROR mismatched types - | ^^^ expected &str, found integral variable + | ^^^ expected &str, found integer | = note: expected type `&str` found type `{integer}` @@ -118,7 +118,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:73:26 | LL | break 'c 123; //~ ERROR mismatched types - | ^^^ expected (), found integral variable + | ^^^ expected (), found integer | = note: expected type `()` found type `{integer}` @@ -136,7 +136,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:85:15 | LL | break 2; //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` @@ -145,7 +145,7 @@ error[E0308]: mismatched types --> $DIR/loop-break-value.rs:90:9 | LL | break; //~ ERROR mismatched types - | ^^^^^ expected (), found integral variable + | ^^^^^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr.rs index 049905467769e..324dc86bd92b8 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr.rs @@ -1,11 +1,16 @@ // Test that we give a note when the old LUB/GLB algorithm would have -// succeeded but the new code (which is stricter) gives an error. +// succeeded but the new code (which requires equality) gives an +// error. However, now that we handle subtyping correctly, we no +// longer get an error, because we recognize these two types as +// equivalent! +// +// compile-pass fn foo( x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8), ) { - let z = match 22 { //~ ERROR incompatible types + let z = match 22 { 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr deleted file mode 100644 index 9c397a8fd2cc5..0000000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: match arms have incompatible types - --> $DIR/old-lub-glb-hr.rs:8:13 - | -LL | let z = match 22 { //~ ERROR incompatible types - | _____________^ -LL | | 0 => x, -LL | | _ => y, - | | - match arm with an incompatible type -LL | | }; - | |_____^ expected bound lifetime parameter, found concrete lifetime - | - = note: expected type `for<'r, 's> fn(&'r u8, &'s u8)` - found type `for<'a> fn(&'a u8, &'a u8)` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 309f2d0ea7663..9be7a813603d4 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -7,7 +7,7 @@ fn foo( x: &for<'a, 'b> Foo<&'a u8, &'b u8>, y: &for<'a> Foo<&'a u8, &'a u8>, ) { - let z = match 22 { //~ ERROR incompatible types + let z = match 22 { //~ ERROR E0308 0 => x, _ => y, }; diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 243414c19c01e..17d3648156b51 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,16 +1,15 @@ -error[E0308]: match arms have incompatible types +error[E0308]: mismatched types --> $DIR/old-lub-glb-object.rs:10:13 | -LL | let z = match 22 { //~ ERROR incompatible types +LL | let z = match 22 { //~ ERROR E0308 | _____________^ LL | | 0 => x, LL | | _ => y, - | | - match arm with an incompatible type LL | | }; - | |_____^ expected bound lifetime parameter 'a, found concrete lifetime + | |_____^ one type is more general than the other | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found type `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: expected type `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found type `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to previous error diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 41c3c9d75c0aa..0b8bfcbdc17ba 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -2,8 +2,10 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:2:30 | LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments - | -------------- ^^^^^^^^ ^^^^^^^ ^ - | | + | -------------- ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` @@ -16,7 +18,7 @@ error: argument never used --> $DIR/format-foreign.rs:3:29 | LL | println!("%1$*2$.*3$f", 123.456); //~ ERROR never used - | ----------- ^^^^^^^ + | ----------- ^^^^^^^ argument never used | | | help: format specifiers use curly braces: `{0:1$.2$}` | @@ -29,8 +31,10 @@ LL | println!(r###"%.*3$s | ______________- LL | | %s!/n LL | | "###, "Hello,", "World", 4); - | | - ^^^^^^^^ ^^^^^^^ ^ - | |____| + | | - ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | | + | | | | argument never used + | |____| argument never used | multiple missing formatting specifiers | = note: printf formatting not supported; see the documentation for `std::fmt` @@ -44,7 +48,7 @@ error: argument never used --> $DIR/format-foreign.rs:12:30 | LL | println!("{} %f", "one", 2.0); //~ ERROR never used - | ------- ^^^ + | ------- ^^^ argument never used | | | formatting specifier missing @@ -52,7 +56,7 @@ error: named argument never used --> $DIR/format-foreign.rs:14:39 | LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used - | ----- ^^^^^ + | ----- ^^^^^ named argument never used | | | help: format specifiers use curly braces: `{NAME}` | @@ -62,8 +66,10 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:15:32 | LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3); - | ---------------- ^ ^ ^ - | | + | ---------------- ^ ^ ^ named argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers | = note: shell formatting not supported; see the documentation for `std::fmt` diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index c94ff2a16714d..0a5e379a4adb4 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -2,8 +2,10 @@ error: multiple unused formatting arguments --> $DIR/format-unused-lables.rs:2:22 | LL | println!("Test", 123, 456, 789); - | ------ ^^^ ^^^ ^^^ - | | + | ------ ^^^ ^^^ ^^^ argument never used + | | | | + | | | argument never used + | | argument never used | multiple missing formatting specifiers error: multiple unused formatting arguments @@ -12,17 +14,17 @@ error: multiple unused formatting arguments LL | println!("Test2", | ------- multiple missing formatting specifiers LL | 123, //~ ERROR multiple unused formatting arguments - | ^^^ + | ^^^ argument never used LL | 456, - | ^^^ + | ^^^ argument never used LL | 789 - | ^^^ + | ^^^ argument never used error: named argument never used --> $DIR/format-unused-lables.rs:11:35 | LL | println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used - | ------------ ^^^^^^ + | ------------ ^^^^^^ named argument never used | | | formatting specifier missing @@ -35,12 +37,12 @@ LL | println!("Some more $STUFF", | | help: format specifiers use curly braces: `{STUFF}` | multiple missing formatting specifiers LL | "woo!", //~ ERROR multiple unused formatting arguments - | ^^^^^^ + | ^^^^^^ argument never used LL | STUFF= LL | "things" - | ^^^^^^^^ + | ^^^^^^^^ named argument never used LL | , UNUSED="args"); - | ^^^^^^ + | ^^^^^^ named argument never used | = note: shell formatting not supported; see the documentation for `std::fmt` diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 8d067c703b731..54969927433a4 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/match-range-fail.rs:17:9 | LL | 'c' ..= 100 => { } - | ^^^^^^^^^^^ expected integral variable, found char + | ^^^^^^^^^^^ expected integer, found char | = note: expected type `{integer}` found type `char` diff --git a/src/test/ui/methods/method-self-arg-1.rs b/src/test/ui/methods/method-self-arg-1.rs index 48be31d94f2ee..4a78ad780c412 100644 --- a/src/test/ui/methods/method-self-arg-1.rs +++ b/src/test/ui/methods/method-self-arg-1.rs @@ -15,5 +15,5 @@ fn main() { Foo::bar(&42); //~ ERROR mismatched types //~| expected type `&Foo` //~| found type `&{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } diff --git a/src/test/ui/methods/method-self-arg-1.stderr b/src/test/ui/methods/method-self-arg-1.stderr index 0756e9b68f2a3..8c80d01b18cb9 100644 --- a/src/test/ui/methods/method-self-arg-1.stderr +++ b/src/test/ui/methods/method-self-arg-1.stderr @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/method-self-arg-1.rs:15:14 | LL | Foo::bar(&42); //~ ERROR mismatched types - | ^^^ expected struct `Foo`, found integral variable + | ^^^ expected struct `Foo`, found integer | = note: expected type `&Foo` found type `&{integer}` diff --git a/src/test/ui/mir-unpretty.stderr b/src/test/ui/mir-unpretty.stderr index 913999c2290ba..59e8c0bf09029 100644 --- a/src/test/ui/mir-unpretty.stderr +++ b/src/test/ui/mir-unpretty.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/mir-unpretty.rs:4:17 | LL | let x: () = 0; //~ ERROR: mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index 4d5bfceb74e95..08f132efd0526 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 - | ^ expected &{integer}, found integral variable + | ^ expected &{integer}, found integer | = note: expected type `&{integer}` found type `{integer}` diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 5256148c771f3..6a5cf7db4eed9 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -49,7 +49,7 @@ LL | fn d() -> X<X<String, String>, String> { | ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type ... LL | x //~ ERROR mismatched types - | ^ expected struct `std::string::String`, found integral variable + | ^ expected struct `std::string::String`, found integer | = note: expected type `X<X<_, std::string::String>, std::string::String>` found type `X<X<_, {integer}>, {integer}>` @@ -61,7 +61,7 @@ LL | fn e() -> X<X<String, String>, String> { | ---------------------------- expected `X<X<std::string::String, std::string::String>, std::string::String>` because of return type ... LL | x //~ ERROR mismatched types - | ^ expected struct `std::string::String`, found integral variable + | ^ expected struct `std::string::String`, found integer | = note: expected type `X<X<_, std::string::String>, _>` found type `X<X<_, {integer}>, _>` diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index c5d9e4b9b766b..437150666be0c 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,6 @@ fn main() { fn baz<F: Fn(*mut &u32)>(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(f); //~ ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 5dd6887005e83..a6628006587c1 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,34 +22,25 @@ LL | a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR type mismatch - | ^^^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` +LL | baz(f); //~ ERROR mismatched types + | ^^^ one type is more general than the other | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 - | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` -error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | baz(f); //~ ERROR type mismatch - | ^^^ expected bound lifetime parameter, found concrete lifetime - | -note: required by `baz` - --> $DIR/closure-arg-type-mismatch.rs:8:1 +LL | baz(f); //~ ERROR mismatched types + | ^^^ one type is more general than the other | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` error: aborting due to 5 previous errors -Some errors occurred: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors occurred: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe7196..152a525493732 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,6 +5,5 @@ impl<T: Fn(&())> Foo for T {} fn baz<T: Foo>(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(|_| ()); //~ ERROR E0308 } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index e55047e96c297..0d87bc228755f 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,32 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | baz(|_| ()); //~ ERROR type mismatch - | ^^^ expected bound lifetime parameter, found concrete lifetime +LL | baz(|_| ()); //~ ERROR E0308 + | ^^^ one type is more general than the other | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz<T: Foo>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | baz(|_| ()); //~ ERROR type mismatch - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` -note: required by `baz` - --> $DIR/closure-mismatch.rs:5:1 - | -LL | fn baz<T: Foo>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^ + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr index 1de8e18c587ba..25203d6f35d28 100644 --- a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/for-loop-has-unit-body.rs:3:9 | LL | x //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/mod-subitem-as-enum-variant.rs b/src/test/ui/mod-subitem-as-enum-variant.rs new file mode 100644 index 0000000000000..ec809d44e942a --- /dev/null +++ b/src/test/ui/mod-subitem-as-enum-variant.rs @@ -0,0 +1,10 @@ + +mod Mod { + pub struct FakeVariant<T>(pub T); +} + +fn main() { + Mod::FakeVariant::<i32>(0); + Mod::<i32>::FakeVariant(0); + //~^ ERROR type arguments are not allowed on this entity [E0109] +} diff --git a/src/test/ui/mod-subitem-as-enum-variant.stderr b/src/test/ui/mod-subitem-as-enum-variant.stderr new file mode 100644 index 0000000000000..d62bad81c3d8d --- /dev/null +++ b/src/test/ui/mod-subitem-as-enum-variant.stderr @@ -0,0 +1,9 @@ +error[E0109]: type arguments are not allowed on this entity + --> $DIR/mod-subitem-as-enum-variant.rs:8:11 + | +LL | Mod::<i32>::FakeVariant(0); + | ^^^ type argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index e3659a2f2f66f..23f7f6c265e2f 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -17,10 +17,10 @@ fn main() { use_x(*p.value); } else { use_x(22); - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } struct WrapMayNotDangle<T> { diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index 28dc686e95cf1..efa825be295f2 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:20:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here ... LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:23:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` diff --git a/src/test/ui/nll/issue-55401.rs b/src/test/ui/nll/issue-55401.rs new file mode 100644 index 0000000000000..2fa234491087d --- /dev/null +++ b/src/test/ui/nll/issue-55401.rs @@ -0,0 +1,8 @@ +#![feature(nll)] + +fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + let (ref y, _z): (&'a u32, u32) = (&22, 44); + *y //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr new file mode 100644 index 0000000000000..9e50db7b6045d --- /dev/null +++ b/src/test/ui/nll/issue-55401.stderr @@ -0,0 +1,11 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-55401.rs:5:5 + | +LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); +LL | *y //~ ERROR + | ^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.rs b/src/test/ui/nll/issue-57265-return-type-wf-check.rs new file mode 100644 index 0000000000000..24c61a4926f0c --- /dev/null +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.rs @@ -0,0 +1,26 @@ +#![feature(nll)] + +use std::any::Any; + +#[derive(Debug, Clone)] +struct S<T: 'static>(T); + +// S<&'a T> is in the return type, so we get an implied bound +// &'a T: 'static +fn foo<'a, T>(x: &'a T) -> (S<&'a T>, Box<dyn Any + 'static>) { + let y = S(x); + + let z = Box::new(y.clone()) as Box<dyn Any + 'static>; + (y, z) +} + +fn main() { + let x = 5; + + // Check that we require that the argument is of type `&'static String`, + // so that the return type is well-formed. + let (_, z) = foo(&"hello".to_string()); + //~^ ERROR temporary value dropped while borrowed + + println!("{:?}", z.downcast_ref::<S<&'static String>>()); +} diff --git a/src/test/ui/nll/issue-57265-return-type-wf-check.stderr b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr new file mode 100644 index 0000000000000..db01212597f5b --- /dev/null +++ b/src/test/ui/nll/issue-57265-return-type-wf-check.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-57265-return-type-wf-check.rs:22:23 + | +LL | let (_, z) = foo(&"hello".to_string()); + | -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr index 5a359cf9ed8f1..123c26195d006 100644 --- a/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr +++ b/src/test/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -1,4 +1,4 @@ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [u32], user_self_ty: None } --> $DIR/dump-adt-brace-struct.rs:18:5 | LL | SomeStruct::<u32> { t: 22 }; //~ ERROR [u32] diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr index 3f159cc92b54f..a1a4e43e8a3e9 100644 --- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr +++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr @@ -1,22 +1,22 @@ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [u32], user_self_ty: None } --> $DIR/dump-fn-method.rs:26:13 | LL | let x = foo::<u32>; //~ ERROR [u32] | ^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } } +error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } --> $DIR/dump-fn-method.rs:32:13 | LL | let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [u8, u16, u32], user_self_ty: None } --> $DIR/dump-fn-method.rs:36:13 | LL | let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } } +error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } --> $DIR/dump-fn-method.rs:44:5 | LL | y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32] diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.rs b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs index a2502a53c9d38..c6264b6d2b32e 100644 --- a/src/test/ui/packed-struct/packed-struct-generic-transmute.rs +++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.rs @@ -3,7 +3,7 @@ // the error points to the start of the file, not the line with the // transmute -// error-pattern: transmute called with types of different sizes +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types use std::mem; diff --git a/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr index b66cb039b802c..744c832dbb407 100644 --- a/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr +++ b/src/test/ui/packed-struct/packed-struct-generic-transmute.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/packed-struct-generic-transmute.rs:24:38 | LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo); | ^^^^^^^^^^^^^^ | - = note: source type: Foo<[u8; 5], i32> (72 bits) - = note: target type: Oof<[u8; 5], i32> (96 bits) + = note: source type: `Foo<[u8; 5], i32>` (72 bits) + = note: target type: `Oof<[u8; 5], i32>` (96 bits) error: aborting due to previous error diff --git a/src/test/ui/packed-struct/packed-struct-transmute.rs b/src/test/ui/packed-struct/packed-struct-transmute.rs index 3d1580004b80b..a7d284025d7a0 100644 --- a/src/test/ui/packed-struct/packed-struct-transmute.rs +++ b/src/test/ui/packed-struct/packed-struct-transmute.rs @@ -4,7 +4,7 @@ // transmute // normalize-stderr-test "\d+ bits" -> "N bits" -// error-pattern: transmute called with types of different sizes +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types use std::mem; diff --git a/src/test/ui/packed-struct/packed-struct-transmute.stderr b/src/test/ui/packed-struct/packed-struct-transmute.stderr index d1fb443f310ec..80a8919f77b38 100644 --- a/src/test/ui/packed-struct/packed-struct-transmute.stderr +++ b/src/test/ui/packed-struct/packed-struct-transmute.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/packed-struct-transmute.rs:26:24 | LL | let oof: Oof = mem::transmute(foo); | ^^^^^^^^^^^^^^ | - = note: source type: Foo (N bits) - = note: target type: Oof (N bits) + = note: source type: `Foo` (N bits) + = note: target type: `Oof` (N bits) error: aborting due to previous error diff --git a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr index 51b1e71a1bb90..ceea4625e3eb3 100644 --- a/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr +++ b/src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `for` | LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A) | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A) + | ^^^^^ error: expected one of `::` or `>`, found `Foo` --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:29 diff --git a/src/test/ui/parser/bad-value-ident-false.stderr b/src/test/ui/parser/bad-value-ident-false.stderr index a78437a05f425..1a5c982a43dbc 100644 --- a/src/test/ui/parser/bad-value-ident-false.stderr +++ b/src/test/ui/parser/bad-value-ident-false.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `false` | LL | fn false() { } //~ ERROR expected identifier, found keyword `false` | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#false() { } //~ ERROR expected identifier, found keyword `false` + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/bad-value-ident-true.stderr b/src/test/ui/parser/bad-value-ident-true.stderr index 948fa4db50e8e..f431706ccd76b 100644 --- a/src/test/ui/parser/bad-value-ident-true.stderr +++ b/src/test/ui/parser/bad-value-ident-true.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `true` | LL | fn true() { } //~ ERROR expected identifier, found keyword `true` | ^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#true() { } //~ ERROR expected identifier, found keyword `true` + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-15980.stderr b/src/test/ui/parser/issue-15980.stderr index 748f21016a33b..96f3b03dc9240 100644 --- a/src/test/ui/parser/issue-15980.stderr +++ b/src/test/ui/parser/issue-15980.stderr @@ -6,6 +6,10 @@ LL | Err(ref e) if e.kind == io::EndOfFile { LL | //~^ NOTE while parsing this struct LL | return | ^^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#return + | error: expected one of `.`, `=>`, `?`, or an operator, found `_` --> $DIR/issue-15980.rs:15:9 diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs index 6895a926b4f0c..f8a2f1cc7e6c9 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.rs +++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs @@ -35,4 +35,7 @@ fn main() { //~^ ERROR invalid character in numeric character escape: //~^^ ERROR form of character escape may only be used with characters in the range [\x00-\x7f] //~^^^ ERROR incorrect unicode escape sequence + + let _ = "\u8f"; + //~^ ERROR incorrect unicode escape sequence } diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index b1a5764e891d8..f6e476ab0cd1d 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -16,7 +16,7 @@ error: incorrect unicode escape sequence LL | let _ = b'/u'; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:10:15 | LL | let _ = b'/u'; @@ -82,7 +82,7 @@ error: incorrect unicode escape sequence LL | let _ = b"/u{a4a4} /xf /u"; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:28:28 | LL | let _ = b"/u{a4a4} /xf /u"; @@ -112,11 +112,19 @@ error: incorrect unicode escape sequence LL | let _ = "/xf /u"; | ^^ | -help: format of unicode escape sequences is `/u{…}` +help: format of unicode escape sequences is `/u{...}` --> $DIR/issue-23620-invalid-escapes.rs:34:18 | LL | let _ = "/xf /u"; | ^^ -error: aborting due to 17 previous errors +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:39:14 + | +LL | let _ = "/u8f"; + | ^^-- + | | + | help: format of unicode escape sequences uses braces: `/u{8f}` + +error: aborting due to 18 previous errors diff --git a/src/test/ui/parser/keyword.stderr b/src/test/ui/parser/keyword.stderr index d97f6c5ce5aff..1c729ff083352 100644 --- a/src/test/ui/parser/keyword.stderr +++ b/src/test/ui/parser/keyword.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `break` | LL | pub mod break { | ^^^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | pub mod r#break { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/macro-keyword.stderr b/src/test/ui/parser/macro-keyword.stderr index 0dca30a60d1da..d3edb04c11951 100644 --- a/src/test/ui/parser/macro-keyword.stderr +++ b/src/test/ui/parser/macro-keyword.stderr @@ -3,6 +3,10 @@ error: expected identifier, found reserved keyword `macro` | LL | fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` | ^^^^^ expected identifier, found reserved keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | fn r#macro() { //~ ERROR expected identifier, found reserved keyword `macro` + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr index bec50e59664d6..0d489beae123a 100644 --- a/src/test/ui/parser/removed-syntax-field-let.stderr +++ b/src/test/ui/parser/removed-syntax-field-let.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `let` | LL | let foo: (), | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#let foo: (), + | ^^^^^ error: expected `:`, found `foo` --> $DIR/removed-syntax-field-let.rs:4:9 diff --git a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr index 3be31ce9cec63..51e1a02cbd763 100644 --- a/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr +++ b/src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `as` | LL | use std::any:: as foo; //~ ERROR expected identifier, found keyword `as` | ^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | use std::any:: r#as foo; //~ ERROR expected identifier, found keyword `as` + | ^^^^ error: expected one of `::`, `;`, or `as`, found `foo` --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:19 diff --git a/src/test/ui/prim-with-args.rs b/src/test/ui/prim-with-args.rs index 52443a729e5bc..b5df0fb76ca6a 100644 --- a/src/test/ui/prim-with-args.rs +++ b/src/test/ui/prim-with-args.rs @@ -1,27 +1,27 @@ fn main() { -let x: isize<isize>; //~ ERROR type parameters are not allowed on this type -let x: i8<isize>; //~ ERROR type parameters are not allowed on this type -let x: i16<isize>; //~ ERROR type parameters are not allowed on this type -let x: i32<isize>; //~ ERROR type parameters are not allowed on this type -let x: i64<isize>; //~ ERROR type parameters are not allowed on this type -let x: usize<isize>; //~ ERROR type parameters are not allowed on this type -let x: u8<isize>; //~ ERROR type parameters are not allowed on this type -let x: u16<isize>; //~ ERROR type parameters are not allowed on this type -let x: u32<isize>; //~ ERROR type parameters are not allowed on this type -let x: u64<isize>; //~ ERROR type parameters are not allowed on this type -let x: char<isize>; //~ ERROR type parameters are not allowed on this type +let x: isize<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i8<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i16<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i32<isize>; //~ ERROR type arguments are not allowed on this entity +let x: i64<isize>; //~ ERROR type arguments are not allowed on this entity +let x: usize<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u8<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u16<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u32<isize>; //~ ERROR type arguments are not allowed on this entity +let x: u64<isize>; //~ ERROR type arguments are not allowed on this entity +let x: char<isize>; //~ ERROR type arguments are not allowed on this entity -let x: isize<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i8<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i16<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i32<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: i64<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: usize<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u8<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u16<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u32<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: u64<'static>; //~ ERROR lifetime parameters are not allowed on this type -let x: char<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this entity +let x: char<'static>; //~ ERROR lifetime arguments are not allowed on this entity } diff --git a/src/test/ui/prim-with-args.stderr b/src/test/ui/prim-with-args.stderr index 190c45a1624d1..91259e87efc02 100644 --- a/src/test/ui/prim-with-args.stderr +++ b/src/test/ui/prim-with-args.stderr @@ -1,134 +1,134 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:3:14 | -LL | let x: isize<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: isize<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:4:11 | -LL | let x: i8<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i8<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:5:12 | -LL | let x: i16<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i16<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:6:12 | -LL | let x: i32<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i32<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:7:12 | -LL | let x: i64<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: i64<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:8:14 | -LL | let x: usize<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: usize<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:9:11 | -LL | let x: u8<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u8<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:10:12 | -LL | let x: u16<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u16<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:11:12 | -LL | let x: u32<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u32<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:12:12 | -LL | let x: u64<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: u64<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/prim-with-args.rs:13:13 | -LL | let x: char<isize>; //~ ERROR type parameters are not allowed on this type - | ^^^^^ type parameter not allowed +LL | let x: char<isize>; //~ ERROR type arguments are not allowed on this entity + | ^^^^^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:15:14 | -LL | let x: isize<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:16:11 | -LL | let x: i8<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:17:12 | -LL | let x: i16<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:18:12 | -LL | let x: i32<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:19:12 | -LL | let x: i64<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:20:14 | -LL | let x: usize<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:21:11 | -LL | let x: u8<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:22:12 | -LL | let x: u16<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:23:12 | -LL | let x: u32<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:24:12 | -LL | let x: u64<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/prim-with-args.rs:25:13 | -LL | let x: char<'static>; //~ ERROR lifetime parameters are not allowed on this type - | ^^^^^^^ lifetime parameter not allowed +LL | let x: char<'static>; //~ ERROR lifetime arguments are not allowed on this entity + | ^^^^^^^ lifetime argument not allowed error: aborting due to 22 previous errors diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.rs b/src/test/ui/privacy/associated-item-privacy-type-binding.rs index ff274ab8f1f8d..591e9df81eb0b 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.rs @@ -9,19 +9,19 @@ mod priv_trait { pub macro mac1() { let _: Box<PubTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private - //~| ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy2 = Box<PubTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr2: PubTr<AssocTy = u8> {} //~^ ERROR trait `priv_trait::PrivTr` is private } pub macro mac2() { let _: Box<PrivTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private - //~| ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>; - //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr1: PrivTr<AssocTy = u8> {} //~^ ERROR trait `priv_trait::PrivTr` is private } diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index 331e2f689b547..7f6886d7f9ad4 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -1,4 +1,4 @@ -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | LL | let _: Box<PubTr<AssocTy = u8>>; @@ -7,7 +7,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | LL | let _: Box<PubTr<AssocTy = u8>>; @@ -16,7 +16,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | LL | type InSignatureTy2 = Box<PubTr<AssocTy = u8>>; @@ -34,7 +34,7 @@ LL | trait InSignatureTr2: PubTr<AssocTy = u8> {} LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | LL | let _: Box<PrivTr<AssocTy = u8>>; @@ -43,7 +43,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | LL | let _: Box<PrivTr<AssocTy = u8>>; @@ -52,7 +52,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | LL | type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>; diff --git a/src/test/ui/privacy/private-in-public-expr-pat.rs b/src/test/ui/privacy/private-in-public-expr-pat.rs new file mode 100644 index 0000000000000..a3e53bdf45de3 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-expr-pat.rs @@ -0,0 +1,13 @@ +// Patterns and expressions are not interface parts and don't produce private-in-public errors. + +// compile-pass + +struct Priv1(usize); +struct Priv2; + +pub struct Pub(Priv2); + +pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK +pub fn public_pat(Pub(Priv2): Pub) {} // OK + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs new file mode 100644 index 0000000000000..02fd92aa7a4ef --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -0,0 +1,13 @@ +#![feature(optin_builtin_traits)] + +#[allow(private_in_public)] +mod m { + pub trait PubPrincipal {} + auto trait PrivNonPrincipal {} + pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } +} + +fn main() { + m::leak_dyn_nonprincipal(); + //~^ ERROR trait `m::PrivNonPrincipal` is private +} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr new file mode 100644 index 0000000000000..2db4925722642 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -0,0 +1,8 @@ +error: trait `m::PrivNonPrincipal` is private + --> $DIR/private-in-public-non-principal-2.rs:11:5 + | +LL | m::leak_dyn_nonprincipal(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs new file mode 100644 index 0000000000000..5de5a685208cd --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -0,0 +1,20 @@ +#![feature(optin_builtin_traits)] + +pub trait PubPrincipal {} +auto trait PrivNonPrincipal {} + +pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } +//~^ WARN private trait `PrivNonPrincipal` in public interface +//~| WARN this was previously accepted + +#[deny(missing_docs)] +fn container() { + impl dyn PubPrincipal { + pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + } + impl dyn PubPrincipal + PrivNonPrincipal { + pub fn check_doc_lint() {} // OK, no missing doc lint + } +} + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr new file mode 100644 index 0000000000000..9967405589777 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -0,0 +1,24 @@ +warning: private trait `PrivNonPrincipal` in public interface (error E0445) + --> $DIR/private-in-public-non-principal.rs:6:1 + | +LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(private_in_public)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> + +error: missing documentation for a method + --> $DIR/private-in-public-non-principal.rs:13:9 + | +LL | pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/private-in-public-non-principal.rs:10:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 0da0d03595d83..29f365b69be4d 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -213,6 +213,15 @@ mod aliases_pub { impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias { type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface } + impl PrivUseAliasTr for Option<<Priv as PrivTr>::AssocAlias> { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for (<Priv as PrivTr>::AssocAlias, Priv) { + type Check = Priv; // OK + } + impl PrivUseAliasTr for Option<(<Priv as PrivTr>::AssocAlias, Priv)> { + type Check = Priv; // OK + } } mod aliases_priv { diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index ab9ff8d64d36c..8f9e7cd74f992 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -297,8 +297,17 @@ LL | struct Priv; LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface | ^^^^^^^^^^^^^^^^^^ can't leak private type +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:217:9 + | +LL | struct Priv; + | - `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + | ^^^^^^^^^^^^^^^^^^ can't leak private type + error: private trait `aliases_priv::PrivTr1` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:238:5 + --> $DIR/private-in-public-warn.rs:247:5 | LL | pub trait Tr1: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,8 +315,8 @@ LL | pub trait Tr1: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: private type `aliases_priv::Priv2` in public interface (error E0446) - --> $DIR/private-in-public-warn.rs:241:5 +error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -315,8 +324,8 @@ LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:241:5 +error: private type `aliases_priv::Priv2` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -324,6 +333,6 @@ LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0446`. diff --git a/src/test/ui/privacy/private-in-public.rs b/src/test/ui/privacy/private-in-public.rs index 288298cfbfcf6..08c00f44f2269 100644 --- a/src/test/ui/privacy/private-in-public.rs +++ b/src/test/ui/privacy/private-in-public.rs @@ -102,7 +102,7 @@ mod aliases_pub { // This should be OK, but associated type aliases are not substituted yet pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - //~^ ERROR private type `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` in public interface + //~^ ERROR private trait `aliases_pub::PrivTr` in public interface //~| ERROR private type `aliases_pub::Priv` in public interface impl PrivUseAlias { @@ -131,7 +131,7 @@ mod aliases_priv { pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `aliases_priv::Priv1` in public interface pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - //~^ ERROR private type `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` in public + //~^ ERROR private trait `aliases_priv::PrivTr` in public interface //~| ERROR private type `aliases_priv::Priv` in public interface } diff --git a/src/test/ui/privacy/private-in-public.stderr b/src/test/ui/privacy/private-in-public.stderr index 2bd7503ab5aae..bf88a83e633cc 100644 --- a/src/test/ui/privacy/private-in-public.stderr +++ b/src/test/ui/privacy/private-in-public.stderr @@ -82,24 +82,36 @@ LL | pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Pri error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:31:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub enum E<T: PrivTr> { V(T) } //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:32:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:33:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub struct S1<T: PrivTr>(T); //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:34:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | / impl<T: PrivTr> Pub<T> { //~ ERROR private trait `traits::PrivTr` in public interface LL | | pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface LL | | } @@ -108,30 +120,45 @@ LL | | } error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:35:9 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:44:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub enum E<T> where T: PrivTr { V(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:46:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f<T>(arg: T) where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:48:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub struct S1<T>(T) where T: PrivTr; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:50:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | / impl<T> Pub<T> where T: PrivTr { LL | | //~^ ERROR private trait `traits_where::PrivTr` in public interface LL | | pub fn f<U>(arg: U) where U: PrivTr {} @@ -142,6 +169,9 @@ LL | | } error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:52:9 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f<U>(arg: U) where U: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait @@ -181,14 +211,14 @@ LL | struct Priv; LL | pub fn f(arg: Priv) {} //~ ERROR private type `impls::Priv` in public interface | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` in public interface +error[E0445]: private trait `aliases_pub::PrivTr` in public interface --> $DIR/private-in-public.rs:104:5 | LL | trait PrivTr { - | - `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` declared as private + | - `aliases_pub::PrivTr` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public.rs:104:5 @@ -226,14 +256,14 @@ LL | struct Priv2; LL | pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` in public interface +error[E0445]: private trait `aliases_priv::PrivTr` in public interface --> $DIR/private-in-public.rs:133:5 | LL | trait PrivTr { - | - `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` declared as private + | - `aliases_priv::PrivTr` declared as private ... LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_priv::Priv` in public interface --> $DIR/private-in-public.rs:133:5 diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index 1eb5fa408cd7f..69b60a56c67f1 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -119,7 +119,7 @@ fn main() { m::leak_anon2(); //~ ERROR type `m::Priv` is private m::leak_anon3(); //~ ERROR type `m::Priv` is private - m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private + m::leak_dyn1(); //~ ERROR trait `m::Trait` is private m::leak_dyn2(); //~ ERROR type `m::Priv` is private m::leak_dyn3(); //~ ERROR type `m::Priv` is private diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index 089fb1d3c3ea8..80a475f7dceea 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -160,10 +160,10 @@ error: type `m::Priv` is private LL | m::leak_anon3(); //~ ERROR type `m::Priv` is private | ^^^^^^^^^^^^^^^ -error: type `(dyn m::Trait + 'static)` is private +error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:122:5 | -LL | m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private +LL | m::leak_dyn1(); //~ ERROR trait `m::Trait` is private | ^^^^^^^^^^^^^^ error: type `m::Priv` is private diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 64d0173cb9c22..1f9103a6d2ee8 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -38,7 +38,7 @@ error[E0308]: mismatched types LL | extern "C" fn baz() { | - possibly return type missing here? LL | 0 //~ ERROR mismatched types - | ^ expected (), found integral variable + | ^ expected (), found integer | = note: expected type `()` found type `{integer}` diff --git a/src/test/ui/qualified/qualified-path-params-2.rs b/src/test/ui/qualified/qualified-path-params-2.rs index 6ee55f54bdbb5..8412983fda549 100644 --- a/src/test/ui/qualified/qualified-path-params-2.rs +++ b/src/test/ui/qualified/qualified-path-params-2.rs @@ -16,7 +16,7 @@ impl S { } type A = <S as Tr>::A::f<u8>; -//~^ ERROR type parameters are not allowed on this type +//~^ ERROR type arguments are not allowed on this entity //~| ERROR ambiguous associated type fn main() {} diff --git a/src/test/ui/qualified/qualified-path-params-2.stderr b/src/test/ui/qualified/qualified-path-params-2.stderr index 91c3d704cb9dd..4e073841b9740 100644 --- a/src/test/ui/qualified/qualified-path-params-2.stderr +++ b/src/test/ui/qualified/qualified-path-params-2.stderr @@ -1,8 +1,8 @@ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/qualified-path-params-2.rs:18:26 | LL | type A = <S as Tr>::A::f<u8>; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/qualified-path-params-2.rs:18:10 diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index a8fe562656ebb..242119cc201da 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -37,8 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly - want_F(bar); //~ ERROR E0308 + want_F(bar); want_F(baz); } @@ -46,11 +45,7 @@ fn supply_F() { fn supply_G() { want_G(foo); want_G(bar); - want_G(baz); - //~^ ERROR mismatched types - //~| expected type `for<'cx> fn(&'cx S) -> &'static S` - //~| found type `for<'r> fn(&'r S) -> &'r S {baz}` - //~| expected concrete lifetime, found bound lifetime parameter 'cx + want_G(baz); //~ ERROR } pub fn main() { diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 0bf6e0514d21e..a9234e43191ea 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,21 +1,12 @@ error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:41:12 + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | -LL | want_F(bar); //~ ERROR E0308 - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` - found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:49:12 - | -LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx +LL | want_G(baz); //~ ERROR + | ^^^ one type is more general than the other | = note: expected type `for<'cx> fn(&'cx S) -> &'static S` - found type `for<'r> fn(&'r S) -> &'r S {baz}` + found type `for<'r> fn(&'r S) -> &'r S` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 5c8b3d3ba6922..47e1d0efdc77b 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,10 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter + | ^ one type is more general than the other | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 8e7f4ccad9cb4..066522548ad45 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -19,7 +19,7 @@ fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR mismatched types + let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 } fn e() { diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 01899349bf701..1e7b99053f77f 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -30,11 +30,11 @@ LL | a(x, y, z); //~ ERROR lifetime mismatch [E0623] error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | -LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; //~ ERROR E0308 + | ^ one type is more general than the other | = note: expected type `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + found type `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa5f6a334b0f0..4d6d342f571a5 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// compile-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -37,8 +39,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - // FIXME(#33684) -- this should be a subtype, but current alg. rejects it incorrectly - want_F(bar); //~ ERROR E0308 + want_F(bar); want_F(baz); } diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr index 30646fe79659e..61eaf9fcf109b 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr @@ -1,12 +1,26 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 +warning: function `want_F` should have a snake case name such as `want_f` + --> $DIR/regions-fn-subtyping-return-static.rs:18:1 | -LL | want_F(bar); //~ ERROR E0308 - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx +LL | fn want_F(f: F) { } + | ^^^^^^^^^^^^^^^^^^^ | - = note: expected type `for<'cx> fn(&'cx S) -> &'cx S` - found type `for<'a> fn(&'a S) -> &S {bar::<'_>}` + = note: #[warn(non_snake_case)] on by default -error: aborting due to previous error +warning: function `want_G` should have a snake case name such as `want_g` + --> $DIR/regions-fn-subtyping-return-static.rs:22:1 + | +LL | fn want_G(f: G) { } + | ^^^^^^^^^^^^^^^^^^^ + +warning: function `supply_F` should have a snake case name such as `supply_f` + --> $DIR/regions-fn-subtyping-return-static.rs:39:1 + | +LL | / fn supply_F() { +LL | | want_F(foo); +LL | | +LL | | want_F(bar); +LL | | +LL | | want_F(baz); +LL | | } + | |_^ -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs index 2f35883cc9916..7d7f62e19792f 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -17,7 +17,7 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { fn d() { // 'a and 'b are early bound in the function `a` because they appear // inconstraints: - let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types + let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 } fn e() { diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index c4d4a159a9c32..a43ee7ec3ace0 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -19,11 +19,11 @@ LL | a(x, y); //~ ERROR lifetime mismatch [E0623] error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | -LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR mismatched types - | ^ expected concrete lifetime, found bound lifetime parameter +LL | let _: fn(&mut &isize, &mut &isize) = a; //~ ERROR E0308 + | ^ one type is more general than the other | = note: expected type `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found type `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index d38706defe7ad..91a0d8590ff34 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -31,9 +31,7 @@ fn with_assoc<'a,'b>() { // outlive 'a. In this case, that means TheType<'b>::TheAssocType, // which is &'b (), must outlive 'a. - // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if - // `_x` is changed to `_` - let _x: &'a WithAssoc<TheType<'b>> = loop { }; + let _: &'a WithAssoc<TheType<'b>> = loop { }; //~^ ERROR reference has a longer lifetime } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr index 2ed9fd4f9b4cf..0d73d3d64322e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.stderr @@ -1,8 +1,8 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-wc.rs:36:13 + --> $DIR/regions-outlives-projection-container-wc.rs:34:12 | -LL | let _x: &'a WithAssoc<TheType<'b>> = loop { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: &'a WithAssoc<TheType<'b>> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 --> $DIR/regions-outlives-projection-container-wc.rs:28:15 diff --git a/src/test/ui/repeat_count.rs b/src/test/ui/repeat_count.rs index 74385c7949790..c42dc8c99719d 100644 --- a/src/test/ui/repeat_count.rs +++ b/src/test/ui/repeat_count.rs @@ -16,7 +16,7 @@ fn main() { //~^ ERROR mismatched types //~| expected type `usize` //~| found type `{float}` - //~| expected usize, found floating-point variable + //~| expected usize, found floating-point number let e = [0; "foo"]; //~^ ERROR mismatched types //~| expected type `usize` diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index b481cd187c597..df3227bfcde13 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -23,7 +23,7 @@ error[E0308]: mismatched types --> $DIR/repeat_count.rs:15:17 | LL | let d = [0; 0.5]; - | ^^^ expected usize, found floating-point variable + | ^^^ expected usize, found floating-point number | = note: expected type `usize` found type `{float}` diff --git a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr index dee32024e4702..9d35e167075ae 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/no-double-error.stderr @@ -1,8 +1,10 @@ error[E0599]: no associated item named `XXX` found for type `u32` in the current scope - --> $DIR/no-double-error.rs:8:9 + --> $DIR/no-double-error.rs:8:14 | LL | u32::XXX => { } //~ ERROR no associated item named - | ^^^^^^^^ associated item not found in `u32` + | -----^^^ + | | + | associated item not found in `u32` error: aborting due to previous error diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.rs b/src/test/ui/rfc1598-generic-associated-types/collections.rs index e1a65c28803e2..5414bb4a6d20e 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.rs +++ b/src/test/ui/rfc1598-generic-associated-types/collections.rs @@ -2,7 +2,7 @@ //~^ WARNING the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. // A Collection trait and collection families. Based on @@ -15,14 +15,14 @@ trait Collection<T> { // Test associated type defaults with parameters type Sibling<U>: Collection<U> = <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] fn empty() -> Self; fn add(&mut self, value: T); fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } trait CollectionFamily { @@ -48,13 +48,13 @@ impl<T> Collection<T> for Vec<T> { } fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32> -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] where C: Collection<i32>, { @@ -66,7 +66,7 @@ where } fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> -//~^ ERROR type parameters are not allowed on this type [E0109] +//~^ ERROR type arguments are not allowed on this entity [E0109] where C: Collection<i32>, { diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr index e90a6b8ad138c..eeed04bd89213 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/collections.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:56:90 | LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32> - | ^^^ type parameter not allowed + | ^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:68:69 | LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32> - | ^^^ type parameter not allowed + | ^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/collections.rs:17:71 | LL | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/collections.rs:24:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; - | ^^^^^ lifetime parameter not allowed + | ^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/collections.rs:50:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { - | ^^^^^ lifetime parameter not allowed + | ^^^^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs index 85935d1cca6bf..d9c482e23e47c 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs @@ -3,7 +3,7 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Foo { @@ -15,15 +15,15 @@ trait Baz { // This weird type tests that we can use universal function call syntax to access the Item on type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } impl<T> Baz for T where T: Foo { type Quux<'a> = T; type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr index 100809f62a55c..fd6116d2da23a 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr @@ -4,23 +4,23 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:17:46 | LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:17:63 | LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/construct_with_other_type.rs:25:40 | LL | type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs index bfdd12003885a..2e6d7470b49a2 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -3,20 +3,20 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Iterable { type Item<'a>; type Iter<'a>: Iterator<Item = Self::Item<'a>> - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] + Deref<Target = Self::Item<'b>>; //~^ ERROR undeclared lifetime - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; //~^ ERROR undeclared lifetime - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index f5b42866dc6b4..3cebab6389557 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -16,23 +16,23 @@ error[E0261]: use of undeclared lifetime name `'undeclared` LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; | ^^^^^^^^^^^ undeclared lifetime -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:47 | LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:13:37 | LL | + Deref<Target = Self::Item<'b>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/generic_associated_type_undeclared_lifetimes.rs:17:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; - | ^^^^^^^^^^^ lifetime parameter not allowed + | ^^^^^^^^^^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs index 16ed4a7546cc3..69258506651c4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.rs +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.rs @@ -3,16 +3,16 @@ use std::ops::Deref; -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. trait Iterable { type Item<'a>; type Iter<'a>: Iterator<Item = Self::Item<'a>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] fn iter<'a>(&'a self) -> Self::Iter<'a>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } // Impl for struct type @@ -21,7 +21,7 @@ impl<T> Iterable for Vec<T> { type Iter<'a> = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } @@ -32,18 +32,18 @@ impl<T> Iterable for [T] { type Iter<'a> = std::slice::Iter<'a, T>; fn iter<'a>(&'a self) -> Self::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] self.iter() } } fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] it.iter() } fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] it.iter().next() } diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr index 41943d7d325e9..cc3ade6f39d90 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr @@ -4,41 +4,41 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:11:47 | LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:40:53 | LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:45:60 | LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:14:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:23:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/iterable.rs:34:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 6 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs index 098d52b20faae..851e331a0e965 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs @@ -2,7 +2,7 @@ //~^ WARNING the feature `generic_associated_types` is incomplete #![feature(associated_type_defaults)] -// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime arguments are not allowed on this entity" errors will be addressed in a // follow-up PR. // FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`. @@ -15,13 +15,13 @@ trait Foo { type E<'a, T>; // Test parameters in default values type FOk<T> = Self::E<'static, T>; - //~^ ERROR type parameters are not allowed on this type [E0109] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] type FErr1 = Self::E<'static, 'static>; // Error - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] type FErr2<T> = Self::E<'static, T, u32>; // Error - //~^ ERROR type parameters are not allowed on this type [E0109] - //~| ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR type arguments are not allowed on this entity [E0109] + //~| ERROR lifetime arguments are not allowed on this entity [E0110] } struct Fooy; diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr index dfd1648e5c0d6..265b0fab77061 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:17:27 | LL | type FOk<T> = Self::E<'static, T>; - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:17:36 | LL | type FOk<T> = Self::E<'static, T>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:20:26 | LL | type FErr1 = Self::E<'static, 'static>; // Error - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:22:29 | LL | type FErr2<T> = Self::E<'static, T, u32>; // Error - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/parameter_number_and_kind.rs:22:38 | LL | type FErr2<T> = Self::E<'static, T, u32>; // Error - | ^ type parameter not allowed + | ^ type argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs index e11670ce1b316..2d188aed42778 100644 --- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs @@ -1,7 +1,7 @@ #![feature(generic_associated_types)] //~^ WARNING the feature `generic_associated_types` is incomplete -// FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR. +// FIXME(#44265): "type argument not allowed" errors will be addressed in a follow-up PR. use std::rc::Rc; use std::sync::Arc; @@ -10,7 +10,7 @@ use std::ops::Deref; trait PointerFamily { type Pointer<T>: Deref<Target = T>; fn new<T>(value: T) -> Self::Pointer<T>; - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] } struct ArcFamily; @@ -18,7 +18,7 @@ struct ArcFamily; impl PointerFamily for ArcFamily { type Pointer<T> = Arc<T>; fn new<T>(value: T) -> Self::Pointer<T> { - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Arc::new(value) } } @@ -28,14 +28,14 @@ struct RcFamily; impl PointerFamily for RcFamily { type Pointer<T> = Rc<T>; fn new<T>(value: T) -> Self::Pointer<T> { - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] Rc::new(value) } } struct Foo<P: PointerFamily> { bar: P::Pointer<String>, - //~^ ERROR type parameters are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on this entity [E0109] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr index 29c442a79e628..2b9eed2a688a2 100644 --- a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr @@ -4,29 +4,29 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:37:21 | LL | bar: P::Pointer<String>, - | ^^^^^^ type parameter not allowed + | ^^^^^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:12:42 | LL | fn new<T>(value: T) -> Self::Pointer<T>; - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:20:42 | LL | fn new<T>(value: T) -> Self::Pointer<T> { - | ^ type parameter not allowed + | ^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/pointer_family.rs:30:42 | LL | fn new<T>(value: T) -> Self::Pointer<T> { - | ^ type parameter not allowed + | ^ type argument not allowed error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs index cb6e576804937..1ef154447903b 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs @@ -1,7 +1,7 @@ #![feature(generic_associated_types)] //~^ WARNING the feature `generic_associated_types` is incomplete -// FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a +// FIXME(#44265): "lifetime argument not allowed on this type" errors will be addressed in a // follow-up PR use std::fmt::Display; @@ -10,13 +10,13 @@ trait StreamingIterator { type Item<'a>; // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. fn next<'a>(&'a self) -> Option<Self::Item<'a>>; - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } struct Foo<T: StreamingIterator> { // Applying a concrete lifetime to the constructor outside the trait. bar: <T as StreamingIterator>::Item<'static>, - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] } // Users can bound parameters by the type constructed by that trait's associated type constructor @@ -24,7 +24,7 @@ struct Foo<T: StreamingIterator> { //FIXME(sunjay): This next line should parse and be valid //fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ } fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } -//~^ ERROR lifetime parameters are not allowed on this type [E0110] +//~^ ERROR lifetime arguments are not allowed on this entity [E0110] // Full example of enumerate iterator @@ -36,9 +36,9 @@ struct StreamEnumerate<I> { impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> { type Item<'a> = (usize, I::Item<'a>); - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] fn next<'a>(&'a self) -> Option<Self::Item<'a>> { - //~^ ERROR lifetime parameters are not allowed on this type [E0110] + //~^ ERROR lifetime arguments are not allowed on this entity [E0110] match self.iter.next() { None => None, Some(val) => { diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr index af5d1b872cc6e..5afbba5d2d744 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr @@ -4,35 +4,35 @@ warning: the feature `generic_associated_types` is incomplete and may cause the LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:18:41 | LL | bar: <T as StreamingIterator>::Item<'static>, - | ^^^^^^^ lifetime parameter not allowed + | ^^^^^^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:26:64 | LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:12:48 | LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>>; - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:38:37 | LL | type Item<'a> = (usize, I::Item<'a>); - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed -error[E0110]: lifetime parameters are not allowed on this type +error[E0110]: lifetime arguments are not allowed on this entity --> $DIR/streaming_iterator.rs:40:48 | LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>> { - | ^^ lifetime parameter not allowed + | ^^ lifetime argument not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rmeta_meta_main.stderr b/src/test/ui/rmeta_meta_main.stderr index b7d7f89cfbb4c..bed9076d84cbe 100644 --- a/src/test/ui/rmeta_meta_main.stderr +++ b/src/test/ui/rmeta_meta_main.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `rmeta_meta::Foo` has no field named `field2` --> $DIR/rmeta_meta_main.rs:13:19 | LL | let _ = Foo { field2: 42 }; //~ ERROR struct `rmeta_meta::Foo` has no field named `field2` - | ^^^^^^ field does not exist - did you mean `field`? + | ^^^^^^ help: a field with a similar name exists: `field` error: aborting due to previous error diff --git a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr index bd72f9c6786b2..6be0052046583 100644 --- a/src/test/ui/rust-2018/dyn-trait-compatibility.stderr +++ b/src/test/ui/rust-2018/dyn-trait-compatibility.stderr @@ -3,6 +3,10 @@ error: expected identifier, found keyword `dyn` | LL | type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | type A1 = dyn::r#dyn; //~ERROR expected identifier, found keyword `dyn` + | ^^^^^ error: expected identifier, found `<` --> $DIR/dyn-trait-compatibility.rs:5:14 diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index e97cb3187846f..e4c17680c90a5 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -27,10 +27,12 @@ LL | x.baz(); //~ ERROR no method named `baz` | ^^^ error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope - --> $DIR/trait-import-suggestions.rs:30:13 + --> $DIR/trait-import-suggestions.rs:30:18 | LL | let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str` - | ^^^^^^^^^^^^^ function or associated item not found in `u32` + | -----^^^^^^^^ + | | + | function or associated item not found in `u32` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs new file mode 100644 index 0000000000000..db723075f93c0 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs @@ -0,0 +1 @@ +pub extern crate core; diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs new file mode 100644 index 0000000000000..bc010a3dd2ba0 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs @@ -0,0 +1 @@ +// Nothing here diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs new file mode 100644 index 0000000000000..9ec3a64113116 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs @@ -0,0 +1,11 @@ +// compile-pass +// edition:2018 +// compile-flags: --extern issue_56596_2 +// aux-build:issue-56596-2.rs + +mod m { + use core::any; + pub use issue_56596_2::*; +} + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs new file mode 100644 index 0000000000000..5c40d78d81c29 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.rs @@ -0,0 +1,14 @@ +// edition:2018 +// compile-flags: --extern issue_56596 +// aux-build:issue-56596.rs + +#![feature(uniform_paths)] + +mod m { + pub mod issue_56596 {} +} + +use m::*; +use issue_56596; //~ ERROR `issue_56596` is ambiguous + +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr new file mode 100644 index 0000000000000..293d0ec6a7208 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-56596.stderr @@ -0,0 +1,18 @@ +error[E0659]: `issue_56596` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-56596.rs:12:5 + | +LL | use issue_56596; //~ ERROR `issue_56596` is ambiguous + | ^^^^^^^^^^^ ambiguous name + | + = note: `issue_56596` could refer to an extern crate passed with `--extern` + = help: use `::issue_56596` to refer to this extern crate unambiguously +note: `issue_56596` could also refer to the module imported here + --> $DIR/issue-56596.rs:11:5 + | +LL | use m::*; + | ^^^^ + = help: use `crate::issue_56596` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/slightly-nice-generic-literal-messages.rs b/src/test/ui/slightly-nice-generic-literal-messages.rs index fcbc2a169a53c..cd0ee174af528 100644 --- a/src/test/ui/slightly-nice-generic-literal-messages.rs +++ b/src/test/ui/slightly-nice-generic-literal-messages.rs @@ -8,7 +8,7 @@ fn main() { //~^ ERROR mismatched types //~| expected type `Foo<{float}, _>` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } } diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr index 767faf5291488..76ebc007df34f 100644 --- a/src/test/ui/slightly-nice-generic-literal-messages.stderr +++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/slightly-nice-generic-literal-messages.rs:7:9 | LL | 1 => {} - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo<{float}, _>` found type `{integer}` diff --git a/src/test/ui/structs/struct-base-wrong-type-2.rs b/src/test/ui/structs/struct-base-wrong-type-2.rs index a88c5d1c13b48..562f75b8e85bd 100644 --- a/src/test/ui/structs/struct-base-wrong-type-2.rs +++ b/src/test/ui/structs/struct-base-wrong-type-2.rs @@ -15,5 +15,5 @@ fn main() { let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types //~| expected type `Foo` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer } diff --git a/src/test/ui/structs/struct-base-wrong-type-2.stderr b/src/test/ui/structs/struct-base-wrong-type-2.stderr index 44ac3483ad6d1..b15ea51bb2d4c 100644 --- a/src/test/ui/structs/struct-base-wrong-type-2.stderr +++ b/src/test/ui/structs/struct-base-wrong-type-2.stderr @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/struct-base-wrong-type-2.rs:15:34 | LL | let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo` found type `{integer}` diff --git a/src/test/ui/structs/struct-base-wrong-type.rs b/src/test/ui/structs/struct-base-wrong-type.rs index 83b5444815159..6252673c296fb 100644 --- a/src/test/ui/structs/struct-base-wrong-type.rs +++ b/src/test/ui/structs/struct-base-wrong-type.rs @@ -14,7 +14,7 @@ static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types //~| expected type `Foo` //~| found type `{integer}` - //~| expected struct `Foo`, found integral variable + //~| expected struct `Foo`, found integer fn main() { let b = Bar { x: 5 }; diff --git a/src/test/ui/structs/struct-base-wrong-type.stderr b/src/test/ui/structs/struct-base-wrong-type.stderr index 8519a9510a9fa..045eb610f7d1f 100644 --- a/src/test/ui/structs/struct-base-wrong-type.stderr +++ b/src/test/ui/structs/struct-base-wrong-type.stderr @@ -11,7 +11,7 @@ error[E0308]: mismatched types --> $DIR/struct-base-wrong-type.rs:14:35 | LL | static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types - | ^ expected struct `Foo`, found integral variable + | ^ expected struct `Foo`, found integer | = note: expected type `Foo` found type `{integer}` diff --git a/src/test/ui/structs/struct-fields-hints-no-dupe.stderr b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr index 105f330463a94..1a88f269347c2 100644 --- a/src/test/ui/structs/struct-fields-hints-no-dupe.stderr +++ b/src/test/ui/structs/struct-fields-hints-no-dupe.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints-no-dupe.rs:10:9 | LL | bar : 42, - | ^^^ field does not exist - did you mean `barr`? + | ^^^ help: a field with a similar name exists: `barr` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fields-hints.stderr b/src/test/ui/structs/struct-fields-hints.stderr index d713030563102..3b8a2b5c7bad0 100644 --- a/src/test/ui/structs/struct-fields-hints.stderr +++ b/src/test/ui/structs/struct-fields-hints.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints.rs:10:9 | LL | bar : 42, - | ^^^ field does not exist - did you mean `car`? + | ^^^ help: a field with a similar name exists: `car` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fields-typo.rs b/src/test/ui/structs/struct-fields-typo.rs index b435a0a47773d..0e9b2ae5145d7 100644 --- a/src/test/ui/structs/struct-fields-typo.rs +++ b/src/test/ui/structs/struct-fields-typo.rs @@ -8,7 +8,8 @@ fn main() { foo: 0, bar: 0.5, }; - let x = foo.baa;//~ no field `baa` on type `BuildData` - //~^ did you mean `bar`? + let x = foo.baa; //~ ERROR no field `baa` on type `BuildData` + //~| HELP a field with a similar name exists + //~| SUGGESTION bar println!("{}", x); } diff --git a/src/test/ui/structs/struct-fields-typo.stderr b/src/test/ui/structs/struct-fields-typo.stderr index 93127ab5beb6e..c2fab714f7c15 100644 --- a/src/test/ui/structs/struct-fields-typo.stderr +++ b/src/test/ui/structs/struct-fields-typo.stderr @@ -1,8 +1,8 @@ error[E0609]: no field `baa` on type `BuildData` --> $DIR/struct-fields-typo.rs:11:17 | -LL | let x = foo.baa;//~ no field `baa` on type `BuildData` - | ^^^ did you mean `bar`? +LL | let x = foo.baa; //~ ERROR no field `baa` on type `BuildData` + | ^^^ help: a field with a similar name exists: `bar` error: aborting due to previous error diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs index 1cafe265b2e0e..7c770852d22d2 100644 --- a/src/test/ui/structs/struct-path-associated-type.rs +++ b/src/test/ui/structs/struct-path-associated-type.rs @@ -13,7 +13,7 @@ fn f<T: Tr>() { //~^ ERROR expected struct, variant or union type, found associated type let z = T::A::<u8> {}; //~^ ERROR expected struct, variant or union type, found associated type - //~| ERROR type parameters are not allowed on this type + //~| ERROR type arguments are not allowed on this entity match S { T::A {} => {} //~^ ERROR expected struct, variant or union type, found associated type @@ -22,7 +22,7 @@ fn f<T: Tr>() { fn g<T: Tr<A = S>>() { let s = T::A {}; // OK - let z = T::A::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this entity match S { T::A {} => {} // OK } @@ -31,7 +31,7 @@ fn g<T: Tr<A = S>>() { fn main() { let s = S::A {}; //~ ERROR ambiguous associated type let z = S::A::<u8> {}; //~ ERROR ambiguous associated type - //~^ ERROR type parameters are not allowed on this type + //~^ ERROR type arguments are not allowed on this entity match S { S::A {} => {} //~ ERROR ambiguous associated type } diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr index 41360d87930d1..80824d9847838 100644 --- a/src/test/ui/structs/struct-path-associated-type.stderr +++ b/src/test/ui/structs/struct-path-associated-type.stderr @@ -4,11 +4,11 @@ error[E0071]: expected struct, variant or union type, found associated type LL | let s = T::A {}; | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:14:20 | LL | let z = T::A::<u8> {}; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0071]: expected struct, variant or union type, found associated type --> $DIR/struct-path-associated-type.rs:14:13 @@ -22,11 +22,11 @@ error[E0071]: expected struct, variant or union type, found associated type LL | T::A {} => {} | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:25:20 | -LL | let z = T::A::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 @@ -34,11 +34,11 @@ error[E0223]: ambiguous associated type LL | let s = S::A {}; //~ ERROR ambiguous associated type | ^^^^ help: use fully-qualified syntax: `<S as Trait>::A` -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-associated-type.rs:33:20 | LL | let z = S::A::<u8> {}; //~ ERROR ambiguous associated type - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs index ccbf3db29b1d9..51ed9e5457eb7 100644 --- a/src/test/ui/structs/struct-path-self.rs +++ b/src/test/ui/structs/struct-path-self.rs @@ -6,7 +6,7 @@ trait Tr { //~^ ERROR expected struct, variant or union type, found Self let z = Self::<u8> {}; //~^ ERROR expected struct, variant or union type, found Self - //~| ERROR type parameters are not allowed on this type + //~| ERROR type arguments are not allowed on this entity match s { Self { .. } => {} //~^ ERROR expected struct, variant or union type, found Self @@ -17,7 +17,7 @@ trait Tr { impl Tr for S { fn f() { let s = Self {}; // OK - let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity match s { Self { .. } => {} // OK } @@ -27,7 +27,7 @@ impl Tr for S { impl S { fn g() { let s = Self {}; // OK - let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type + let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity match s { Self { .. } => {} // OK } diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr index a1df1a0764ccb..cda6b7a533f65 100644 --- a/src/test/ui/structs/struct-path-self.stderr +++ b/src/test/ui/structs/struct-path-self.stderr @@ -4,11 +4,11 @@ error[E0071]: expected struct, variant or union type, found Self LL | let s = Self {}; | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:7:24 | LL | let z = Self::<u8> {}; - | ^^ type parameter not allowed + | ^^ type argument not allowed error[E0071]: expected struct, variant or union type, found Self --> $DIR/struct-path-self.rs:7:17 @@ -22,17 +22,17 @@ error[E0071]: expected struct, variant or union type, found Self LL | Self { .. } => {} | ^^^^ not a struct -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:20:24 | -LL | let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed -error[E0109]: type parameters are not allowed on this type +error[E0109]: type arguments are not allowed on this entity --> $DIR/struct-path-self.rs:30:24 | -LL | let z = Self::<u8> {}; //~ ERROR type parameters are not allowed on this type - | ^^ type parameter not allowed +LL | let z = Self::<u8> {}; //~ ERROR type arguments are not allowed on this entity + | ^^ type argument not allowed error: aborting due to 6 previous errors diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.rs b/src/test/ui/structs/structure-constructor-type-mismatch.rs index 54319e1ea4fc4..8850f6ea89fa3 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.rs +++ b/src/test/ui/structs/structure-constructor-type-mismatch.rs @@ -16,32 +16,32 @@ fn main() { let pt = PointF { x: 1, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 2, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer }; let pt2 = Point::<f32> { x: 3, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 4, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer }; let pair = PairF { x: 5, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 6, }; let pair2 = PairF::<i32> { x: 7, //~^ ERROR mismatched types - //~| expected f32, found integral variable + //~| expected f32, found integer y: 8, }; diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr index 6abc75110e1f0..3c1ed8e69a6bd 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | x: 1, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `1.0` | = note: expected type `f32` @@ -16,7 +16,7 @@ error[E0308]: mismatched types LL | y: 2, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `2.0` | = note: expected type `f32` @@ -28,7 +28,7 @@ error[E0308]: mismatched types LL | x: 3, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `3.0` | = note: expected type `f32` @@ -40,7 +40,7 @@ error[E0308]: mismatched types LL | y: 4, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `4.0` | = note: expected type `f32` @@ -52,7 +52,7 @@ error[E0308]: mismatched types LL | x: 5, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `5.0` | = note: expected type `f32` @@ -64,7 +64,7 @@ error[E0308]: mismatched types LL | x: 7, | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `7.0` | = note: expected type `f32` @@ -82,7 +82,7 @@ error[E0308]: mismatched types LL | x: 9, //~ ERROR mismatched types | ^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `9.0` | = note: expected type `f32` @@ -94,7 +94,7 @@ error[E0308]: mismatched types LL | y: 10, //~ ERROR mismatched types | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `10.0` | = note: expected type `f32` @@ -110,7 +110,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:54:9 | LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments - | ^^^^^^^^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Point<{integer}>` found type `Point<f32>` @@ -119,7 +119,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:59:9 | LL | PointF { .. } => {} //~ ERROR mismatched types - | ^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Point<{integer}>` found type `Point<f32>` @@ -128,7 +128,7 @@ error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:67:9 | LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types - | ^^^^^^^^^^^^^^^^^^^ expected integral variable, found f32 + | ^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | = note: expected type `Pair<{integer}, {integer}>` found type `Pair<f32, u32>` diff --git a/src/test/ui/as-ref.rs b/src/test/ui/suggestions/as-ref.rs similarity index 52% rename from src/test/ui/as-ref.rs rename to src/test/ui/suggestions/as-ref.rs index 822d10f2ca7b3..03f04c389f1f3 100644 --- a/src/test/ui/as-ref.rs +++ b/src/test/ui/suggestions/as-ref.rs @@ -12,4 +12,14 @@ fn main() { //~^ ERROR mismatched types [E0308] opt.and_then(|arg| Ok(takes_ref(arg))); //~^ ERROR mismatched types [E0308] + let x: &Option<usize> = &Some(3); + let y: Option<&usize> = x; + //~^ ERROR mismatched types [E0308] + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, &usize> = x; + //~^ ERROR mismatched types [E0308] + // note: do not suggest because of `E: usize` + let x: &Result<usize, usize> = &Ok(3); + let y: Result<&usize, usize> = x; + //~^ ERROR mismatched types [E0308] } diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/suggestions/as-ref.stderr new file mode 100644 index 0000000000000..7273496a7ce06 --- /dev/null +++ b/src/test/ui/suggestions/as-ref.stderr @@ -0,0 +1,81 @@ +error[E0308]: mismatched types + --> $DIR/as-ref.rs:6:27 + | +LL | opt.map(|arg| takes_ref(arg)); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:8:37 + | +LL | opt.and_then(|arg| Some(takes_ref(arg))); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:11:27 + | +LL | opt.map(|arg| takes_ref(arg)); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:13:35 + | +LL | opt.and_then(|arg| Ok(takes_ref(arg))); + | - ^^^ expected &Foo, found struct `Foo` + | | + | help: consider using `as_ref` instead: `as_ref().` + | + = note: expected type `&Foo` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:16:27 + | +LL | let y: Option<&usize> = x; + | ^ + | | + | expected enum `std::option::Option`, found reference + | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()` + | + = note: expected type `std::option::Option<&usize>` + found type `&std::option::Option<usize>` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:19:35 + | +LL | let y: Result<&usize, &usize> = x; + | ^ expected enum `std::result::Result`, found reference + | + = note: expected type `std::result::Result<&usize, &usize>` + found type `&std::result::Result<usize, usize>` +help: you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()` + | +LL | let y: Result<&usize, &usize> = x.as_ref(); + | ^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:23:34 + | +LL | let y: Result<&usize, usize> = x; + | ^ expected enum `std::result::Result`, found reference + | + = note: expected type `std::result::Result<&usize, usize>` + found type `&std::result::Result<usize, usize>` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/suggestions/suggest-private-fields.stderr index 5f0176473ea74..524558e0ec564 100644 --- a/src/test/ui/suggestions/suggest-private-fields.stderr +++ b/src/test/ui/suggestions/suggest-private-fields.stderr @@ -2,7 +2,7 @@ error[E0560]: struct `xc::B` has no field named `aa` --> $DIR/suggest-private-fields.rs:15:9 | LL | aa: 20, - | ^^ field does not exist - did you mean `a`? + | ^^ help: a field with a similar name exists: `a` error[E0560]: struct `xc::B` has no field named `bb` --> $DIR/suggest-private-fields.rs:17:9 @@ -16,13 +16,13 @@ error[E0560]: struct `A` has no field named `aa` --> $DIR/suggest-private-fields.rs:22:9 | LL | aa: 20, - | ^^ field does not exist - did you mean `a`? + | ^^ help: a field with a similar name exists: `a` error[E0560]: struct `A` has no field named `bb` --> $DIR/suggest-private-fields.rs:24:9 | LL | bb: 20, - | ^^ field does not exist - did you mean `b`? + | ^^ help: a field with a similar name exists: `b` error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 5913f7b4b18a0..c65a9a3ed945c 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -33,26 +33,30 @@ LL | c.a(); //~ ERROR method `a` is private | ^ error[E0599]: no function or associated item named `a` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:78:5 + --> $DIR/trait-item-privacy.rs:78:8 | LL | struct S; | --------- function or associated item `a` not found for this ... LL | S::a(&S); - | ^^^^ function or associated item not found in `S` + | ---^ + | | + | function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `a`, perhaps you need to implement it: candidate #1: `method::A` error[E0599]: no function or associated item named `b` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:80:5 + --> $DIR/trait-item-privacy.rs:80:8 | LL | struct S; | --------- function or associated item `b` not found for this ... LL | S::b(&S); - | ^^^^ function or associated item not found in `S` + | ---^ + | | + | function or associated item not found in `S` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: @@ -67,26 +71,30 @@ LL | C::a(&S); //~ ERROR method `a` is private | ^^^^ error[E0599]: no associated item named `A` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:97:5 + --> $DIR/trait-item-privacy.rs:97:8 | LL | struct S; | --------- associated item `A` not found for this ... LL | S::A; //~ ERROR no associated item named `A` found for type `S` in the current scope - | ^^^^ associated item not found in `S` + | ---^ + | | + | associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `A`, perhaps you need to implement it: candidate #1: `assoc_const::A` error[E0599]: no associated item named `B` found for type `S` in the current scope - --> $DIR/trait-item-privacy.rs:98:5 + --> $DIR/trait-item-privacy.rs:98:8 | LL | struct S; | --------- associated item `B` not found for this ... LL | S::B; //~ ERROR no associated item named `B` found for type `S` in the current scope - | ^^^^ associated item not found in `S` + | ---^ + | | + | associated item not found in `S` | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope, perhaps add a `use` for it: diff --git a/src/test/ui/transmute-equal-assoc-types.rs b/src/test/ui/transmute-equal-assoc-types.rs new file mode 100644 index 0000000000000..6f357543e5c44 --- /dev/null +++ b/src/test/ui/transmute-equal-assoc-types.rs @@ -0,0 +1,9 @@ +trait Foo { + type Bar; +} + +unsafe fn noop<F: Foo>(foo: F::Bar) -> F::Bar { + ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes +} + +fn main() {} diff --git a/src/test/ui/transmute-equal-assoc-types.stderr b/src/test/ui/transmute-equal-assoc-types.stderr new file mode 100644 index 0000000000000..46bbf1c185889 --- /dev/null +++ b/src/test/ui/transmute-equal-assoc-types.stderr @@ -0,0 +1,11 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-equal-assoc-types.rs:6:5 + | +LL | ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `<F as Foo>::Bar` does not have a fixed size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index 6c6fa47a50d6a..ea233a47a78c1 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -1,5 +1,5 @@ -// normalize-stderr-32bit: "&str \(64 bits\)" -> "&str ($$STR bits)" -// normalize-stderr-64bit: "&str \(128 bits\)" -> "&str ($$STR bits)" +// normalize-stderr-32bit: "`&str` \(64 bits\)" -> "`&str` ($$STR bits)" +// normalize-stderr-64bit: "`&str` \(128 bits\)" -> "`&str` ($$STR bits)" @@ -13,20 +13,20 @@ pub trait TypeConstructor<'a> { unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T) -> <C as TypeConstructor<'b>>::T where for<'z> C: TypeConstructor<'z> { - transmute(x) //~ ERROR transmute called with types of different sizes + transmute(x) //~ ERROR cannot transmute between types of different sizes } unsafe fn sizes() { - let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes + let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes } unsafe fn ptrs() { - let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes + let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes } union Foo { x: () } unsafe fn vary() { - let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes + let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes } fn main() {} diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index 9a344747e8fce..f4e88fc860acd 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -1,38 +1,38 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:16:5 | -LL | transmute(x) //~ ERROR transmute called with types of different sizes +LL | transmute(x) //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: <C as TypeConstructor<'a>>::T (size can vary because of <C as TypeConstructor>::T) - = note: target type: <C as TypeConstructor<'b>>::T (size can vary because of <C as TypeConstructor>::T) + = note: source type: `<C as TypeConstructor<'a>>::T` (size can vary because of <C as TypeConstructor>::T) + = note: target type: `<C as TypeConstructor<'b>>::T` (size can vary because of <C as TypeConstructor>::T) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:20:17 | -LL | let x: u8 = transmute(10u16); //~ ERROR transmute called with types of different sizes +LL | let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: u16 (16 bits) - = note: target type: u8 (8 bits) + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:24:17 | -LL | let x: u8 = transmute("test"); //~ ERROR transmute called with types of different sizes +LL | let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &str ($STR bits) - = note: target type: u8 (8 bits) + = note: source type: `&str` ($STR bits) + = note: target type: `u8` (8 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:29:18 | -LL | let x: Foo = transmute(10); //~ ERROR transmute called with types of different sizes +LL | let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: i32 (32 bits) - = note: target type: Foo (0 bits) + = note: source type: `i32` (32 bits) + = note: target type: `Foo` (0 bits) error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-different-sizes.rs b/src/test/ui/transmute/transmute-different-sizes.rs index 00bdd8c0230ac..690decf639285 100644 --- a/src/test/ui/transmute/transmute-different-sizes.rs +++ b/src/test/ui/transmute/transmute-different-sizes.rs @@ -9,12 +9,12 @@ use std::mem::transmute; unsafe fn f() { let _: i8 = transmute(16i16); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn g<T>(x: &T) { let _: i8 = transmute(x); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } trait Specializable { type Output; } @@ -25,7 +25,7 @@ impl<T> Specializable for T { unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output { transmute(x) - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/transmute/transmute-different-sizes.stderr b/src/test/ui/transmute/transmute-different-sizes.stderr index 3fb9300c1348a..07a38df6973a1 100644 --- a/src/test/ui/transmute/transmute-different-sizes.stderr +++ b/src/test/ui/transmute/transmute-different-sizes.stderr @@ -1,29 +1,29 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:11:17 | LL | let _: i8 = transmute(16i16); | ^^^^^^^^^ | - = note: source type: i16 (N bits) - = note: target type: i8 (N bits) + = note: source type: `i16` (N bits) + = note: target type: `i8` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:16:17 | LL | let _: i8 = transmute(x); | ^^^^^^^^^ | - = note: source type: &T (N bits) - = note: target type: i8 (N bits) + = note: source type: `&T` (N bits) + = note: target type: `i8` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-different-sizes.rs:27:5 | LL | transmute(x) | ^^^^^^^^^ | - = note: source type: u16 (N bits) - = note: target type: <T as Specializable>::Output (this type's size can vary) + = note: source type: `u16` (N bits) + = note: target type: `<T as Specializable>::Output` (this type does not have a fixed size) error: aborting due to 3 previous errors diff --git a/src/test/ui/transmute/transmute-fat-pointers.rs b/src/test/ui/transmute/transmute-fat-pointers.rs index f9385ef8994b2..7c1beffd14ed4 100644 --- a/src/test/ui/transmute/transmute-fat-pointers.rs +++ b/src/test/ui/transmute/transmute-fat-pointers.rs @@ -7,11 +7,11 @@ use std::mem::transmute; fn a<T, U: ?Sized>(x: &[T]) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn c<T, U>(x: &T) -> &U { @@ -23,11 +23,11 @@ fn d<T, U>(x: &[T]) -> &[U] { } fn e<T: ?Sized, U>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn f<T, U: ?Sized>(x: &T) -> &U { - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } fn main() { } diff --git a/src/test/ui/transmute/transmute-fat-pointers.stderr b/src/test/ui/transmute/transmute-fat-pointers.stderr index aed89ab84ca72..4b34950881a48 100644 --- a/src/test/ui/transmute/transmute-fat-pointers.stderr +++ b/src/test/ui/transmute/transmute-fat-pointers.stderr @@ -1,38 +1,38 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:10:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &[T] (N bits) - = note: target type: &U (pointer to U) + = note: source type: `&[T]` (N bits) + = note: target type: `&U` (pointer to `U`) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:14:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &U (pointer to U) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (pointer to `U`) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:26:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &U (N bits) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (N bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fat-pointers.rs:30:14 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (N bits) - = note: target type: &U (pointer to U) + = note: source type: `&T` (N bits) + = note: target type: `&U` (pointer to `U`) error: aborting due to 4 previous errors diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs index b06751f376e90..f858a199e48e3 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.rs +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.rs @@ -2,7 +2,7 @@ use std::mem; unsafe fn foo() -> (i8, *const (), Option<fn()>) { let i = mem::transmute(bar); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types let p = mem::transmute(foo); @@ -19,7 +19,7 @@ unsafe fn foo() -> (i8, *const (), Option<fn()>) { unsafe fn bar() { // Error as usual if the resulting type is not pointer-sized. mem::transmute::<_, u8>(main); - //~^ ERROR transmute called with types of different sizes + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types mem::transmute::<_, *mut ()>(foo); diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr index 07e8c60e91e16..d08078bcfbaea 100644 --- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr +++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-from-fn-item-types-error.rs:4:13 | LL | let i = mem::transmute(bar); | ^^^^^^^^^^^^^^ | - = note: source type: unsafe fn() {bar} (0 bits) - = note: target type: i8 (8 bits) + = note: source type: `unsafe fn() {bar}` (0 bits) + = note: target type: `i8` (8 bits) error[E0591]: can't transmute zero-sized type --> $DIR/transmute-from-fn-item-types-error.rs:8:13 @@ -27,14 +27,14 @@ LL | let of = mem::transmute(main); = note: target type: std::option::Option<fn()> = help: cast with `as` to a pointer instead -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-from-fn-item-types-error.rs:21:5 | LL | mem::transmute::<_, u8>(main); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: source type: fn() {main} (0 bits) - = note: target type: u8 (8 bits) + = note: source type: `fn() {main}` (0 bits) + = note: target type: `u8` (8 bits) error[E0591]: can't transmute zero-sized type --> $DIR/transmute-from-fn-item-types-error.rs:25:5 diff --git a/src/test/ui/transmute/transmute-impl.rs b/src/test/ui/transmute/transmute-impl.rs index 23fddfe038e29..df422bda166c1 100644 --- a/src/test/ui/transmute/transmute-impl.rs +++ b/src/test/ui/transmute/transmute-impl.rs @@ -18,7 +18,7 @@ impl<T: ?Sized> Foo<T> { fn n(x: &T) -> &isize { // Not OK here, because T : Sized is not in scope. - unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes } } diff --git a/src/test/ui/transmute/transmute-impl.stderr b/src/test/ui/transmute/transmute-impl.stderr index ad46c24e9c6c1..8acc0aaf3ab52 100644 --- a/src/test/ui/transmute/transmute-impl.stderr +++ b/src/test/ui/transmute/transmute-impl.stderr @@ -1,11 +1,11 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-impl.rs:21:18 | -LL | unsafe { transmute(x) } //~ ERROR transmute called with types of different sizes +LL | unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes | ^^^^^^^^^ | - = note: source type: &T (pointer to T) - = note: target type: &isize (N bits) + = note: source type: `&T` (pointer to `T`) + = note: target type: `&isize` (N bits) error: aborting due to previous error diff --git a/src/test/ui/transmute/transmute-type-parameters.rs b/src/test/ui/transmute/transmute-type-parameters.rs index 812386cf1653a..5f44b2d0f0163 100644 --- a/src/test/ui/transmute/transmute-type-parameters.rs +++ b/src/test/ui/transmute/transmute-type-parameters.rs @@ -4,17 +4,17 @@ use std::mem::transmute; unsafe fn f<T>(x: T) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn g<T>(x: (T, i32)) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn h<T>(x: [T; 10]) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } struct Bad<T> { @@ -23,7 +23,7 @@ struct Bad<T> { unsafe fn i<T>(x: Bad<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } enum Worse<T> { @@ -33,12 +33,12 @@ enum Worse<T> { unsafe fn j<T>(x: Worse<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } unsafe fn k<T>(x: Option<T>) { let _: i32 = transmute(x); -//~^ ERROR transmute called with types of different sizes +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } fn main() {} diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr index c7cdf31dcd56c..a355a1bf31833 100644 --- a/src/test/ui/transmute/transmute-type-parameters.stderr +++ b/src/test/ui/transmute/transmute-type-parameters.stderr @@ -1,56 +1,56 @@ -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:6:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: T (this type's size can vary) - = note: target type: i32 (32 bits) + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:11:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: (T, i32) (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `(T, i32)` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:16:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: [T; 10] (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `[T; 10]` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:25:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: Bad<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `Bad<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:35:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: Worse<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `Worse<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) -error[E0512]: transmute called with types of different sizes +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-type-parameters.rs:40:18 | LL | let _: i32 = transmute(x); | ^^^^^^^^^ | - = note: source type: std::option::Option<T> (size can vary because of T) - = note: target type: i32 (32 bits) + = note: source type: `std::option::Option<T>` (size can vary because of T) + = note: target type: `i32` (32 bits) error: aborting due to 6 previous errors diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index b16aa59090d04..63650086bcaa9 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -6,6 +6,10 @@ LL | let try_result: Option<_> = try { LL | //~^ ERROR expected struct, variant or union type, found macro `try` LL | let x = 5; //~ ERROR expected identifier, found keyword | ^^^ expected identifier, found keyword +help: you can escape reserved keywords to use them as identifiers + | +LL | r#let x = 5; //~ ERROR expected identifier, found keyword + | ^^^^^ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr index cf52c4ce15266..0cbd737debde5 100644 --- a/src/test/ui/try-block/try-block-type-error.stderr +++ b/src/test/ui/try-block/try-block-type-error.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving `<std::option::Option<f32> as std::ops::Tr LL | 42 | ^^ | | - | expected f32, found integral variable + | expected f32, found integer | help: use a float literal: `42.0` | = note: expected type `f32` diff --git a/src/test/ui/tuple/tuple-index-not-tuple.stderr b/src/test/ui/tuple/tuple-index-not-tuple.stderr index ab9ac4c4142fe..a1bcdfaedbc60 100644 --- a/src/test/ui/tuple/tuple-index-not-tuple.stderr +++ b/src/test/ui/tuple/tuple-index-not-tuple.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `0` on type `Point` --> $DIR/tuple-index-not-tuple.rs:6:12 | LL | origin.0; - | ^ did you mean `x`? + | ^ help: a field with a similar name exists: `x` error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 diff --git a/src/test/ui/tuple/tuple-index-out-of-bounds.stderr b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr index 86e977a01b76d..7d7c5cd7892ea 100644 --- a/src/test/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/src/test/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `2` on type `Point` --> $DIR/tuple-index-out-of-bounds.rs:7:12 | LL | origin.2; - | ^ did you mean `0`? + | ^ help: a field with a similar name exists: `0` error[E0609]: no field `2` on type `({integer}, {integer})` --> $DIR/tuple-index-out-of-bounds.rs:12:11 diff --git a/src/test/ui/type-alias-enum-variants-panic.rs b/src/test/ui/type-alias-enum-variants-panic.rs new file mode 100644 index 0000000000000..f97592f5d3b15 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-panic.rs @@ -0,0 +1,17 @@ +// ignore-tidy-linelength + +#![feature(type_alias_enum_variants)] + +#![allow(unreachable_code)] + +enum Enum { Variant {} } +type Alias = Enum; + +fn main() { + Alias::Variant; + //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533] + let Alias::Variant = panic!(); + //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533] + let Alias::Variant(..) = panic!(); + //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164] +} diff --git a/src/test/ui/type-alias-enum-variants-panic.stderr b/src/test/ui/type-alias-enum-variants-panic.stderr new file mode 100644 index 0000000000000..3480d116383ee --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-panic.stderr @@ -0,0 +1,22 @@ +error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:11:5 + | +LL | Alias::Variant; + | ^^^^^^^^^^^^^^ + +error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:13:9 + | +LL | let Alias::Variant = panic!(); + | ^^^^^^^^^^^^^^ + +error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant` + --> $DIR/type-alias-enum-variants-panic.rs:15:9 + | +LL | let Alias::Variant(..) = panic!(); + | ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 3 previous errors + +Some errors occurred: E0164, E0533. +For more information about an error, try `rustc --explain E0164`. diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs new file mode 100644 index 0000000000000..3ec200d57c55d --- /dev/null +++ b/src/test/ui/type-alias-enum-variants.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_enum_variants)] + +type Alias<T> = Option<T>; + +fn main() { + let _ = Option::<u8>::None; // OK + let _ = Option::None::<u8>; // OK (Lint in future!) + let _ = Alias::<u8>::None; // OK + let _ = Alias::None::<u8>; // Error + //~^ type arguments are not allowed on this entity +} diff --git a/src/test/ui/type-alias-enum-variants.stderr b/src/test/ui/type-alias-enum-variants.stderr new file mode 100644 index 0000000000000..cf81f5b27ac6b --- /dev/null +++ b/src/test/ui/type-alias-enum-variants.stderr @@ -0,0 +1,9 @@ +error[E0109]: type arguments are not allowed on this entity + --> $DIR/type-alias-enum-variants.rs:9:27 + | +LL | let _ = Alias::None::<u8>; // Error + | ^^ type argument not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/src/test/ui/type/type-mismatch-multiple.rs b/src/test/ui/type/type-mismatch-multiple.rs index f2e289a11b75e..1904ccf5d5945 100644 --- a/src/test/ui/type/type-mismatch-multiple.rs +++ b/src/test/ui/type/type-mismatch-multiple.rs @@ -4,7 +4,7 @@ fn main() { let a: bool = 1; let b: i32 = true; } //~^ ERROR mismatched types //~| expected type `bool` //~| found type `{integer}` -//~| expected bool, found integral variable +//~| expected bool, found integer //~| ERROR mismatched types //~| expected i32, found bool diff --git a/src/test/ui/type/type-mismatch-multiple.stderr b/src/test/ui/type/type-mismatch-multiple.stderr index b38579046b585..8f6b23ea091a2 100644 --- a/src/test/ui/type/type-mismatch-multiple.stderr +++ b/src/test/ui/type/type-mismatch-multiple.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-multiple.rs:3:27 | LL | fn main() { let a: bool = 1; let b: i32 = true; } - | ^ expected bool, found integral variable + | ^ expected bool, found integer | = note: expected type `bool` found type `{integer}` diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 0297d883b8c59..a576fdde1173e 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -187,16 +187,20 @@ LL | let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN` error[E0599]: no associated item named `NN` found for type `<u8 as Tr>::Y` in the current scope - --> $DIR/ufcs-partially-resolved.rs:38:5 + --> $DIR/ufcs-partially-resolved.rs:38:20 | LL | <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `<u8 as Tr>::Y` - | ^^^^^^^^^^^^^^^^^ associated item not found in `<u8 as Tr>::Y` + | ---------------^^ + | | + | associated item not found in `<u8 as Tr>::Y` error[E0599]: no associated item named `N` found for type `<u8 as Dr>::X` in the current scope - --> $DIR/ufcs-partially-resolved.rs:55:5 + --> $DIR/ufcs-partially-resolved.rs:55:20 | LL | <u8 as Dr>::X::N; //~ ERROR no associated item named `N` found for type `<u8 as Dr>::X` - | ^^^^^^^^^^^^^^^^ associated item not found in `<u8 as Dr>::X` + | ---------------^ + | | + | associated item not found in `<u8 as Dr>::X` error: aborting due to 32 previous errors diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs index ad527a9791802..b2d8c0efea8fe 100644 --- a/src/test/ui/union/union-suggest-field.rs +++ b/src/test/ui/union/union-suggest-field.rs @@ -9,8 +9,12 @@ impl U { fn main() { let u = U { principle: 0 }; //~^ ERROR union `U` has no field named `principle` + //~| HELP a field with a similar name exists + //~| SUGGESTION principal let w = u.principial; //~ ERROR no field `principial` on type `U` - //~^ did you mean `principal`? + //~| HELP a field with a similar name exists + //~| SUGGESTION principal let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` + //~| HELP maybe a `()` to call it is missing } diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.stderr index 15464eea4c2f3..91d6b30ea0267 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.stderr @@ -2,16 +2,16 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:10:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ field does not exist - did you mean `principal`? + | ^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0609]: no field `principial` on type `U` - --> $DIR/union-suggest-field.rs:12:15 + --> $DIR/union-suggest-field.rs:14:15 | LL | let w = u.principial; //~ ERROR no field `principial` on type `U` - | ^^^^^^^^^^ did you mean `principal`? + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0615]: attempted to take value of method `calculate` on type `U` - --> $DIR/union-suggest-field.rs:15:15 + --> $DIR/union-suggest-field.rs:18:15 | LL | let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` | ^^^^^^^^^ diff --git a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr index a3cfcc8921766..18cba2047356a 100644 --- a/src/test/ui/unsized-locals/borrow-after-move.nll.stderr +++ b/src/test/ui/unsized-locals/borrow-after-move.nll.stderr @@ -6,6 +6,8 @@ LL | let y = *x; LL | drop_unsized(y); LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:22:24 @@ -26,6 +28,8 @@ LL | let y = *x; LL | y.foo(); LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `y` --> $DIR/borrow-after-move.rs:32:24 @@ -45,6 +49,8 @@ LL | x.foo(); | - value moved here LL | println!("{}", &x); | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error: aborting due to 5 previous errors diff --git a/src/test/ui/unsized-locals/double-move.nll.stderr b/src/test/ui/unsized-locals/double-move.nll.stderr index 0555a8944bf94..bbe6da70fb112 100644 --- a/src/test/ui/unsized-locals/double-move.nll.stderr +++ b/src/test/ui/unsized-locals/double-move.nll.stderr @@ -15,6 +15,8 @@ LL | let _y = *x; | -- value moved here LL | drop_unsized(x); //~ERROR use of moved value | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:32:18 @@ -23,6 +25,8 @@ LL | drop_unsized(x); | - value moved here LL | let _y = *x; //~ERROR use of moved value | ^^ value used here after move + | + = note: move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait error[E0382]: use of moved value: `y` --> $DIR/double-move.rs:39:9 @@ -41,6 +45,8 @@ LL | let _y = *x; | -- value moved here LL | x.foo(); //~ERROR use of moved value | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 @@ -49,6 +55,8 @@ LL | x.foo(); | - value moved here LL | let _y = *x; //~ERROR use of moved value | ^^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error: aborting due to 6 previous errors diff --git a/src/test/ui/unspecified-self-in-trait-ref.stderr b/src/test/ui/unspecified-self-in-trait-ref.stderr index cb7ee93338f68..b295b39d33c1d 100644 --- a/src/test/ui/unspecified-self-in-trait-ref.stderr +++ b/src/test/ui/unspecified-self-in-trait-ref.stderr @@ -1,26 +1,34 @@ error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:10:13 + --> $DIR/unspecified-self-in-trait-ref.rs:10:18 | LL | let a = Foo::lol(); - | ^^^^^^^^ function or associated item not found in `dyn Foo<_>` + | -----^^^ + | | + | function or associated item not found in `dyn Foo<_>` error[E0599]: no function or associated item named `lol` found for type `dyn Foo<_>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:12:13 + --> $DIR/unspecified-self-in-trait-ref.rs:12:23 | LL | let b = Foo::<_>::lol(); - | ^^^^^^^^^^^^^ function or associated item not found in `dyn Foo<_>` + | ----------^^^ + | | + | function or associated item not found in `dyn Foo<_>` error[E0599]: no function or associated item named `lol` found for type `dyn Bar<_, _>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:14:13 + --> $DIR/unspecified-self-in-trait-ref.rs:14:18 | LL | let c = Bar::lol(); - | ^^^^^^^^ function or associated item not found in `dyn Bar<_, _>` + | -----^^^ + | | + | function or associated item not found in `dyn Bar<_, _>` error[E0599]: no function or associated item named `lol` found for type `dyn Bar<usize, _>` in the current scope - --> $DIR/unspecified-self-in-trait-ref.rs:16:13 + --> $DIR/unspecified-self-in-trait-ref.rs:16:30 | LL | let d = Bar::<usize, _>::lol(); - | ^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `dyn Bar<usize, _>` + | -----------------^^^ + | | + | function or associated item not found in `dyn Bar<usize, _>` error[E0393]: the type parameter `A` must be explicitly specified --> $DIR/unspecified-self-in-trait-ref.rs:18:13 diff --git a/src/test/ui/use/use-after-move-self.nll.stderr b/src/test/ui/use/use-after-move-self.nll.stderr index 28ee8224af39a..3e11e94e993f5 100644 --- a/src/test/ui/use/use-after-move-self.nll.stderr +++ b/src/test/ui/use/use-after-move-self.nll.stderr @@ -5,6 +5,8 @@ LL | self.bar(); | ---- value moved here LL | return *self.x; //~ ERROR use of moved value: `*self.x` | ^^^^^^^ value used here after move + | + = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr index 4279ed78d39f9..b1bb4a3001557 100644 --- a/src/test/ui/utf8_idents.stderr +++ b/src/test/ui/utf8_idents.stderr @@ -1,4 +1,4 @@ -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:4:5 | LL | 'β, //~ ERROR non-ascii idents are not fully supported @@ -6,7 +6,7 @@ LL | 'β, //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:5:5 | LL | γ //~ ERROR non-ascii idents are not fully supported @@ -14,7 +14,7 @@ LL | γ //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:9:5 | LL | δ: usize //~ ERROR non-ascii idents are not fully supported @@ -22,7 +22,7 @@ LL | δ: usize //~ ERROR non-ascii idents are not fully supported | = help: add #![feature(non_ascii_idents)] to the crate attributes to enable -error[E0658]: non-ascii idents are not fully supported. (see issue #28979) +error[E0658]: non-ascii idents are not fully supported. (see issue #55467) --> $DIR/utf8_idents.rs:13:9 | LL | let α = 0.00001f64; //~ ERROR non-ascii idents are not fully supported diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 10b25c734037a..0ce38e69f6b0f 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -18,6 +18,5 @@ fn foo<T>(x: &T) {} fn main() { - foo(&X); - //~^ error: `for<'a> &'a _: Bar` is not satisfied + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index dbe68b82c24cb..afc80bf4d8ee6 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,19 +1,12 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied +error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:21:5 | -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough + | ^^^ | - = help: the following implementations were found: - <&'static u32 as Bar> -note: required by `foo` - --> $DIR/where-for-self-2.rs:16:1 - | -LL | / fn foo<T>(x: &T) -LL | | where for<'a> &'a T: Bar -LL | | {} - | |__^ + = note: Due to a where-clause on `foo`, + = note: `&'0 _` must implement `Bar` for any lifetime `'0` + = note: but `&'1 u32` only implements `Bar` for the lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/cargo b/src/tools/cargo index 2cf1f5dda2f7e..0d1f1bbeabd5b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 2cf1f5dda2f7ed84e94c4d32f643e0f1f15352f0 +Subproject commit 0d1f1bbeabd5b43a7f3ecfa16540af8e76d5efb4 diff --git a/src/tools/clippy b/src/tools/clippy index f7bdf500d9389..39bd84494f4a9 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit f7bdf500d93895b6c02f8ae6a73002207f85e523 +Subproject commit 39bd84494f4a9b40f2e3b38416a91d52d5c4738b diff --git a/src/tools/miri b/src/tools/miri index bccadeb4f7cbe..2e2a33aab8972 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit bccadeb4f7cbeeb14097a365653148afe8bbd159 +Subproject commit 2e2a33aab897273a36498d526530f648d6113dc8 diff --git a/src/tools/rls b/src/tools/rls index bd5b899afb05e..6f5e4bba7b158 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit bd5b899afb05e14d33e210ede3da241ca1ca088f +Subproject commit 6f5e4bba7b1586fca6e0ea7724cadb5683b2f308 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 5acfee28fad67..ca440167f9f07 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -53,6 +53,7 @@ features = [ curl-sys = { version = "0.4.13", optional = true } parking_lot = { version = "0.6", features = ['nightly'] } rand = { version = "0.5.5", features = ["i128_support"] } +serde = { version = "1.0.82", features = ['derive'] } serde_json = { version = "1.0.31", features = ["raw_value"] } smallvec = { version = "0.6", features = ['union'] } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index c41da93a98310..7150241ee4dba 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -81,9 +81,9 @@ function extractFunction(content, functionName) { // Stupid function extractor for array. function extractArrayVariable(content, arrayName) { - var splitter = "var " + arrayName; + var splitter = new RegExp("(?:var|const|let) " + arrayName); while (true) { - var start = content.indexOf(splitter); + var start = content.search(splitter); if (start === -1) { break; } @@ -126,9 +126,9 @@ function extractArrayVariable(content, arrayName) { // Stupid function extractor for variable. function extractVariable(content, varName) { - var splitter = "var " + varName; + var splitter = new RegExp("(?:var|const|let) " + varName); while (true) { - var start = content.indexOf(splitter); + var start = content.search(splitter); if (start === -1) { break; } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ff7a040ca09a5..7f0f0c6f79fcc 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -106,7 +106,9 @@ const WHITELIST: &[Crate] = &[ Crate("parking_lot_core"), Crate("pkg-config"), Crate("polonius-engine"), + Crate("proc-macro2"), Crate("quick-error"), + Crate("quote"), Crate("rand"), Crate("rand_chacha"), Crate("rand_core"), @@ -129,8 +131,10 @@ const WHITELIST: &[Crate] = &[ Crate("semver"), Crate("semver-parser"), Crate("serde"), + Crate("serde_derive"), Crate("smallvec"), Crate("stable_deref_trait"), + Crate("syn"), Crate("tempfile"), Crate("termcolor"), Crate("terminon"), @@ -138,6 +142,7 @@ const WHITELIST: &[Crate] = &[ Crate("thread_local"), Crate("ucd-util"), Crate("unicode-width"), + Crate("unicode-xid"), Crate("unreachable"), Crate("utf8-ranges"), Crate("vcpkg"),