[[package]]
name = "minifier"
-version = "0.0.11"
+version = "0.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-arena"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "rustc-ap-rustc_cratesio_shim"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "rustc-ap-rustc_data_structures"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (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)",
[[package]]
name = "rustc-ap-rustc_errors"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-rustc_target"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "rustc-ap-serialize"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
[[package]]
name = "rustc-ap-syntax"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-ap-syntax_pos"
-version = "156.0.0"
+version = "164.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
name = "rustc_allocator"
version = "0.0.0"
dependencies = [
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_errors 0.0.0",
"rustc_target 0.0.0",
name = "rustdoc"
version = "0.0.0"
dependencies = [
- "minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "26f3e36a4db1981b16567e4abfd6ddc3641bc9b950bdc868701f656bf9b74bdd"
+"checksum minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "78cb57f9a385530d60f2d67f6e108050b478b7a0ffd0bb9c350803e1356535dd"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
"checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa"
"checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
"checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
"checksum rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e794b25832224eea9252ebfa9f94ab7070d0a60c977793112c611501cb56b48d"
-"checksum rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83e91a01cd6c5a9e4f68c2b5c81b62b172aa9e00fc2fec862c0899e3fac1fd32"
+"checksum rustc-ap-arena 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f0687e373d86505f31faeaee87d2be552843a830a0a20e252e76337b9596161"
"checksum rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78241b2ecb82ebb9221b4b7d37c024ff1f2e43f1b099f38a997f030fc7894b0"
-"checksum rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8ea8fadc5d66c1527771816e83f7e7599543bd2e1583e279855370ab2f18e5"
+"checksum rustc-ap-rustc_cratesio_shim 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab5b83e209f3bcdb3c058a996d54b67db58eed5496bd114a781d9faa021aba7"
"checksum rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5529c3927f32b0b56d1f6449a34f2218dc2160c6a6dde0cf47954d83a9a45764"
-"checksum rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "742ba74bc7d0f3ded56148329650f137fa5b90f7f0ecc4b4952150f32c66b147"
+"checksum rustc-ap-rustc_data_structures 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb330c149e9b133d4707718a7981d65ce4eb14f2d59cb487761aa922fefb206"
"checksum rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1fef44a7d63f5d204c981adb26a14e85fe7ee5962050a4f664df6f425f9b48"
-"checksum rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3714046c6f8c1c259822aefcca21b1862710a6cec24fd34c0796117f074c6769"
+"checksum rustc-ap-rustc_errors 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e19ae6a813d5cdd12b8b95cea71438bf8a5fa3505bea1e7d68d438a8ac5ae7b"
"checksum rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3939a9f7bf063536dd646894ca43b1378ec6a56ac5b2698cc6ba0b42bfadbdc"
-"checksum rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b982c4517c18080895b06149ce8aa8279fd013f629030bb7a179bfcff6d74ef2"
+"checksum rustc-ap-rustc_target 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867d4a6bc1b62d373fc6ec72632d5cbd36f3cb1f4e51282d0c7b4e771b393031"
"checksum rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "692169d0bac8a4547f9778039460799e162664477a1eaec15d31507705f8c736"
-"checksum rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27c7700595bff1a64ddb6f593c69db3f6d66b76b059b26137236c7e21e36db70"
+"checksum rustc-ap-serialize 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e095f23598f115432ffef263201e030626f454d183cf425ef68fcca984f6594b"
"checksum rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e93ee3817b007d56b5c5b151e6cd7c7063455a1facaf9e0ca01f9d9365b716"
-"checksum rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6482d98c8be57d3cfe55dab744dd1a87f8462dc2ea0a8a4960f7bb1565be049"
+"checksum rustc-ap-syntax 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab8f97532dabc3713ac3e8d11a85f1a5b154486e79a0c2643d62078f0f948ce2"
"checksum rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe5d24a137d6e202cd6eb96cb74f8cb4a2b257c42b74dd624e136b4e19f0a47d"
-"checksum rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20af5e200b61a3e5ba4f58ed3cbd7593569faf8f0956d5233f4f27fee51b4c81"
+"checksum rustc-ap-syntax_pos 164.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e098adae207a4b8d470bc5e9565904cfe65dca799ba4c9efc872e7436eb5a67"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
}
} else {
for path in paths {
+ // strip CurDir prefix if present
+ let path = match path.strip_prefix(".") {
+ Ok(p) => p,
+ Err(_) => path,
+ };
+
let mut attempted_run = false;
for (desc, should_run) in v.iter().zip(&should_runs) {
if let Some(suite) = should_run.is_suite_path(path) {
} else if component == "rustfmt" {
format!("{}-{}", component, builder.rustfmt_package_vers())
} else if component == "llvm-tools" {
- format!("{}-{}", component, builder.llvm_tools_vers())
+ format!("{}-{}", component, builder.llvm_tools_package_vers())
} else {
assert!(component.starts_with("rust"));
format!("{}-{}", component, builder.rust_package_vers())
let cargo_installer = builder.ensure(Cargo { stage, target });
let rustfmt_installer = builder.ensure(Rustfmt { stage, target });
let rls_installer = builder.ensure(Rls { stage, target });
+ let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
let mingw_installer = builder.ensure(Mingw { host: target });
let analysis_installer = builder.ensure(Analysis {
compiler: builder.compiler(stage, self.host),
tarballs.push(cargo_installer);
tarballs.extend(rls_installer.clone());
tarballs.extend(rustfmt_installer.clone());
+ tarballs.extend(llvm_tools_installer.clone());
tarballs.push(analysis_installer);
tarballs.push(std_installer);
if builder.config.docs {
cmd.arg(builder.package_vers(&builder.release_num("cargo")));
cmd.arg(builder.package_vers(&builder.release_num("rls")));
cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
- cmd.arg(builder.llvm_tools_vers());
+ cmd.arg(builder.llvm_tools_package_vers());
cmd.arg(addr);
builder.create_dir(&distdir(builder));
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct LlvmTools {
pub stage: u32,
- pub compiler: Compiler,
pub target: Interned<String>,
}
fn make_run(run: RunConfig) {
run.builder.ensure(LlvmTools {
stage: run.builder.top_stage,
- compiler: run.builder.compiler(run.builder.top_stage, run.target),
target: run.target,
});
}
fn run(self, builder: &Builder) -> Option<PathBuf> {
- let compiler = self.compiler;
- let host = compiler.host;
-
let stage = self.stage;
+ let target = self.target;
assert!(builder.config.extended);
- builder.info(&format!("Dist LlvmTools stage{} ({})", stage, host));
+ builder.info(&format!("Dist LlvmTools stage{} ({})", stage, target));
let src = builder.src.join("src/llvm");
let name = pkgname(builder, "llvm-tools");
// Prepare the image directory
for tool in LLVM_TOOLS {
let exe = builder
- .llvm_out(host)
+ .llvm_out(target)
.join("bin")
- .join(exe(tool, &compiler.host));
+ .join(exe(tool, &target));
builder.install(&exe, &image.join("bin"), 0o755);
}
builder.create_dir(&overlay);
builder.install(&src.join("README.txt"), &overlay, 0o644);
builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
+ builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
// Generate the installer tarball
let mut cmd = rust_installer(builder);
.arg("--work-dir").arg(&tmpdir(builder))
.arg("--output-dir").arg(&distdir(builder))
.arg("--non-installed-overlay").arg(&overlay)
- .arg(format!("--package-name={}-{}", name, host))
+ .arg(format!("--package-name={}-{}", name, target))
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--component-name=llvm-tools");
builder.run(&mut cmd);
- Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host)))
+ Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
}
}
self.package_vers(&self.release_num("rustfmt"))
}
- fn llvm_tools_vers(&self) -> String {
- // japaric: should we use LLVM version here?
- // let stdout = build_helper::output(
- // Command::new(self.llvm_out(self.config.build).join("build/bin/llvm-size"))
- // .arg("--version"),
- // );
-
- // for line in stdout.lines() {
- // if line.contains("LLVM version") {
- // if let Some(vers) = line.split_whitespace().nth(2) {
- // return vers.to_string();
- // }
- // }
- // }
-
- // panic!("The output of $LLVM_TOOL has changed; \
- // please fix `bootstrap::Build.llvm_tools_vers`");
+ fn llvm_tools_package_vers(&self) -> String {
+ self.package_vers(&self.rust_version())
+ }
+ fn llvm_tools_vers(&self) -> String {
self.rust_version()
}
// Get test-args by striping suite path
let mut test_args: Vec<&str> = paths
.iter()
+ .map(|p| {
+ match p.strip_prefix(".") {
+ Ok(path) => path,
+ Err(_) => p,
+ }
+ })
.filter(|p| p.starts_with(suite_path) && p.is_file())
.map(|p| p.strip_prefix(suite_path).unwrap().to_str().unwrap())
.collect();
compiles, then the test will fail. However please note that code failing
with the current Rust release may work in a future release, as new features
are added.
+
+## Syntax reference
+
+The *exact* syntax for code blocks, including the edge cases, can be found
+in the [Fenced Code Blocks](https://spec.commonmark.org/0.28/#fenced-code-blocks)
+section of the CommonMark specification.
+
+Rustdoc also accepts *indented* code blocks as an alternative to fenced
+code blocks: instead of surrounding your code with three backticks, you
+can indent each line by four or more spaces.
+
+``````markdown
+ let foo = "foo";
+ assert_eq!(foo, "foo");
+``````
+
+These, too, are documented in the CommonMark specification, in the
+[Indented Code Blocks](https://spec.commonmark.org/0.28/#indented-code-blocks)
+section.
+
+However, it's preferable to use fenced code blocks over indented code blocks.
+Not only are fenced code blocks considered more idiomatic for Rust code,
+but there is no way to use directives such as `ignore` or `should_panic` with
+indented code blocks.
--- /dev/null
+# `irrefutable_let_patterns`
+
+The tracking issue for this feature is: [#44495]
+
+[#44495]: https://github.com/rust-lang/rust/issues/44495
+
+------------------------
+
+This feature changes the way that "irrefutable patterns" are handled
+in the `if let` and `while let` forms. An *irrefutable pattern* is one
+that cannot fail to match -- for example, the `_` pattern matches any
+value, and hence it is "irrefutable". Without this feature, using an
+irrefutable pattern in an `if let` gives a hard error (since often
+this indicates programmer error). But when the feature is enabled, the
+error becomes a lint (since in some cases irrefutable patterns are
+expected). This means you can use `#[allow]` to silence the lint:
+
+```rust
+#![feature(irrefutable_let_patterns)]
+
+#[allow(irrefutable_let_patterns)]
+fn main() {
+ // These two examples used to be errors, but now they
+ // trigger a lint (that is allowed):
+ if let _ = 5 {}
+ while let _ = 5 { break; }
+}
+```
}
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
+#[rustc_on_unimplemented(
+ message="vector indices are of type `usize` or ranges of `usize`",
+ label="vector indices are of type `usize` or ranges of `usize`",
+)]
impl<T, I> Index<I> for Vec<T>
where
I: ::core::slice::SliceIndex<[T]>,
}
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
+#[rustc_on_unimplemented(
+ message="vector indices are of type `usize` or ranges of `usize`",
+ label="vector indices are of type `usize` or ranges of `usize`",
+)]
impl<T, I> IndexMut<I> for Vec<T>
where
I: ::core::slice::SliceIndex<[T]>,
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")]
#[doc(alias = "!=")]
-#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
+#[rustc_on_unimplemented(
+ message="can't compare `{Self}` with `{Rhs}`",
+ label="no implementation for `{Self} == {Rhs}`",
+)]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// by `==`.
#[doc(alias = "<")]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
-#[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
+#[rustc_on_unimplemented(
+ message="can't compare `{Self}` with `{Rhs}`",
+ label="no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
+)]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values if one exists.
///
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
- built from an iterator over elements of type `{A}`"]
+#[rustc_on_unimplemented(
+ message="a collection of type `{Self}` cannot be built from an iterator \
+ over elements of type `{A}`",
+ label="a collection of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`",
+)]
pub trait FromIterator<A>: Sized {
/// Creates a value from an iterator.
///
/// [arc]: ../../std/sync/struct.Arc.html
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
+#[rustc_on_unimplemented(
+ message="`{Self}` cannot be sent between threads safely",
+ label="`{Self}` cannot be sent between threads safely"
+)]
pub unsafe auto trait Send {
// empty.
}
/// [trait object]: ../../book/first-edition/trait-objects.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
-#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
+#[rustc_on_unimplemented(
+ message="the size for value values of type `{Self}` cannot be known at compilation time",
+ label="doesn't have a size known at compile-time",
+ note="to learn more, visit <https://doc.rust-lang.org/book/second-edition/\
+ ch19-04-advanced-types.html#dynamically-sized-types--sized>",
+)]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
pub trait Sized {
// Empty.
pub fn new(reference: &'a mut T) -> PinMut<'a, T> {
PinMut { inner: reference }
}
+
+ /// Get a mutable reference to the data inside of this `PinMut`.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
+ this.inner
+ }
}
/// the data out of the mutable reference you receive when you call this
/// function.
#[unstable(feature = "pin", issue = "49150")]
- pub unsafe fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
+ pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
this.inner
}
/// Construct a new pin by mapping the interior value.
///
- /// For example, if you wanted to get a `PinMut` of a field of something, you
- /// could use this to get access to that field in one line of code.
+ /// For example, if you wanted to get a `PinMut` of a field of something,
+ /// you could use this to get access to that field in one line of code.
///
/// This function is unsafe. You must guarantee that the data you return
/// will not move so long as the argument value does not move (for example,
/// because it is one of the fields of that value), and also that you do
/// not move out of the argument you receive to the interior function.
#[unstable(feature = "pin", issue = "49150")]
- pub unsafe fn map<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
+ pub unsafe fn map_unchecked<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
F: FnOnce(&mut T) -> &mut U
{
PinMut { inner: f(this.inner) }
/// assert_eq!(nucleotide_count[Nucleotide::T], 12);
/// ```
#[lang = "index"]
-#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
+#[rustc_on_unimplemented(
+ message="the type `{Self}` cannot be indexed by `{Idx}`",
+ label="`{Self}` cannot be indexed by `{Idx}`",
+)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "]")]
#[doc(alias = "[")]
/// balance[Side::Left] = Weight::Kilogram(3.0);
/// ```
#[lang = "index_mut"]
-#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"]
+#[rustc_on_unimplemented(
+ message="the type `{Self}` cannot be mutably indexed by `{Idx}`",
+ label="`{Self}` cannot be mutably indexed by `{Idx}`",
+)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "[")]
#[doc(alias = "]")]
#![stable(feature = "rust1", since = "1.0.0")]
use iter::{FromIterator, FusedIterator, TrustedLen};
-use {mem, ops};
+use {hint, mem, ops};
use mem::PinMut;
// Note that this is not a lang item per se, but it has a hidden dependency on
#[unstable(feature = "pin", issue = "49150")]
pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option<PinMut<'a, T>> {
unsafe {
- PinMut::get_mut(self).as_mut().map(|x| PinMut::new_unchecked(x))
+ PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x))
}
}
match *self {
Some(ref mut v) => v,
- _ => unreachable!(),
+ None => unsafe { hint::unreachable_unchecked() },
}
}
match *self {
Some(ref mut v) => v,
- _ => unreachable!(),
+ None => unsafe { hint::unreachable_unchecked() },
}
}
_: ::syntax_pos::Span,
stream: tokenstream::TokenStream)
-> tokenstream::TokenStream {
- let mut info = cx.current_expansion.mark.expn_info().unwrap();
- info.callee.allow_internal_unstable = true;
- cx.current_expansion.mark.set_expn_info(info);
::__internal::set_sess(cx, || TokenStream(stream).quote().0)
}
}
self.add_unreachable_node()
}
- hir::ExprAgain(destination) => {
+ hir::ExprContinue(destination) => {
let (target_scope, cont_dest) =
self.find_scope_edge(expr, destination, ScopeCfKind::Continue);
let a = self.add_ast_node(expr.hir_id.local_id, &[pred]);
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
+
E0697, // closures cannot be static
+
+ E0707, // multiple elided lifetimes used in arguments of `async fn`
+ E0708, // `async` non-`move` closures with arguments are not currently supported
+ E0709, // multiple different lifetimes used in arguments of `async fn`
}
//! This order consistency is required in a few places in rustc, for
//! example generator inference, and possibly also HIR borrowck.
-use rustc_target::spec::abi::Abi;
use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute};
use syntax_pos::Span;
use hir::*;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> {
- /// fn foo() or extern "Abi" fn foo()
- ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]),
+ /// #[xxx] pub async/const/extern "Abi" fn foo()
+ ItemFn(Name, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
/// fn foo(&self)
Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
fn visit_trait_ref(&mut self, t: &'v TraitRef) {
walk_trait_ref(self, t)
}
- fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
- walk_ty_param_bound(self, bounds)
+ fn visit_param_bound(&mut self, bounds: &'v GenericBound) {
+ walk_param_bound(self, bounds)
}
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
walk_poly_trait_ref(self, t, m)
fn visit_label(&mut self, label: &'v Label) {
walk_label(self, label)
}
+ fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg) {
+ match generic_arg {
+ GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+ GenericArg::Type(ty) => self.visit_ty(ty),
+ }
+ }
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
walk_lifetime(self, lifetime)
}
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
- fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
- walk_path_parameters(self, path_span, path_parameters)
+ fn visit_generic_args(&mut self, path_span: Span, generic_args: &'v GenericArgs) {
+ walk_generic_args(self, path_span, generic_args)
}
fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
walk_assoc_type_binding(self, type_binding)
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
visitor.visit_id(lifetime.id);
match lifetime.name {
- LifetimeName::Name(name) => {
+ LifetimeName::Param(ParamName::Plain(name)) => {
visitor.visit_name(lifetime.span, name);
}
- LifetimeName::Fresh(_) |
+ LifetimeName::Param(ParamName::Fresh(_)) |
LifetimeName::Static |
LifetimeName::Implicit |
LifetimeName::Underscore => {}
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
- ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
+ ItemFn(ref declaration, header, ref generics, body_id) => {
visitor.visit_fn(FnKind::ItemFn(item.name,
generics,
- unsafety,
- constness,
- abi,
+ header,
&item.vis,
&item.attrs),
declaration,
ItemExistential(ExistTy {ref generics, ref bounds, impl_trait_fn}) => {
visitor.visit_id(item.id);
walk_generics(visitor, generics);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
if let Some(impl_trait_fn) = impl_trait_fn {
visitor.visit_def_mention(Def::Fn(impl_trait_fn))
}
ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
visitor.visit_id(item.id);
visitor.visit_generics(generics);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
}
ItemTraitAlias(ref generics, ref bounds) => {
visitor.visit_id(item.id);
visitor.visit_generics(generics);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
}
}
walk_list!(visitor, visit_attribute, &item.attrs);
path_span: Span,
segment: &'v PathSegment) {
visitor.visit_name(path_span, segment.name);
- if let Some(ref parameters) = segment.parameters {
- visitor.visit_path_parameters(path_span, parameters);
+ if let Some(ref args) = segment.args {
+ visitor.visit_generic_args(path_span, args);
}
}
-pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
- _path_span: Span,
- path_parameters: &'v PathParameters) {
- walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
- walk_list!(visitor, visit_ty, &path_parameters.types);
- walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
+pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V,
+ _path_span: Span,
+ generic_args: &'v GenericArgs) {
+ walk_list!(visitor, visit_generic_arg, &generic_args.args);
+ walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings);
}
pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
walk_list!(visitor, visit_attribute, &foreign_item.attrs);
}
-pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
+pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound) {
match *bound {
- TraitTyParamBound(ref typ, modifier) => {
+ GenericBound::Trait(ref typ, modifier) => {
visitor.visit_poly_trait_ref(typ, modifier);
}
- RegionTyParamBound(ref lifetime) => {
- visitor.visit_lifetime(lifetime);
- }
+ GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
}
}
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
- match *param {
- GenericParam::Lifetime(ref ld) => {
- visitor.visit_id(ld.lifetime.id);
- match ld.lifetime.name {
- LifetimeName::Name(name) => {
- visitor.visit_name(ld.lifetime.span, name);
- }
- LifetimeName::Fresh(_) |
- LifetimeName::Static |
- LifetimeName::Implicit |
- LifetimeName::Underscore => {}
- }
- walk_list!(visitor, visit_lifetime, &ld.bounds);
- }
- GenericParam::Type(ref ty_param) => {
- visitor.visit_id(ty_param.id);
- visitor.visit_name(ty_param.span, ty_param.name);
- walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds);
- walk_list!(visitor, visit_ty, &ty_param.default);
- walk_list!(visitor, visit_attribute, ty_param.attrs.iter());
- }
+ visitor.visit_id(param.id);
+ walk_list!(visitor, visit_attribute, ¶m.attrs);
+ match param.name {
+ ParamName::Plain(name) => visitor.visit_name(param.span, name),
+ ParamName::Fresh(_) => {}
+ }
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
}
+ walk_list!(visitor, visit_param_bound, ¶m.bounds);
}
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
ref bound_generic_params,
..}) => {
visitor.visit_ty(bounded_ty);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_generic_param, bound_generic_params);
}
&WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
visitor.visit_lifetime(lifetime);
- walk_list!(visitor, visit_lifetime, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
}
&WherePredicate::EqPredicate(WhereEqPredicate{id,
ref lhs_ty,
}
TraitItemKind::Type(ref bounds, ref default) => {
visitor.visit_id(trait_item.id);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, default);
}
}
}
walk_list!(visitor, visit_expr, opt_expr);
}
- ExprAgain(ref destination) => {
+ ExprContinue(ref destination) => {
if let Some(ref label) = destination.label {
visitor.visit_label(label);
match destination.target_id {
//! in the HIR, especially for multiple identifiers.
use dep_graph::DepGraph;
-use hir;
+use hir::{self, ParamName};
use hir::HirVec;
use hir::map::{DefKey, DefPathData, Definitions};
use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
use hir::def::{Def, PathResolution, PerNS};
+use hir::GenericArg;
use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES};
use middle::cstore::CrateStore;
use rustc_data_structures::indexed_vec::IndexVec;
use std::iter;
use std::mem;
use syntax::attr;
+use syntax::ast;
use syntax::ast::*;
use syntax::errors;
use syntax::ext::hygiene::{Mark, SyntaxContext};
// When traversing a signature such as `fn foo(x: impl Trait)`,
// we record `impl Trait` as a new type parameter, then later
// add it on to `foo`s generics.
- in_band_ty_params: Vec<hir::TyParam>,
+ in_band_ty_params: Vec<hir::GenericParam>,
// Used to create lifetime definitions from in-band lifetime usages.
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
// (i.e. it doesn't appear in the in_scope_lifetimes list), it is added
// to this list. The results of this list are then added to the list of
// lifetime definitions in the corresponding impl or function generics.
- lifetimes_to_define: Vec<(Span, hir::LifetimeName)>,
+ lifetimes_to_define: Vec<(Span, ParamName)>,
// Whether or not in-band lifetimes are being collected. This is used to
// indicate whether or not we're in a place where new lifetimes will result
span: Span,
crate_root: Option<&str>,
components: &[&str],
+ params: Option<P<hir::GenericArgs>>,
is_value: bool,
) -> hir::Path;
}
let count = generics
.params
.iter()
- .filter(|param| param.is_lifetime_param())
+ .filter(|param| match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => true,
+ _ => false,
+ })
.count();
self.lctx.type_def_lifetime_params.insert(def_id, count);
}
});
if item_lowered {
- let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
+ let item_generics = match self.lctx.items.get(&item.id).unwrap().node {
hir::Item_::ItemImpl(_, _, _, ref generics, ..)
| hir::Item_::ItemTrait(_, _, ref generics, ..) => {
- generics.lifetimes().cloned().collect::<Vec<_>>()
+ generics.params.clone()
}
- _ => Vec::new(),
+ _ => HirVec::new(),
};
- self.lctx
- .with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
- let this = &mut ItemLowerer { lctx: this };
- if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
- this.with_trait_impl_ref(opt_trait_ref, |this| {
- visit::walk_item(this, item)
- });
- } else {
- visit::walk_item(this, item);
- }
- });
+ self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| {
+ let this = &mut ItemLowerer { lctx: this };
+ if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
+ this.with_trait_impl_ref(opt_trait_ref, |this| {
+ visit::walk_item(this, item)
+ });
+ } else {
+ visit::walk_item(this, item);
+ }
+ });
}
}
}
}
- fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) {
+ fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId {
if self.item_local_id_counters.insert(owner, 0).is_some() {
bug!(
"Tried to allocate item_local_id_counter for {:?} twice",
);
}
// Always allocate the first HirId for the owner itself
- self.lower_node_id_with_owner(owner, owner);
+ self.lower_node_id_with_owner(owner, owner)
}
fn lower_node_id_generic<F>(&mut self, ast_node_id: NodeId, alloc_hir_id: F) -> LoweredNodeId
{
let counter = self.item_local_id_counters
.insert(owner, HIR_ID_COUNTER_LOCKED)
- .unwrap();
+ .unwrap_or_else(|| panic!("No item_local_id_counters entry for {:?}", owner));
let def_index = self.resolver.definitions().opt_def_index(owner).unwrap();
self.current_hir_id_owner.push((def_index, counter));
let ret = f(self);
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(codemap::ExpnInfo {
call_site: span,
- callee: codemap::NameAndSpan {
- format: codemap::CompilerDesugaring(reason),
- span: Some(span),
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: codemap::hygiene::default_edition(),
- },
+ def_site: Some(span),
+ format: codemap::CompilerDesugaring(reason),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: codemap::hygiene::default_edition(),
});
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
// that collisions are ok here and this shouldn't
// really show up for end-user.
let str_name = match hir_name {
- hir::LifetimeName::Name(n) => n.as_str(),
- hir::LifetimeName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
- hir::LifetimeName::Implicit
- | hir::LifetimeName::Underscore
- | hir::LifetimeName::Static => {
- span_bug!(span, "unexpected in-band lifetime name: {:?}", hir_name)
- }
+ ParamName::Plain(name) => name.as_str(),
+ ParamName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
};
// Add a definition for the in-band lifetime def
self.resolver.definitions().create_def_with_parent(
parent_id.index,
def_node_id,
- DefPathData::LifetimeDef(str_name.as_interned_str()),
+ DefPathData::LifetimeParam(str_name.as_interned_str()),
DefIndexAddressSpace::High,
Mark::root(),
span,
);
- hir::GenericParam::Lifetime(hir::LifetimeDef {
- lifetime: hir::Lifetime {
- id: def_node_id,
- span,
- name: hir_name,
- },
- bounds: Vec::new().into(),
+ hir::GenericParam {
+ id: def_node_id,
+ name: hir_name,
+ attrs: hir_vec![],
+ bounds: hir_vec![],
+ span,
pure_wrt_drop: false,
- in_band: true,
- })
+ kind: hir::GenericParamKind::Lifetime { in_band: true }
+ }
})
- .chain(
- in_band_ty_params
- .into_iter()
- .map(|tp| hir::GenericParam::Type(tp)),
- )
+ .chain(in_band_ty_params.into_iter())
.collect();
(params, res)
return;
}
- let hir_name = hir::LifetimeName::Name(name);
+ let hir_name = ParamName::Plain(name);
- if self.lifetimes_to_define
- .iter()
- .any(|(_, lt_name)| *lt_name == hir_name)
- {
+ if self.lifetimes_to_define.iter().any(|(_, lt_name)| *lt_name == hir_name) {
return;
}
/// When we have either an elided or `'_` lifetime in an impl
/// header, we convert it to
- fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> hir::LifetimeName {
+ fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
assert!(self.is_collecting_in_band_lifetimes);
let index = self.lifetimes_to_define.len();
- let hir_name = hir::LifetimeName::Fresh(index);
+ let hir_name = ParamName::Fresh(index);
self.lifetimes_to_define.push((span, hir_name));
hir_name
}
- // Evaluates `f` with the lifetimes in `lt_defs` in-scope.
+ // Evaluates `f` with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined, and
// which are new in-band lifetimes that need to have a definition created
// for them.
- fn with_in_scope_lifetime_defs<'l, T, F>(
- &mut self,
- lt_defs: impl Iterator<Item = &'l LifetimeDef>,
- f: F,
- ) -> T
+ fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &Vec<GenericParam>, f: F) -> T
where
F: FnOnce(&mut LoweringContext) -> T,
{
let old_len = self.in_scope_lifetimes.len();
- let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name);
+ let lt_def_names = params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => Some(param.ident.name),
+ _ => None,
+ });
self.in_scope_lifetimes.extend(lt_def_names);
let res = f(self);
res
}
- // Same as the method above, but accepts `hir::LifetimeDef`s
- // instead of `ast::LifetimeDef`s.
+ // Same as the method above, but accepts `hir::GenericParam`s
+ // instead of `ast::GenericParam`s.
// This should only be used with generics that have already had their
// in-band lifetimes added. In practice, this means that this function is
// only used when lowering a child item of a trait or impl.
- fn with_parent_impl_lifetime_defs<T, F>(&mut self, lt_defs: &[hir::LifetimeDef], f: F) -> T
- where
+ fn with_parent_impl_lifetime_defs<T, F>(&mut self,
+ params: &HirVec<hir::GenericParam>,
+ f: F
+ ) -> T where
F: FnOnce(&mut LoweringContext) -> T,
{
let old_len = self.in_scope_lifetimes.len();
- let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.name.name());
+ let lt_def_names = params.iter().filter_map(|param| match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => Some(param.name.name()),
+ _ => None,
+ });
self.in_scope_lifetimes.extend(lt_def_names);
let res = f(self);
F: FnOnce(&mut LoweringContext) -> T,
{
let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
- generics.params.iter().filter_map(|p| match p {
- GenericParam::Lifetime(ld) => Some(ld),
- _ => None,
- }),
+ &generics.params,
|this| {
let itctx = ImplTraitContext::Universal(parent_id);
this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
result
}
+ fn make_async_expr(
+ &mut self,
+ capture_clause: CaptureBy,
+ closure_node_id: NodeId,
+ ret_ty: Option<&Ty>,
+ body: impl FnOnce(&mut LoweringContext) -> hir::Expr,
+ ) -> hir::Expr_ {
+ let prev_is_generator = mem::replace(&mut self.is_generator, true);
+ let body_expr = body(self);
+ let span = body_expr.span;
+ let output = match ret_ty {
+ Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
+ None => FunctionRetTy::Default(span),
+ };
+ let decl = FnDecl {
+ inputs: vec![],
+ output,
+ variadic: false
+ };
+ let body_id = self.record_body(body_expr, Some(&decl));
+ self.is_generator = prev_is_generator;
+
+ let capture_clause = self.lower_capture_clause(capture_clause);
+ let closure_hir_id = self.lower_node_id(closure_node_id).hir_id;
+ let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false);
+ let generator = hir::Expr {
+ id: closure_node_id,
+ hir_id: closure_hir_id,
+ node: hir::ExprClosure(capture_clause, decl, body_id, span,
+ Some(hir::GeneratorMovability::Static)),
+ span,
+ attrs: ThinVec::new(),
+ };
+
+ let unstable_span = self.allow_internal_unstable(CompilerDesugaringKind::Async, span);
+ let gen_future = self.expr_std_path(
+ unstable_span, &["future", "from_generator"], None, ThinVec::new());
+ hir::ExprCall(P(gen_future), hir_vec![generator])
+ }
+
fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
where
F: FnOnce(&mut LoweringContext) -> hir::Expr,
}
}
+ fn lower_generic_arg(&mut self,
+ arg: &ast::GenericArg,
+ itctx: ImplTraitContext)
+ -> hir::GenericArg {
+ match arg {
+ ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
+ ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)),
+ }
+ }
+
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
let kind = match t.node {
TyKind::Infer => hir::TyInfer,
hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(
- f.generic_params.iter().filter_map(|p| match p {
- GenericParam::Lifetime(ld) => Some(ld),
- _ => None,
- }),
+ &f.generic_params,
|this| {
this.with_anonymous_lifetime_mode(
AnonymousLifetimeMode::PassThrough,
),
unsafety: this.lower_unsafety(f.unsafety),
abi: f.abi,
- decl: this.lower_fn_decl(&f.decl, None, false),
+ decl: this.lower_fn_decl(&f.decl, None, false, false),
arg_names: this.lower_fn_args_to_names(&f.decl),
}))
},
let bounds = bounds
.iter()
.filter_map(|bound| match *bound {
- TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
+ GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
Some(self.lower_poly_trait_ref(ty, itctx))
}
- TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
- RegionTyParamBound(ref lifetime) => {
+ GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+ GenericBound::Outlives(ref lifetime) => {
if lifetime_bound.is_none() {
lifetime_bound = Some(self.lower_lifetime(lifetime));
}
let span = t.span;
match itctx {
ImplTraitContext::Existential(fn_def_id) => {
-
- // We need to manually repeat the code of `next_id` because the lowering
- // needs to happen while the owner_id is pointing to the item itself,
- // because items are their own owners
- let exist_ty_node_id = self.sess.next_node_id();
-
- // Make sure we know that some funky desugaring has been going on here.
- // This is a first: there is code in other places like for loop
- // desugaring that explicitly states that we don't want to track that.
- // Not tracking it makes lints in rustc and clippy very fragile as
- // frequently opened issues show.
- let exist_ty_span = self.allow_internal_unstable(
- CompilerDesugaringKind::ExistentialReturnType,
- t.span,
- );
-
- // Pull a new definition from the ether
- let exist_ty_def_index = self
- .resolver
- .definitions()
- .create_def_with_parent(
- fn_def_id.index,
- exist_ty_node_id,
- DefPathData::ExistentialImplTrait,
- DefIndexAddressSpace::High,
- Mark::root(),
- exist_ty_span,
- );
-
- // the `t` is just for printing debug messages
- self.allocate_hir_id_counter(exist_ty_node_id, t);
-
- let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| {
- lctx.lower_bounds(bounds, itctx)
- });
-
- let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
- exist_ty_node_id,
- exist_ty_def_index,
- &hir_bounds,
- );
-
- self.with_hir_id_owner(exist_ty_node_id, |lctx| {
- let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy {
- generics: hir::Generics {
- params: lifetime_defs,
- where_clause: hir::WhereClause {
- id: lctx.next_id().node_id,
- predicates: Vec::new().into(),
- },
- span,
- },
- bounds: hir_bounds,
- impl_trait_fn: Some(fn_def_id),
- });
- let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
- // Generate an `existential type Foo: Trait;` declaration
- trace!("creating existential type with id {:#?}", exist_ty_id);
- // Set the name to `impl Bound1 + Bound2`
- let exist_ty_name = Symbol::intern(&pprust::ty_to_string(t));
-
- trace!("exist ty def index: {:#?}", exist_ty_def_index);
- let exist_ty_item = hir::Item {
- id: exist_ty_id.node_id,
- hir_id: exist_ty_id.hir_id,
- name: exist_ty_name,
- attrs: Default::default(),
- node: exist_ty_item_kind,
- vis: hir::Visibility::Inherited,
- span: exist_ty_span,
- };
-
- // Insert the item into the global list. This usually happens
- // automatically for all AST items. But this existential type item
- // does not actually exist in the AST.
- lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
-
- // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
- hir::TyImplTraitExistential(
- hir::ItemId {
- id: exist_ty_id.node_id
- },
- DefId::local(exist_ty_def_index),
- lifetimes,
- )
- })
+ self.lower_existential_impl_trait(
+ span, fn_def_id, |this| this.lower_param_bounds(bounds, itctx))
}
ImplTraitContext::Universal(def_id) => {
let def_node_id = self.next_id().node_id;
span,
);
- let hir_bounds = self.lower_bounds(bounds, itctx);
+ let hir_bounds = self.lower_param_bounds(bounds, itctx);
// Set the name to `impl Bound1 + Bound2`
let name = Symbol::intern(&pprust::ty_to_string(t));
- self.in_band_ty_params.push(hir::TyParam {
- name,
+ self.in_band_ty_params.push(hir::GenericParam {
id: def_node_id,
- bounds: hir_bounds,
- default: None,
+ name: ParamName::Plain(name),
span,
pure_wrt_drop: false,
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
- attrs: P::new(),
+ attrs: hir_vec![],
+ bounds: hir_bounds,
+ kind: hir::GenericParamKind::Type {
+ default: None,
+ synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+ }
});
hir::TyPath(hir::QPath::Resolved(
})
}
+ fn lower_existential_impl_trait(
+ &mut self,
+ span: Span,
+ fn_def_id: DefId,
+ lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::GenericBounds,
+ ) -> hir::Ty_ {
+ // We need to manually repeat the code of `next_id` because the lowering
+ // needs to happen while the owner_id is pointing to the item itself,
+ // because items are their own owners
+ let exist_ty_node_id = self.sess.next_node_id();
+
+ // Make sure we know that some funky desugaring has been going on here.
+ // This is a first: there is code in other places like for loop
+ // desugaring that explicitly states that we don't want to track that.
+ // Not tracking it makes lints in rustc and clippy very fragile as
+ // frequently opened issues show.
+ let exist_ty_span = self.allow_internal_unstable(
+ CompilerDesugaringKind::ExistentialReturnType,
+ span,
+ );
+
+ // Pull a new definition from the ether
+ let exist_ty_def_index = self
+ .resolver
+ .definitions()
+ .create_def_with_parent(
+ fn_def_id.index,
+ exist_ty_node_id,
+ DefPathData::ExistentialImplTrait,
+ DefIndexAddressSpace::High,
+ Mark::root(),
+ exist_ty_span,
+ );
+
+ self.allocate_hir_id_counter(exist_ty_node_id, &"existential impl trait");
+
+ let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, lower_bounds);
+
+ let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
+ exist_ty_node_id,
+ exist_ty_def_index,
+ &hir_bounds,
+ );
+
+ self.with_hir_id_owner(exist_ty_node_id, |lctx| {
+ let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy {
+ generics: hir::Generics {
+ params: lifetime_defs,
+ where_clause: hir::WhereClause {
+ id: lctx.next_id().node_id,
+ predicates: Vec::new().into(),
+ },
+ span,
+ },
+ bounds: hir_bounds,
+ impl_trait_fn: Some(fn_def_id),
+ });
+ let exist_ty_id = lctx.lower_node_id(exist_ty_node_id);
+ // Generate an `existential type Foo: Trait;` declaration
+ trace!("creating existential type with id {:#?}", exist_ty_id);
+
+ trace!("exist ty def index: {:#?}", exist_ty_def_index);
+ let exist_ty_item = hir::Item {
+ id: exist_ty_id.node_id,
+ hir_id: exist_ty_id.hir_id,
+ name: keywords::Invalid.name(),
+ attrs: Default::default(),
+ node: exist_ty_item_kind,
+ vis: hir::Visibility::Inherited,
+ span: exist_ty_span,
+ };
+
+ // Insert the item into the global list. This usually happens
+ // automatically for all AST items. But this existential type item
+ // does not actually exist in the AST.
+ lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
+
+ // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
+ hir::TyImplTraitExistential(
+ hir::ItemId {
+ id: exist_ty_id.node_id
+ },
+ DefId::local(exist_ty_def_index),
+ lifetimes,
+ )
+ })
+ }
+
fn lifetimes_from_impl_trait_bounds(
&mut self,
exist_ty_id: NodeId,
parent_index: DefIndex,
- bounds: &hir::TyParamBounds,
+ bounds: &hir::GenericBounds,
) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
// This visitor walks over impl trait bounds and creates defs for all lifetimes which
// appear in the bounds, excluding lifetimes that are created within the bounds.
hir::intravisit::NestedVisitorMap::None
}
- fn visit_path_parameters(&mut self, span: Span, parameters: &'v hir::PathParameters) {
+ fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
// Don't collect elided lifetimes used inside of `Fn()` syntax.
if parameters.parenthesized {
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
self.collect_elided_lifetimes = false;
- hir::intravisit::walk_path_parameters(self, span, parameters);
+ hir::intravisit::walk_generic_args(self, span, parameters);
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
} else {
- hir::intravisit::walk_path_parameters(self, span, parameters);
+ hir::intravisit::walk_generic_args(self, span, parameters);
}
}
fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
// Record the introduction of 'a in `for<'a> ...`
- if let hir::GenericParam::Lifetime(ref lt_def) = *param {
+ if let hir::GenericParamKind::Lifetime { .. } = param.kind {
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
- self.currently_bound_lifetimes.push(lt_def.lifetime.name);
+ let lt_name = hir::LifetimeName::Param(param.name);
+ self.currently_bound_lifetimes.push(lt_name);
}
hir::intravisit::walk_generic_param(self, param);
return;
}
}
- name @ hir::LifetimeName::Fresh(_) => name,
- name @ hir::LifetimeName::Name(_) => name,
+ hir::LifetimeName::Param(_) => lifetime.name,
hir::LifetimeName::Static => return,
};
if !self.currently_bound_lifetimes.contains(&name)
- && !self.already_defined_lifetimes.contains(&name)
- {
+ && !self.already_defined_lifetimes.contains(&name) {
self.already_defined_lifetimes.insert(name);
self.output_lifetimes.push(hir::Lifetime {
self.context.resolver.definitions().create_def_with_parent(
self.parent,
def_node_id,
- DefPathData::LifetimeDef(name.name().as_interned_str()),
+ DefPathData::LifetimeParam(name.name().as_interned_str()),
DefIndexAddressSpace::High,
Mark::root(),
lifetime.span,
);
- let def_lifetime = hir::Lifetime {
+
+ let name = match name {
+ hir::LifetimeName::Underscore => {
+ hir::ParamName::Plain(keywords::UnderscoreLifetime.name())
+ }
+ hir::LifetimeName::Param(param_name) => param_name,
+ _ => bug!("expected LifetimeName::Param or ParamName::Plain"),
+ };
+
+ self.output_lifetime_params.push(hir::GenericParam {
id: def_node_id,
- span: lifetime.span,
name,
- };
- self.output_lifetime_params
- .push(hir::GenericParam::Lifetime(hir::LifetimeDef {
- lifetime: def_lifetime,
- bounds: Vec::new().into(),
- pure_wrt_drop: false,
+ span: lifetime.span,
+ pure_wrt_drop: false,
+ attrs: hir_vec![],
+ bounds: hir_vec![],
+ kind: hir::GenericParamKind::Lifetime {
in_band: false,
- }));
+ }
+ });
}
}
}
};
for bound in bounds {
- hir::intravisit::walk_ty_param_bound(&mut lifetime_collector, &bound);
+ hir::intravisit::walk_param_bound(&mut lifetime_collector, &bound);
}
(
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext,
) -> hir::PathSegment {
- let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
+ let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
let msg = "parenthesized parameters may only be used with a trait";
- match **parameters {
- PathParameters::AngleBracketed(ref data) => {
+ match **generic_args {
+ GenericArgs::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
- PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
+ GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Warn => {
self.sess.buffer_lint(
data.span,
msg.into(),
);
- (hir::PathParameters::none(), true)
+ (hir::GenericArgs::none(), true)
}
ParenthesizedGenericArgs::Err => {
struct_span_err!(self.sess, data.span, E0214, "{}", msg)
.span_label(data.span, "only traits may use parentheses")
.emit();
- (hir::PathParameters::none(), true)
+ (hir::GenericArgs::none(), true)
}
},
}
self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
};
- if !parameters.parenthesized && parameters.lifetimes.is_empty() {
- parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes);
+ let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
+ GenericArg::Lifetime(_) => true,
+ _ => false,
+ });
+ if !generic_args.parenthesized && !has_lifetimes {
+ generic_args.args =
+ self.elided_path_lifetimes(path_span, expected_lifetimes)
+ .into_iter()
+ .map(|lt| GenericArg::Lifetime(lt))
+ .chain(generic_args.args.into_iter())
+ .collect();
}
hir::PathSegment::new(
self.lower_ident(segment.ident),
- parameters,
+ generic_args,
infer_types,
)
}
fn lower_angle_bracketed_parameter_data(
&mut self,
- data: &AngleBracketedParameterData,
+ data: &AngleBracketedArgs,
param_mode: ParamMode,
itctx: ImplTraitContext,
- ) -> (hir::PathParameters, bool) {
- let &AngleBracketedParameterData {
- ref lifetimes,
- ref types,
- ref bindings,
- ..
- } = data;
- (
- hir::PathParameters {
- lifetimes: self.lower_lifetimes(lifetimes),
- types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(),
- bindings: bindings
- .iter()
- .map(|b| self.lower_ty_binding(b, itctx))
- .collect(),
- parenthesized: false,
- },
- types.is_empty() && param_mode == ParamMode::Optional,
- )
+ ) -> (hir::GenericArgs, bool) {
+ let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
+ let has_types = args.iter().any(|arg| match arg {
+ ast::GenericArg::Type(_) => true,
+ _ => false,
+ });
+ (hir::GenericArgs {
+ args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(),
+ bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
+ parenthesized: false,
+ },
+ !has_types && param_mode == ParamMode::Optional)
}
fn lower_parenthesized_parameter_data(
&mut self,
- data: &ParenthesizedParameterData,
- ) -> (hir::PathParameters, bool) {
+ data: &ParenthesisedArgs,
+ ) -> (hir::GenericArgs, bool) {
// Switch to `PassThrough` mode for anonymous lifetimes: this
// means that we permit things like `&Ref<T>`, where `Ref` has
// a hidden lifetime parameter. This is needed for backwards
AnonymousLifetimeMode::PassThrough,
|this| {
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
- let &ParenthesizedParameterData {
- ref inputs,
- ref output,
- span,
- } = data;
- let inputs = inputs
- .iter()
- .map(|ty| this.lower_ty(ty, DISALLOWED))
- .collect();
+ let &ParenthesisedArgs { ref inputs, ref output, span } = data;
+ let inputs = inputs.iter().map(|ty| this.lower_ty(ty, DISALLOWED)).collect();
let mk_tup = |this: &mut Self, tys, span| {
let LoweredNodeId { node_id, hir_id } = this.next_id();
- P(hir::Ty {
- node: hir::TyTup(tys),
- id: node_id,
- hir_id,
- span,
- })
+ P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
};
(
- hir::PathParameters {
- lifetimes: hir::HirVec::new(),
- types: hir_vec![mk_tup(this, inputs, span)],
+ hir::GenericArgs {
+ args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
bindings: hir_vec![
hir::TypeBinding {
id: this.next_id().node_id,
.collect()
}
+ // Lowers a function declaration.
+ //
+ // decl: the unlowered (ast) function declaration.
+ // fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the
+ // given DefId, otherwise impl Trait is disallowed. Must be `Some` if
+ // make_ret_async is true.
+ // impl_trait_return_allow: determines whether impl Trait can be used in return position.
+ // This guards against trait declarations and implementations where impl Trait is
+ // disallowed.
+ // make_ret_async: if enabled, converts `-> T` into `-> impl Future<Output = T>` in the
+ // return type. This is used for `async fn` declarations.
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_def_id: Option<DefId>,
impl_trait_return_allow: bool,
+ make_ret_async: bool,
) -> P<hir::FnDecl> {
- // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
- // then impl Trait arguments are lowered into generic parameters on the given
- // fn_def_id, otherwise impl Trait is disallowed. (for now)
- //
- // Furthermore, if impl_trait_return_allow is true, then impl Trait may be used in
- // return positions as well. This guards against trait declarations and their impls
- // where impl Trait is disallowed. (again for now)
- P(hir::FnDecl {
- inputs: decl.inputs
- .iter()
- .map(|arg| {
- if let Some(def_id) = fn_def_id {
- self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
- } else {
- self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
- }
- })
- .collect(),
- output: match decl.output {
+ let inputs = decl.inputs
+ .iter()
+ .map(|arg| {
+ if let Some(def_id) = fn_def_id {
+ self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
+ } else {
+ self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
+ }
+ })
+ .collect::<HirVec<_>>();
+
+ let output = if make_ret_async {
+ self.lower_async_fn_ret_ty(
+ &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"))
+ } else {
+ match decl.output {
FunctionRetTy::Ty(ref ty) => match fn_def_id {
Some(def_id) if impl_trait_return_allow => {
hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id)))
_ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)),
},
FunctionRetTy::Default(span) => hir::DefaultReturn(span),
- },
+ }
+ };
+
+ P(hir::FnDecl {
+ inputs,
+ output,
variadic: decl.variadic,
has_implicit_self: decl.inputs.get(0).map_or(false, |arg| match arg.ty.node {
TyKind::ImplicitSelf => true,
})
}
- fn lower_ty_param_bound(
+ // Transform `-> T` into `-> impl Future<Output = T>` for `async fn`
+ //
+ // fn_span: the span of the async function declaration. Used for error reporting.
+ // inputs: lowered types of arguments to the function. Used to collect lifetimes.
+ // output: unlowered output type (`T` in `-> T`)
+ // fn_def_id: DefId of the parent function. Used to create child impl trait definition.
+ fn lower_async_fn_ret_ty(
&mut self,
- tpb: &TyParamBound,
- itctx: ImplTraitContext,
- ) -> hir::TyParamBound {
- match *tpb {
- TraitTyParamBound(ref ty, modifier) => hir::TraitTyParamBound(
- self.lower_poly_trait_ref(ty, itctx),
- self.lower_trait_bound_modifier(modifier),
- ),
- RegionTyParamBound(ref lifetime) => {
- hir::RegionTyParamBound(self.lower_lifetime(lifetime))
+ inputs: &[P<hir::Ty>],
+ output: &FunctionRetTy,
+ fn_def_id: DefId,
+ ) -> hir::FunctionRetTy {
+ // Get lifetimes used in the input arguments to the function. Our output type must also
+ // have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed
+ // because `impl Trait + 'a + 'b` doesn't allow for capture `'a` and `'b` where neither
+ // is a subset of the other. We really want some new lifetime that is a subset of all input
+ // lifetimes, but that doesn't exist at the moment.
+
+ struct AsyncFnLifetimeCollector<'r, 'a: 'r> {
+ context: &'r mut LoweringContext<'a>,
+ // Lifetimes bound by HRTB
+ currently_bound_lifetimes: Vec<hir::LifetimeName>,
+ // Whether to count elided lifetimes.
+ // Disabled inside of `Fn` or `fn` syntax.
+ collect_elided_lifetimes: bool,
+ // The lifetime found.
+ // Multiple different or elided lifetimes cannot appear in async fn for now.
+ output_lifetime: Option<(hir::LifetimeName, Span)>,
+ }
+
+ impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for AsyncFnLifetimeCollector<'r, 'a> {
+ fn nested_visit_map<'this>(
+ &'this mut self,
+ ) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
+ hir::intravisit::NestedVisitorMap::None
+ }
+
+ fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
+ // Don't collect elided lifetimes used inside of `Fn()` syntax.
+ if parameters.parenthesized {
+ let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+ self.collect_elided_lifetimes = false;
+ hir::intravisit::walk_generic_args(self, span, parameters);
+ self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+ } else {
+ hir::intravisit::walk_generic_args(self, span, parameters);
+ }
+ }
+
+ fn visit_ty(&mut self, t: &'v hir::Ty) {
+ // Don't collect elided lifetimes used inside of `fn()` syntax
+ if let &hir::Ty_::TyBareFn(_) = &t.node {
+ let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+ self.collect_elided_lifetimes = false;
+
+ // Record the "stack height" of `for<'a>` lifetime bindings
+ // to be able to later fully undo their introduction.
+ let old_len = self.currently_bound_lifetimes.len();
+ hir::intravisit::walk_ty(self, t);
+ self.currently_bound_lifetimes.truncate(old_len);
+
+ self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+ } else {
+ hir::intravisit::walk_ty(self, t);
+ }
+ }
+
+ fn visit_poly_trait_ref(
+ &mut self,
+ trait_ref: &'v hir::PolyTraitRef,
+ modifier: hir::TraitBoundModifier,
+ ) {
+ // Record the "stack height" of `for<'a>` lifetime bindings
+ // to be able to later fully undo their introduction.
+ let old_len = self.currently_bound_lifetimes.len();
+ hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
+ self.currently_bound_lifetimes.truncate(old_len);
+ }
+
+ fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
+ // Record the introduction of 'a in `for<'a> ...`
+ if let hir::GenericParamKind::Lifetime { .. } = param.kind {
+ // Introduce lifetimes one at a time so that we can handle
+ // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
+ let lt_name = hir::LifetimeName::Param(param.name);
+ self.currently_bound_lifetimes.push(lt_name);
+ }
+
+ hir::intravisit::walk_generic_param(self, param);
+ }
+
+ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
+ let name = match lifetime.name {
+ hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+ if self.collect_elided_lifetimes {
+ // Use `'_` for both implicit and underscore lifetimes in
+ // `abstract type Foo<'_>: SomeTrait<'_>;`
+ hir::LifetimeName::Underscore
+ } else {
+ return;
+ }
+ }
+ hir::LifetimeName::Param(_) => lifetime.name,
+ hir::LifetimeName::Static => return,
+ };
+
+ if !self.currently_bound_lifetimes.contains(&name) {
+ if let Some((current_lt_name, current_lt_span)) = self.output_lifetime {
+ // We don't currently have a reliable way to desugar `async fn` with
+ // multiple potentially unrelated input lifetimes into
+ // `-> impl Trait + 'lt`, so we report an error in this case.
+ if current_lt_name != name {
+ struct_span_err!(
+ self.context.sess,
+ current_lt_span.between(lifetime.span),
+ E0709,
+ "multiple different lifetimes used in arguments of `async fn`",
+ )
+ .span_label(current_lt_span, "first lifetime here")
+ .span_label(lifetime.span, "different lifetime here")
+ .help("`async fn` can only accept borrowed values \
+ with identical lifetimes")
+ .emit()
+ } else if current_lt_name.is_elided() && name.is_elided() {
+ struct_span_err!(
+ self.context.sess,
+ current_lt_span.between(lifetime.span),
+ E0707,
+ "multiple elided lifetimes used in arguments of `async fn`",
+ )
+ .span_label(current_lt_span, "first lifetime here")
+ .span_label(lifetime.span, "different lifetime here")
+ .help("consider giving these arguments named lifetimes")
+ .emit()
+ }
+ } else {
+ self.output_lifetime = Some((name, lifetime.span));
+ }
+ }
}
}
+
+ let bound_lifetime = {
+ let mut lifetime_collector = AsyncFnLifetimeCollector {
+ context: self,
+ currently_bound_lifetimes: Vec::new(),
+ collect_elided_lifetimes: true,
+ output_lifetime: None,
+ };
+
+ for arg in inputs {
+ hir::intravisit::walk_ty(&mut lifetime_collector, arg);
+ }
+ lifetime_collector.output_lifetime
+ };
+
+ let span = match output {
+ FunctionRetTy::Ty(ty) => ty.span,
+ FunctionRetTy::Default(span) => *span,
+ };
+
+ let impl_trait_ty = self.lower_existential_impl_trait(
+ span, fn_def_id, |this| {
+ let output_ty = match output {
+ FunctionRetTy::Ty(ty) =>
+ this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)),
+ FunctionRetTy::Default(span) => {
+ let LoweredNodeId { node_id, hir_id } = this.next_id();
+ P(hir::Ty {
+ id: node_id,
+ hir_id: hir_id,
+ node: hir::TyTup(hir_vec![]),
+ span: *span,
+ })
+ }
+ };
+
+ // "<Output = T>"
+ let future_params = P(hir::GenericArgs {
+ args: hir_vec![],
+ bindings: hir_vec![hir::TypeBinding {
+ name: Symbol::intern(FN_OUTPUT_NAME),
+ ty: output_ty,
+ id: this.next_id().node_id,
+ span,
+ }],
+ parenthesized: false,
+ });
+
+ let future_path =
+ this.std_path(span, &["future", "Future"], Some(future_params), false);
+
+ let mut bounds = vec![
+ hir::GenericBound::Trait(
+ hir::PolyTraitRef {
+ trait_ref: hir::TraitRef {
+ path: future_path,
+ ref_id: this.next_id().node_id,
+ },
+ bound_generic_params: hir_vec![],
+ span,
+ },
+ hir::TraitBoundModifier::None
+ ),
+ ];
+
+ if let Some((name, span)) = bound_lifetime {
+ bounds.push(hir::GenericBound::Outlives(
+ hir::Lifetime { id: this.next_id().node_id, name, span }));
+ }
+
+ hir::HirVec::from(bounds)
+ });
+
+ let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let impl_trait_ty = P(hir::Ty {
+ id: node_id,
+ node: impl_trait_ty,
+ span,
+ hir_id,
+ });
+
+ hir::FunctionRetTy::Return(impl_trait_ty)
}
- fn lower_ty_param(
+ fn lower_param_bound(
&mut self,
- tp: &TyParam,
- add_bounds: &[TyParamBound],
+ tpb: &GenericBound,
itctx: ImplTraitContext,
- ) -> hir::TyParam {
- let mut name = self.lower_ident(tp.ident);
-
- // Don't expose `Self` (recovered "keyword used as ident" parse error).
- // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
- // Instead, use gensym("Self") to create a distinct name that looks the same.
- if name == keywords::SelfType.name() {
- name = Symbol::gensym("Self");
- }
-
- let mut bounds = self.lower_bounds(&tp.bounds, itctx);
- if !add_bounds.is_empty() {
- bounds = bounds
- .into_iter()
- .chain(self.lower_bounds(add_bounds, itctx).into_iter())
- .collect();
- }
-
- hir::TyParam {
- id: self.lower_node_id(tp.id).node_id,
- name,
- bounds,
- default: tp.default
- .as_ref()
- .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
- span: tp.ident.span,
- pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"),
- synthetic: tp.attrs
- .iter()
- .filter(|attr| attr.check_name("rustc_synthetic"))
- .map(|_| hir::SyntheticTyParamKind::ImplTrait)
- .nth(0),
- attrs: self.lower_attrs(&tp.attrs),
+ ) -> hir::GenericBound {
+ match *tpb {
+ GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
+ self.lower_poly_trait_ref(ty, itctx),
+ self.lower_trait_bound_modifier(modifier),
+ ),
+ GenericBound::Outlives(ref lifetime) => {
+ hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
+ }
}
}
x if x == "'_" => match self.anonymous_lifetime_mode {
AnonymousLifetimeMode::CreateParameter => {
let fresh_name = self.collect_fresh_in_band_lifetime(span);
- self.new_named_lifetime(l.id, span, fresh_name)
+ self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
}
AnonymousLifetimeMode::PassThrough => {
},
name => {
self.maybe_collect_in_band_lifetime(span, name);
- self.new_named_lifetime(l.id, span, hir::LifetimeName::Name(name))
+ let param_name = ParamName::Plain(name);
+ self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
}
}
}
}
}
- fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
- let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
- self.is_collecting_in_band_lifetimes = false;
-
- let def = hir::LifetimeDef {
- lifetime: self.lower_lifetime(&l.lifetime),
- bounds: self.lower_lifetimes(&l.bounds),
- pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
- in_band: false,
- };
-
- self.is_collecting_in_band_lifetimes = was_collecting_in_band;
-
- def
- }
-
- fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
- lts.iter().map(|l| self.lower_lifetime(l)).collect()
- }
-
fn lower_generic_params(
&mut self,
params: &Vec<GenericParam>,
- add_bounds: &NodeMap<Vec<TyParamBound>>,
+ add_bounds: &NodeMap<Vec<GenericBound>>,
itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> {
- params
- .iter()
- .map(|param| match *param {
- GenericParam::Lifetime(ref lifetime_def) => {
- hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def))
+ params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
+ }
+
+ fn lower_generic_param(&mut self,
+ param: &GenericParam,
+ add_bounds: &NodeMap<Vec<GenericBound>>,
+ itctx: ImplTraitContext)
+ -> hir::GenericParam {
+ let mut bounds = self.lower_param_bounds(¶m.bounds, itctx);
+ match param.kind {
+ GenericParamKind::Lifetime => {
+ let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
+ self.is_collecting_in_band_lifetimes = false;
+
+ let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
+ let param_name = match lt.name {
+ hir::LifetimeName::Param(param_name) => param_name,
+ _ => hir::ParamName::Plain(lt.name.name()),
+ };
+ let param = hir::GenericParam {
+ id: lt.id,
+ name: param_name,
+ span: lt.span,
+ pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
+ attrs: self.lower_attrs(¶m.attrs),
+ bounds,
+ kind: hir::GenericParamKind::Lifetime { in_band: false }
+ };
+
+ self.is_collecting_in_band_lifetimes = was_collecting_in_band;
+
+ param
+ }
+ GenericParamKind::Type { ref default, .. } => {
+ let mut name = self.lower_ident(param.ident);
+
+ // Don't expose `Self` (recovered "keyword used as ident" parse error).
+ // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
+ // Instead, use gensym("Self") to create a distinct name that looks the same.
+ if name == keywords::SelfType.name() {
+ name = Symbol::gensym("Self");
}
- GenericParam::Type(ref ty_param) => hir::GenericParam::Type(self.lower_ty_param(
- ty_param,
- add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x),
- itctx,
- )),
- })
- .collect()
+
+ let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x);
+ if !add_bounds.is_empty() {
+ bounds = bounds.into_iter()
+ .chain(self.lower_param_bounds(add_bounds, itctx).into_iter())
+ .collect();
+ }
+
+ hir::GenericParam {
+ id: self.lower_node_id(param.id).node_id,
+ name: hir::ParamName::Plain(name),
+ span: param.ident.span,
+ pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
+ attrs: self.lower_attrs(¶m.attrs),
+ bounds,
+ kind: hir::GenericParamKind::Type {
+ default: default.as_ref().map(|x| {
+ self.lower_ty(x, ImplTraitContext::Disallowed)
+ }),
+ synthetic: param.attrs.iter()
+ .filter(|attr| attr.check_name("rustc_synthetic"))
+ .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+ .next(),
+ }
+ }
+ }
+ }
}
- fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics {
+ fn lower_generics(
+ &mut self,
+ generics: &Generics,
+ itctx: ImplTraitContext)
+ -> hir::Generics
+ {
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
// FIXME: This could probably be done with less rightward drift. Also looks like two control
// paths where report_error is called are also the only paths that advance to after
// the match statement, so the error reporting could probably just be moved there.
let mut add_bounds = NodeMap();
- for pred in &g.where_clause.predicates {
+ for pred in &generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
'next_bound: for bound in &bound_pred.bounds {
- if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
+ if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
let report_error = |this: &mut Self| {
this.diagnostic().span_err(
bound_pred.bounded_ty.span,
if let Some(node_id) =
self.resolver.definitions().as_local_node_id(def_id)
{
- for param in &g.params {
- if let GenericParam::Type(ref ty_param) = *param {
- if node_id == ty_param.id {
- add_bounds
- .entry(ty_param.id)
- .or_insert(Vec::new())
- .push(bound.clone());
- continue 'next_bound;
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Type { .. } => {
+ if node_id == param.id {
+ add_bounds.entry(param.id)
+ .or_insert(Vec::new())
+ .push(bound.clone());
+ continue 'next_bound;
+ }
}
+ _ => {}
}
}
}
}
hir::Generics {
- params: self.lower_generic_params(&g.params, &add_bounds, itctx),
- where_clause: self.lower_where_clause(&g.where_clause),
- span: g.span,
+ params: self.lower_generic_params(&generics.params, &add_bounds, itctx),
+ where_clause: self.lower_where_clause(&generics.where_clause),
+ span: generics.span,
}
}
span,
}) => {
self.with_in_scope_lifetime_defs(
- bound_generic_params.iter().filter_map(|p| match p {
- GenericParam::Lifetime(ld) => Some(ld),
- _ => None,
- }),
+ &bound_generic_params,
|this| {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: this.lower_generic_params(
.filter_map(|bound| match *bound {
// Ignore `?Trait` bounds.
// Tthey were copied into type parameters already.
- TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
- _ => Some(this.lower_ty_param_bound(
+ GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
+ _ => Some(this.lower_param_bound(
bound,
ImplTraitContext::Disallowed,
)),
}) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
span,
lifetime: self.lower_lifetime(lifetime),
- bounds: bounds
- .iter()
- .map(|bound| self.lower_lifetime(bound))
- .collect(),
+ bounds: self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
}),
WherePredicate::EqPredicate(WhereEqPredicate {
id,
let bound_generic_params =
self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx);
let trait_ref = self.with_parent_impl_lifetime_defs(
- &bound_generic_params
- .iter()
- .filter_map(|p| match *p {
- hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()),
- _ => None,
- })
- .collect::<Vec<_>>(),
+ &bound_generic_params,
|this| this.lower_trait_ref(&p.trait_ref, itctx),
);
}
}
- fn lower_bounds(
- &mut self,
- bounds: &[TyParamBound],
- itctx: ImplTraitContext,
- ) -> hir::TyParamBounds {
- bounds
- .iter()
- .map(|bound| self.lower_ty_param_bound(bound, itctx))
- .collect()
+ fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext)
+ -> hir::GenericBounds {
+ bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect()
}
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
let value = self.lower_body(None, |this| this.lower_expr(e));
hir::ItemConst(self.lower_ty(t, ImplTraitContext::Disallowed), value)
}
- ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
+ ItemKind::Fn(ref decl, header, ref generics, ref body) => {
let fn_def_id = self.resolver.definitions().local_def_id(id);
+
self.with_new_scopes(|this| {
+ // Note: we don't need to change the return type from `T` to
+ // `impl Future<Output = T>` here because lower_body
+ // only cares about the input argument patterns in the function
+ // declaration (decl), not the return types.
let body_id = this.lower_body(Some(decl), |this| {
- let body = this.lower_block(body, false);
- this.expr_block(body, ThinVec::new())
+ if let IsAsync::Async(async_node_id) = header.asyncness {
+ let async_expr = this.make_async_expr(
+ CaptureBy::Value, async_node_id, None,
+ |this| {
+ let body = this.lower_block(body, false);
+ this.expr_block(body, ThinVec::new())
+ });
+ this.expr(body.span, async_expr, ThinVec::new())
+ } else {
+ let body = this.lower_block(body, false);
+ this.expr_block(body, ThinVec::new())
+ }
});
+
let (generics, fn_decl) = this.add_in_band_defs(
generics,
fn_def_id,
AnonymousLifetimeMode::PassThrough,
- |this| this.lower_fn_decl(decl, Some(fn_def_id), true),
+ |this| this.lower_fn_decl(
+ decl, Some(fn_def_id), true, header.asyncness.is_async())
);
hir::ItemFn(
fn_decl,
- this.lower_unsafety(unsafety),
- this.lower_constness(constness),
- abi,
+ this.lower_fn_header(header),
generics,
body_id,
)
);
let new_impl_items = self.with_in_scope_lifetime_defs(
- ast_generics.params.iter().filter_map(|p| match p {
- GenericParam::Lifetime(ld) => Some(ld),
- _ => None,
- }),
+ &ast_generics.params,
|this| {
impl_items
.iter()
)
}
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
- let bounds = self.lower_bounds(bounds, ImplTraitContext::Disallowed);
+ let bounds = self.lower_param_bounds(bounds, ImplTraitContext::Disallowed);
let items = items
.iter()
.map(|item| self.lower_trait_item_ref(item))
}
ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemTraitAlias(
self.lower_generics(generics, ImplTraitContext::Disallowed),
- self.lower_bounds(bounds, ImplTraitContext::Disallowed),
+ self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
),
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
}
AnonymousLifetimeMode::PassThrough,
|this| {
hir::TraitItemKind::Method(
- this.lower_method_sig(sig, trait_item_def_id, false),
+ this.lower_method_sig(sig, trait_item_def_id, false, false),
hir::TraitMethod::Required(names),
)
},
AnonymousLifetimeMode::PassThrough,
|this| {
hir::TraitItemKind::Method(
- this.lower_method_sig(sig, trait_item_def_id, false),
+ this.lower_method_sig(sig, trait_item_def_id, false, false),
hir::TraitMethod::Provided(body_id),
)
},
TraitItemKind::Type(ref bounds, ref default) => (
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
hir::TraitItemKind::Type(
- self.lower_bounds(bounds, ImplTraitContext::Disallowed),
+ self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
default
.as_ref()
.map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
}
ImplItemKind::Method(ref sig, ref body) => {
let body_id = self.lower_body(Some(&sig.decl), |this| {
- let body = this.lower_block(body, false);
- this.expr_block(body, ThinVec::new())
+ if let IsAsync::Async(async_node_id) = sig.header.asyncness {
+ let async_expr = this.make_async_expr(
+ CaptureBy::Value, async_node_id, None,
+ |this| {
+ let body = this.lower_block(body, false);
+ this.expr_block(body, ThinVec::new())
+ });
+ this.expr(body.span, async_expr, ThinVec::new())
+ } else {
+ let body = this.lower_block(body, false);
+ this.expr_block(body, ThinVec::new())
+ }
});
let impl_trait_return_allow = !self.is_in_trait_impl;
sig,
impl_item_def_id,
impl_trait_return_allow,
+ sig.header.asyncness.is_async(),
),
body_id,
)
|this| {
(
// Disallow impl Trait in foreign items
- this.lower_fn_decl(fdec, None, false),
+ this.lower_fn_decl(fdec, None, false, false),
this.lower_fn_args_to_names(fdec),
)
},
sig: &MethodSig,
fn_def_id: DefId,
impl_trait_return_allow: bool,
+ is_async: bool,
) -> hir::MethodSig {
hir::MethodSig {
- abi: sig.abi,
- unsafety: self.lower_unsafety(sig.unsafety),
- constness: self.lower_constness(sig.constness),
- decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow),
+ header: self.lower_fn_header(sig.header),
+ decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async),
}
}
}
}
+ fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+ hir::FnHeader {
+ unsafety: self.lower_unsafety(h.unsafety),
+ asyncness: self.lower_asyncness(h.asyncness),
+ constness: self.lower_constness(h.constness),
+ abi: h.abi,
+ }
+ }
+
fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
match u {
Unsafety::Unsafe => hir::Unsafety::Unsafe,
}
}
+ fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
+ match a {
+ IsAsync::Async(_) => hir::IsAsync::Async,
+ IsAsync::NotAsync => hir::IsAsync::NotAsync,
+ }
+ }
+
fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
match u {
UnOp::Deref => hir::UnDeref,
arms.iter().map(|x| self.lower_arm(x)).collect(),
hir::MatchSource::Normal,
),
- ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => {
- self.with_new_scopes(|this| {
- let mut is_generator = false;
- let body_id = this.lower_body(Some(decl), |this| {
- let e = this.lower_expr(body);
- is_generator = this.is_generator;
- e
- });
- let generator_option = if is_generator {
- if !decl.inputs.is_empty() {
- span_err!(
- this.sess,
- fn_decl_span,
- E0628,
- "generators cannot have explicit arguments"
- );
- this.sess.abort_if_errors();
- }
- Some(match movability {
- Movability::Movable => hir::GeneratorMovability::Movable,
- Movability::Static => hir::GeneratorMovability::Static,
- })
- } else {
- if movability == Movability::Static {
- span_err!(
+ ExprKind::Async(capture_clause, closure_node_id, ref block) => {
+ self.make_async_expr(capture_clause, closure_node_id, None, |this| {
+ this.with_new_scopes(|this| {
+ let block = this.lower_block(block, false);
+ this.expr_block(block, ThinVec::new())
+ })
+ })
+ }
+ ExprKind::Closure(
+ capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
+ ) => {
+ if let IsAsync::Async(async_closure_node_id) = asyncness {
+ let outer_decl = FnDecl {
+ inputs: decl.inputs.clone(),
+ output: FunctionRetTy::Default(fn_decl_span),
+ variadic: false,
+ };
+ // We need to lower the declaration outside the new scope, because we
+ // have to conserve the state of being inside a loop condition for the
+ // closure argument types.
+ let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
+
+ self.with_new_scopes(|this| {
+ // FIXME(cramertj) allow `async` non-`move` closures with
+ if capture_clause == CaptureBy::Ref &&
+ !decl.inputs.is_empty()
+ {
+ struct_span_err!(
this.sess,
fn_decl_span,
- E0697,
- "closures cannot be static"
- );
+ E0708,
+ "`async` non-`move` closures with arguments \
+ are not currently supported",
+ )
+ .help("consider using `let` statements to manually capture \
+ variables by reference before entering an \
+ `async move` closure")
+ .emit();
}
- None
- };
- hir::ExprClosure(
- this.lower_capture_clause(capture_clause),
- this.lower_fn_decl(decl, None, false),
- body_id,
- fn_decl_span,
- generator_option,
- )
- })
+
+ // Transform `async |x: u8| -> X { ... }` into
+ // `|x: u8| future_from_generator(|| -> X { ... })`
+ let body_id = this.lower_body(Some(&outer_decl), |this| {
+ let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
+ Some(&**ty)
+ } else { None };
+ let async_body = this.make_async_expr(
+ capture_clause, async_closure_node_id, async_ret_ty,
+ |this| {
+ this.with_new_scopes(|this| this.lower_expr(body))
+ });
+ this.expr(fn_decl_span, async_body, ThinVec::new())
+ });
+ hir::ExprClosure(
+ this.lower_capture_clause(capture_clause),
+ fn_decl,
+ body_id,
+ fn_decl_span,
+ None,
+ )
+ })
+ } else {
+ // Lower outside new scope to preserve `is_in_loop_condition`.
+ let fn_decl = self.lower_fn_decl(decl, None, false, false);
+
+ self.with_new_scopes(|this| {
+ let mut is_generator = false;
+ let body_id = this.lower_body(Some(decl), |this| {
+ let e = this.lower_expr(body);
+ is_generator = this.is_generator;
+ e
+ });
+ let generator_option = if is_generator {
+ if !decl.inputs.is_empty() {
+ span_err!(
+ this.sess,
+ fn_decl_span,
+ E0628,
+ "generators cannot have explicit arguments"
+ );
+ this.sess.abort_if_errors();
+ }
+ Some(match movability {
+ Movability::Movable => hir::GeneratorMovability::Movable,
+ Movability::Static => hir::GeneratorMovability::Static,
+ })
+ } else {
+ if movability == Movability::Static {
+ span_err!(
+ this.sess,
+ fn_decl_span,
+ E0697,
+ "closures cannot be static"
+ );
+ }
+ None
+ };
+ hir::ExprClosure(
+ this.lower_capture_clause(capture_clause),
+ fn_decl,
+ body_id,
+ fn_decl_span,
+ generator_option,
+ )
+ })
+ }
}
ExprKind::Block(ref blk, opt_label) => {
hir::ExprBlock(self.lower_block(blk,
let id = self.next_id();
let e1 = self.lower_expr(e1);
let e2 = self.lower_expr(e2);
- let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false));
+ let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], None, false));
let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path));
let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new")));
let new_path = hir::QPath::TypeRelative(ty, new_seg);
let struct_path = iter::once("ops")
.chain(iter::once(path))
.collect::<Vec<_>>();
- let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
+ let struct_path = self.std_path(unstable_span, &struct_path, None, is_unit);
let struct_path = hir::QPath::Resolved(None, P(struct_path));
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
)
}
ExprKind::Continue(opt_label) => {
- hir::ExprAgain(if self.is_in_loop_condition && opt_label.is_none() {
+ hir::ExprContinue(if self.is_in_loop_condition && opt_label.is_none() {
hir::Destination {
label: None,
target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
let iter = P(self.expr_ident(head_sp, iter, iter_pat.id));
let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
let next_path = &["iter", "Iterator", "next"];
- let next_path = P(self.expr_std_path(head_sp, next_path, ThinVec::new()));
+ let next_path = P(self.expr_std_path(head_sp, next_path, None, ThinVec::new()));
let next_expr = P(self.expr_call(head_sp, next_path, hir_vec![ref_mut_iter]));
let arms = hir_vec![pat_arm, break_arm];
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = &["iter", "IntoIterator", "into_iter"];
- let into_iter = P(self.expr_std_path(head_sp, into_iter_path, ThinVec::new()));
+ let into_iter = P(self.expr_std_path(
+ head_sp, into_iter_path, None, ThinVec::new()));
P(self.expr_call(head_sp, into_iter, hir_vec![head]))
};
let sub_expr = self.lower_expr(sub_expr);
let path = &["ops", "Try", "into_result"];
- let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
+ let path = P(self.expr_std_path(
+ unstable_span, path, None, ThinVec::new()));
P(self.expr_call(e.span, path, hir_vec![sub_expr]))
};
let err_local = self.pat_ident(e.span, err_ident);
let from_expr = {
let path = &["convert", "From", "from"];
- let from = P(self.expr_std_path(e.span, path, ThinVec::new()));
+ let from = P(self.expr_std_path(
+ e.span, path, None, ThinVec::new()));
let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
self.expr_call(e.span, from, hir_vec![err_expr])
&mut self,
span: Span,
components: &[&str],
+ params: Option<P<hir::GenericArgs>>,
attrs: ThinVec<Attribute>,
) -> hir::Expr {
- let path = self.std_path(span, components, true);
+ let path = self.std_path(span, components, params, true);
self.expr(
span,
hir::ExprPath(hir::QPath::Resolved(None, P(path))),
components: &[&str],
subpats: hir::HirVec<P<hir::Pat>>,
) -> P<hir::Pat> {
- let path = self.std_path(span, components, true);
+ let path = self.std_path(span, components, None, true);
let qpath = hir::QPath::Resolved(None, P(path));
let pt = if subpats.is_empty() {
hir::PatKind::Path(qpath)
/// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
/// The path is also resolved according to `is_value`.
- fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
+ fn std_path(
+ &mut self,
+ span: Span,
+ components: &[&str],
+ params: Option<P<hir::GenericArgs>>,
+ is_value: bool
+ ) -> hir::Path {
self.resolver
- .resolve_str_path(span, self.crate_root, components, is_value)
+ .resolve_str_path(span, self.crate_root, components, params, is_value)
}
fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
hir::Lifetime {
id: self.next_id().node_id,
span,
- name: fresh_name,
+ name: hir::LifetimeName::Param(fresh_name),
}
}
unstable_span: Span,
) -> P<hir::Expr> {
let path = &["ops", "Try", method];
- let from_err = P(self.expr_std_path(unstable_span, path,
+ let from_err = P(self.expr_std_path(unstable_span, path, None,
ThinVec::new()));
P(self.expr_call(e.span, from_err, hir_vec![e]))
}
use hir::map::{self, Node};
use hir::{Expr, FnDecl};
use hir::intravisit::FnKind;
-use rustc_target::spec::abi;
use syntax::ast::{Attribute, Name, NodeId};
use syntax_pos::Span;
struct ItemFnParts<'a> {
name: Name,
decl: &'a ast::FnDecl,
- unsafety: ast::Unsafety,
- constness: ast::Constness,
- abi: abi::Abi,
+ header: ast::FnHeader,
vis: &'a ast::Visibility,
generics: &'a ast::Generics,
body: ast::BodyId,
pub fn constness(self) -> ast::Constness {
match self.kind() {
- FnKind::ItemFn(_, _, _, constness, ..) => {
- constness
- }
- FnKind::Method(_, m, ..) => {
- m.constness
- }
+ FnKind::ItemFn(_, _, header, ..) => header.constness,
+ FnKind::Method(_, m, ..) => m.header.constness,
_ => ast::Constness::NotConst
}
}
+ pub fn asyncness(self) -> ast::IsAsync {
+ match self.kind() {
+ FnKind::ItemFn(_, _, header, ..) => header.asyncness,
+ FnKind::Method(_, m, ..) => m.header.asyncness,
+ _ => ast::IsAsync::NotAsync
+ }
+ }
+
pub fn unsafety(self) -> ast::Unsafety {
match self.kind() {
- FnKind::ItemFn(_, _, unsafety, ..) => {
- unsafety
- }
- FnKind::Method(_, m, ..) => {
- m.unsafety
- }
+ FnKind::ItemFn(_, _, header, ..) => header.unsafety,
+ FnKind::Method(_, m, ..) => m.header.unsafety,
_ => ast::Unsafety::Normal
}
}
pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
- FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
+ FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
};
let closure = |c: ClosureParts<'a>| {
FnKind::Closure(c.attrs)
{
match self.node {
map::NodeItem(i) => match i.node {
- ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, block) =>
+ ast::ItemFn(ref decl, header, ref generics, block) =>
item_fn(ItemFnParts {
id: i.id,
name: i.name,
decl: &decl,
- unsafety,
body: block,
- generics,
- abi,
vis: &i.vis,
- constness,
span: i.span,
attrs: &i.attrs,
+ header,
+ generics,
}),
_ => bug!("item FnLikeNode that is not fn-like"),
},
NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
- NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
+ NodeGenericParam(n) => EntryGenericParam(parent, dep_node_index, n),
NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
NodeMacroDef(n) => EntryMacroDef(dep_node_index, n),
}
fn visit_generic_param(&mut self, param: &'hir GenericParam) {
- match *param {
- GenericParam::Lifetime(ref ld) => {
- self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime));
- }
- GenericParam::Type(ref ty_param) => {
- self.insert(ty_param.id, NodeTyParam(ty_param));
- }
- }
+ self.insert(param.id, NodeGenericParam(param));
intravisit::walk_generic_param(self, param);
}
self.parent_def = parent;
}
+ fn visit_async_fn(
+ &mut self,
+ id: NodeId,
+ async_node_id: NodeId,
+ name: Name,
+ span: Span,
+ visit_fn: impl FnOnce(&mut DefCollector<'a>)
+ ) {
+ // For async functions, we need to create their inner defs inside of a
+ // closure to match their desugared representation.
+ let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
+ let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
+ return self.with_parent(fn_def, |this| {
+ let closure_def = this.create_def(async_node_id,
+ DefPathData::ClosureExpr,
+ REGULAR_SPACE,
+ span);
+ this.with_parent(closure_def, visit_fn)
+ })
+ }
+
fn visit_macro_invoc(&mut self, id: NodeId) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData {
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
+ ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => {
+ return self.visit_async_fn(
+ i.id,
+ async_node_id,
+ i.ident.name,
+ i.span,
+ |this| visit::walk_item(this, i)
+ )
+ }
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name.as_interned_str()),
}
fn visit_generic_param(&mut self, param: &'a GenericParam) {
- match *param {
- GenericParam::Lifetime(ref lifetime_def) => {
- self.create_def(
- lifetime_def.lifetime.id,
- DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
- REGULAR_SPACE,
- lifetime_def.lifetime.ident.span
- );
- }
- GenericParam::Type(ref ty_param) => {
- self.create_def(
- ty_param.id,
- DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
- REGULAR_SPACE,
- ty_param.ident.span
- );
- }
- }
+ let name = param.ident.name.as_interned_str();
+ let def_path_data = match param.kind {
+ GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name),
+ GenericParamKind::Type { .. } => DefPathData::TypeParam(name),
+ };
+ self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span);
visit::walk_generic_param(self, param);
}
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.node {
+ ImplItemKind::Method(MethodSig {
+ header: FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..
+ }, ..) => {
+ return self.visit_async_fn(
+ ii.id,
+ async_node_id,
+ ii.ident.name,
+ ii.span,
+ |this| visit::walk_impl_item(this, ii)
+ )
+ }
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_interned_str()),
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
match expr.node {
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
- ExprKind::Closure(..) => {
- let def = self.create_def(expr.id,
+ ExprKind::Closure(_, asyncness, ..) => {
+ let closure_def = self.create_def(expr.id,
DefPathData::ClosureExpr,
REGULAR_SPACE,
expr.span);
- self.parent_def = Some(def);
+ self.parent_def = Some(closure_def);
+
+ // Async closures desugar to closures inside of closures, so
+ // we must create two defs.
+ if let IsAsync::Async(async_id) = asyncness {
+ let async_def = self.create_def(async_id,
+ DefPathData::ClosureExpr,
+ REGULAR_SPACE,
+ expr.span);
+ self.parent_def = Some(async_def);
+ }
+ }
+ ExprKind::Async(_, async_id, _) => {
+ let async_def = self.create_def(async_id,
+ DefPathData::ClosureExpr,
+ REGULAR_SPACE,
+ expr.span);
+ self.parent_def = Some(async_def);
}
_ => {}
- }
+ };
visit::walk_expr(self, expr);
self.parent_def = parent_def;
node_to_def_index: NodeMap<DefIndex>,
def_index_to_node: [Vec<ast::NodeId>; 2],
pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
- macro_def_scopes: FxHashMap<Mark, DefId>,
- expansions: FxHashMap<DefIndex, Mark>,
+ /// If `Mark` is an ID of some macro expansion,
+ /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
+ parent_modules_of_macro_defs: FxHashMap<Mark, DefId>,
+ /// Item with a given `DefIndex` was defined during opaque macro expansion with ID `Mark`.
+ /// It can actually be defined during transparent macro expansions inside that opaque expansion,
+ /// but transparent expansions are ignored here.
+ opaque_expansions_that_defined: FxHashMap<DefIndex, Mark>,
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
def_index_to_span: FxHashMap<DefIndex, Span>,
}
self.def_index_to_node[1].clone(),
],
node_to_hir_id: self.node_to_hir_id.clone(),
- macro_def_scopes: self.macro_def_scopes.clone(),
- expansions: self.expansions.clone(),
+ parent_modules_of_macro_defs: self.parent_modules_of_macro_defs.clone(),
+ opaque_expansions_that_defined: self.opaque_expansions_that_defined.clone(),
next_disambiguator: self.next_disambiguator.clone(),
def_index_to_span: self.def_index_to_span.clone(),
}
/// A type parameter (generic parameter)
TypeParam(InternedString),
/// A lifetime definition
- LifetimeDef(InternedString),
+ LifetimeParam(InternedString),
/// A variant of a enum
EnumVariant(InternedString),
/// A struct field
node_to_def_index: NodeMap(),
def_index_to_node: [vec![], vec![]],
node_to_hir_id: IndexVec::new(),
- macro_def_scopes: FxHashMap(),
- expansions: FxHashMap(),
+ parent_modules_of_macro_defs: FxHashMap(),
+ opaque_expansions_that_defined: FxHashMap(),
next_disambiguator: FxHashMap(),
def_index_to_span: FxHashMap(),
}
let expansion = expansion.modern();
if expansion != Mark::root() {
- self.expansions.insert(index, expansion);
+ self.opaque_expansions_that_defined.insert(index, expansion);
}
// The span is added if it isn't DUMMY_SP
self.node_to_hir_id = mapping;
}
- pub fn expansion(&self, index: DefIndex) -> Mark {
- self.expansions.get(&index).cloned().unwrap_or(Mark::root())
+ pub fn opaque_expansion_that_defined(&self, index: DefIndex) -> Mark {
+ self.opaque_expansions_that_defined.get(&index).cloned().unwrap_or(Mark::root())
}
- pub fn macro_def_scope(&self, mark: Mark) -> DefId {
- self.macro_def_scopes[&mark]
+ pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId {
+ self.parent_modules_of_macro_defs[&mark]
}
- pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
- self.macro_def_scopes.insert(mark, scope);
+ pub fn add_parent_module_of_macro_def(&mut self, mark: Mark, module: DefId) {
+ self.parent_modules_of_macro_defs.insert(mark, module);
}
}
Module(name) |
MacroDef(name) |
TypeParam(name) |
- LifetimeDef(name) |
+ LifetimeParam(name) |
EnumVariant(name) |
Field(name) |
GlobalMetaData(name) => Some(name),
Module(name) |
MacroDef(name) |
TypeParam(name) |
- LifetimeDef(name) |
+ LifetimeParam(name) |
EnumVariant(name) |
Field(name) |
GlobalMetaData(name) => {
NodeStructCtor(&'hir VariantData),
NodeLifetime(&'hir Lifetime),
- NodeTyParam(&'hir TyParam),
+ NodeGenericParam(&'hir GenericParam),
NodeVisibility(&'hir Visibility),
}
EntryBlock(NodeId, DepNodeIndex, &'hir Block),
EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
- EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam),
+ EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam),
EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
EntryLocal(NodeId, DepNodeIndex, &'hir Local),
EntryBlock(id, _, _) => id,
EntryStructCtor(id, _, _) => id,
EntryLifetime(id, _, _) => id,
- EntryTyParam(id, _, _) => id,
+ EntryGenericParam(id, _, _) => id,
EntryVisibility(id, _, _) => id,
EntryLocal(id, _, _) => id,
EntryBlock(_, _, n) => NodeBlock(n),
EntryStructCtor(_, _, n) => NodeStructCtor(n),
EntryLifetime(_, _, n) => NodeLifetime(n),
- EntryTyParam(_, _, n) => NodeTyParam(n),
+ EntryGenericParam(_, _, n) => NodeGenericParam(n),
EntryVisibility(_, _, n) => NodeVisibility(n),
EntryLocal(_, _, n) => NodeLocal(n),
EntryMacroDef(_, n) => NodeMacroDef(n),
match self {
EntryItem(_, _, ref item) => {
match item.node {
- ItemFn(ref fn_decl, _, _, _, _, _) => Some(&fn_decl),
+ ItemFn(ref fn_decl, _, _, _) => Some(&fn_decl),
_ => None,
}
}
match item.node {
ItemConst(_, body) |
ItemStatic(.., body) |
- ItemFn(_, _, _, _, _, body) => Some(body),
+ ItemFn(_, _, _, body) => Some(body),
_ => None,
}
}
EntryBlock(_, dep_node_index, _) |
EntryStructCtor(_, dep_node_index, _) |
EntryLifetime(_, dep_node_index, _) |
- EntryTyParam(_, dep_node_index, _) |
+ EntryGenericParam(_, dep_node_index, _) |
EntryVisibility(_, dep_node_index, _) |
EntryAnonConst(_, dep_node_index, _) |
EntryExpr(_, dep_node_index, _) |
Some(Def::Macro(self.local_def_id(macro_def.id),
MacroKind::Bang))
}
- NodeTyParam(param) => {
- Some(Def::TyParam(self.local_def_id(param.id)))
+ NodeGenericParam(param) => {
+ Some(match param.kind {
+ GenericParamKind::Lifetime { .. } => Def::Local(param.id),
+ GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)),
+ })
}
}
}
pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
match self.get(id) {
NodeItem(&Item { node: ItemTrait(..), .. }) => id,
- NodeTyParam(_) => self.get_parent_node(id),
+ NodeGenericParam(_) => self.get_parent_node(id),
_ => {
bug!("ty_param_owner: {} not a type parameter",
self.node_to_string(id))
NodeItem(&Item { node: ItemTrait(..), .. }) => {
keywords::SelfType.name()
}
- NodeTyParam(tp) => tp.name,
- _ => {
- bug!("ty_param_name: {} not a type parameter",
- self.node_to_string(id))
- }
+ NodeGenericParam(param) => param.name.name(),
+ _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)),
}
}
NodeVariant(v) => v.node.name,
NodeField(f) => f.ident.name,
NodeLifetime(lt) => lt.name.name(),
- NodeTyParam(tp) => tp.name,
+ NodeGenericParam(param) => param.name.name(),
NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
NodeStructCtor(_) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
Some(NodeField(ref f)) => Some(&f.attrs[..]),
Some(NodeExpr(ref e)) => Some(&*e.attrs),
Some(NodeStmt(ref s)) => Some(s.node.attrs()),
- Some(NodeTyParam(tp)) => Some(&tp.attrs[..]),
+ Some(NodeGenericParam(param)) => Some(¶m.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
Some(NodeStructCtor(_)) => {
Some(EntryBlock(_, _, block)) => block.span,
Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
- Some(EntryTyParam(_, _, ty_param)) => ty_param.span,
+ Some(EntryGenericParam(_, _, param)) => param.span,
Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
Some(EntryLocal(_, _, local)) => local.span,
impl<'a> print::State<'a> {
pub fn print_node(&mut self, node: Node) -> io::Result<()> {
match node {
- NodeItem(a) => self.print_item(&a),
- NodeForeignItem(a) => self.print_foreign_item(&a),
- NodeTraitItem(a) => self.print_trait_item(a),
- NodeImplItem(a) => self.print_impl_item(a),
- NodeVariant(a) => self.print_variant(&a),
- NodeAnonConst(a) => self.print_anon_const(&a),
- NodeExpr(a) => self.print_expr(&a),
- NodeStmt(a) => self.print_stmt(&a),
- NodeTy(a) => self.print_type(&a),
- NodeTraitRef(a) => self.print_trait_ref(&a),
+ NodeItem(a) => self.print_item(&a),
+ NodeForeignItem(a) => self.print_foreign_item(&a),
+ NodeTraitItem(a) => self.print_trait_item(a),
+ NodeImplItem(a) => self.print_impl_item(a),
+ NodeVariant(a) => self.print_variant(&a),
+ NodeAnonConst(a) => self.print_anon_const(&a),
+ NodeExpr(a) => self.print_expr(&a),
+ NodeStmt(a) => self.print_stmt(&a),
+ NodeTy(a) => self.print_type(&a),
+ NodeTraitRef(a) => self.print_trait_ref(&a),
NodeBinding(a) |
- NodePat(a) => self.print_pat(&a),
- NodeBlock(a) => {
+ NodePat(a) => self.print_pat(&a),
+ NodeBlock(a) => {
use syntax::print::pprust::PrintState;
// containing cbox, will be closed by print-block at }
self.ibox(0)?;
self.print_block(&a)
}
- NodeLifetime(a) => self.print_lifetime(&a),
- NodeVisibility(a) => self.print_visibility(&a),
- NodeTyParam(_) => bug!("cannot print TyParam"),
- NodeField(_) => bug!("cannot print StructField"),
+ NodeLifetime(a) => self.print_lifetime(&a),
+ NodeVisibility(a) => self.print_visibility(&a),
+ NodeGenericParam(_) => bug!("cannot print NodeGenericParam"),
+ NodeField(_) => bug!("cannot print StructField"),
// these cases do not carry enough information in the
// hir_map to reconstruct their full structure for pretty
// printing.
- NodeStructCtor(_) => bug!("cannot print isolated StructCtor"),
- NodeLocal(a) => self.print_local_decl(&a),
- NodeMacroDef(_) => bug!("cannot print MacroDef"),
+ NodeStructCtor(_) => bug!("cannot print isolated StructCtor"),
+ NodeLocal(a) => self.print_local_decl(&a),
+ NodeMacroDef(_) => bug!("cannot print MacroDef"),
}
}
}
Some(NodeLifetime(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
}
- Some(NodeTyParam(ref ty_param)) => {
- format!("typaram {:?}{}", ty_param, id_str)
+ Some(NodeGenericParam(ref param)) => {
+ format!("generic_param {:?}{}", param, id_str)
}
Some(NodeVisibility(ref vis)) => {
format!("visibility {:?}{}", vis, id_str)
pub use self::PrimTy::*;
pub use self::Stmt_::*;
pub use self::Ty_::*;
-pub use self::TyParamBound::*;
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
pub use self::Visibility::{Public, Inherited};
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap;
use std::fmt;
-use std::iter;
-use std::slice;
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
/// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar
}
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
-pub enum LifetimeName {
- /// User typed nothing. e.g. the lifetime in `&u32`.
- Implicit,
-
- /// User typed `'_`.
- Underscore,
+pub enum ParamName {
+ /// Some user-given name like `T` or `'x`.
+ Plain(Name),
/// Synthetic name generated when user elided a lifetime in an impl header,
/// e.g. the lifetimes in cases like these:
/// where `'f` is something like `Fresh(0)`. The indices are
/// unique per impl, but not necessarily continuous.
Fresh(usize),
+}
+
+impl ParamName {
+ pub fn name(&self) -> Name {
+ match *self {
+ ParamName::Plain(name) => name,
+ ParamName::Fresh(_) => keywords::UnderscoreLifetime.name(),
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub enum LifetimeName {
+ /// User-given names or fresh (synthetic) names.
+ Param(ParamName),
+
+ /// User typed nothing. e.g. the lifetime in `&u32`.
+ Implicit,
+
+ /// User typed `'_`.
+ Underscore,
/// User wrote `'static`
Static,
-
- /// Some user-given name like `'x`
- Name(Name),
}
impl LifetimeName {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
- Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(),
+ Underscore => keywords::UnderscoreLifetime.name(),
Static => keywords::StaticLifetime.name(),
- Name(name) => name,
+ Param(param_name) => param_name.name(),
+ }
+ }
+
+ pub fn is_elided(&self) -> bool {
+ use self::LifetimeName::*;
+ match self {
+ Implicit | Underscore => true,
+
+ // It might seem surprising that `Fresh(_)` counts as
+ // *not* elided -- but this is because, as far as the code
+ // in the compiler is concerned -- `Fresh(_)` variants act
+ // equivalently to "some fresh name". They correspond to
+ // early-bound regions on an impl, in other words.
+ Param(_) | Static => false,
}
}
+
+ fn is_static(&self) -> bool {
+ self == &LifetimeName::Static
+ }
}
impl fmt::Debug for Lifetime {
impl Lifetime {
pub fn is_elided(&self) -> bool {
- use self::LifetimeName::*;
- match self.name {
- Implicit | Underscore => true,
-
- // It might seem surprising that `Fresh(_)` counts as
- // *not* elided -- but this is because, as far as the code
- // in the compiler is concerned -- `Fresh(_)` variants act
- // equivalently to "some fresh name". They correspond to
- // early-bound regions on an impl, in other words.
- Fresh(_) | Static | Name(_) => false,
- }
+ self.name.is_elided()
}
pub fn is_static(&self) -> bool {
- self.name == LifetimeName::Static
+ self.name.is_static()
}
}
-/// A lifetime definition, eg `'a: 'b+'c+'d`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct LifetimeDef {
- pub lifetime: Lifetime,
- pub bounds: HirVec<Lifetime>,
- pub pure_wrt_drop: bool,
- // Indicates that the lifetime definition was synthetically added
- // as a result of an in-band lifetime usage like
- // `fn foo(x: &'a u8) -> &'a u8 { x }`
- pub in_band: bool,
-}
-
/// A "Path" is essentially Rust's notion of a name; for instance:
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
/// this is more than just simple syntactic sugar; the use of
/// parens affects the region binding rules, so we preserve the
/// distinction.
- pub parameters: Option<P<PathParameters>>,
+ pub args: Option<P<GenericArgs>>,
/// Whether to infer remaining type parameters, if any.
/// This only applies to expression and pattern paths, and
PathSegment {
name,
infer_types: true,
- parameters: None
+ args: None,
}
}
- pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self {
+ pub fn new(name: Name, args: GenericArgs, infer_types: bool) -> Self {
PathSegment {
name,
infer_types,
- parameters: if parameters.is_empty() {
+ args: if args.is_empty() {
None
} else {
- Some(P(parameters))
+ Some(P(args))
}
}
}
// FIXME: hack required because you can't create a static
- // PathParameters, so you can't just return a &PathParameters.
- pub fn with_parameters<F, R>(&self, f: F) -> R
- where F: FnOnce(&PathParameters) -> R
+ // GenericArgs, so you can't just return a &GenericArgs.
+ pub fn with_generic_args<F, R>(&self, f: F) -> R
+ where F: FnOnce(&GenericArgs) -> R
{
- let dummy = PathParameters::none();
- f(if let Some(ref params) = self.parameters {
- ¶ms
+ let dummy = GenericArgs::none();
+ f(if let Some(ref args) = self.args {
+ &args
} else {
&dummy
})
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct PathParameters {
- /// The lifetime parameters for this path segment.
- pub lifetimes: HirVec<Lifetime>,
- /// The type parameters for this path segment, if present.
- pub types: HirVec<P<Ty>>,
+pub enum GenericArg {
+ Lifetime(Lifetime),
+ Type(P<Ty>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct GenericArgs {
+ /// The generic arguments for this path segment.
+ pub args: HirVec<GenericArg>,
/// Bindings (equality constraints) on associated types, if present.
/// E.g., `Foo<A=Bar>`.
pub bindings: HirVec<TypeBinding>,
- /// Were parameters written in parenthesized form `Fn(T) -> U`?
+ /// Were arguments written in parenthesized form `Fn(T) -> U`?
/// This is required mostly for pretty-printing and diagnostics,
/// but also for changing lifetime elision rules to be "function-like".
pub parenthesized: bool,
}
-impl PathParameters {
+impl GenericArgs {
pub fn none() -> Self {
Self {
- lifetimes: HirVec::new(),
- types: HirVec::new(),
+ args: HirVec::new(),
bindings: HirVec::new(),
parenthesized: false,
}
}
pub fn is_empty(&self) -> bool {
- self.lifetimes.is_empty() && self.types.is_empty() &&
- self.bindings.is_empty() && !self.parenthesized
+ self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
}
pub fn inputs(&self) -> &[P<Ty>] {
if self.parenthesized {
- if let Some(ref ty) = self.types.get(0) {
- if let TyTup(ref tys) = ty.node {
- return tys;
+ for arg in &self.args {
+ match arg {
+ GenericArg::Lifetime(_) => {}
+ GenericArg::Type(ref ty) => {
+ if let TyTup(ref tys) = ty.node {
+ return tys;
+ }
+ break;
+ }
}
}
}
- bug!("PathParameters::inputs: not a `Fn(T) -> U`");
+ bug!("GenericArgs::inputs: not a `Fn(T) -> U`");
}
}
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitBoundModifier {
+ None,
+ Maybe,
+}
+
/// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and
/// detects Copy, Send and Sync.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TyParamBound {
- TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
- RegionTyParamBound(Lifetime),
+pub enum GenericBound {
+ Trait(PolyTraitRef, TraitBoundModifier),
+ Outlives(Lifetime),
}
-impl TyParamBound {
+impl GenericBound {
pub fn span(&self) -> Span {
match self {
- &TraitTyParamBound(ref t, ..) => t.span,
- &RegionTyParamBound(ref l) => l.span,
+ &GenericBound::Trait(ref t, ..) => t.span,
+ &GenericBound::Outlives(ref l) => l.span,
}
}
}
-/// A modifier on a bound, currently this is only used for `?Sized`, where the
-/// modifier is `Maybe`. Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitBoundModifier {
- None,
- Maybe,
-}
+pub type GenericBounds = HirVec<GenericBound>;
-pub type TyParamBounds = HirVec<TyParamBound>;
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum GenericParamKind {
+ /// A lifetime definition, eg `'a: 'b + 'c + 'd`.
+ Lifetime {
+ // Indicates that the lifetime definition was synthetically added
+ // as a result of an in-band lifetime usage like:
+ // `fn foo(x: &'a u8) -> &'a u8 { x }`
+ in_band: bool,
+ },
+ Type {
+ default: Option<P<Ty>>,
+ synthetic: Option<SyntheticTyParamKind>,
+ }
+}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TyParam {
- pub name: Name,
+pub struct GenericParam {
pub id: NodeId,
- pub bounds: TyParamBounds,
- pub default: Option<P<Ty>>,
+ pub name: ParamName,
+ pub attrs: HirVec<Attribute>,
+ pub bounds: GenericBounds,
pub span: Span,
pub pure_wrt_drop: bool,
- pub synthetic: Option<SyntheticTyParamKind>,
- pub attrs: HirVec<Attribute>,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum GenericParam {
- Lifetime(LifetimeDef),
- Type(TyParam),
-}
-
-impl GenericParam {
- pub fn is_lifetime_param(&self) -> bool {
- match *self {
- GenericParam::Lifetime(_) => true,
- _ => false,
- }
- }
- pub fn is_type_param(&self) -> bool {
- match *self {
- GenericParam::Type(_) => true,
- _ => false,
- }
- }
+ pub kind: GenericParamKind,
}
-pub trait GenericParamsExt {
- fn lifetimes<'a>(&'a self) -> iter::FilterMap<
- slice::Iter<GenericParam>,
- fn(&GenericParam) -> Option<&LifetimeDef>,
- >;
-
- fn ty_params<'a>(&'a self) -> iter::FilterMap<
- slice::Iter<GenericParam>,
- fn(&GenericParam) -> Option<&TyParam>,
- >;
-}
-
-impl GenericParamsExt for [GenericParam] {
- fn lifetimes<'a>(&'a self) -> iter::FilterMap<
- slice::Iter<GenericParam>,
- fn(&GenericParam) -> Option<&LifetimeDef>,
- > {
- self.iter().filter_map(|param| match *param {
- GenericParam::Lifetime(ref l) => Some(l),
- _ => None,
- })
- }
-
- fn ty_params<'a>(&'a self) -> iter::FilterMap<
- slice::Iter<GenericParam>,
- fn(&GenericParam) -> Option<&TyParam>,
- > {
- self.iter().filter_map(|param| match *param {
- GenericParam::Type(ref t) => Some(t),
- _ => None,
- })
- }
+pub struct GenericParamCount {
+ pub lifetimes: usize,
+ pub types: usize,
}
/// Represents lifetimes and type parameters attached to a declaration
}
}
- pub fn is_lt_parameterized(&self) -> bool {
- self.params.iter().any(|param| param.is_lifetime_param())
- }
-
- pub fn is_type_parameterized(&self) -> bool {
- self.params.iter().any(|param| param.is_type_param())
- }
-
- pub fn lifetimes<'a>(&'a self) -> impl Iterator<Item = &'a LifetimeDef> {
- self.params.lifetimes()
- }
+ pub fn own_counts(&self) -> GenericParamCount {
+ // We could cache this as a property of `GenericParamCount`, but
+ // the aim is to refactor this away entirely eventually and the
+ // presence of this method will be a constant reminder.
+ let mut own_counts = GenericParamCount {
+ lifetimes: 0,
+ types: 0,
+ };
- pub fn ty_params<'a>(&'a self) -> impl Iterator<Item = &'a TyParam> {
- self.params.ty_params()
- }
-}
-
-pub enum UnsafeGeneric {
- Region(LifetimeDef, &'static str),
- Type(TyParam, &'static str),
-}
-
-impl UnsafeGeneric {
- pub fn attr_name(&self) -> &'static str {
- match *self {
- UnsafeGeneric::Region(_, s) => s,
- UnsafeGeneric::Type(_, s) => s,
- }
- }
-}
-
-impl Generics {
- pub fn carries_unsafe_attr(&self) -> Option<UnsafeGeneric> {
for param in &self.params {
- match *param {
- GenericParam::Lifetime(ref l) => {
- if l.pure_wrt_drop {
- return Some(UnsafeGeneric::Region(l.clone(), "may_dangle"));
- }
- }
- GenericParam::Type(ref t) => {
- if t.pure_wrt_drop {
- return Some(UnsafeGeneric::Type(t.clone(), "may_dangle"));
- }
- }
- }
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
+ GenericParamKind::Type { .. } => own_counts.types += 1,
+ };
}
- None
+ own_counts
}
}
/// The type being bounded
pub bounded_ty: P<Ty>,
/// Trait and lifetime bounds (`Clone+Send+'static`)
- pub bounds: TyParamBounds,
+ pub bounds: GenericBounds,
}
/// A lifetime predicate, e.g. `'a: 'b+'c`
pub struct WhereRegionPredicate {
pub span: Span,
pub lifetime: Lifetime,
- pub bounds: HirVec<Lifetime>,
+ pub bounds: GenericBounds,
}
/// An equality predicate (unsupported), e.g. `T=int`
ExprPath(..) => ExprPrecedence::Path,
ExprAddrOf(..) => ExprPrecedence::AddrOf,
ExprBreak(..) => ExprPrecedence::Break,
- ExprAgain(..) => ExprPrecedence::Continue,
+ ExprContinue(..) => ExprPrecedence::Continue,
ExprRet(..) => ExprPrecedence::Ret,
ExprInlineAsm(..) => ExprPrecedence::InlineAsm,
ExprStruct(..) => ExprPrecedence::Struct,
/// A `break`, with an optional label to break
ExprBreak(Destination, Option<P<Expr>>),
/// A `continue`, with an optional label
- ExprAgain(Destination),
+ ExprContinue(Destination),
/// A `return`, with an optional value to be returned
ExprRet(Option<P<Expr>>),
/// Represents a method's signature in a trait declaration or implementation.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MethodSig {
- pub unsafety: Unsafety,
- pub constness: Constness,
- pub abi: Abi,
+ pub header: FnHeader,
pub decl: P<FnDecl>,
}
Method(MethodSig, TraitMethod),
/// An associated type with (possibly empty) bounds and optional concrete
/// type
- Type(TyParamBounds, Option<P<Ty>>),
+ Type(GenericBounds, Option<P<Ty>>),
}
// The bodies for items are stored "out of line", in a separate
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ExistTy {
pub generics: Generics,
- pub bounds: TyParamBounds,
+ pub bounds: GenericBounds,
pub impl_trait_fn: Option<DefId>,
}
No
}
-#[derive(Copy, Clone, PartialEq, Eq,PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAsync {
+ Async,
+ NotAsync,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Unsafety {
Unsafe,
Normal,
pub span: Span,
}
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FnHeader {
+ pub unsafety: Unsafety,
+ pub constness: Constness,
+ pub asyncness: IsAsync,
+ pub abi: Abi,
+}
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Item_ {
/// An `extern crate` item, with optional *original* crate name if the crate was renamed.
/// A `const` item
ItemConst(P<Ty>, BodyId),
/// A function declaration
- ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
+ ItemFn(P<FnDecl>, FnHeader, Generics, BodyId),
/// A module
ItemMod(Mod),
/// An external module
/// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
ItemUnion(VariantData, Generics),
/// Represents a Trait Declaration
- ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
+ ItemTrait(IsAuto, Unsafety, Generics, GenericBounds, HirVec<TraitItemRef>),
/// Represents a Trait Alias Declaration
- ItemTraitAlias(Generics, TyParamBounds),
+ ItemTraitAlias(Generics, GenericBounds),
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
pub fn generics(&self) -> Option<&Generics> {
Some(match *self {
- ItemFn(_, _, _, _, ref generics, _) |
+ ItemFn(_, _, ref generics, _) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
use syntax_pos::{self, BytePos, FileName};
use hir;
-use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
+use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
+use hir::{GenericParam, GenericParamKind, GenericArg};
use std::cell::Cell;
use std::io::{self, Write, Read};
hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => {
self.head("")?;
self.print_fn(decl,
- hir::Unsafety::Normal,
- hir::Constness::NotConst,
- Abi::Rust,
+ hir::FnHeader {
+ unsafety: hir::Unsafety::Normal,
+ constness: hir::Constness::NotConst,
+ abi: Abi::Rust,
+ asyncness: hir::IsAsync::NotAsync,
+ },
Some(item.name),
generics,
&item.vis,
fn print_associated_type(&mut self,
name: ast::Name,
- bounds: Option<&hir::TyParamBounds>,
+ bounds: Option<&hir::GenericBounds>,
ty: Option<&hir::Ty>)
-> io::Result<()> {
self.word_space("type")?;
self.s.word(";")?;
self.end()?; // end the outer cbox
}
- hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => {
+ hir::ItemFn(ref decl, header, ref typarams, body) => {
self.head("")?;
self.print_fn(decl,
- unsafety,
- constness,
- abi,
+ header,
Some(item.name),
typarams,
&item.vis,
self.word_space(":")?;
let mut real_bounds = Vec::with_capacity(exist.bounds.len());
for b in exist.bounds.iter() {
- if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
+ if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
- if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
+ if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
- if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
+ if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
body_id: Option<hir::BodyId>)
-> io::Result<()> {
self.print_fn(&m.decl,
- m.unsafety,
- m.constness,
- m.abi,
+ m.header,
Some(name),
generics,
vis,
self.s.word(".")?;
self.print_name(segment.name)?;
- segment.with_parameters(|parameters| {
- if !parameters.lifetimes.is_empty() ||
- !parameters.types.is_empty() ||
- !parameters.bindings.is_empty()
- {
- self.print_path_parameters(¶meters, segment.infer_types, true)
- } else {
- Ok(())
+ segment.with_generic_args(|generic_args| {
+ if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
+ return self.print_generic_args(&generic_args, segment.infer_types, true);
}
+ Ok(())
})?;
self.print_call_post(base_args)
}
self.s.space()?;
}
}
- hir::ExprAgain(destination) => {
+ hir::ExprContinue(destination) => {
self.s.word("continue")?;
self.s.space()?;
if let Some(label) = destination.label {
if segment.name != keywords::CrateRoot.name() &&
segment.name != keywords::DollarCrate.name() {
self.print_name(segment.name)?;
- segment.with_parameters(|parameters| {
- self.print_path_parameters(parameters,
- segment.infer_types,
- colons_before_params)
+ segment.with_generic_args(|generic_args| {
+ self.print_generic_args(generic_args, segment.infer_types,
+ colons_before_params)
})?;
}
}
if segment.name != keywords::CrateRoot.name() &&
segment.name != keywords::DollarCrate.name() {
self.print_name(segment.name)?;
- segment.with_parameters(|parameters| {
- self.print_path_parameters(parameters,
- segment.infer_types,
- colons_before_params)
+ segment.with_generic_args(|generic_args| {
+ self.print_generic_args(generic_args,
+ segment.infer_types,
+ colons_before_params)
})?;
}
}
self.s.word("::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
- item_segment.with_parameters(|parameters| {
- self.print_path_parameters(parameters,
- item_segment.infer_types,
- colons_before_params)
+ item_segment.with_generic_args(|generic_args| {
+ self.print_generic_args(generic_args,
+ item_segment.infer_types,
+ colons_before_params)
})
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
self.s.word(">")?;
self.s.word("::")?;
self.print_name(item_segment.name)?;
- item_segment.with_parameters(|parameters| {
- self.print_path_parameters(parameters,
- item_segment.infer_types,
- colons_before_params)
+ item_segment.with_generic_args(|generic_args| {
+ self.print_generic_args(generic_args,
+ item_segment.infer_types,
+ colons_before_params)
})
}
}
}
- fn print_path_parameters(&mut self,
- parameters: &hir::PathParameters,
+ fn print_generic_args(&mut self,
+ generic_args: &hir::GenericArgs,
infer_types: bool,
colons_before_params: bool)
-> io::Result<()> {
- if parameters.parenthesized {
+ if generic_args.parenthesized {
self.s.word("(")?;
- self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+ self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty))?;
self.s.word(")")?;
self.space_if_not_bol()?;
self.word_space("->")?;
- self.print_type(¶meters.bindings[0].ty)?;
+ self.print_type(&generic_args.bindings[0].ty)?;
} else {
let start = if colons_before_params { "::<" } else { "<" };
let empty = Cell::new(true);
}
};
- if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
- for lifetime in ¶meters.lifetimes {
- start_or_comma(self)?;
- self.print_lifetime(lifetime)?;
+ let mut types = vec![];
+ let mut elide_lifetimes = true;
+ for arg in &generic_args.args {
+ match arg {
+ GenericArg::Lifetime(lt) => {
+ if !lt.is_elided() {
+ elide_lifetimes = false;
+ }
+ }
+ GenericArg::Type(ty) => {
+ types.push(ty);
+ }
}
}
-
- if !parameters.types.is_empty() {
+ if !elide_lifetimes {
+ start_or_comma(self)?;
+ self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
+ match generic_arg {
+ GenericArg::Lifetime(lt) => s.print_lifetime(lt),
+ GenericArg::Type(ty) => s.print_type(ty),
+ }
+ })?;
+ } else if !types.is_empty() {
start_or_comma(self)?;
- self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?;
+ self.commasep(Inconsistent, &types, |s, ty| s.print_type(&ty))?;
}
// FIXME(eddyb) This would leak into error messages, e.g.:
self.s.word("..")?;
}
- for binding in parameters.bindings.iter() {
+ for binding in generic_args.bindings.iter() {
start_or_comma(self)?;
self.print_name(binding.name)?;
self.s.space()?;
pub fn print_fn(&mut self,
decl: &hir::FnDecl,
- unsafety: hir::Unsafety,
- constness: hir::Constness,
- abi: Abi,
+ header: hir::FnHeader,
name: Option<ast::Name>,
generics: &hir::Generics,
vis: &hir::Visibility,
arg_names: &[Spanned<ast::Name>],
body_id: Option<hir::BodyId>)
-> io::Result<()> {
- self.print_fn_header_info(unsafety, constness, abi, vis)?;
+ self.print_fn_header_info(header, vis)?;
if let Some(name) = name {
self.nbsp()?;
}
}
- pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> {
+ pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> {
if !bounds.is_empty() {
self.s.word(prefix)?;
let mut first = true;
}
match bound {
- TraitTyParamBound(tref, modifier) => {
+ GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
self.s.word("?")?;
}
self.print_poly_trait_ref(tref)?;
}
- RegionTyParamBound(lt) => {
+ GenericBound::Outlives(lt) => {
self.print_lifetime(lt)?;
}
}
Ok(())
}
- pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
- self.print_name(lifetime.name.name())
- }
-
- pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
- self.print_lifetime(&lifetime.lifetime)?;
- let mut sep = ":";
- for v in &lifetime.bounds {
- self.s.word(sep)?;
- self.print_lifetime(v)?;
- sep = "+";
- }
- Ok(())
- }
-
- pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> {
+ pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("<")?;
self.commasep(Inconsistent, generic_params, |s, param| {
- match *param {
- hir::GenericParam::Lifetime(ref ld) => s.print_lifetime_def(ld),
- hir::GenericParam::Type(ref tp) => s.print_ty_param(tp),
- }
+ s.print_generic_param(param)
})?;
self.s.word(">")?;
Ok(())
}
- pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
- self.print_name(param.name)?;
- self.print_bounds(":", ¶m.bounds)?;
- match param.default {
- Some(ref default) => {
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(&default)
+ pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
+ self.print_name(param.name.name())?;
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let mut sep = ":";
+ for bound in ¶m.bounds {
+ match bound {
+ GenericBound::Outlives(lt) => {
+ self.s.word(sep)?;
+ self.print_lifetime(lt)?;
+ sep = "+";
+ }
+ _ => bug!(),
+ }
+ }
+ Ok(())
+ }
+ GenericParamKind::Type { ref default, .. } => {
+ self.print_bounds(":", ¶m.bounds)?;
+ match default {
+ Some(default) => {
+ self.s.space()?;
+ self.word_space("=")?;
+ self.print_type(&default)
+ }
+ _ => Ok(()),
+ }
}
- _ => Ok(()),
}
}
+ pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
+ self.print_name(lifetime.name.name())
+ }
+
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
if where_clause.predicates.is_empty() {
return Ok(());
self.s.word(":")?;
for (i, bound) in bounds.iter().enumerate() {
- self.print_lifetime(bound)?;
+ match bound {
+ GenericBound::Outlives(lt) => {
+ self.print_lifetime(lt)?;
+ }
+ _ => bug!(),
+ }
if i != 0 {
self.s.word(":")?;
span: syntax_pos::DUMMY_SP,
};
self.print_fn(decl,
- unsafety,
- hir::Constness::NotConst,
- abi,
+ hir::FnHeader {
+ unsafety,
+ abi,
+ constness: hir::Constness::NotConst,
+ asyncness: hir::IsAsync::NotAsync,
+ },
name,
&generics,
&hir::Inherited,
}
pub fn print_fn_header_info(&mut self,
- unsafety: hir::Unsafety,
- constness: hir::Constness,
- abi: Abi,
+ header: hir::FnHeader,
vis: &hir::Visibility)
-> io::Result<()> {
self.s.word(&visibility_qualified(vis, ""))?;
- self.print_unsafety(unsafety)?;
- match constness {
+ match header.constness {
hir::Constness::NotConst => {}
hir::Constness::Const => self.word_nbsp("const")?,
}
- if abi != Abi::Rust {
+ match header.asyncness {
+ hir::IsAsync::NotAsync => {}
+ hir::IsAsync::Async => self.word_nbsp("async")?,
+ }
+
+ self.print_unsafety(header.unsafety)?;
+
+ if header.abi != Abi::Rust {
self.word_nbsp("extern")?;
- self.word_nbsp(&abi.to_string())?;
+ self.word_nbsp(&header.abi.to_string())?;
}
self.s.word("fn")
}
}
+impl_stable_hash_for!(enum hir::ParamName {
+ Plain(name),
+ Fresh(index)
+});
+
impl_stable_hash_for!(enum hir::LifetimeName {
+ Param(param_name),
Implicit,
Underscore,
- Fresh(index),
Static,
- Name(name)
});
impl_stable_hash_for!(struct hir::Label {
name
});
-impl_stable_hash_for!(struct hir::LifetimeDef {
- lifetime,
- bounds,
- pure_wrt_drop,
- in_band
-});
-
impl_stable_hash_for!(struct hir::Path {
span,
def,
impl_stable_hash_for!(struct hir::PathSegment {
name,
infer_types,
- parameters
+ args
+});
+
+impl_stable_hash_for!(enum hir::GenericArg {
+ Lifetime(lt),
+ Type(ty)
});
-impl_stable_hash_for!(struct hir::PathParameters {
- lifetimes,
- types,
+impl_stable_hash_for!(struct hir::GenericArgs {
+ args,
bindings,
parenthesized
});
-impl_stable_hash_for!(enum hir::TyParamBound {
- TraitTyParamBound(poly_trait_ref, trait_bound_modifier),
- RegionTyParamBound(lifetime)
+impl_stable_hash_for!(enum hir::GenericBound {
+ Trait(poly_trait_ref, trait_bound_modifier),
+ Outlives(lifetime)
});
impl_stable_hash_for!(enum hir::TraitBoundModifier {
Maybe
});
-impl_stable_hash_for!(struct hir::TyParam {
- name,
+impl_stable_hash_for!(struct hir::GenericParam {
id,
- bounds,
- default,
+ name,
span,
pure_wrt_drop,
- synthetic,
- attrs
+ attrs,
+ bounds,
+ kind
});
-impl_stable_hash_for!(enum hir::GenericParam {
- Lifetime(lifetime_def),
- Type(ty_param)
-});
+impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ hir::GenericParamKind::Lifetime { in_band } => {
+ in_band.hash_stable(hcx, hasher);
+ }
+ hir::GenericParamKind::Type { ref default, synthetic } => {
+ default.hash_stable(hcx, hasher);
+ synthetic.hash_stable(hcx, hasher);
+ }
+ }
+ }
+}
impl_stable_hash_for!(struct hir::Generics {
params,
});
impl_stable_hash_for!(struct hir::MethodSig {
- unsafety,
- constness,
- abi,
+ header,
decl
});
span
});
+impl_stable_hash_for!(struct hir::FnHeader {
+ unsafety,
+ constness,
+ asyncness,
+ abi
+});
+
impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
ExprPath(path),
ExprAddrOf(mutability, sub),
ExprBreak(destination, sub),
- ExprAgain(destination),
+ ExprContinue(destination),
ExprRet(val),
ExprInlineAsm(asm, inputs, outputs),
ExprStruct(path, fields, base),
ItemUse(path, use_kind),
ItemStatic(ty, mutability, body_id),
ItemConst(ty, body_id),
- ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
+ ItemFn(fn_decl, header, generics, body_id),
ItemMod(module),
ItemForeignMod(foreign_mod),
ItemGlobalAsm(global_asm),
Normal
});
+impl_stable_hash_for!(enum hir::IsAsync {
+ Async,
+ NotAsync
+});
impl_stable_hash_for!(enum hir::Constness {
Const,
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
call_site,
- callee
-});
-
-impl_stable_hash_for!(struct ::syntax_pos::hygiene::NameAndSpan {
+ def_site,
format,
allow_internal_unstable,
allow_internal_unsafe,
- edition,
- span
+ edition
});
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
});
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
+ Async,
DotFill,
QuestionMark,
ExistentialReturnType,
Proven, Ambiguous
});
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WhereClauseAtom<'tcx> {
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WhereClause<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
- use traits::WhereClauseAtom::*;
+ use traits::WhereClause::*;
mem::discriminant(self).hash_stable(hcx, hasher);
match self {
Implemented(trait_ref) => trait_ref.hash_stable(hcx, hasher),
ProjectionEq(projection) => projection.hash_stable(hcx, hasher),
+ TypeOutlives(ty_outlives) => ty_outlives.hash_stable(hcx, hasher),
+ RegionOutlives(region_outlives) => region_outlives.hash_stable(hcx, hasher),
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WellFormed<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::WellFormed::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Trait(trait_ref) => trait_ref.hash_stable(hcx, hasher),
+ Ty(ty) => ty.hash_stable(hcx, hasher),
+ }
+ }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::FromEnv<'tcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ use traits::FromEnv::*;
+
+ mem::discriminant(self).hash_stable(hcx, hasher);
+ match self {
+ Trait(trait_ref) => trait_ref.hash_stable(hcx, hasher),
+ Ty(ty) => ty.hash_stable(hcx, hasher),
}
}
}
mem::discriminant(self).hash_stable(hcx, hasher);
match self {
- Holds(where_clause) |
- WellFormed(where_clause) |
- FromEnv(where_clause) => where_clause.hash_stable(hcx, hasher),
-
- WellFormedTy(ty) => ty.hash_stable(hcx, hasher),
+ Holds(wc) => wc.hash_stable(hcx, hasher),
+ WellFormed(wf) => wf.hash_stable(hcx, hasher),
+ FromEnv(from_env) => from_env.hash_stable(hcx, hasher),
Normalize(projection) => projection.hash_stable(hcx, hasher),
- FromEnvTy(ty) => ty.hash_stable(hcx, hasher),
- RegionOutlives(predicate) => predicate.hash_stable(hcx, hasher),
- TypeOutlives(predicate) => predicate.hash_stable(hcx, hasher),
}
}
}
instantiated_ty: Ty<'gcx>,
) -> Ty<'gcx> {
debug!(
- "infer_anon_definition_from_instantiation(instantiated_ty={:?})",
- instantiated_ty
+ "infer_anon_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
+ def_id, instantiated_ty
);
let gcx = self.tcx.global_tcx();
//! For a more detailed look at what is happening here, check
//! out the [chapter in the rustc guide][c].
//!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html
+//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
use infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TypeVariableOrigin};
use rustc_data_structures::indexed_vec::Idx;
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#processing-the-canonicalized-query-result
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
pub fn instantiate_query_result<R>(
&self,
cause: &ObligationCause<'tcx>,
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#canonicalizing-the-query
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
pub fn canonicalize_query<V>(&self, value: &V) -> (V::Canonicalized, CanonicalVarValues<'tcx>)
where
V: Canonicalize<'gcx, 'tcx>,
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#canonicalizing-the-query-result
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
pub fn canonicalize_response<V>(
&self,
value: &V,
// Get the `hir::TyParam` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
- let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) {
- p.bounds.len() > 0
- } else {
- false
- };
+ let mut has_bounds = false;
+ if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
+ has_bounds = !param.bounds.is_empty();
+ }
let sp = hir.span(id);
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
- let sp = if has_lifetimes {
+ let sp = if has_bounds {
sp.to(self.tcx
.sess
.codemap()
} else {
sp
};
- (sp, has_lifetimes)
+ (sp, has_bounds)
})
} else {
None
/// For more information about how skolemization for HRTBs works, see
/// the [rustc guide].
///
- /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
+ /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>)
-> (T, SkolemizationMap<'tcx>)
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
## Terminology
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
## Terminology
"detects name collision with an existing but unstable method"
}
+declare_lint! {
+ pub IRREFUTABLE_LET_PATTERNS,
+ Deny,
+ "detects irrefutable patterns in if-let and while-let statements"
+}
+
declare_lint! {
pub UNUSED_LABELS,
Allow,
"warn about documentation intra links resolution failure"
}
+declare_lint! {
+ pub WHERE_CLAUSES_OBJECT_SAFETY,
+ Warn,
+ "checks the object safety of where clauses"
+}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
BARE_TRAIT_OBJECTS,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
+ IRREFUTABLE_LET_PATTERNS,
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
DUPLICATE_MACRO_EXPORTS,
INTRA_DOC_LINK_RESOLUTION_FAILURE,
+ WHERE_CLAUSES_OBJECT_SAFETY,
)
}
}
debug!("consume_body(body={:?})", body);
for arg in &body.arguments {
- let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.hir_id));
+ let arg_ty = return_if_err!(self.mc.pat_ty_adjusted(&arg.pat));
+ debug!("consume_body: arg_ty = {:?}", arg_ty);
let fn_body_scope_r =
self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id)));
self.consume_exprs(inputs);
}
- hir::ExprAgain(..) |
+ hir::ExprContinue(..) |
hir::ExprLit(..) => {}
hir::ExprLoop(ref blk, _, _) => {
hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) |
- hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) |
+ hir::ExprContinue(_) | hir::ExprLit(_) | hir::ExprRet(..) |
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprInlineAsm(..) | hir::ExprBox(..) | hir::ExprYield(..) |
}
}
- hir::ExprAgain(label) => {
+ hir::ExprContinue(label) => {
// Find which label this expr continues to
let sc = match label.target_id {
Ok(node_id) => node_id,
hir::ExprIndex(..) | hir::ExprField(..) |
hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprBinary(..) |
hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
- hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
+ hir::ExprBreak(..) | hir::ExprContinue(..) | hir::ExprLit(_) |
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprClosure(..) | hir::ExprPath(_) | hir::ExprYield(..) |
/// implicit deref patterns attached (e.g., it is really
/// `&Some(x)`). In that case, we return the "outermost" type
/// (e.g., `&Option<T>).
- fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
+ pub fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
// Check for implicit `&` types wrapping the pattern; note
// that these are never attached to binding patterns, so
// actually this is somewhat "disjoint" from the code below
hir::ExprBinary(..) | hir::ExprWhile(..) |
hir::ExprBlock(..) | hir::ExprLoop(..) | hir::ExprMatch(..) |
hir::ExprLit(..) | hir::ExprBreak(..) |
- hir::ExprAgain(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) |
+ hir::ExprContinue(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprInlineAsm(..) | hir::ExprBox(..) => {
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
}
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
- let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
+ let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
self.cat_pattern_(subcmt, &subpat, op)?;
};
for fp in field_pats {
- let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
+ let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
let f_index = self.tcx.field_index(fp.node.id, self.tables);
let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
fp.node.ident, field_ty));
ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
- let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
+ let subpat_ty = self.pat_ty_unadjusted(&subpat)?; // see (*2)
let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
self.cat_pattern_(subcmt, &subpat, op)?;
use hir::def::Def;
use hir::def_id::{DefId, CrateNum};
use rustc_data_structures::sync::Lrc;
-use ty::{self, TyCtxt};
+use ty::{self, TyCtxt, GenericParamDefKind};
use ty::query::Providers;
use middle::privacy;
use session::config;
// Returns true if the given set of generics implies that the item it's
// associated with must be inlined.
-fn generics_require_inlining(generics: &hir::Generics) -> bool {
- generics.params.iter().any(|param| param.is_type_param())
+fn generics_require_inlining(generics: &ty::Generics) -> bool {
+ for param in &generics.params {
+ match param.kind {
+ GenericParamDefKind::Lifetime { .. } => {}
+ GenericParamDefKind::Type { .. } => return true,
+ }
+ }
+ false
}
// Returns true if the given item must be inlined because it may be
// monomorphized or it was marked with `#[inline]`. This will only return
// true for functions.
-fn item_might_be_inlined(item: &hir::Item, attrs: CodegenFnAttrs) -> bool {
+fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ item: &hir::Item,
+ attrs: CodegenFnAttrs) -> bool {
if attrs.requests_inline() {
return true
}
match item.node {
- hir::ItemImpl(_, _, _, ref generics, ..) |
- hir::ItemFn(.., ref generics, _) => {
+ hir::ItemImpl(..) |
+ hir::ItemFn(..) => {
+ let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
generics_require_inlining(generics)
}
_ => false,
impl_item: &hir::ImplItem,
impl_src: DefId) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
- if codegen_fn_attrs.requests_inline() ||
- generics_require_inlining(&impl_item.generics) {
+ let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id));
+ if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) {
return true
}
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
match tcx.hir.find(impl_node_id) {
Some(hir_map::NodeItem(item)) =>
- item_might_be_inlined(&item, codegen_fn_attrs),
+ item_might_be_inlined(tcx, &item, codegen_fn_attrs),
Some(..) | None =>
span_bug!(impl_item.span, "impl did is not an item")
}
Some(hir_map::NodeItem(item)) => {
match item.node {
hir::ItemFn(..) =>
- item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)),
+ item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)),
_ => false,
}
}
hir::ImplItemKind::Const(..) => true,
hir::ImplItemKind::Method(..) => {
let attrs = self.tcx.codegen_fn_attrs(def_id);
- if generics_require_inlining(&impl_item.generics) ||
+ let generics = self.tcx.generics_of(def_id);
+ if generics_require_inlining(&generics) ||
attrs.requests_inline() {
true
} else {
// does too.
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
match self.tcx.hir.expect_item(impl_node_id).node {
- hir::ItemImpl(_, _, _, ref generics, ..) => {
- generics_require_inlining(generics)
+ hir::ItemImpl(..) => {
+ let generics = self.tcx.generics_of(impl_did);
+ generics_require_inlining(&generics)
}
_ => false
}
// If we are building an executable, only explicitly extern
// types need to be exported.
if let hir_map::NodeItem(item) = *node {
- let reachable = if let hir::ItemFn(.., abi, _, _) = item.node {
- abi != Abi::Rust
+ let reachable = if let hir::ItemFn(_, header, ..) = item.node {
+ header.abi != Abi::Rust
} else {
false
};
match item.node {
hir::ItemFn(.., body) => {
let def_id = self.tcx.hir.local_def_id(item.id);
- if item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)) {
+ if item_might_be_inlined(self.tcx,
+ &item,
+ self.tcx.codegen_fn_attrs(def_id)) {
self.visit_nested_body(body);
}
}
//! For more information about how MIR-based region-checking works,
//! see the [rustc guide].
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
use ich::{StableHashingContext, NodeIdHashingMode};
use util::nodemap::{FxHashMap, FxHashSet};
use hir::def::Def;
use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use hir::map::Map;
-use hir::ItemLocalId;
-use hir::LifetimeName;
+use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName};
use ty::{self, TyCtxt, GenericParamDefKind};
use errors::DiagnosticBuilder;
use session::Session;
use std::cell::Cell;
use std::mem::replace;
-use std::slice;
use syntax::ast;
use syntax::attr;
use syntax::ptr::P;
+use syntax::symbol::keywords;
use syntax_pos::Span;
use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet};
use hir::intravisit::{self, NestedVisitorMap, Visitor};
-use hir::{self, GenericParamsExt};
+use hir::{self, GenericParamKind};
/// The origin of a named lifetime definition.
///
}
impl LifetimeDefOrigin {
- fn from_is_in_band(is_in_band: bool) -> Self {
- if is_in_band {
- LifetimeDefOrigin::InBand
- } else {
- LifetimeDefOrigin::Explicit
+ fn from_param(param: &GenericParam) -> Self {
+ match param.kind {
+ GenericParamKind::Lifetime { in_band } => {
+ if in_band {
+ LifetimeDefOrigin::InBand
+ } else {
+ LifetimeDefOrigin::Explicit
+ }
+ }
+ _ => bug!("expected a lifetime param"),
}
}
}
}
impl Region {
- fn early(
- hir_map: &Map,
- index: &mut u32,
- def: &hir::LifetimeDef,
- ) -> (hir::LifetimeName, Region) {
+ fn early(hir_map: &Map, index: &mut u32, param: &GenericParam) -> (ParamName, Region) {
let i = *index;
*index += 1;
- let def_id = hir_map.local_def_id(def.lifetime.id);
- let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
+ let def_id = hir_map.local_def_id(param.id);
+ let origin = LifetimeDefOrigin::from_param(param);
debug!("Region::early: index={} def_id={:?}", i, def_id);
- (def.lifetime.name, Region::EarlyBound(i, def_id, origin))
+ (param.name, Region::EarlyBound(i, def_id, origin))
}
- fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
+ fn late(hir_map: &Map, param: &GenericParam) -> (ParamName, Region) {
let depth = ty::INNERMOST;
- let def_id = hir_map.local_def_id(def.lifetime.id);
- let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
+ let def_id = hir_map.local_def_id(param.id);
+ let origin = LifetimeDefOrigin::from_param(param);
debug!(
- "Region::late: def={:?} depth={:?} def_id={:?} origin={:?}",
- def,
+ "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
+ param,
depth,
def_id,
origin,
);
- (def.lifetime.name, Region::LateBound(depth, def_id, origin))
+ (param.name, Region::LateBound(depth, def_id, origin))
}
fn late_anon(index: &Cell<u32>) -> Region {
}
}
- fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) -> Option<Region> {
+ fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option<Region>
+ where L: Iterator<Item = &'a hir::Lifetime> {
if let Region::EarlyBound(index, _, _) = self {
- params
- .get(index as usize)
- .and_then(|lifetime| map.defs.get(&lifetime.id).cloned())
+ params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.id).cloned())
} else {
Some(self)
}
/// it should be shifted by the number of `Binder`s in between the
/// declaration `Binder` and the location it's referenced from.
Binder {
- lifetimes: FxHashMap<hir::LifetimeName, Region>,
+ lifetimes: FxHashMap<hir::ParamName, Region>,
/// if we extend this scope with another scope, what is the next index
/// we should use for an early-bound region?
fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node {
- hir::ItemFn(ref decl, _, _, _, ref generics, _) => {
+ hir::ItemFn(ref decl, _, ref generics, _) => {
self.visit_early_late(None, decl, generics, |this| {
intravisit::walk_item(this, item);
});
} else {
0
};
- let lifetimes = generics
- .lifetimes()
- .map(|def| Region::early(&self.tcx.hir, &mut index, def))
- .collect();
- let next_early_index = index + generics.ty_params().count() as u32;
+ let mut type_count = 0;
+ let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ type_count += 1;
+ None
+ }
+ }).collect();
let scope = Scope::Binder {
lifetimes,
- next_early_index,
+ next_early_index: index + type_count,
abstract_type_parent: true,
track_lifetime_uses,
s: ROOT_SCOPE,
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
let scope = Scope::Binder {
- lifetimes: c.generic_params
- .lifetimes()
- .map(|def| Region::late(&self.tcx.hir, def))
- .collect(),
+ lifetimes: c.generic_params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::late(&self.tcx.hir, param))
+ }
+ _ => None,
+ }).collect(),
s: self.scope,
next_early_index,
track_lifetime_uses: true,
// resolved the same as the `'_` in `&'_ Foo`.
//
// cc #48468
- self.resolve_elided_lifetimes(slice::from_ref(lifetime), false)
+ self.resolve_elided_lifetimes(vec![lifetime], false)
}
- LifetimeName::Fresh(_) | LifetimeName::Static | LifetimeName::Name(_) => {
+ LifetimeName::Param(_) | LifetimeName::Static => {
// If the user wrote an explicit name, use that.
self.visit_lifetime(lifetime);
}
// and ban them. Type variables instantiated inside binders aren't
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
- let def = self.map.defs.get(&lifetime.id);
- if let Some(&Region::LateBound(_, def_id, _)) = def {
+ let def = self.map.defs.get(&lifetime.id).cloned();
+ if let Some(Region::LateBound(_, def_id, _)) = def {
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.tcx.hir.get_parent_node(node_id);
"`impl Trait` can only capture lifetimes \
bound at the fn or impl level"
);
+ self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
}
}
let mut elision = None;
let mut lifetimes = FxHashMap();
- for lt_def in generics.lifetimes() {
- let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, <_def);
- if let hir::LifetimeName::Underscore = lt_name {
- // Pick the elided lifetime "definition" if one exists and use it to make
- // an elision scope.
- elision = Some(region);
- } else {
- lifetimes.insert(lt_name, region);
+ let mut type_count = 0;
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m);
+ if let hir::ParamName::Plain(param_name) = name {
+ if param_name == keywords::UnderscoreLifetime.name() {
+ // Pick the elided lifetime "definition" if one exists
+ // and use it to make an elision scope.
+ elision = Some(reg);
+ } else {
+ lifetimes.insert(name, reg);
+ }
+ } else {
+ lifetimes.insert(name, reg);
+ }
+ }
+ GenericParamKind::Type { .. } => {
+ type_count += 1;
+ }
}
}
-
- let next_early_index = index + generics.ty_params().count() as u32;
+ let next_early_index = index + type_count;
if let Some(elision_region) = elision {
let scope = Scope::Elision {
this.with(scope, |_old_scope, this| {
this.visit_generics(generics);
for bound in bounds {
- this.visit_ty_param_bound(bound);
+ this.visit_param_bound(bound);
}
});
});
self.with(scope, |_old_scope, this| {
this.visit_generics(generics);
for bound in bounds {
- this.visit_ty_param_bound(bound);
+ this.visit_param_bound(bound);
}
});
}
let generics = &trait_item.generics;
let mut index = self.next_early_index();
debug!("visit_ty: index = {}", index);
- let lifetimes = generics
- .lifetimes()
- .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
- .collect();
-
- let next_early_index = index + generics.ty_params().count() as u32;
+ let mut type_count = 0;
+ let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ type_count += 1;
+ None
+ }
+ }).collect();
let scope = Scope::Binder {
lifetimes,
- next_early_index,
+ next_early_index: index + type_count,
s: self.scope,
track_lifetime_uses: true,
abstract_type_parent: true,
self.with(scope, |_old_scope, this| {
this.visit_generics(generics);
for bound in bounds {
- this.visit_ty_param_bound(bound);
+ this.visit_param_bound(bound);
}
if let Some(ty) = ty {
this.visit_ty(ty);
Type(ref ty) => {
let generics = &impl_item.generics;
let mut index = self.next_early_index();
+ let mut next_early_index = index;
debug!("visit_ty: index = {}", index);
- let lifetimes = generics
- .lifetimes()
- .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
- .collect();
-
- let next_early_index = index + generics.ty_params().count() as u32;
+ let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ None
+ }
+ }).collect();
let scope = Scope::Binder {
lifetimes,
next_early_index,
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if lifetime_ref.is_elided() {
- self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false);
+ self.resolve_elided_lifetimes(vec![lifetime_ref], false);
return;
}
if lifetime_ref.is_static() {
fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
- if let Some(ref parameters) = segment.parameters {
- self.visit_segment_parameters(path.def, depth, parameters);
+ if let Some(ref args) = segment.args {
+ self.visit_segment_args(path.def, depth, args);
}
}
}
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
- check_mixed_explicit_and_in_band_defs(
- self.tcx,
- &generics.lifetimes().cloned().collect::<Vec<_>>(),
- );
- for ty_param in generics.ty_params() {
- walk_list!(self, visit_ty_param_bound, &ty_param.bounds);
- if let Some(ref ty) = ty_param.default {
- self.visit_ty(&ty);
+ check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { ref default, .. } => {
+ walk_list!(self, visit_param_bound, ¶m.bounds);
+ if let Some(ref ty) = default {
+ self.visit_ty(&ty);
+ }
+ }
}
}
for predicate in &generics.where_clause.predicates {
ref bound_generic_params,
..
}) => {
- if bound_generic_params.iter().any(|p| p.is_lifetime_param()) {
+ let lifetimes: FxHashMap<_, _> = bound_generic_params.iter()
+ .filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::late(&self.tcx.hir, param))
+ }
+ _ => None,
+ }).collect();
+ if !lifetimes.is_empty() {
self.trait_ref_hack = true;
let next_early_index = self.next_early_index();
let scope = Scope::Binder {
- lifetimes: bound_generic_params
- .lifetimes()
- .map(|def| Region::late(&self.tcx.hir, def))
- .collect(),
+ lifetimes,
s: self.scope,
next_early_index,
track_lifetime_uses: true,
let result = self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
this.visit_ty(&bounded_ty);
- walk_list!(this, visit_ty_param_bound, bounds);
+ walk_list!(this, visit_param_bound, bounds);
});
self.trait_ref_hack = false;
result
} else {
self.visit_ty(&bounded_ty);
- walk_list!(self, visit_ty_param_bound, bounds);
+ walk_list!(self, visit_param_bound, bounds);
}
}
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
..
}) => {
self.visit_lifetime(lifetime);
- for bound in bounds {
- self.visit_lifetime(bound);
- }
+ walk_list!(self, visit_param_bound, bounds);
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
ref lhs_ty,
|| trait_ref
.bound_generic_params
.iter()
- .any(|p| p.is_lifetime_param())
+ .any(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => true,
+ _ => false,
+ })
{
if self.trait_ref_hack {
span_err!(
}
let next_early_index = self.next_early_index();
let scope = Scope::Binder {
- lifetimes: trait_ref
- .bound_generic_params
- .lifetimes()
- .map(|def| Region::late(&self.tcx.hir, def))
- .collect(),
+ lifetimes: trait_ref.bound_generic_params.iter()
+ .filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::late(&self.tcx.hir, param))
+ }
+ _ => None,
+ }).collect(),
s: self.scope,
next_early_index,
track_lifetime_uses: true,
span: span,
}
}
-fn shadower_lifetime(l: &hir::Lifetime) -> Shadower {
+fn shadower_lifetime(param: &hir::GenericParam) -> Shadower {
Shadower {
kind: ShadowKind::Lifetime,
- span: l.span,
+ span: param.span,
}
}
fn check_mixed_explicit_and_in_band_defs(
tcx: TyCtxt<'_, '_, '_>,
- lifetime_defs: &[hir::LifetimeDef],
+ params: &P<[hir::GenericParam]>,
) {
- let oob_def = lifetime_defs.iter().find(|lt| !lt.in_band);
- let in_band_def = lifetime_defs.iter().find(|lt| lt.in_band);
-
- if let (Some(oob_def), Some(in_band_def)) = (oob_def, in_band_def) {
+ let in_bands: Vec<_> = params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { in_band, .. } => Some((in_band, param.span)),
+ _ => None,
+ }).collect();
+ let out_of_band = in_bands.iter().find(|(in_band, _)| !in_band);
+ let in_band = in_bands.iter().find(|(in_band, _)| *in_band);
+
+ if let (Some((_, out_of_band_span)), Some((_, in_band_span)))
+ = (out_of_band, in_band) {
struct_span_err!(
tcx.sess,
- in_band_def.lifetime.span,
+ *in_band_span,
E0688,
"cannot mix in-band and explicit lifetime definitions"
).span_label(
- in_band_def.lifetime.span,
+ *in_band_span,
"in-band lifetime definition here",
- )
- .span_label(oob_def.lifetime.span, "explicit lifetime definition here")
- .emit();
+ ).span_label(*out_of_band_span, "explicit lifetime definition here")
+ .emit();
}
}
ref lifetimes, s, ..
} => {
// FIXME (#24278): non-hygienic comparison
- if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
+ let param_name = hir::ParamName::Plain(label);
+ if let Some(def) = lifetimes.get(¶m_name) {
let node_id = tcx.hir.as_local_node_id(def.id().unwrap()).unwrap();
signal_shadowing_problem(
.map(|set| match *set {
Set1::Empty => "BaseDefault".to_string(),
Set1::One(Region::Static) => "'static".to_string(),
- Set1::One(Region::EarlyBound(i, _, _)) => generics
- .lifetimes()
- .nth(i as usize)
- .unwrap()
- .lifetime
- .name
- .name()
- .to_string(),
+ Set1::One(Region::EarlyBound(mut i, _, _)) => {
+ generics.params.iter().find_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ if i == 0 {
+ return Some(param.name.name().to_string());
+ }
+ i -= 1;
+ None
+ }
+ _ => None,
+ }).unwrap()
+ }
Set1::One(_) => bug!(),
Set1::Many => "Ambiguous".to_string(),
})
tcx: TyCtxt<'_, '_, '_>,
generics: &hir::Generics,
) -> Vec<ObjectLifetimeDefault> {
- fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) {
+ fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound]) {
for bound in bounds {
- if let hir::RegionTyParamBound(ref lifetime) = *bound {
+ if let hir::GenericBound::Outlives(ref lifetime) = *bound {
set.insert(lifetime.name);
}
}
}
- generics
- .ty_params()
- .map(|param| {
+ generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => None,
+ GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
add_bounds(&mut set, ¶m.bounds);
}
}
- match set {
+ Some(match set {
Set1::Empty => Set1::Empty,
Set1::One(name) => {
if name == hir::LifetimeName::Static {
Set1::One(Region::Static)
} else {
- generics
- .lifetimes()
- .enumerate()
- .find(|&(_, def)| def.lifetime.name == name)
- .map_or(Set1::Many, |(i, def)| {
- let def_id = tcx.hir.local_def_id(def.lifetime.id);
- let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
- Set1::One(Region::EarlyBound(i as u32, def_id, origin))
- })
+ generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some((
+ param.id,
+ hir::LifetimeName::Param(param.name),
+ LifetimeDefOrigin::from_param(param),
+ ))
+ }
+ _ => None,
+ })
+ .enumerate()
+ .find(|&(_, (_, lt_name, _))| lt_name == name)
+ .map_or(Set1::Many, |(i, (id, _, origin))| {
+ let def_id = tcx.hir.local_def_id(id);
+ Set1::One(Region::EarlyBound(i as u32, def_id, origin))
+ })
}
}
Set1::Many => Set1::Many,
- }
- })
- .collect()
+ })
+ }
+ })
+ .collect()
}
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
lifetimeuseset
);
match lifetimeuseset {
- Some(LifetimeUseSet::One(_)) => {
+ Some(LifetimeUseSet::One(lifetime)) => {
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
debug!("node id first={:?}", node_id);
- if let hir::map::NodeLifetime(hir_lifetime) = self.tcx.hir.get(node_id) {
- let span = hir_lifetime.span;
- let id = hir_lifetime.id;
- debug!(
- "id ={:?} span = {:?} hir_lifetime = {:?}",
- node_id, span, hir_lifetime
+ if let Some((id, span, name)) = match self.tcx.hir.get(node_id) {
+ hir::map::NodeLifetime(hir_lifetime) => {
+ Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.name()))
+ }
+ hir::map::NodeGenericParam(param) => {
+ Some((param.id, param.span, param.name.name()))
+ }
+ _ => None,
+ } {
+ debug!("id = {:?} span = {:?} name = {:?}", node_id, span, name);
+ let mut err = self.tcx.struct_span_lint_node(
+ lint::builtin::SINGLE_USE_LIFETIMES,
+ id,
+ span,
+ &format!("lifetime parameter `{}` only used once", name),
);
-
- self.tcx
- .struct_span_lint_node(
- lint::builtin::SINGLE_USE_LIFETIMES,
- id,
- span,
- &format!(
- "lifetime parameter `{}` only used once",
- hir_lifetime.name.name()
- ),
- )
- .emit();
+ err.span_label(span, "this lifetime...");
+ err.span_label(lifetime.span, "...is used only here");
+ err.emit();
}
}
Some(LifetimeUseSet::Many) => {
}
None => {
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
- if let hir::map::NodeLifetime(hir_lifetime) = self.tcx.hir.get(node_id) {
- let span = hir_lifetime.span;
- let id = hir_lifetime.id;
-
- self.tcx
- .struct_span_lint_node(
- lint::builtin::UNUSED_LIFETIMES,
- id,
- span,
- &format!(
- "lifetime parameter `{}` never used",
- hir_lifetime.name.name()
- ),
- )
- .emit();
+ if let Some((id, span, name)) = match self.tcx.hir.get(node_id) {
+ hir::map::NodeLifetime(hir_lifetime) => {
+ Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.name()))
+ }
+ hir::map::NodeGenericParam(param) => {
+ Some((param.id, param.span, param.name.name()))
+ }
+ _ => None,
+ } {
+ debug!("id ={:?} span = {:?} name = {:?}", node_id, span, name);
+ self.tcx.struct_span_lint_node(
+ lint::builtin::UNUSED_LIFETIMES,
+ id,
+ span,
+ &format!("lifetime parameter `{}` never used", name)
+ ).emit();
}
}
}
}
}
- let lifetimes = generics
- .lifetimes()
- .map(|def| {
- if self.map.late_bound.contains(&def.lifetime.id) {
- Region::late(&self.tcx.hir, def)
+ let mut type_count = 0;
+ let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ if self.map.late_bound.contains(¶m.id) {
+ Some(Region::late(&self.tcx.hir, param))
} else {
- Region::early(&self.tcx.hir, &mut index, def)
+ Some(Region::early(&self.tcx.hir, &mut index, param))
}
- })
- .collect();
-
- let next_early_index = index + generics.ty_params().count() as u32;
+ }
+ GenericParamKind::Type { .. } => {
+ type_count += 1;
+ None
+ }
+ }).collect();
+ let next_early_index = index + type_count;
let scope = Scope::Binder {
lifetimes,
break None;
}
- Scope::Binder {
- ref lifetimes, s, ..
- } => {
- if let Some(&def) = lifetimes.get(&lifetime_ref.name) {
+ Scope::Binder { ref lifetimes, s, .. } => {
+ let name = match lifetime_ref.name {
+ LifetimeName::Param(param_name) => param_name,
+ _ => bug!("expected LifetimeName::Param"),
+ };
+ if let Some(&def) = lifetimes.get(&name) {
break Some(def.shifted(late_depth));
} else {
late_depth += 1;
}
}
- fn visit_segment_parameters(
+ fn visit_segment_args(
&mut self,
def: Def,
depth: usize,
- params: &'tcx hir::PathParameters,
+ generic_args: &'tcx hir::GenericArgs,
) {
- if params.parenthesized {
+ if generic_args.parenthesized {
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
- self.visit_fn_like_elision(params.inputs(), Some(¶ms.bindings[0].ty));
+ self.visit_fn_like_elision(generic_args.inputs(),
+ Some(&generic_args.bindings[0].ty));
self.is_in_fn_syntax = was_in_fn_syntax;
return;
}
- if params.lifetimes.iter().all(|l| l.is_elided()) {
- self.resolve_elided_lifetimes(¶ms.lifetimes, true);
- } else {
- for l in ¶ms.lifetimes {
- self.visit_lifetime(l);
+ let mut elide_lifetimes = true;
+ let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
+ hir::GenericArg::Lifetime(lt) => {
+ if !lt.is_elided() {
+ elide_lifetimes = false;
+ }
+ Some(lt)
}
+ _ => None,
+ }).collect();
+ if elide_lifetimes {
+ self.resolve_elided_lifetimes(lifetimes, true);
+ } else {
+ lifetimes.iter().for_each(|lt| self.visit_lifetime(lt));
}
// Figure out if this is a type/trait segment,
}).collect()
})
};
- unsubst
- .iter()
- .map(|set| match *set {
- Set1::Empty => if in_body {
- None
- } else {
- Some(Region::Static)
- },
- Set1::One(r) => r.subst(¶ms.lifetimes, map),
- Set1::Many => None,
- })
- .collect()
+ unsubst.iter()
+ .map(|set| match *set {
+ Set1::Empty => if in_body {
+ None
+ } else {
+ Some(Region::Static)
+ },
+ Set1::One(r) => {
+ let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
+ GenericArg::Lifetime(lt) => Some(lt),
+ _ => None,
+ });
+ r.subst(lifetimes, map)
+ }
+ Set1::Many => None,
+ })
+ .collect()
});
- for (i, ty) in params.types.iter().enumerate() {
- if let Some(<) = object_lifetime_defaults.get(i) {
- let scope = Scope::ObjectLifetimeDefault {
- lifetime: lt,
- s: self.scope,
- };
- self.with(scope, |_, this| this.visit_ty(ty));
- } else {
- self.visit_ty(ty);
+ let mut i = 0;
+ for arg in &generic_args.args {
+ match arg {
+ GenericArg::Lifetime(_) => {}
+ GenericArg::Type(ty) => {
+ if let Some(<) = object_lifetime_defaults.get(i) {
+ let scope = Scope::ObjectLifetimeDefault {
+ lifetime: lt,
+ s: self.scope,
+ };
+ self.with(scope, |_, this| this.visit_ty(ty));
+ } else {
+ self.visit_ty(ty);
+ }
+ i += 1;
+ }
}
}
- for b in ¶ms.bindings {
+ for b in &generic_args.bindings {
self.visit_assoc_type_binding(b);
}
}
}
fn visit_generic_param(&mut self, param: &hir::GenericParam) {
- if let hir::GenericParam::Lifetime(_) = *param {
+ if let hir::GenericParamKind::Lifetime { .. } = param.kind {
// FIXME(eddyb) Do we want this? It only makes a difference
// if this `for<'a>` lifetime parameter is never used.
self.have_bound_regions = true;
}
}
- fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) {
+ fn resolve_elided_lifetimes(&mut self,
+ lifetime_refs: Vec<&'tcx hir::Lifetime>,
+ deprecated: bool) {
if lifetime_refs.is_empty() {
return;
}
}
fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
- for (i, lifetime_i) in params.lifetimes().enumerate() {
- match lifetime_i.lifetime.name {
- hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
- let lifetime = lifetime_i.lifetime;
- let name = lifetime.name.name();
+ let lifetimes: Vec<_> = params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => Some((param, param.name)),
+ _ => None,
+ }).collect();
+ for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() {
+ if let hir::ParamName::Plain(_) = lifetime_i_name {
+ let name = lifetime_i_name.name();
+ if name == keywords::UnderscoreLifetime.name() ||
+ name == keywords::StaticLifetime.name() {
let mut err = struct_span_err!(
self.tcx.sess,
- lifetime.span,
+ lifetime_i.span,
E0262,
"invalid lifetime parameter name: `{}`",
name
);
err.span_label(
- lifetime.span,
+ lifetime_i.span,
format!("{} is a reserved lifetime name", name),
);
err.emit();
}
- hir::LifetimeName::Fresh(_)
- | hir::LifetimeName::Implicit
- | hir::LifetimeName::Name(_) => {}
}
// It is a hard error to shadow a lifetime within the same scope.
- for lifetime_j in params.lifetimes().skip(i + 1) {
- if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
+ for (lifetime_j, lifetime_j_name) in lifetimes.iter().skip(i + 1) {
+ if lifetime_i_name == lifetime_j_name {
struct_span_err!(
self.tcx.sess,
- lifetime_j.lifetime.span,
+ lifetime_j.span,
E0263,
"lifetime name `{}` declared twice in the same scope",
- lifetime_j.lifetime.name.name()
- ).span_label(lifetime_j.lifetime.span, "declared twice")
- .span_label(lifetime_i.lifetime.span, "previous declaration here")
- .emit();
+ lifetime_j.name.name()
+ ).span_label(lifetime_j.span, "declared twice")
+ .span_label(lifetime_i.span, "previous declaration here")
+ .emit();
}
}
// It is a soft error to shadow a lifetime within a parent scope.
- self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
+ self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i);
for bound in &lifetime_i.bounds {
- match bound.name {
- hir::LifetimeName::Underscore => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- bound.span,
- E0637,
- "invalid lifetime bound name: `'_`"
- );
- err.span_label(bound.span, "`'_` is a reserved lifetime name");
- err.emit();
- }
- hir::LifetimeName::Static => {
- self.insert_lifetime(bound, Region::Static);
- self.tcx
- .sess
- .struct_span_warn(
- lifetime_i.lifetime.span.to(bound.span),
+ match bound {
+ hir::GenericBound::Outlives(lt) => match lt.name {
+ hir::LifetimeName::Underscore => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ lt.span,
+ E0637,
+ "invalid lifetime bound name: `'_`"
+ );
+ err.span_label(lt.span, "`'_` is a reserved lifetime name");
+ err.emit();
+ }
+ hir::LifetimeName::Static => {
+ self.insert_lifetime(lt, Region::Static);
+ self.tcx.sess.struct_span_warn(
+ lifetime_i.span.to(lt.span),
&format!(
"unnecessary lifetime parameter `{}`",
- lifetime_i.lifetime.name.name()
+ lifetime_i.name.name(),
),
- )
- .help(&format!(
+ ).help(&format!(
"you can use the `'static` lifetime directly, in place \
- of `{}`",
- lifetime_i.lifetime.name.name()
- ))
- .emit();
- }
- hir::LifetimeName::Fresh(_)
- | hir::LifetimeName::Implicit
- | hir::LifetimeName::Name(_) => {
- self.resolve_lifetime_ref(bound);
+ of `{}`",
+ lifetime_i.name.name(),
+ )).emit();
+ }
+ hir::LifetimeName::Param(_)
+ | hir::LifetimeName::Implicit => {
+ self.resolve_lifetime_ref(lt);
+ }
}
+ _ => bug!(),
}
}
}
}
- fn check_lifetime_def_for_shadowing(
+ fn check_lifetime_param_for_shadowing(
&self,
mut old_scope: ScopeRef,
- lifetime: &'tcx hir::Lifetime,
+ param: &'tcx hir::GenericParam,
) {
for &(label, label_span) in &self.labels_in_fn {
// FIXME (#24278): non-hygienic comparison
- if lifetime.name.name() == label {
+ if param.name.name() == label {
signal_shadowing_problem(
self.tcx,
label,
original_label(label_span),
- shadower_lifetime(&lifetime),
+ shadower_lifetime(¶m),
);
return;
}
Scope::Binder {
ref lifetimes, s, ..
} => {
- if let Some(&def) = lifetimes.get(&lifetime.name) {
+ if let Some(&def) = lifetimes.get(¶m.name) {
let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap();
signal_shadowing_problem(
self.tcx,
- lifetime.name.name(),
+ param.name.name(),
original_lifetime(self.tcx.hir.span(node_id)),
- shadower_lifetime(&lifetime),
+ shadower_lifetime(¶m),
);
return;
}
}
}
}
+
+ /// Sometimes we resolve a lifetime, but later find that it is an
+ /// error (esp. around impl trait). In that case, we remove the
+ /// entry into `map.defs` so as not to confuse later code.
+ fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
+ let old_value = self.map.defs.remove(&lifetime_ref.id);
+ assert_eq!(old_value, Some(bad_def));
+ }
}
///////////////////////////////////////////////////////////////////////////
appears_in_where_clause.visit_generics(generics);
for param in &generics.params {
- match *param {
- hir::GenericParam::Lifetime(ref lifetime_def) => {
- if !lifetime_def.bounds.is_empty() {
+ match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {
+ if !param.bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced
- appears_in_where_clause.regions.insert(lifetime_def.lifetime.name);
+ appears_in_where_clause.regions.insert(hir::LifetimeName::Param(param.name));
}
}
- hir::GenericParam::Type(_) => {}
+ hir::GenericParamKind::Type { .. } => {}
}
}
// - appear in the inputs
// - do not appear in the where-clauses
// - are not implicitly captured by `impl Trait`
- for lifetime in generics.lifetimes() {
- let name = lifetime.lifetime.name;
-
+ for param in &generics.params {
+ let lt_name = hir::LifetimeName::Param(param.name);
// appears in the where clauses? early-bound.
- if appears_in_where_clause.regions.contains(&name) {
+ if appears_in_where_clause.regions.contains(<_name) {
continue;
}
// does not appear in the inputs, but appears in the return type? early-bound.
- if !constrained_by_input.regions.contains(&name)
- && appears_in_output.regions.contains(&name)
+ if !constrained_by_input.regions.contains(<_name)
+ && appears_in_output.regions.contains(<_name)
{
continue;
}
- debug!(
- "insert_late_bound_lifetimes: \
- lifetime {:?} with id {:?} is late-bound",
- lifetime.lifetime.name, lifetime.lifetime.id
- );
+ debug!("insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound",
+ param.name.name(),
+ param.id);
- let inserted = map.late_bound.insert(lifetime.lifetime.id);
- assert!(
- inserted,
- "visited lifetime {:?} twice",
- lifetime.lifetime.id
- );
+ let inserted = map.late_bound.insert(param.id);
+ assert!(inserted, "visited lifetime {:?} twice", param.id);
}
return;
debug!("stability: \
inspecting def_id={:?} span={:?} of stability={:?}", def_id, span, stability);
- if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, .. }), ..})
+ if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..})
= stability {
if let Some(id) = id {
- lint_deprecated(def_id, id, Some(reason));
+ if deprecation_in_effect(&since.as_str()) {
+ lint_deprecated(def_id, id, Some(reason));
+ }
}
}
//! MIR datatypes and passes. See the [rustc guide] for more info.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html
use graphviz::IntoCow;
use hir::def::CtorKind;
let names_map: FxHashSet<String> = generics
.params
.iter()
- .filter_map(|param| {
- match param.kind {
- ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
- _ => None
- }
+ .filter_map(|param| match param.kind {
+ ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
+ _ => None
})
.collect();
//! See rustc guide chapters on [trait-resolution] and [trait-specialization] for more info on how
//! this works.
//!
-//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html
-//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/trait-specialization.html
+//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
+//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
use hir::def_id::{DefId, LOCAL_CRATE};
use syntax_pos::DUMMY_SP;
}
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
- let desugaring = k.as_symbol().as_str();
flags.push(("from_desugaring".to_string(), None));
- flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
+ flags.push(("from_desugaring".to_string(), Some(k.name().to_string())));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
//! Trait Resolution. See [rustc guide] for more info on how this works.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
pub use self::SelectionError::*;
pub use self::FulfillmentErrorCode::*;
pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
/// The following types:
-/// * `WhereClauseAtom`
+/// * `WhereClause`
+/// * `WellFormed`
+/// * `FromEnv`
/// * `DomainGoal`
/// * `Goal`
/// * `Clause`
/// logic programming clauses. They are part of the interface
/// for the chalk SLG solver.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
-pub enum WhereClauseAtom<'tcx> {
+pub enum WhereClause<'tcx> {
Implemented(ty::TraitPredicate<'tcx>),
ProjectionEq(ty::ProjectionPredicate<'tcx>),
+ RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
+ TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum WellFormed<'tcx> {
+ Trait(ty::TraitPredicate<'tcx>),
+ Ty(Ty<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum FromEnv<'tcx> {
+ Trait(ty::TraitPredicate<'tcx>),
+ Ty(Ty<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum DomainGoal<'tcx> {
- Holds(WhereClauseAtom<'tcx>),
- WellFormed(WhereClauseAtom<'tcx>),
- FromEnv(WhereClauseAtom<'tcx>),
- WellFormedTy(Ty<'tcx>),
+ Holds(WhereClause<'tcx>),
+ WellFormed(WellFormed<'tcx>),
+ FromEnv(FromEnv<'tcx>),
Normalize(ty::ProjectionPredicate<'tcx>),
- FromEnvTy(Ty<'tcx>),
- RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
- TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
}
pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>;
pub type Goals<'tcx> = &'tcx Slice<Goal<'tcx>>;
+impl<'tcx> DomainGoal<'tcx> {
+ pub fn into_goal(self) -> Goal<'tcx> {
+ Goal::DomainGoal(self)
+ }
+}
+
impl<'tcx> Goal<'tcx> {
pub fn from_poly_domain_goal<'a>(
domain_goal: PolyDomainGoal<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
) -> Goal<'tcx> {
match domain_goal.no_late_bound_regions() {
- Some(p) => p.into(),
+ Some(p) => p.into_goal(),
None => Goal::Quantified(
QuantifierKind::Universal,
- domain_goal.map_bound(|p| tcx.mk_goal(Goal::from(p)))
+ domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal()))
),
}
}
}
-impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
- fn from(domain_goal: DomainGoal<'tcx>) -> Self {
- Goal::DomainGoal(domain_goal)
- }
-}
-
/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
/// Harrop Formulas".
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
use super::elaborate_predicates;
use hir::def_id::DefId;
+use lint;
use traits;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::subst::Substs;
use ty::util::ExplicitSelf;
use std::borrow::Cow;
use syntax::ast;
+use syntax_pos::Span;
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObjectSafetyViolation {
/// Self : Sized declared on the trait
SizedSelf,
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
format!("method `{}` references the `Self` type \
in its arguments or return type", name).into(),
+ ObjectSafetyViolation::Method(name,
+ MethodViolationCode::WhereClauseReferencesSelf(_)) =>
+ format!("method `{}` references the `Self` type in where clauses", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
format!("method `{}` has generic type parameters", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::NonStandardSelfType) =>
/// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
ReferencesSelf,
+ /// e.g. `fn foo(&self) where Self: Clone`
+ WhereClauseReferencesSelf(Span),
+
/// e.g., `fn foo<A>()`
Generic,
.filter_map(|item| {
self.object_safety_violation_for_method(trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.name, code))
+ }).filter(|violation| {
+ if let ObjectSafetyViolation::Method(_,
+ MethodViolationCode::WhereClauseReferencesSelf(span)) = violation {
+ // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
+ // It's also hard to get a use site span, so we use the method definition span.
+ self.lint_node_note(
+ lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
+ ast::CRATE_NODE_ID,
+ *span,
+ &format!("the trait `{}` cannot be made into an object",
+ self.item_path_str(trait_def_id)),
+ &violation.error_msg());
+ false
+ } else {
+ true
+ }
}).collect();
// Check the trait itself.
return false;
}
- self.virtual_call_violation_for_method(trait_def_id, method).is_none()
+ match self.virtual_call_violation_for_method(trait_def_id, method) {
+ None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
+ Some(_) => false,
+ }
}
/// Returns `Some(_)` if this method cannot be called on a trait
return Some(MethodViolationCode::Generic);
}
+ if self.predicates_of(method.def_id).predicates.into_iter()
+ // A trait object can't claim to live more than the concrete type,
+ // so outlives predicates will always hold.
+ .filter(|p| p.to_opt_type_outlives().is_none())
+ .collect::<Vec<_>>()
+ // Do a shallow visit so that `contains_illegal_self_type_reference`
+ // may apply it's custom visiting.
+ .visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) {
+ let span = self.def_span(method.def_id);
+ return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
+ }
+
None
}
//! See [rustc guide] for more info on how this works.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#selection
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection
use self::SelectionCandidate::*;
use self::EvaluationResult::*;
// candidates. See [rustc guide] for more details.
//
// [rustc guide]:
- // https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#candidate-assembly
+ // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly
fn candidate_from_obligation<'o>(&mut self,
stack: &TraitObligationStack<'o, 'tcx>)
// type error. See [rustc guide] for more details.
//
// [rustc guide]:
- // https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#confirmation
+ // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation
fn confirm_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
//! See the [rustc guide] for a bit more detail on how specialization
//! fits together with the rest of the trait machinery.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-specialization.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
use super::{SelectionContext, FulfillmentContext};
use super::util::impl_trait_ref_and_oblig;
} where T: TypeFoldable<'tcx>
}
-impl<'tcx> fmt::Display for traits::WhereClauseAtom<'tcx> {
+impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- use traits::WhereClauseAtom::*;
+ use traits::WhereClause::*;
match self {
Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+ RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
+ TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::WellFormed::*;
+
+ match self {
+ Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
+ Ty(ty) => write!(fmt, "WellFormed({})", ty),
+ }
+ }
+}
+
+impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ use traits::FromEnv::*;
+
+ match self {
+ Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
+ Ty(ty) => write!(fmt, "FromEnv({})", ty),
}
}
}
impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use traits::DomainGoal::*;
- use traits::WhereClauseAtom::*;
match self {
Holds(wc) => write!(fmt, "{}", wc),
- WellFormed(Implemented(trait_ref)) => write!(fmt, "WellFormed({})", trait_ref),
- WellFormed(ProjectionEq(projection)) => write!(fmt, "WellFormed({})", projection),
- FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref),
- FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection),
- WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty),
+ WellFormed(wf) => write!(fmt, "{}", wf),
+ FromEnv(from_env) => write!(fmt, "{}", from_env),
Normalize(projection) => write!(fmt, "Normalize({})", projection),
- FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty),
- RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
- TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
}
}
}
}
EnumTypeFoldableImpl! {
- impl<'tcx> TypeFoldable<'tcx> for traits::WhereClauseAtom<'tcx> {
- (traits::WhereClauseAtom::Implemented)(trait_ref),
- (traits::WhereClauseAtom::ProjectionEq)(projection),
+ impl<'tcx> TypeFoldable<'tcx> for traits::WhereClause<'tcx> {
+ (traits::WhereClause::Implemented)(trait_ref),
+ (traits::WhereClause::ProjectionEq)(projection),
+ (traits::WhereClause::TypeOutlives)(ty_outlives),
+ (traits::WhereClause::RegionOutlives)(region_outlives),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
+ type Lifted = traits::WhereClause<'tcx>;
+ (traits::WhereClause::Implemented)(trait_ref),
+ (traits::WhereClause::ProjectionEq)(projection),
+ (traits::WhereClause::TypeOutlives)(ty_outlives),
+ (traits::WhereClause::RegionOutlives)(region_outlives),
+ }
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::WellFormed<'tcx> {
+ (traits::WellFormed::Trait)(trait_ref),
+ (traits::WellFormed::Ty)(ty),
+ }
+}
+
+EnumLiftImpl! {
+ impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
+ type Lifted = traits::WellFormed<'tcx>;
+ (traits::WellFormed::Trait)(trait_ref),
+ (traits::WellFormed::Ty)(ty),
+ }
+}
+
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for traits::FromEnv<'tcx> {
+ (traits::FromEnv::Trait)(trait_ref),
+ (traits::FromEnv::Ty)(ty),
}
}
EnumLiftImpl! {
- impl<'a, 'tcx> Lift<'tcx> for traits::WhereClauseAtom<'a> {
- type Lifted = traits::WhereClauseAtom<'tcx>;
- (traits::WhereClauseAtom::Implemented)(trait_ref),
- (traits::WhereClauseAtom::ProjectionEq)(projection),
+ impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
+ type Lifted = traits::FromEnv<'tcx>;
+ (traits::FromEnv::Trait)(trait_ref),
+ (traits::FromEnv::Ty)(ty),
}
}
EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
(traits::DomainGoal::Holds)(wc),
- (traits::DomainGoal::WellFormed)(wc),
- (traits::DomainGoal::FromEnv)(wc),
- (traits::DomainGoal::WellFormedTy)(ty),
+ (traits::DomainGoal::WellFormed)(wf),
+ (traits::DomainGoal::FromEnv)(from_env),
(traits::DomainGoal::Normalize)(projection),
- (traits::DomainGoal::FromEnvTy)(ty),
- (traits::DomainGoal::RegionOutlives)(predicate),
- (traits::DomainGoal::TypeOutlives)(predicate),
}
}
impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
type Lifted = traits::DomainGoal<'tcx>;
(traits::DomainGoal::Holds)(wc),
- (traits::DomainGoal::WellFormed)(wc),
- (traits::DomainGoal::FromEnv)(wc),
- (traits::DomainGoal::WellFormedTy)(ty),
+ (traits::DomainGoal::WellFormed)(wf),
+ (traits::DomainGoal::FromEnv)(from_env),
(traits::DomainGoal::Normalize)(projection),
- (traits::DomainGoal::FromEnvTy)(ty),
- (traits::DomainGoal::RegionOutlives)(predicate),
- (traits::DomainGoal::TypeOutlives)(predicate),
}
}
fn has_late_bound_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
}
+
+ /// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
+ fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
+
+ pub struct Visitor<F>(F);
+
+ impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor<F> {
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+ self.0(ty)
+ }
+ }
+
+ self.visit_with(&mut Visitor(visit))
+ }
}
/// The TypeFolder trait defines the actual *folding*. There is a
data @ DefPathData::ValueNs(..) |
data @ DefPathData::Module(..) |
data @ DefPathData::TypeParam(..) |
- data @ DefPathData::LifetimeDef(..) |
+ data @ DefPathData::LifetimeParam(..) |
data @ DefPathData::EnumVariant(..) |
data @ DefPathData::Field(..) |
data @ DefPathData::AnonConst |
}
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
- let expansion = match scope.krate {
- LOCAL_CRATE => self.hir.definitions().expansion(scope.index),
+ ident = ident.modern();
+ let target_expansion = match scope.krate {
+ LOCAL_CRATE => self.hir.definitions().opaque_expansion_that_defined(scope.index),
_ => Mark::root(),
};
- ident = ident.modern();
- let scope = match ident.span.adjust(expansion) {
- Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def),
+ let scope = match ident.span.adjust(target_expansion) {
+ Some(actual_expansion) =>
+ self.hir.definitions().parent_module_of_macro_def(actual_expansion),
None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
None => self.hir.get_module_parent(block),
};
///
/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
+/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub enum RegionKind {
// Region bound in a type or fn declaration which will be
DefPathData::MacroDef(_) |
DefPathData::ClosureExpr |
DefPathData::TypeParam(_) |
- DefPathData::LifetimeDef(_) |
+ DefPathData::LifetimeParam(_) |
DefPathData::Field(_) |
DefPathData::StructCtor |
DefPathData::AnonConst |
if !verbose {
let mut type_params =
- generics.params.iter().rev().filter_map(|param| {
- match param.kind {
- GenericParamDefKind::Type { has_default, .. } => {
- Some((param.def_id, has_default))
- }
- GenericParamDefKind::Lifetime => None,
+ generics.params.iter().rev().filter_map(|param| match param.kind {
+ GenericParamDefKind::Lifetime => None,
+ GenericParamDefKind::Type { has_default, .. } => {
+ Some((param.def_id, has_default))
}
}).peekable();
let has_default = {
TyParam(ref param_ty) => write!(f, "{}", param_ty),
TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
TyDynamic(data, r) => {
- data.print(f, cx)?;
let r = r.print_to_string(cx);
if !r.is_empty() {
- write!(f, " + {}", r)
+ write!(f, "(")?;
+ }
+ write!(f, "dyn ")?;
+ data.print(f, cx)?;
+ if !r.is_empty() {
+ write!(f, " + {})", r)
} else {
Ok(())
}
rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
+log = "0.4"
use rustc::middle::allocator::AllocatorKind;
use rustc_errors;
-use rustc_target::spec::abi::Abi;
-use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
-use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety};
-use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
-use syntax::attr;
-use syntax::codemap::{dummy_spanned, respan};
-use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan};
-use syntax::ext::base::ExtCtxt;
-use syntax::ext::base::Resolver;
-use syntax::ext::build::AstBuilder;
-use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::hygiene::{self, Mark, SyntaxContext};
-use syntax::fold::{self, Folder};
-use syntax::parse::ParseSess;
-use syntax::ptr::P;
-use syntax::symbol::Symbol;
-use syntax::util::small_vector::SmallVector;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax::{
+ ast::{
+ self, Arg, Attribute, Crate, Expr, FnHeader, Generics, Ident, Item, ItemKind,
+ LitKind, Mac, Mod, Mutability, StrStyle, Ty, TyKind, Unsafety, VisibilityKind,
+ },
+ attr,
+ codemap::{
+ respan, ExpnInfo, MacroAttribute,
+ },
+ ext::{
+ base::{ExtCtxt, Resolver},
+ build::AstBuilder,
+ expand::ExpansionConfig,
+ hygiene::{self, Mark, SyntaxContext},
+ },
+ fold::{self, Folder},
+ parse::ParseSess,
+ ptr::P,
+ symbol::Symbol,
+ util::small_vector::SmallVector,
+};
+use syntax_pos::Span;
use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};
sess: &ParseSess,
resolver: &mut Resolver,
krate: Crate,
+ crate_name: String,
handler: &rustc_errors::Handler,
) -> ast::Crate {
ExpandAllocatorDirectives {
sess,
resolver,
found: false,
+ crate_name: Some(crate_name),
+ in_submod: -1, // -1 to account for the "root" module
}.fold_crate(krate)
}
handler: &'a rustc_errors::Handler,
sess: &'a ParseSess,
resolver: &'a mut Resolver,
+ crate_name: Option<String>,
+
+ // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
+ // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
+ in_submod: isize,
}
impl<'a> Folder for ExpandAllocatorDirectives<'a> {
fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
+ debug!("in submodule {}", self.in_submod);
+
let name = if attr::contains_name(&item.attrs, "global_allocator") {
"global_allocator"
} else {
}
}
+ if self.in_submod > 0 {
+ self.handler
+ .span_err(item.span, "`global_allocator` cannot be used in submodules");
+ return SmallVector::one(item);
+ }
+
if self.found {
- self.handler.span_err(
- item.span,
- "cannot define more than one \
- #[global_allocator]",
- );
+ self.handler
+ .span_err(item.span, "cannot define more than one #[global_allocator]");
return SmallVector::one(item);
}
self.found = true;
+ // Create a fresh Mark for the new macro expansion we are about to do
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
- call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern(name)),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- },
+ call_site: item.span, // use the call site of the static
+ def_site: None,
+ format: MacroAttribute(Symbol::intern(name)),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
+
+ // Tie the span to the macro expansion info we just created
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
- let ecfg = ExpansionConfig::default(name.to_string());
+
+ // Create an expansion config
+ let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());
+
+ // Generate a bunch of new items using the AllocFnFactory
let mut f = AllocFnFactory {
span,
kind: AllocatorKind::Global,
core: Ident::from_str("core"),
cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
};
+
+ // We will generate a new submodule. To `use` the static from that module, we need to get
+ // the `super::...` path.
let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]);
+
+ // Generate the items in the submodule
let mut items = vec![
+ // import `core` to use allocators
f.cx.item_extern_crate(f.span, f.core),
+ // `use` the `global_allocator` in `super`
f.cx.item_use_simple(
f.span,
respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
super_path,
),
];
- for method in ALLOCATOR_METHODS {
- items.push(f.allocator_fn(method));
- }
+
+ // Add the allocator methods to the submodule
+ items.extend(
+ ALLOCATOR_METHODS
+ .iter()
+ .map(|method| f.allocator_fn(method)),
+ );
+
+ // Generate the submodule itself
let name = f.kind.fn_name("allocator_abi");
let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name));
let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();
- let mut ret = SmallVector::new();
+ // Return the item and new submodule
+ let mut ret = SmallVector::with_capacity(2);
ret.push(item);
ret.push(module);
+
return ret;
}
+ // If we enter a submodule, take note.
+ fn fold_mod(&mut self, m: Mod) -> Mod {
+ debug!("enter submodule");
+ self.in_submod += 1;
+ let ret = fold::noop_fold_mod(m, self);
+ self.in_submod -= 1;
+ debug!("exit submodule");
+ ret
+ }
+
+ // `fold_mac` is disabled by default. Enable it here.
fn fold_mac(&mut self, mac: Mac) -> Mac {
fold::noop_fold_mac(mac, self)
}
let (output_ty, output_expr) = self.ret_ty(&method.output, result);
let kind = ItemKind::Fn(
self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
- Unsafety::Unsafe,
- dummy_spanned(Constness::NotConst),
- Abi::Rust,
+ FnHeader {
+ unsafety: Unsafety::Unsafe,
+ ..FnHeader::default()
+ },
Generics::default(),
self.cx.block_expr(output_expr),
);
#![feature(rustc_private)]
+#[macro_use] extern crate log;
extern crate rustc;
extern crate rustc_errors;
extern crate rustc_target;
> 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-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.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
let mut err = self.cannot_act_on_moved_value(use_span,
verb,
msg,
- &format!("{}", nl),
+ Some(format!("{}", nl)),
Origin::Ast);
let need_note = match lp.ty.sty {
ty::TypeVariants::TyClosure(id, _) => {
return;
}
+ // probestack doesn't play nice either with gcov profiling.
+ if cx.sess().opts.debugging_opts.profile {
+ return;
+ }
+
// Flag our internal `__rust_probestack` function as the stack probe symbol.
// This is defined in the `compiler-builtins` crate for each architecture.
llvm::AddFunctionAttrStringValue(
"##,
}
-
-
-register_diagnostics! {
- E0558
-}
obligation: O,
state: Cell<NodeState>,
- /// Obligations that depend on this obligation for their
- /// completion. They must all be in a non-pending state.
- dependents: Vec<NodeIndex>,
/// The parent of a node - the original obligation of
/// which it is a subobligation. Except for error reporting,
- /// this is just another member of `dependents`.
+ /// it is just like any member of `dependents`.
parent: Option<NodeIndex>,
+
+ /// Obligations that depend on this obligation for their
+ /// completion. They must all be in a non-pending state.
+ dependents: Vec<NodeIndex>,
}
/// The state of one node in some tree within the forest. This
Entry::Occupied(o) => {
debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!",
obligation, parent, o.get());
+ let node = &mut self.nodes[o.get().get()];
if let Some(parent) = parent {
- if self.nodes[o.get().get()].dependents.contains(&parent) {
- debug!("register_obligation_at({:?}, {:?}) - duplicate subobligation",
- obligation, parent);
- } else {
- self.nodes[o.get().get()].dependents.push(parent);
+ // If the node is already in `waiting_cache`, it's already
+ // been marked with a parent. (It's possible that parent
+ // has been cleared by `apply_rewrites`, though.) So just
+ // dump `parent` into `node.dependents`... unless it's
+ // already in `node.dependents` or `node.parent`.
+ if !node.dependents.contains(&parent) && Some(parent) != node.parent {
+ node.dependents.push(parent);
}
}
- if let NodeState::Error = self.nodes[o.get().get()].state.get() {
+ if let NodeState::Error = node.state.get() {
Err(())
} else {
Ok(())
NodeState::Success => {
node.state.set(NodeState::OnDfsStack);
stack.push(index);
- if let Some(parent) = node.parent {
- self.find_cycles_from_node(stack, processor, parent.get());
- }
- for dependent in &node.dependents {
+ for dependent in node.parent.iter().chain(node.dependents.iter()) {
self.find_cycles_from_node(stack, processor, dependent.get());
}
stack.pop();
}
error_stack.extend(
- node.dependents.iter().cloned().chain(node.parent).map(|x| x.get())
+ node.parent.iter().chain(node.dependents.iter()).map(|x| x.get())
);
}
#[inline]
fn mark_neighbors_as_waiting_from(&self, node: &Node<O>) {
- if let Some(parent) = node.parent {
- self.mark_as_waiting_from(&self.nodes[parent.get()]);
- }
-
- for dependent in &node.dependents {
+ for dependent in node.parent.iter().chain(node.dependents.iter()) {
self.mark_as_waiting_from(&self.nodes[dependent.get()]);
}
}
fn new(parent: Option<NodeIndex>, obligation: O) -> Node<O> {
Node {
obligation,
- parent,
state: Cell::new(NodeState::Pending),
+ parent,
dependents: vec![],
}
}
});
}
+ // Expand global allocators, which are treated as an in-tree proc macro
krate = time(sess, "creating allocators", || {
- allocator::expand::modify(&sess.parse_sess, &mut resolver, krate, sess.diagnostic())
+ allocator::expand::modify(
+ &sess.parse_sess,
+ &mut resolver,
+ krate,
+ crate_name.to_string(),
+ sess.diagnostic(),
+ )
});
+ // Done with macro expansion!
+
after_expand(&krate)?;
if sess.opts.debugging_opts.input_stats {
ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
- match seg.parameters.as_ref().map(|p| &**p) {
+ match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
None => false,
- Some(&ast::PathParameters::AngleBracketed(ref data)) =>
- any_involves_impl_trait(data.types.iter()) ||
- any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)),
- Some(&ast::PathParameters::Parenthesized(ref data)) =>
+ Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
+ let types = data.args.iter().filter_map(|arg| match arg {
+ ast::GenericArg::Type(ty) => Some(ty),
+ _ => None,
+ });
+ any_involves_impl_trait(types.into_iter()) ||
+ any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty))
+ },
+ Some(&ast::GenericArgs::Parenthesized(ref data)) => {
any_involves_impl_trait(data.inputs.iter()) ||
- any_involves_impl_trait(data.output.iter()),
+ any_involves_impl_trait(data.output.iter())
+ }
}
}),
_ => false,
fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind {
let is_const = match i {
ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
- ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) =>
- constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ ast::ItemKind::Fn(ref decl, ref header, _, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
_ => false,
};
self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
let is_const = match i.node {
ast::TraitItemKind::Const(..) => true,
- ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
- constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
_ => false,
};
self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
let is_const = match i.node {
ast::ImplItemKind::Const(..) => true,
- ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
- constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
+ ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref header, .. }, _) =>
+ header.constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
_ => false,
};
self.run(is_const, |s| fold::noop_fold_impl_item(i, s))
use syntax::attr;
use syntax_pos::Span;
-use rustc::hir::{self, PatKind};
+use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind;
#[derive(PartialEq)]
}
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
- if let hir::GenericParam::Type(ref gen) = *param {
- if gen.synthetic.is_none() {
- self.check_case(cx, "type parameter", gen.name, gen.span);
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { synthetic, .. } => {
+ if synthetic.is_none() {
+ self.check_case(cx, "type parameter", param.name.name(), param.span);
+ }
}
}
}
}
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
- if let hir::GenericParam::Lifetime(ref ld) = *param {
- self.check_snake_case(
- cx,
- "lifetime",
- &ld.lifetime.name.name().as_str(),
- Some(ld.lifetime.span)
- );
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let name = param.name.name().as_str();
+ self.check_snake_case(cx, "lifetime", &name, Some(param.span));
+ }
+ GenericParamKind::Type { .. } => {}
}
}
_ => (),
}
}
- FnKind::ItemFn(name, _, _, _, abi, _, attrs) => {
+ FnKind::ItemFn(name, _, header, _, attrs) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
- if abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
+ if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
return;
}
self.check_snake_case(cx, "function", &name.as_str(), Some(span))
use syntax::symbol::keywords;
use syntax::errors::{Applicability, DiagnosticBuilder};
-use rustc::hir::{self, PatKind};
+use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind;
use bad_style::{MethodLateContext, method_context};
span: Span,
_: ast::NodeId) {
match fk {
- FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, ..) => {
+ FnKind::ItemFn(_, _, hir::FnHeader { unsafety: hir::Unsafety::Unsafe, .. }, ..) => {
self.report_unsafe(cx, span, "declaration of an `unsafe` function")
}
FnKind::Method(_, sig, ..) => {
- if sig.unsafety == hir::Unsafety::Unsafe {
+ if sig.header.unsafety == hir::Unsafety::Unsafe {
self.report_unsafe(cx, span, "implementation of an `unsafe` method")
}
}
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node {
- if sig.unsafety == hir::Unsafety::Unsafe {
+ if sig.header.unsafety == hir::Unsafety::Unsafe {
self.report_unsafe(cx, item.span, "declaration of an `unsafe` method")
}
}
}
err.emit();
}
- if generics.is_type_parameterized() {
- let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
- it.span,
- "functions generic over \
- types must be mangled");
- err.span_suggestion_short(no_mangle_attr.span,
- "remove this attribute",
- "".to_owned());
- err.emit();
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { .. } => {
+ let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
+ it.span,
+ "functions generic over \
+ types must be mangled");
+ err.span_suggestion_short(no_mangle_attr.span,
+ "remove this attribute",
+ "".to_owned());
+ err.emit();
+ break;
+ }
+ }
}
}
}
}
// The parameters must not have bounds
for param in type_alias_generics.params.iter() {
- let spans : Vec<_> = match param {
- &hir::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(),
- &hir::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(),
- };
+ let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
if !spans.is_empty() {
let mut err = cx.struct_span_lint(
TYPE_ALIAS_BOUNDS,
reference: "issue TBD",
edition: Some(Edition::Edition2018),
},
+ FutureIncompatibleInfo {
+ id: LintId::of(WHERE_CLAUSES_OBJECT_SAFETY),
+ reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
+ edition: None,
+ },
FutureIncompatibleInfo {
id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
- if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
- if gens.params.iter().all(|param| param.is_lifetime_param()) {
- // sizes only make sense for non-generic types
- let item_def_id = cx.tcx.hir.local_def_id(it.id);
- let t = cx.tcx.type_of(item_def_id);
- let ty = cx.tcx.erase_regions(&t);
- let layout = cx.layout_of(ty).unwrap_or_else(|e| {
- bug!("failed to get layout for `{}`: {}", t, e)
- });
-
- if let layout::Variants::Tagged { ref variants, ref tag, .. } = layout.variants {
- let discr_size = tag.value.size(cx.tcx).bytes();
-
- debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
- t, layout.size.bytes(), layout);
-
- let (largest, slargest, largest_index) = enum_definition.variants
- .iter()
- .zip(variants)
- .map(|(variant, variant_layout)| {
- // Subtract the size of the enum discriminant
- let bytes = variant_layout.size.bytes()
- .saturating_sub(discr_size);
-
- debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);
- bytes
- })
- .enumerate()
- .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
- (size, l, idx)
- } else if size > s {
- (l, size, li)
- } else {
- (l, s, li)
- });
-
- // we only warn if the largest variant is at least thrice as large as
- // the second-largest.
- if largest > slargest * 3 && slargest > 0 {
- cx.span_lint(VARIANT_SIZE_DIFFERENCES,
- enum_definition.variants[largest_index].span,
- &format!("enum variant is more than three times larger \
- ({} bytes) than the next largest",
- largest));
+ if let hir::ItemEnum(ref enum_definition, _) = it.node {
+ let item_def_id = cx.tcx.hir.local_def_id(it.id);
+ let generics = cx.tcx.generics_of(item_def_id);
+ for param in &generics.params {
+ match param.kind {
+ ty::GenericParamDefKind::Lifetime { .. } => {},
+ ty::GenericParamDefKind::Type { .. } => return,
+ }
+ }
+ // Sizes only make sense for non-generic types.
+ let t = cx.tcx.type_of(item_def_id);
+ let ty = cx.tcx.erase_regions(&t);
+ match cx.layout_of(ty) {
+ Ok(layout) => {
+ let variants = &layout.variants;
+ if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants {
+ let discr_size = tag.value.size(cx.tcx).bytes();
+
+ debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
+ t, layout.size.bytes(), layout);
+
+ let (largest, slargest, largest_index) = enum_definition.variants
+ .iter()
+ .zip(variants)
+ .map(|(variant, variant_layout)| {
+ // Subtract the size of the enum discriminant.
+ let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
+
+ debug!("- variant `{}` is {} bytes large",
+ variant.node.name,
+ bytes);
+ bytes
+ })
+ .enumerate()
+ .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
+ (size, l, idx)
+ } else if size > s {
+ (l, size, li)
+ } else {
+ (l, s, li)
+ });
+
+ // We only warn if the largest variant is at least thrice as large as
+ // the second-largest.
+ if largest > slargest * 3 && slargest > 0 {
+ cx.span_lint(VARIANT_SIZE_DIFFERENCES,
+ enum_definition.variants[largest_index].span,
+ &format!("enum variant is more than three times \
+ larger ({} bytes) than the next largest",
+ largest));
+ }
}
}
+ Err(ty::layout::LayoutError::Unknown(_)) => return,
+ Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
+ bug!("failed to get layout for `{}`: {}", t, err);
+ }
}
}
}
name: &str,
expand: fn(TokenStream) -> TokenStream) {
let expand = SyntaxExtension::ProcMacro(
- Box::new(BangProcMacro { inner: expand }), self.edition
+ Box::new(BangProcMacro { inner: expand }), false, self.edition
);
self.extensions.push((Symbol::intern(name), Lrc::new(expand)));
}
} else if data.name == "proc_macro" &&
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
let ext = SyntaxExtension::ProcMacro(Box::new(::proc_macro::__internal::Quoter),
- data.root.edition);
+ true, data.root.edition);
return LoadedMacro::ProcMacro(Lrc::new(ext));
}
ty::AssociatedKind::Method => {
let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
FnData {
- constness: sig.constness,
+ constness: sig.header.constness,
arg_names: self.encode_fn_arg_names_for_body(body),
sig: self.lazy(&tcx.fn_sig(def_id)),
}
let needs_inline = (generics.requires_monomorphization(self.tcx) ||
tcx.codegen_fn_attrs(def_id).requests_inline()) &&
!self.metadata_output_only();
- let is_const_fn = sig.constness == hir::Constness::Const;
+ let is_const_fn = sig.header.constness == hir::Constness::Const;
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
needs_inline || is_const_fn || always_encode_mir
},
self.encode_rendered_const_for_body(body_id)
)
}
- hir::ItemFn(_, _, constness, .., body) => {
+ hir::ItemFn(_, header, .., body) => {
let data = FnData {
- constness,
+ constness: header.constness,
arg_names: self.encode_fn_arg_names_for_body(body),
sig: self.lazy(&tcx.fn_sig(def_id)),
};
self.encode_optimized_mir(def_id)
}
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
- hir::ItemFn(_, _, constness, _, ref generics, _) => {
- let has_tps = generics.ty_params().next().is_some();
+ hir::ItemFn(_, header, ..) => {
+ let generics = tcx.generics_of(def_id);
+ let has_types = generics.params.iter().any(|param| match param.kind {
+ ty::GenericParamDefKind::Type { .. } => true,
+ _ => false,
+ });
let needs_inline =
- (has_tps || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
+ (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
!self.metadata_output_only();
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
- if needs_inline || constness == hir::Constness::Const || always_encode_mir {
+ if needs_inline
+ || header.constness == hir::Constness::Const
+ || always_encode_mir
+ {
self.encode_optimized_mir(def_id)
} else {
None
}
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
- for ty_param in generics.ty_params() {
- let def_id = self.tcx.hir.local_def_id(ty_param.id);
- let has_default = Untracked(ty_param.default.is_some());
- self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default));
- }
+ generics.params.iter().for_each(|param| match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {}
+ hir::GenericParamKind::Type { ref default, .. } => {
+ let def_id = self.tcx.hir.local_def_id(param.id);
+ let has_default = Untracked(default.is_some());
+ let encode_info = IsolatedEncoder::encode_info_for_ty_param;
+ self.record(def_id, encode_info, (def_id, has_default));
+ }
+ });
}
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
self.moved_error_reported.insert(root_place.clone());
- let item_msg = match self.describe_place(place) {
+ let item_msg = match self.describe_place_with_options(place, IncludingDowncast(true)) {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
.cannot_act_on_uninitialized_variable(
span,
desired_action.as_noun(),
- &self.describe_place(place).unwrap_or("_".to_owned()),
+ &self
+ .describe_place_with_options(place, IncludingDowncast(true))
+ .unwrap_or("_".to_owned()),
Origin::Mir,
)
.span_label(span, format!("use of possibly uninitialized {}", item_msg))
span,
desired_action.as_noun(),
msg,
- &self.describe_place(place).unwrap_or("_".to_owned()),
+ self.describe_place_with_options(&place, IncludingDowncast(true)),
Origin::Mir,
);
let mut is_loop_move = false;
- for moi in mois {
+ for moi in &mois {
let move_msg = ""; //FIXME: add " (into closure)"
- let move_span = self.mir.source_info(self.move_data.moves[*moi].source).span;
+ let move_span = self
+ .mir
+ .source_info(self.move_data.moves[**moi].source)
+ .span;
if span == move_span {
err.span_label(
span,
};
if needs_note {
- let note_msg = match self.describe_place(place) {
- Some(name) => format!("`{}`", name),
- None => "value".to_owned(),
- };
+ let mpi = self.move_data.moves[*mois[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
+ ));
+ }
}
}
let local_decl = &self.mir.local_decls[*local];
if let Some(name) = local_decl.name {
if local_decl.can_be_made_mutable() {
- err.span_label(local_decl.source_info.span,
- format!("consider changing this to `mut {}`", name));
+ err.span_label(
+ local_decl.source_info.span,
+ format!("consider changing this to `mut {}`", name),
+ );
}
}
}
}
}
+pub(super) struct IncludingDowncast(bool);
+
impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// End-user visible description of `place` if one can be found. If the
// place is a temporary for instance, None will be returned.
pub(super) fn describe_place(&self, place: &Place<'tcx>) -> Option<String> {
+ self.describe_place_with_options(place, IncludingDowncast(false))
+ }
+
+ // End-user visible description of `place` if one can be found. If the
+ // place is a temporary for instance, None will be returned.
+ // `IncludingDowncast` parameter makes the function return `Err` if `ProjectionElem` is
+ // `Downcast` and `IncludingDowncast` is true
+ pub(super) fn describe_place_with_options(
+ &self,
+ place: &Place<'tcx>,
+ including_downcast: IncludingDowncast,
+ ) -> Option<String> {
let mut buf = String::new();
- match self.append_place_to_string(place, &mut buf, false) {
+ match self.append_place_to_string(place, &mut buf, false, &including_downcast) {
Ok(()) => Some(buf),
Err(()) => None,
}
place: &Place<'tcx>,
buf: &mut String,
mut autoderef: bool,
+ including_downcast: &IncludingDowncast,
) -> Result<(), ()> {
match *place {
Place::Local(local) => {
}
} else {
if autoderef {
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
} else {
buf.push_str(&"*");
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
}
}
}
ProjectionElem::Downcast(..) => {
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
+ if including_downcast.0 {
+ return Err(());
+ }
}
ProjectionElem::Field(field, _ty) => {
autoderef = true;
buf.push_str(&name);
} else {
let field_name = self.describe_field(&proj.base, field);
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
buf.push_str(&format!(".{}", field_name));
}
}
ProjectionElem::Index(index) => {
autoderef = true;
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
buf.push_str("[");
if let Err(_) = self.append_local_to_string(index, buf) {
buf.push_str("..");
// Since it isn't possible to borrow an element on a particular index and
// then use another while the borrow is held, don't output indices details
// to avoid confusing the end-user
- self.append_place_to_string(&proj.base, buf, autoderef)?;
+ self.append_place_to_string(
+ &proj.base,
+ buf,
+ autoderef,
+ &including_downcast,
+ )?;
buf.push_str(&"[..]");
}
};
use rustc::hir::def_id::DefId;
use rustc::hir::map::definitions::DefPathData;
use rustc::infer::InferCtxt;
-use rustc::ty::{self, ParamEnv, TyCtxt};
-use rustc::ty::query::Providers;
use rustc::lint::builtin::UNUSED_MUT;
use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand};
-use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind};
+use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
+use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
+use rustc::ty::query::Providers;
+use rustc::ty::{self, ParamEnv, TyCtxt};
use rustc_data_structures::control_flow_graph::dominators::Dominators;
use rustc_data_structures::fx::FxHashSet;
use syntax_pos::Span;
-use dataflow::{do_dataflow, DebugFormatted};
+use dataflow::indexes::BorrowIndex;
+use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
+use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
+use dataflow::Borrows;
+use dataflow::DataflowResultsConsumer;
use dataflow::FlowAtLocation;
use dataflow::MoveDataParamEnv;
-use dataflow::{DataflowResultsConsumer};
-use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
+use dataflow::{do_dataflow, DebugFormatted};
use dataflow::{EverInitializedPlaces, MovingOutStatements};
-use dataflow::Borrows;
-use dataflow::indexes::BorrowIndex;
-use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
-use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
+use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
use util::borrowck_errors::{BorrowckErrors, Origin};
use util::collect_writes::FindAssignments;
-use self::borrow_set::{BorrowSet, BorrowData};
+use self::borrow_set::{BorrowData, BorrowSet};
use self::flows::Flows;
use self::location::LocationTable;
use self::prefixes::PrefixSet;
mod error_reporting;
mod flows;
mod location;
+mod path_utils;
crate mod place_ext;
mod prefixes;
-mod path_utils;
+mod used_muts;
pub(crate) mod nll;
};
}
-fn mir_borrowck<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId,
-) -> BorrowCheckResult<'tcx> {
+fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> {
let input_mir = tcx.mir_validated(def_id);
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
let tcx = infcx.tcx;
let attributes = tcx.get_attrs(def_id);
let param_env = tcx.param_env(def_id);
- let id = tcx.hir
+ let id = tcx
+ .hir
.as_local_node_id(def_id)
.expect("do_mir_borrowck: non-local DefId");
// borrow to provide feedback about why this
// was a move rather than a copy.
match ty.sty {
- ty::TyArray(..) | ty::TySlice(..) =>
- tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin),
- _ => tcx.cannot_move_out_of(span, "borrowed content", origin)
+ ty::TyArray(..) | ty::TySlice(..) => {
+ tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin)
+ }
+ _ => tcx.cannot_move_out_of(span, "borrowed content", origin),
}
}
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
// Note that this set is expected to be small - only upvars from closures
// would have a chance of erroneously adding non-user-defined mutable vars
// to the set.
- let temporary_used_locals: FxHashSet<Local> =
- mbcx.used_mut.iter()
- .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
- .cloned()
- .collect();
-
- for local in temporary_used_locals {
- for location in mbcx.mir.find_assignments(local) {
- for moi in &mbcx.move_data.loc_map[location] {
- let mpi = &mbcx.move_data.moves[*moi].path;
- let path = &mbcx.move_data.move_paths[*mpi];
- debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set",
- path.place, local, path.place);
- if let Place::Local(user_local) = path.place {
- mbcx.used_mut.insert(user_local);
- }
- }
- }
- }
+ let temporary_used_locals: FxHashSet<Local> = mbcx
+ .used_mut
+ .iter()
+ .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
+ .cloned()
+ .collect();
+ mbcx.gather_used_muts(temporary_used_locals);
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
- for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) {
+ for local in mbcx
+ .mir
+ .mut_vars_and_args_iter()
+ .filter(|local| !mbcx.used_mut.contains(local))
+ {
if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
let local_decl = &mbcx.mir.local_decls[local];
// Skip over locals that begin with an underscore or have no name
match local_decl.name {
- Some(name) => if name.as_str().starts_with("_") { continue; },
+ Some(name) => if name.as_str().starts_with("_") {
+ continue;
+ },
None => continue,
}
UNUSED_MUT,
vsi[local_decl.source_info.scope].lint_root,
span,
- "variable does not need to be mutable"
- )
- .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
- .emit();
+ "variable does not need to be mutable",
+ ).span_suggestion_short(mut_span, "remove this `mut`", "".to_owned())
+ .emit();
}
}
);
}
StatementKind::ReadForMatch(ref place) => {
- self.access_place(ContextKind::ReadForMatch.new(location),
- (place, span),
- (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
- LocalMutationIsAllowed::No,
- flow_state,
- );
+ self.access_place(
+ ContextKind::ReadForMatch.new(location),
+ (place, span),
+ (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+ LocalMutationIsAllowed::No,
+ flow_state,
+ );
}
StatementKind::SetDiscriminant {
ref place,
// ignored when consuming results (update to
// flow_state already handled).
}
- StatementKind::Nop |
- StatementKind::UserAssertTy(..) |
- StatementKind::Validate(..) |
- StatementKind::StorageLive(..) => {
+ StatementKind::Nop
+ | StatementKind::UserAssertTy(..)
+ | StatementKind::Validate(..)
+ | StatementKind::StorageLive(..) => {
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
// to borrow check.
}
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
if let BoundsCheck { ref len, ref index } = *msg {
self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
- self.consume_operand(
- ContextKind::Assert.new(loc),
- (index, span),
- flow_state,
- );
+ self.consume_operand(ContextKind::Assert.new(loc), (index, span), flow_state);
}
}
WriteAndRead,
}
-use self::ShallowOrDeep::{Deep, Shallow};
use self::ReadOrWrite::{Activation, Read, Reservation, Write};
+use self::ShallowOrDeep::{Deep, Shallow};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum ArtificialField {
span: Span,
) {
let gcx = self.tcx.global_tcx();
- let drop_field = |
- mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
- (index, field): (usize, ty::Ty<'gcx>),
- | {
+ let drop_field = |mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+ (index, field): (usize, ty::Ty<'gcx>)| {
let field_ty = gcx.normalize_erasing_regions(mir.param_env, field);
let place = drop_place.clone().field(Field::new(index), field_ty);
}
// Same as above, but for tuples.
ty::TyTuple(tys) => {
- tys.iter().cloned().enumerate()
+ tys.iter()
+ .cloned()
+ .enumerate()
.for_each(|field| drop_field(self, field));
}
// Closures also have disjoint fields, but they are only
// directly accessed in the body of the closure.
ty::TyClosure(def, substs)
- if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
- => {
- substs.upvar_tys(def, self.tcx).enumerate()
+ if *drop_place == Place::Local(Local::new(1))
+ && !self.mir.upvar_decls.is_empty() =>
+ {
+ substs
+ .upvar_tys(def, self.tcx)
+ .enumerate()
.for_each(|field| drop_field(self, field));
}
// Generators also have disjoint fields, but they are only
// directly accessed in the body of the generator.
ty::TyGenerator(def, substs, _)
- if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
- => {
- substs.upvar_tys(def, self.tcx).enumerate()
+ if *drop_place == Place::Local(Local::new(1))
+ && !self.mir.upvar_decls.is_empty() =>
+ {
+ substs
+ .upvar_tys(def, self.tcx)
+ .enumerate()
.for_each(|field| drop_field(self, field));
}
_ => {
}
}
- if self.access_place_error_reported
+ if self
+ .access_place_error_reported
.contains(&(place_span.0.clone(), place_span.1))
{
debug!(
) -> bool {
debug!(
"check_access_for_conflict(context={:?}, place_span={:?}, sd={:?}, rw={:?})",
- context,
- place_span,
- sd,
- rw,
+ context, place_span, sd, rw,
);
let mut error_reported = false;
(sd, place_span.0),
&borrow_set,
flow_state.borrows_in_scope(location),
- |this, borrow_index, borrow|
- match (rw, borrow.kind) {
+ |this, borrow_index, borrow| match (rw, borrow.kind) {
// Obviously an activation is compatible with its own
// reservation (or even prior activating uses of same
// borrow); so don't check if they interfere.
}
ReadKind::Borrow(bk) => {
error_reported = true;
- this.report_conflicting_borrow(
- context,
- place_span,
- bk,
- &borrow,
- )
+ this.report_conflicting_borrow(context, place_span, bk, &borrow)
}
}
Control::Break
match kind {
WriteKind::MutableBorrow(bk) => {
error_reported = true;
- this.report_conflicting_borrow(
- context,
- place_span,
- bk,
- &borrow,
- )
+ this.report_conflicting_borrow(context, place_span, bk, &borrow)
}
WriteKind::StorageDeadOrDrop => {
error_reported = true;
// moved into the closure and subsequently used by the closure,
// in order to populate our used_mut set.
if let AggregateKind::Closure(def_id, _) = &**aggregate_kind {
- let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id);
+ let BorrowCheckResult {
+ used_mut_upvars, ..
+ } = self.tcx.mir_borrowck(*def_id);
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
for field in used_mut_upvars {
match operands[field.index()] {
self.used_mut_upvars.push(field);
}
}
- Operand::Move(Place::Static(..)) |
- Operand::Copy(..) |
- Operand::Constant(..) => {}
+ Operand::Move(Place::Static(..))
+ | Operand::Copy(..)
+ | Operand::Constant(..) => {}
}
}
}
Place::Static(statik) => {
// Thread-locals might be dropped after the function exits, but
// "true" statics will never be.
- let is_thread_local = self.tcx
+ let is_thread_local = self
+ .tcx
.get_attrs(statik.def_id)
.iter()
.any(|attr| attr.check_name("thread_local"));
Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
| Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
| Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
- | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) =>
- {
+ | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) => {
let is_local_mutation_allowed = match borrow_kind {
BorrowKind::Unique => LocalMutationIsAllowed::Yes,
BorrowKind::Mut { .. } => is_local_mutation_allowed,
// `act` and `acted_on` are strings that let us abstract over
// the verbs used in some diagnostic messages.
- let act; let acted_on;
+ let act;
+ let acted_on;
match error_access {
AccessKind::Mutate => {
let item_msg = match the_place_err {
Place::Projection(box Projection {
base: _,
- elem: ProjectionElem::Deref }
- ) => match self.describe_place(place) {
- Some(description) =>
- format!("`{}` which is behind a `&` reference", description),
+ elem: ProjectionElem::Deref,
+ }) => match self.describe_place(place) {
+ Some(description) => {
+ format!("`{}` which is behind a `&` reference", description)
+ }
None => format!("data in a `&` reference"),
},
_ => item_msg,
};
err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
- act = "assign"; acted_on = "written";
+ act = "assign";
+ acted_on = "written";
}
AccessKind::MutableBorrow => {
- err = self.tcx
+ err = self
+ .tcx
.cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
- act = "borrow as mutable"; acted_on = "borrowed as mutable";
+ act = "borrow as mutable";
+ acted_on = "borrowed as mutable";
}
}
let local_decl = &self.mir.local_decls[*local];
assert_eq!(local_decl.mutability, Mutability::Not);
- err.span_label(span, format!("cannot {ACT}", ACT=act));
- err.span_suggestion(local_decl.source_info.span,
- "consider changing this to be mutable",
- format!("mut {}", local_decl.name.unwrap()));
+ err.span_label(span, format!("cannot {ACT}", ACT = act));
+ err.span_suggestion(
+ local_decl.source_info.span,
+ "consider changing this to be mutable",
+ format!("mut {}", local_decl.name.unwrap()),
+ );
}
// complete hack to approximate old AST-borrowck
// diagnostic: if the span starts with a mutable borrow of
// a local variable, then just suggest the user remove it.
- Place::Local(_) if {
- if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- snippet.starts_with("&mut ")
- } else {
- false
- }
- } => {
- err.span_label(span, format!("cannot {ACT}", ACT=act));
+ Place::Local(_)
+ if {
+ if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+ snippet.starts_with("&mut ")
+ } else {
+ false
+ }
+ } =>
+ {
+ err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_label(span, "try removing `&mut` here");
}
//
// FIXME: can this case be generalized to work for an
// arbitrary base for the projection?
- Place::Projection(box Projection { base: Place::Local(local),
- elem: ProjectionElem::Deref })
- if self.mir.local_decls[*local].is_nonref_binding() =>
+ Place::Projection(box Projection {
+ base: Place::Local(local),
+ elem: ProjectionElem::Deref,
+ }) if self.mir.local_decls[*local].is_nonref_binding() =>
{
let (err_help_span, suggested_code) =
find_place_to_suggest_ampmut(self.tcx, self.mir, *local);
- err.span_suggestion(err_help_span,
- "consider changing this to be a mutable reference",
- suggested_code);
+ err.span_suggestion(
+ err_help_span,
+ "consider changing this to be a mutable reference",
+ suggested_code,
+ );
let local_decl = &self.mir.local_decls[*local];
if let Some(name) = local_decl.name {
err.span_label(
- span, format!("`{NAME}` is a `&` reference, \
- so the data it refers to cannot be {ACTED_ON}",
- NAME=name, ACTED_ON=acted_on));
+ span,
+ format!(
+ "`{NAME}` is a `&` reference, \
+ so the data it refers to cannot be {ACTED_ON}",
+ NAME = name,
+ ACTED_ON = acted_on
+ ),
+ );
} else {
- err.span_label(span, format!("cannot {ACT} through `&`-reference", ACT=act));
+ err.span_label(
+ span,
+ format!("cannot {ACT} through `&`-reference", ACT = act),
+ );
}
}
_ => {
- err.span_label(span, format!("cannot {ACT}", ACT=act));
+ err.span_label(span, format!("cannot {ACT}", ACT = act));
}
}
// for example, if the RHS is present and the Type is not, then the type is going to
// be inferred *from* the RHS, which means we should highlight that (and suggest
// that they borrow the RHS mutably).
- fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
- mir: &Mir<'tcx>,
- local: Local) -> (Span, String)
- {
+ fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(
+ tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+ mir: &Mir<'tcx>,
+ local: Local,
+ ) -> (Span, String) {
// This implementation attempts to emulate AST-borrowck prioritization
// by trying (3.), then (2.) and finally falling back on (1.).
let locations = mir.find_assignments(local);
// if this is a variable binding with an explicit type,
// try to highlight that for the suggestion.
Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
- opt_ty_info: Some(ty_span), .. }))) => ty_span,
+ opt_ty_info: Some(ty_span),
+ ..
+ }))) => ty_span,
Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
fn add_used_mut<'d>(
&mut self,
root_place: RootPlace<'d, 'tcx>,
- flow_state: &Flows<'cx, 'gcx, 'tcx>
+ flow_state: &Flows<'cx, 'gcx, 'tcx>,
) {
match root_place {
RootPlace {
let local = &self.mir.local_decls[local];
match local.mutability {
Mutability::Not => match is_local_mutation_allowed {
- LocalMutationIsAllowed::Yes => {
- Ok(RootPlace {
- place,
- is_local_mutation_allowed: LocalMutationIsAllowed::Yes
- })
- }
- LocalMutationIsAllowed::ExceptUpvars => {
- Ok(RootPlace {
- place,
- is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars
- })
- }
+ LocalMutationIsAllowed::Yes => Ok(RootPlace {
+ place,
+ is_local_mutation_allowed: LocalMutationIsAllowed::Yes,
+ }),
+ LocalMutationIsAllowed::ExceptUpvars => Ok(RootPlace {
+ place,
+ is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars,
+ }),
LocalMutationIsAllowed::No => Err(place),
},
- Mutability::Mut => Ok(RootPlace { place, is_local_mutation_allowed }),
+ Mutability::Mut => Ok(RootPlace {
+ place,
+ is_local_mutation_allowed,
+ }),
}
}
- Place::Static(ref static_) =>
+ Place::Static(ref static_) => {
if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
Err(place)
} else {
- Ok(RootPlace { place, is_local_mutation_allowed })
- },
+ Ok(RootPlace {
+ place,
+ is_local_mutation_allowed,
+ })
+ }
+ }
Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
// `*mut` raw pointers are always mutable, regardless of
// context. The users have to check by themselves.
hir::MutMutable => {
- return Ok(RootPlace { place, is_local_mutation_allowed });
+ return Ok(RootPlace {
+ place,
+ is_local_mutation_allowed,
+ });
}
}
}
// }
// ```
let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?;
- Ok(RootPlace { place, is_local_mutation_allowed })
+ Ok(RootPlace {
+ place,
+ is_local_mutation_allowed,
+ })
}
}
} else {
match *place {
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(field, _ty) => {
- let is_projection_from_ty_closure = proj.base
+ let is_projection_from_ty_closure = proj
+ .base
.ty(self.mir, self.tcx)
.to_ty(self.tcx)
.is_closure();
}
}
}
-
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::{Local, Location, Place};
+
+use rustc_data_structures::fx::FxHashSet;
+
+use borrow_check::MirBorrowckCtxt;
+use util::collect_writes::is_place_assignment;
+
+impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+ /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
+ /// local variables lint, to update the context's `used_mut` in a single walk.
+ crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
+ let mut visitor = GatherUsedMutsVisitor {
+ needles: locals,
+ mbcx: self,
+ };
+ visitor.visit_mir(visitor.mbcx.mir);
+ }
+}
+
+/// MIR visitor gathering the assignments to a set of locals, in a single walk.
+/// 'visit = the duration of the MIR walk
+struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
+ needles: FxHashSet<Local>,
+ mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+}
+
+impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
+ fn visit_local(
+ &mut self,
+ local: &Local,
+ place_context: PlaceContext<'tcx>,
+ location: Location,
+ ) {
+ if !self.needles.contains(local) {
+ return;
+ }
+
+ if is_place_assignment(&place_context) {
+ // Propagate the Local assigned at this Location as a used mutable local variable
+ for moi in &self.mbcx.move_data.loc_map[location] {
+ let mpi = &self.mbcx.move_data.moves[*moi].path;
+ let path = &self.mbcx.move_data.move_paths[*mpi];
+ debug!(
+ "assignment of {:?} to {:?}, adding {:?} to used mutable set",
+ path.place, local, path.place
+ );
+ if let Place::Local(user_local) = path.place {
+ self.mbcx.used_mut.insert(user_local);
+ }
+ }
+ }
+ }
+}
// ==============
/// Finds the breakable scope for a given label. This is used for
/// resolving `break` and `continue`.
- pub fn find_breakable_scope(&mut self,
+ pub fn find_breakable_scope(&self,
span: Span,
label: region::Scope)
- -> &mut BreakableScope<'tcx> {
+ -> &BreakableScope<'tcx> {
// find the loop-scope with the correct id
- self.breakable_scopes.iter_mut()
+ self.breakable_scopes.iter()
.rev()
.filter(|breakable_scope| breakable_scope.region_scope == label)
.next()
Err(err) => bug!("invalid loop id for break: {}", err)
}
}
- hir::ExprAgain(dest) => {
+ hir::ExprContinue(dest) => {
match dest.target_id {
Ok(loop_id) => ExprKind::Continue {
label: region::Scope::Node(cx.tcx.hir.node_to_hir_id(loop_id).local_id),
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::mir::Field;
+use rustc::mir::interpret::ConstValue;
use rustc::util::common::ErrorReported;
use syntax_pos::{Span, DUMMY_SP};
suffix: &[Pattern<'tcx>]
) -> Result<bool, ErrorReported> {
let data: &[u8] = match *ctor {
- ConstantValue(const_val @ &ty::Const { val: ConstVal::Value(..), .. }) => {
- if let Some(ptr) = const_val.to_ptr() {
- let is_array_ptr = const_val.ty
+ ConstantValue(&ty::Const { val: ConstVal::Value(const_val), ty }) => {
+ let val = match const_val {
+ ConstValue::ByRef(..) => bug!("unexpected ConstValue::ByRef"),
+ ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val,
+ };
+ if let Ok(ptr) = val.to_ptr() {
+ let is_array_ptr = ty
.builtin_deref(true)
.and_then(|t| t.ty.builtin_index())
.map_or(false, |t| t == tcx.types.u8);
assert!(is_array_ptr);
tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref()
} else {
- bug!()
+ bug!("unexpected non-ptr ConstantValue")
}
}
_ => bug!()
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
use rustc::lint;
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc::util::common::ErrorReported;
use rustc::hir::def::*;
);
let label_msg = match pat.node {
PatKind::Path(hir::QPath::Resolved(None, ref path))
- if path.segments.len() == 1 && path.segments[0].parameters.is_none() => {
+ if path.segments.len() == 1 && path.segments[0].args.is_none() => {
format!("interpreted as a {} pattern, not new variable", path.def.kind_name())
}
_ => format!("pattern `{}` not covered", pattern_string),
"pattern binding `{}` is named the same as one \
of the variants of the type `{}`",
name.node, ty_path);
- help!(err,
- "if you meant to match on a variant, \
- consider making the path in the pattern qualified: `{}::{}`",
- ty_path, name.node);
+ err.span_suggestion_with_applicability(
+ p.span,
+ "to match on the variant, qualify the path",
+ format!("{}::{}", ty_path, name.node),
+ Applicability::MachineApplicable
+ );
err.emit();
}
}
NotUseful => {
match source {
hir::MatchSource::IfLetDesugar { .. } => {
- if printed_if_let_err {
- // we already printed an irrefutable if-let pattern error.
- // We don't want two, that's just confusing.
+ if cx.tcx.features().irrefutable_let_patterns {
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id, pat.span,
+ "irrefutable if-let pattern");
} else {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
- struct_span_err!(cx.tcx.sess, span, E0162,
- "irrefutable if-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
- printed_if_let_err = true;
+ if printed_if_let_err {
+ // we already printed an irrefutable if-let pattern error.
+ // We don't want two, that's just confusing.
+ } else {
+ // find the first arm pattern so we can use its span
+ let &(ref first_arm_pats, _) = &arms[0];
+ let first_pat = &first_arm_pats[0];
+ let span = first_pat.0.span;
+ struct_span_err!(cx.tcx.sess, span, E0162,
+ "irrefutable if-let pattern")
+ .span_label(span, "irrefutable pattern")
+ .emit();
+ printed_if_let_err = true;
+ }
}
},
hir::MatchSource::WhileLetDesugar => {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
-
// check which arm we're on.
match arm_index {
// The arm with the user-specified pattern.
0 => {
cx.tcx.lint_node(
- lint::builtin::UNREACHABLE_PATTERNS,
+ lint::builtin::UNREACHABLE_PATTERNS,
hir_pat.id, pat.span,
"unreachable pattern");
},
// The arm with the wildcard pattern.
1 => {
- struct_span_err!(cx.tcx.sess, span, E0165,
- "irrefutable while-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
+ if cx.tcx.features().irrefutable_let_patterns {
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id, pat.span,
+ "irrefutable while-let pattern");
+ } else {
+ // find the first arm pattern so we can use its span
+ let &(ref first_arm_pats, _) = &arms[0];
+ let first_pat = &first_arm_pats[0];
+ let span = first_pat.0.span;
+ struct_span_err!(cx.tcx.sess, span, E0165,
+ "irrefutable while-let pattern")
+ .span_label(span, "irrefutable pattern")
+ .emit();
+ }
},
_ => bug!(),
}
}
PatKind::Slice(ref prefix, ref slice, ref suffix) => {
- let ty = self.tables.node_id_to_type(pat.hir_id);
match ty.sty {
ty::TyRef(_, ty, _) =>
PatternKind::Deref {
pat.span, ty, prefix, slice, suffix))
},
},
-
ty::TySlice(..) |
ty::TyArray(..) =>
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
-
+ ty::TyError => { // Avoid ICE
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
ref sty =>
span_bug!(
pat.span,
}
PatKind::Tuple(ref subpatterns, ddpos) => {
- let ty = self.tables.node_id_to_type(pat.hir_id);
match ty.sty {
ty::TyTuple(ref tys) => {
let subpatterns =
PatternKind::Leaf { subpatterns: subpatterns }
}
-
+ ty::TyError => { // Avoid ICE (#50577)
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
}
}
let var_ty = self.tables.node_id_to_type(pat.hir_id);
let region = match var_ty.sty {
ty::TyRef(r, _, _) => Some(r),
+ ty::TyError => { // Avoid ICE
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
_ => None,
};
let bm = *self.tables.pat_binding_modes().get(pat.hir_id)
let def = self.tables.qpath_def(qpath, pat.hir_id);
let adt_def = match ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
- _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
+ ty::TyError => { // Avoid ICE (#50585)
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
+ _ => span_bug!(pat.span,
+ "tuple struct pattern not applied to an ADT {:?}",
+ ty.sty),
};
let variant_def = adt_def.variant_of_def(def);
let substs = match ty.sty {
ty::TyAdt(_, substs) |
ty::TyFnDef(_, substs) => substs,
+ ty::TyError => { // Avoid ICE (#50585)
+ return PatternKind::Wild;
+ }
_ => bug!("inappropriate type for def: {:?}", ty.sty),
};
PatternKind::Variant {
item: &'tcx hir::Item,
output: &mut Vec<MonoItem<'tcx>>) {
match item.node {
- hir::ItemImpl(_,
- _,
- _,
- ref generics,
- ..,
- ref impl_item_refs) => {
- if generics.is_type_parameterized() {
- return
+ hir::ItemImpl(_, _, _, ref generics, .., ref impl_item_refs) => {
+ for param in &generics.params {
+ match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {}
+ hir::GenericParamKind::Type { .. } => return,
+ }
}
let impl_def_id = tcx.hir.local_def_id(item.id);
if used_unsafe.contains(&parent_id) {
Some(("block".to_string(), parent_id))
} else if let Some(hir::map::NodeItem(&hir::Item {
- node: hir::ItemFn(_, fn_unsafety, _, _, _, _),
+ node: hir::ItemFn(_, header, _, _),
..
})) = tcx.hir.find(parent_id) {
- match fn_unsafety {
+ match header.unsafety {
hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
hir::Unsafety::Normal => None,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc::ty::{self, TyCtxt};
use rustc::session::config::BorrowckMode;
+use rustc::ty::{self, TyCtxt};
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
use syntax_pos::{MultiSpan, Span};
use std::fmt;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum Origin { Ast, Mir }
+pub enum Origin {
+ Ast,
+ Mir,
+}
impl fmt::Display for Origin {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
}
pub trait BorrowckErrors<'cx>: Sized + Copy {
- fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'cx>;
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId,
+ ) -> DiagnosticBuilder<'cx>;
- fn struct_span_err<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'cx>;
+ fn struct_span_err<S: Into<MultiSpan>>(self, sp: S, msg: &str) -> DiagnosticBuilder<'cx>;
/// Cancels the given error if we shouldn't emit errors for a given
/// origin in the current mode.
///
/// Always make sure that the error gets passed through this function
/// before you return it.
- fn cancel_if_wrong_origin(self,
- diag: DiagnosticBuilder<'cx>,
- o: Origin)
- -> DiagnosticBuilder<'cx>;
-
- fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0505,
- "cannot move out of `{}` because it is borrowed{OGN}",
- desc, OGN=o);
+ fn cancel_if_wrong_origin(
+ self,
+ diag: DiagnosticBuilder<'cx>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx>;
+
+ fn cannot_move_when_borrowed(
+ self,
+ span: Span,
+ desc: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0505,
+ "cannot move out of `{}` because it is borrowed{OGN}",
+ desc,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_use_when_mutably_borrowed(self,
- span: Span,
- desc: &str,
- borrow_span: Span,
- borrow_desc: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, span, E0503,
- "cannot use `{}` because it was mutably borrowed{OGN}",
- desc, OGN=o);
-
- err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc));
+ fn cannot_use_when_mutably_borrowed(
+ self,
+ span: Span,
+ desc: &str,
+ borrow_span: Span,
+ borrow_desc: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0503,
+ "cannot use `{}` because it was mutably borrowed{OGN}",
+ desc,
+ OGN = o
+ );
+
+ err.span_label(
+ borrow_span,
+ format!("borrow of `{}` occurs here", borrow_desc),
+ );
err.span_label(span, format!("use of borrowed `{}`", borrow_desc));
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_uninitialized_variable(self,
- span: Span,
- verb: &str,
- desc: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0381,
- "{} of possibly uninitialized variable: `{}`{OGN}",
- verb, desc, OGN=o);
+ fn cannot_act_on_uninitialized_variable(
+ self,
+ span: Span,
+ verb: &str,
+ desc: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0381,
+ "{} of possibly uninitialized variable: `{}`{OGN}",
+ verb,
+ desc,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_mutably_borrow_multiply(self,
- new_loan_span: Span,
- desc: &str,
- opt_via: &str,
- old_loan_span: Span,
- old_opt_via: &str,
- old_load_end_span: Option<Span>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, new_loan_span, E0499,
- "cannot borrow `{}`{} as mutable more than once at a time{OGN}",
- desc, opt_via, OGN=o);
+ fn cannot_mutably_borrow_multiply(
+ self,
+ new_loan_span: Span,
+ desc: &str,
+ opt_via: &str,
+ old_loan_span: Span,
+ old_opt_via: &str,
+ old_load_end_span: Option<Span>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0499,
+ "cannot borrow `{}`{} as mutable more than once at a time{OGN}",
+ desc,
+ opt_via,
+ OGN = o
+ );
if old_loan_span == new_loan_span {
// Both borrows are happening in the same place
// Meaning the borrow is occurring in a loop
- err.span_label(new_loan_span,
- format!("mutable borrow starts here in previous \
- iteration of loop{}", opt_via));
+ err.span_label(
+ new_loan_span,
+ format!(
+ "mutable borrow starts here in previous \
+ iteration of loop{}",
+ opt_via
+ ),
+ );
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, "mutable borrow ends here");
}
} else {
- err.span_label(old_loan_span,
- format!("first mutable borrow occurs here{}", old_opt_via));
- err.span_label(new_loan_span,
- format!("second mutable borrow occurs here{}", opt_via));
+ err.span_label(
+ old_loan_span,
+ format!("first mutable borrow occurs here{}", old_opt_via),
+ );
+ err.span_label(
+ new_loan_span,
+ format!("second mutable borrow occurs here{}", opt_via),
+ );
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, "first borrow ends here");
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_uniquely_borrow_by_two_closures(self,
- new_loan_span: Span,
- desc: &str,
- old_loan_span: Span,
- old_load_end_span: Option<Span>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, new_loan_span, E0524,
- "two closures require unique access to `{}` at the same time{OGN}",
- desc, OGN=o);
- err.span_label(
- old_loan_span,
- "first closure is constructed here");
- err.span_label(
+ fn cannot_uniquely_borrow_by_two_closures(
+ self,
+ new_loan_span: Span,
+ desc: &str,
+ old_loan_span: Span,
+ old_load_end_span: Option<Span>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
new_loan_span,
- "second closure is constructed here");
+ E0524,
+ "two closures require unique access to `{}` at the same time{OGN}",
+ desc,
+ OGN = o
+ );
+ err.span_label(old_loan_span, "first closure is constructed here");
+ err.span_label(new_loan_span, "second closure is constructed here");
if let Some(old_load_end_span) = old_load_end_span {
- err.span_label(
- old_load_end_span,
- "borrow from first closure ends here");
+ err.span_label(old_load_end_span, "borrow from first closure ends here");
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_uniquely_borrow_by_one_closure(self,
- new_loan_span: Span,
- desc_new: &str,
- opt_via: &str,
- old_loan_span: Span,
- noun_old: &str,
- old_opt_via: &str,
- previous_end_span: Option<Span>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, new_loan_span, E0500,
- "closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
- desc_new, noun_old, old_opt_via, OGN=o);
- err.span_label(new_loan_span,
- format!("closure construction occurs here{}", opt_via));
- err.span_label(old_loan_span,
- format!("borrow occurs here{}", old_opt_via));
+ fn cannot_uniquely_borrow_by_one_closure(
+ self,
+ new_loan_span: Span,
+ desc_new: &str,
+ opt_via: &str,
+ old_loan_span: Span,
+ noun_old: &str,
+ old_opt_via: &str,
+ previous_end_span: Option<Span>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0500,
+ "closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
+ desc_new,
+ noun_old,
+ old_opt_via,
+ OGN = o
+ );
+ err.span_label(
+ new_loan_span,
+ format!("closure construction occurs here{}", opt_via),
+ );
+ err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
if let Some(previous_end_span) = previous_end_span {
err.span_label(previous_end_span, "borrow ends here");
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reborrow_already_uniquely_borrowed(self,
- new_loan_span: Span,
- desc_new: &str,
- opt_via: &str,
- kind_new: &str,
- old_loan_span: Span,
- old_opt_via: &str,
- previous_end_span: Option<Span>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, new_loan_span, E0501,
- "cannot borrow `{}`{} as {} because previous closure \
- requires unique access{OGN}",
- desc_new, opt_via, kind_new, OGN=o);
- err.span_label(new_loan_span,
- format!("borrow occurs here{}", opt_via));
- err.span_label(old_loan_span,
- format!("closure construction occurs here{}", old_opt_via));
+ fn cannot_reborrow_already_uniquely_borrowed(
+ self,
+ new_loan_span: Span,
+ desc_new: &str,
+ opt_via: &str,
+ kind_new: &str,
+ old_loan_span: Span,
+ old_opt_via: &str,
+ previous_end_span: Option<Span>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0501,
+ "cannot borrow `{}`{} as {} because previous closure \
+ requires unique access{OGN}",
+ desc_new,
+ opt_via,
+ kind_new,
+ OGN = o
+ );
+ err.span_label(new_loan_span, format!("borrow occurs here{}", opt_via));
+ err.span_label(
+ old_loan_span,
+ format!("closure construction occurs here{}", old_opt_via),
+ );
if let Some(previous_end_span) = previous_end_span {
err.span_label(previous_end_span, "borrow from closure ends here");
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reborrow_already_borrowed(self,
- span: Span,
- desc_new: &str,
- msg_new: &str,
- kind_new: &str,
- old_span: Span,
- noun_old: &str,
- kind_old: &str,
- msg_old: &str,
- old_load_end_span: Option<Span>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, span, E0502,
- "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
- desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o);
+ fn cannot_reborrow_already_borrowed(
+ self,
+ span: Span,
+ desc_new: &str,
+ msg_new: &str,
+ kind_new: &str,
+ old_span: Span,
+ noun_old: &str,
+ kind_old: &str,
+ msg_old: &str,
+ old_load_end_span: Option<Span>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0502,
+ "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
+ desc_new,
+ msg_new,
+ kind_new,
+ noun_old,
+ kind_old,
+ msg_old,
+ OGN = o
+ );
err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
- err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, msg_old));
+ err.span_label(
+ old_span,
+ format!("{} borrow occurs here{}", kind_old, msg_old),
+ );
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
}
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, span, E0506,
- "cannot assign to `{}` because it is borrowed{OGN}",
- desc, OGN=o);
+ fn cannot_assign_to_borrowed(
+ self,
+ span: Span,
+ borrow_span: Span,
+ desc: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0506,
+ "cannot assign to `{}` because it is borrowed{OGN}",
+ desc,
+ OGN = o
+ );
err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc));
- err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc));
+ err.span_label(
+ span,
+ format!("assignment to borrowed `{}` occurs here", desc),
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0504,
- "cannot move `{}` into closure because it is borrowed{OGN}",
- desc, OGN=o);
+ fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0504,
+ "cannot move `{}` into closure because it is borrowed{OGN}",
+ desc,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cannot_reassign_immutable(
+ self,
+ span: Span,
+ desc: &str,
+ is_arg: bool,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
let msg = if is_arg {
"to immutable argument"
} else {
"twice to immutable variable"
};
- let err = struct_span_err!(self, span, E0384,
- "cannot assign {} `{}`{OGN}",
- msg, desc, OGN=o);
+ let err = struct_span_err!(
+ self,
+ span,
+ E0384,
+ "cannot assign {} `{}`{OGN}",
+ msg,
+ desc,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign(self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0594,
- "cannot assign to {}{OGN}",
- desc, OGN=o);
+ fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(self, span, E0594, "cannot assign to {}{OGN}", desc, OGN = o);
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_static(self, span: Span, desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> {
self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
}
- fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, move_from_span, E0507,
- "cannot move out of {}{OGN}",
- move_from_desc, OGN=o);
+ fn cannot_move_out_of(
+ self,
+ move_from_span: Span,
+ move_from_desc: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ move_from_span,
+ E0507,
+ "cannot move out of {}{OGN}",
+ move_from_desc,
+ OGN = o
+ );
err.span_label(
move_from_span,
- format!("cannot move out of {}", move_from_desc));
+ format!("cannot move out of {}", move_from_desc),
+ );
self.cancel_if_wrong_origin(err, o)
}
/// Signal an error due to an attempt to move out of the interior
/// of an array or slice. `is_index` is None when error origin
/// didn't capture whether there was an indexing operation or not.
- fn cannot_move_out_of_interior_noncopy(self,
- move_from_span: Span,
- ty: ty::Ty,
- is_index: Option<bool>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cannot_move_out_of_interior_noncopy(
+ self,
+ move_from_span: Span,
+ ty: ty::Ty,
+ is_index: Option<bool>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
let type_name = match (&ty.sty, is_index) {
- (&ty::TyArray(_, _), Some(true)) |
- (&ty::TyArray(_, _), None) => "array",
- (&ty::TySlice(_), _) => "slice",
+ (&ty::TyArray(_, _), Some(true)) | (&ty::TyArray(_, _), None) => "array",
+ (&ty::TySlice(_), _) => "slice",
_ => span_bug!(move_from_span, "this path should not cause illegal move"),
};
- let mut err = struct_span_err!(self, move_from_span, E0508,
- "cannot move out of type `{}`, \
- a non-copy {}{OGN}",
- ty, type_name, OGN=o);
+ let mut err = struct_span_err!(
+ self,
+ move_from_span,
+ E0508,
+ "cannot move out of type `{}`, \
+ a non-copy {}{OGN}",
+ ty,
+ type_name,
+ OGN = o
+ );
err.span_label(move_from_span, "cannot move out of here");
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_move_out_of_interior_of_drop(self,
- move_from_span: Span,
- container_ty: ty::Ty,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, move_from_span, E0509,
- "cannot move out of type `{}`, \
- which implements the `Drop` trait{OGN}",
- container_ty, OGN=o);
+ fn cannot_move_out_of_interior_of_drop(
+ self,
+ move_from_span: Span,
+ container_ty: ty::Ty,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ move_from_span,
+ E0509,
+ "cannot move out of type `{}`, \
+ which implements the `Drop` trait{OGN}",
+ container_ty,
+ OGN = o
+ );
err.span_label(move_from_span, "cannot move out of here");
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_moved_value(self,
- use_span: Span,
- verb: &str,
- optional_adverb_for_moved: &str,
- moved_path: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, use_span, E0382,
- "{} of {}moved value: `{}`{OGN}",
- verb, optional_adverb_for_moved, moved_path, OGN=o);
+ fn cannot_act_on_moved_value(
+ self,
+ use_span: Span,
+ verb: &str,
+ optional_adverb_for_moved: &str,
+ moved_path: Option<String>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let moved_path = moved_path
+ .map(|mp| format!(": `{}`", mp))
+ .unwrap_or("".to_owned());
+
+ let err = struct_span_err!(
+ self,
+ use_span,
+ E0382,
+ "{} of {}moved value{}{OGN}",
+ verb,
+ optional_adverb_for_moved,
+ moved_path,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_partially_reinit_an_uninit_struct(self,
- span: Span,
- uninit_path: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self,
- span,
- E0383,
- "partial reinitialization of uninitialized structure `{}`{OGN}",
- uninit_path, OGN=o);
+ fn cannot_partially_reinit_an_uninit_struct(
+ self,
+ span: Span,
+ uninit_path: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0383,
+ "partial reinitialization of uninitialized structure `{}`{OGN}",
+ uninit_path,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn closure_cannot_assign_to_borrowed(self,
- span: Span,
- descr: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
- descr, OGN=o);
+ fn closure_cannot_assign_to_borrowed(
+ self,
+ span: Span,
+ descr: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0595,
+ "closure cannot assign to {}{OGN}",
+ descr,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_borrow_path_as_mutable(self,
- span: Span,
- path: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
- path, OGN=o);
+ fn cannot_borrow_path_as_mutable(
+ self,
+ span: Span,
+ path: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0596,
+ "cannot borrow {} as mutable{OGN}",
+ path,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_borrow_across_generator_yield(self,
- span: Span,
- yield_span: Span,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self,
- span,
- E0626,
- "borrow may still be in use when generator yields{OGN}",
- OGN=o);
+ fn cannot_borrow_across_generator_yield(
+ self,
+ span: Span,
+ yield_span: Span,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0626,
+ "borrow may still be in use when generator yields{OGN}",
+ OGN = o
+ );
err.span_label(yield_span, "possible yield occurs here");
self.cancel_if_wrong_origin(err, o)
}
- fn path_does_not_live_long_enough(self,
- span: Span,
- path: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
- path, OGN=o);
+ fn path_does_not_live_long_enough(
+ self,
+ span: Span,
+ path: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0597,
+ "{} does not live long enough{OGN}",
+ path,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn lifetime_too_short_for_reborrow(self,
- span: Span,
- path: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let err = struct_span_err!(self, span, E0598,
- "lifetime of {} is too short to guarantee \
- its contents can be safely reborrowed{OGN}",
- path, OGN=o);
+ fn lifetime_too_short_for_reborrow(
+ self,
+ span: Span,
+ path: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let err = struct_span_err!(
+ self,
+ span,
+ E0598,
+ "lifetime of {} is too short to guarantee \
+ its contents can be safely reborrowed{OGN}",
+ path,
+ OGN = o
+ );
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_act_on_capture_in_sharable_fn(self,
- span: Span,
- bad_thing: &str,
- help: (Span, &str),
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cannot_act_on_capture_in_sharable_fn(
+ self,
+ span: Span,
+ bad_thing: &str,
+ help: (Span, &str),
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
let (help_span, help_msg) = help;
- let mut err = struct_span_err!(self, span, E0387,
- "{} in a captured outer variable in an `Fn` closure{OGN}",
- bad_thing, OGN=o);
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0387,
+ "{} in a captured outer variable in an `Fn` closure{OGN}",
+ bad_thing,
+ OGN = o
+ );
err.span_help(help_span, help_msg);
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_assign_into_immutable_reference(self,
- span: Span,
- bad_thing: &str,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
- bad_thing, OGN=o);
+ fn cannot_assign_into_immutable_reference(
+ self,
+ span: Span,
+ bad_thing: &str,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0389,
+ "{} in a `&` reference{OGN}",
+ bad_thing,
+ OGN = o
+ );
err.span_label(span, "assignment into an immutable reference");
self.cancel_if_wrong_origin(err, o)
}
- fn cannot_capture_in_long_lived_closure(self,
- closure_span: Span,
- borrowed_path: &str,
- capture_span: Span,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
- let mut err = struct_span_err!(self, closure_span, E0373,
- "closure may outlive the current function, \
- but it borrows {}, \
- which is owned by the current function{OGN}",
- borrowed_path, OGN=o);
+ fn cannot_capture_in_long_lived_closure(
+ self,
+ closure_span: Span,
+ borrowed_path: &str,
+ capture_span: Span,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
+ let mut err = struct_span_err!(
+ self,
+ closure_span,
+ E0373,
+ "closure may outlive the current function, \
+ but it borrows {}, \
+ which is owned by the current function{OGN}",
+ borrowed_path,
+ OGN = o
+ );
err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
- .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
+ .span_label(
+ closure_span,
+ format!("may outlive borrowed value {}", borrowed_path),
+ );
self.cancel_if_wrong_origin(err, o)
}
}
impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
- fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str,
- code: DiagnosticId)
- -> DiagnosticBuilder<'cx>
- {
+ fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ self,
+ sp: S,
+ msg: &str,
+ code: DiagnosticId,
+ ) -> DiagnosticBuilder<'cx> {
self.sess.struct_span_err_with_code(sp, msg, code)
}
- fn struct_span_err<S: Into<MultiSpan>>(self,
- sp: S,
- msg: &str)
- -> DiagnosticBuilder<'cx>
- {
+ fn struct_span_err<S: Into<MultiSpan>>(self, sp: S, msg: &str) -> DiagnosticBuilder<'cx> {
self.sess.struct_span_err(sp, msg)
}
- fn cancel_if_wrong_origin(self,
- mut diag: DiagnosticBuilder<'cx>,
- o: Origin)
- -> DiagnosticBuilder<'cx>
- {
+ fn cancel_if_wrong_origin(
+ self,
+ mut diag: DiagnosticBuilder<'cx>,
+ o: Origin,
+ ) -> DiagnosticBuilder<'cx> {
if !o.should_emit_errors(self.borrowck_mode()) {
self.sess.diagnostic().cancel(&mut diag);
}
return;
}
- match place_context {
- PlaceContext::Store | PlaceContext::Call => {
- self.locations.push(location);
- }
- PlaceContext::AsmOutput |
- PlaceContext::Drop |
- PlaceContext::Inspect |
- PlaceContext::Borrow { .. } |
- PlaceContext::Projection(..) |
- PlaceContext::Copy |
- PlaceContext::Move |
- PlaceContext::StorageLive |
- PlaceContext::StorageDead |
- PlaceContext::Validate => {
- // TO-DO
- // self.super_local(local)
- }
+ if is_place_assignment(&place_context) {
+ self.locations.push(location);
}
}
- // TO-DO
- // fn super_local()
+}
+
+/// Returns true if this place context represents an assignment statement
+crate fn is_place_assignment(place_context: &PlaceContext) -> bool {
+ match *place_context {
+ PlaceContext::Store | PlaceContext::Call | PlaceContext::AsmOutput => true,
+ PlaceContext::Drop
+ | PlaceContext::Inspect
+ | PlaceContext::Borrow { .. }
+ | PlaceContext::Projection(..)
+ | PlaceContext::Copy
+ | PlaceContext::Move
+ | PlaceContext::StorageLive
+ | PlaceContext::StorageDead
+ | PlaceContext::Validate => false,
+ }
}
}
}
+ fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
+ if asyncness.is_async() {
+ struct_span_err!(self.session, span, E0706,
+ "trait fns cannot be declared `async`").emit()
+ }
+ }
+
fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
match constness.node {
Constness::Const => {
}
}
- fn no_questions_in_bounds(&self, bounds: &TyParamBounds, where_: &str, is_trait: bool) {
+ fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
for bound in bounds {
- if let TraitTyParamBound(ref poly, TraitBoundModifier::Maybe) = *bound {
+ if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
let mut err = self.err_handler().struct_span_err(poly.span,
&format!("`?Trait` is not permitted in {}", where_));
if is_trait {
}
fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParam>) {
- // Check: Only lifetime parameters
- let non_lifetime_param_spans : Vec<_> = params.iter()
- .filter_map(|param| match *param {
- GenericParam::Lifetime(_) => None,
- GenericParam::Type(ref t) => Some(t.ident.span),
- }).collect();
- if !non_lifetime_param_spans.is_empty() {
- self.err_handler().span_err(non_lifetime_param_spans,
- "only lifetime parameters can be used in this context");
- }
-
- // Check: No bounds on lifetime parameters
- for param in params.iter() {
- match *param {
- GenericParam::Lifetime(ref l) => {
- if !l.bounds.is_empty() {
- let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect();
- self.err_handler().span_err(spans,
- "lifetime bounds cannot be used in this context");
+ // Check only lifetime parameters are present and that the lifetime
+ // parameters that are present have no bounds.
+ let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ if !param.bounds.is_empty() {
+ let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+ self.err_handler()
+ .span_err(spans, "lifetime bounds cannot be used in this context");
}
+ None
}
- GenericParam::Type(_) => {}
- }
+ _ => Some(param.ident.span),
+ }).collect();
+ if !non_lt_param_spans.is_empty() {
+ self.err_handler().span_err(non_lt_param_spans,
+ "only lifetime parameters can be used in this context");
}
}
}
TyKind::TraitObject(ref bounds, ..) => {
let mut any_lifetime_bounds = false;
for bound in bounds {
- if let RegionTyParamBound(ref lifetime) = *bound {
+ if let GenericBound::Outlives(ref lifetime) = *bound {
if any_lifetime_bounds {
span_err!(self.session, lifetime.ident.span, E0226,
"only a single explicit lifetime bound is permitted");
}
TyKind::ImplTrait(ref bounds) => {
if !bounds.iter()
- .any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
+ .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
self.err_handler().span_err(ty.span, "at least one trait must be specified");
}
}
// }
// foo!(bar::baz<T>);
use_tree.prefix.segments.iter().find(|segment| {
- segment.parameters.is_some()
+ segment.args.is_some()
}).map(|segment| {
- self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
+ self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
"generic arguments in import path");
});
for impl_item in impl_items {
self.invalid_visibility(&impl_item.vis, None);
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
- self.check_trait_fn_not_const(sig.constness);
+ self.check_trait_fn_not_const(sig.header.constness);
+ self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness);
}
}
}
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
- if generics.is_parameterized() {
+ if !generics.params.is_empty() {
struct_span_err!(self.session, item.span, E0567,
"auto traits cannot have generic parameters").emit();
}
self.no_questions_in_bounds(bounds, "supertraits", true);
for trait_item in trait_items {
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
- self.check_trait_fn_not_const(sig.constness);
+ self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness);
+ self.check_trait_fn_not_const(sig.header.constness);
if block.is_none() {
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
if mut_ident {
}
ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
for param in params {
- if let GenericParam::Type(TyParam {
- ident,
- ref bounds,
- ref default,
- ..
- }) = *param
- {
- if !bounds.is_empty() {
- self.err_handler().span_err(ident.span,
- "type parameters on the left side of a \
- trait alias cannot be bounded");
- }
- if !default.is_none() {
- self.err_handler().span_err(ident.span,
- "type parameters on the left side of a \
- trait alias cannot have defaults");
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { ref default, .. } => {
+ if !param.bounds.is_empty() {
+ self.err_handler()
+ .span_err(param.ident.span, "type parameters on the left \
+ side of a trait alias cannot be bounded");
+ }
+ if !default.is_none() {
+ self.err_handler()
+ .span_err(param.ident.span, "type parameters on the left \
+ side of a trait alias cannot have defaults");
+ }
}
}
}
fn visit_vis(&mut self, vis: &'a Visibility) {
match vis.node {
VisibilityKind::Restricted { ref path, .. } => {
- path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
- self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
+ path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
+ self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
"generic arguments in visibility path");
});
}
visit::walk_vis(self, vis)
}
- fn visit_generics(&mut self, g: &'a Generics) {
+ fn visit_generics(&mut self, generics: &'a Generics) {
let mut seen_non_lifetime_param = false;
let mut seen_default = None;
- for param in &g.params {
- match (param, seen_non_lifetime_param) {
- (&GenericParam::Lifetime(ref ld), true) => {
+ for param in &generics.params {
+ match (¶m.kind, seen_non_lifetime_param) {
+ (GenericParamKind::Lifetime { .. }, true) => {
self.err_handler()
- .span_err(ld.lifetime.ident.span, "lifetime parameters must be leading");
+ .span_err(param.ident.span, "lifetime parameters must be leading");
},
- (&GenericParam::Lifetime(_), false) => {}
- _ => {
+ (GenericParamKind::Lifetime { .. }, false) => {}
+ (GenericParamKind::Type { ref default, .. }, _) => {
seen_non_lifetime_param = true;
+ if default.is_some() {
+ seen_default = Some(param.ident.span);
+ } else if let Some(span) = seen_default {
+ self.err_handler()
+ .span_err(span, "type parameters with a default must be trailing");
+ break;
+ }
}
}
-
- if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param {
- seen_default = Some(ty_param.ident.span);
- } else if let Some(span) = seen_default {
- self.err_handler()
- .span_err(span, "type parameters with a default must be trailing");
- break
- }
}
- for predicate in &g.where_clause.predicates {
+ for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
self.err_handler().span_err(predicate.span, "equality constraints are not yet \
supported in where clauses (#20041)");
}
}
- visit::walk_generics(self, g)
+ visit::walk_generics(self, generics)
}
fn visit_generic_param(&mut self, param: &'a GenericParam) {
- if let GenericParam::Lifetime(ref ld) = *param {
- self.check_lifetime(ld.lifetime.ident);
+ if let GenericParamKind::Lifetime { .. } = param.kind {
+ self.check_lifetime(param.ident);
}
visit::walk_generic_param(self, param);
}
visit::walk_ty(self, t);
}
}
- fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters) {
- match *path_parameters {
- PathParameters::AngleBracketed(ref params) => {
- for type_ in ¶ms.types {
- self.visit_ty(type_);
- }
- for type_binding in ¶ms.bindings {
+ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
+ match *generic_args {
+ GenericArgs::AngleBracketed(ref data) => {
+ data.args.iter().for_each(|arg| match arg {
+ GenericArg::Type(ty) => self.visit_ty(ty),
+ _ => {}
+ });
+ for type_binding in &data.bindings {
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
// are allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
}
}
- PathParameters::Parenthesized(ref params) => {
- for type_ in ¶ms.inputs {
+ GenericArgs::Parenthesized(ref data) => {
+ for type_ in &data.inputs {
self.visit_ty(type_);
}
- if let Some(ref type_) = params.output {
+ if let Some(ref type_) = data.output {
// `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
//
// To implement this, we disallow `impl Trait` from `qself`
// (for cases like `<impl Trait>::Foo>`)
- // but we allow `impl Trait` in `PathParameters`
+ // but we allow `impl Trait` in `GenericArgs`
// iff there are no more PathSegments.
if let Some(ref qself) = *qself {
// `impl Trait` in `qself` is always illegal
E0666, // nested `impl Trait` is illegal
E0667, // `impl Trait` in projections
E0696, // `continue` pointing to a labeled block
+ E0706, // `async fn` in trait
}
hir_visit::walk_impl_item(self, ii)
}
- fn visit_ty_param_bound(&mut self, bounds: &'v hir::TyParamBound) {
- self.record("TyParamBound", Id::None, bounds);
- hir_visit::walk_ty_param_bound(self, bounds)
+ fn visit_param_bound(&mut self, bounds: &'v hir::GenericBound) {
+ self.record("GenericBound", Id::None, bounds);
+ hir_visit::walk_param_bound(self, bounds)
}
fn visit_struct_field(&mut self, s: &'v hir::StructField) {
ast_visit::walk_impl_item(self, ii)
}
- fn visit_ty_param_bound(&mut self, bounds: &'v ast::TyParamBound) {
- self.record("TyParamBound", Id::None, bounds);
- ast_visit::walk_ty_param_bound(self, bounds)
+ fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) {
+ self.record("GenericBound", Id::None, bounds);
+ ast_visit::walk_param_bound(self, bounds)
}
fn visit_struct_field(&mut self, s: &'v ast::StructField) {
self.require_break_cx("break", e.span);
}
- hir::ExprAgain(label) => {
+ hir::ExprContinue(label) => {
self.require_label_in_labeled_block(e.span, &label, "continue");
match label.target_id {
// More control flow (also not very meaningful).
hir::ExprBreak(..) |
- hir::ExprAgain(_) |
+ hir::ExprContinue(_) |
hir::ExprRet(_) |
// Generator expressions
extern crate syntax_pos;
extern crate rustc_data_structures;
-use rustc::hir::{self, PatKind};
+use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::def::Def;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
self.access_levels.is_public(trait_id)
}
- fn check_ty_param_bound(&mut self,
- ty_param_bound: &hir::TyParamBound) {
- if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
+ fn check_generic_bound(&mut self, bound: &hir::GenericBound) {
+ if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
if self.path_is_private_type(&trait_ref.trait_ref.path) {
self.old_error_set.insert(trait_ref.trait_ref.ref_id);
}
}
for bound in bounds.iter() {
- self.check_ty_param_bound(bound)
+ self.check_generic_bound(bound)
}
}
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
- for ty_param in generics.ty_params() {
- for bound in ty_param.bounds.iter() {
- self.check_ty_param_bound(bound)
+ generics.params.iter().for_each(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { .. } => {
+ for bound in ¶m.bounds {
+ self.check_generic_bound(bound);
+ }
}
- }
+ });
for predicate in &generics.where_clause.predicates {
match predicate {
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {
for bound in bound_pred.bounds.iter() {
- self.check_ty_param_bound(bound)
+ self.check_generic_bound(bound)
}
}
&hir::WherePredicate::RegionPredicate(_) => {}
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::codemap::CodeMap;
-use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
+use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::visit::{self, FnKind, Visitor};
use syntax::attr;
-use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
-use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
+use syntax::ast::{Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind};
+use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics};
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
function_kind: FnKind<'tcx>,
declaration: &'tcx FnDecl,
_: Span,
- node_id: NodeId) {
- let rib_kind = match function_kind {
- FnKind::ItemFn(..) => {
- ItemRibKind
- }
- FnKind::Method(_, _, _, _) => {
- TraitOrImplItemRibKind
- }
- FnKind::Closure(_) => ClosureRibKind(node_id),
+ node_id: NodeId)
+ {
+ let (rib_kind, asyncness) = match function_kind {
+ FnKind::ItemFn(_, ref header, ..) =>
+ (ItemRibKind, header.asyncness),
+ FnKind::Method(_, ref sig, _, _) =>
+ (TraitOrImplItemRibKind, sig.header.asyncness),
+ FnKind::Closure(_) =>
+ // Async closures aren't resolved through `visit_fn`-- they're
+ // processed separately
+ (ClosureRibKind(node_id), IsAsync::NotAsync),
};
// Create a value rib for the function.
}
visit::walk_fn_ret_ty(self, &declaration.output);
- // Resolve the function body.
+ // Resolve the function body, potentially inside the body of an async closure
+ if let IsAsync::Async(async_closure_id) = asyncness {
+ let rib_kind = ClosureRibKind(async_closure_id);
+ self.ribs[ValueNS].push(Rib::new(rib_kind));
+ self.label_ribs.push(Rib::new(rib_kind));
+ }
+
match function_kind {
FnKind::ItemFn(.., body) |
FnKind::Method(.., body) => {
}
};
+ // Leave the body of the async closure
+ if asyncness.is_async() {
+ self.label_ribs.pop();
+ self.ribs[ValueNS].pop();
+ }
+
debug!("(resolving function) leaving function");
self.label_ribs.pop();
// put all the parameters on the ban list and then remove
// them one by one as they are processed and become available.
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
+ let mut found_default = false;
default_ban_rib.bindings.extend(generics.params.iter()
- .filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None })
- .skip_while(|p| p.default.is_none())
- .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
+ .filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => None,
+ GenericParamKind::Type { ref default, .. } => {
+ if found_default || default.is_some() {
+ found_default = true;
+ return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
+ }
+ None
+ }
+ }));
for param in &generics.params {
- match *param {
- GenericParam::Lifetime(_) => self.visit_generic_param(param),
- GenericParam::Type(ref ty_param) => {
- for bound in &ty_param.bounds {
- self.visit_ty_param_bound(bound);
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
+ GenericParamKind::Type { ref default, .. } => {
+ for bound in ¶m.bounds {
+ self.visit_param_bound(bound);
}
- if let Some(ref ty) = ty_param.default {
+ if let Some(ref ty) = default {
self.ribs[TypeNS].push(default_ban_rib);
self.visit_ty(ty);
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
}
// Allow all following defaults to refer to this type parameter.
- default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name));
+ default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
}
}
}
- for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
+ for p in &generics.where_clause.predicates {
+ self.visit_where_predicate(p);
+ }
}
}
|resolver, span, error| resolve_error(resolver, span, error))
}
- fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
- components: &[&str], is_value: bool) -> hir::Path {
+ fn resolve_str_path(
+ &mut self,
+ span: Span,
+ crate_root: Option<&str>,
+ components: &[&str],
+ args: Option<P<hir::GenericArgs>>,
+ is_value: bool
+ ) -> hir::Path {
+ let mut segments = iter::once(keywords::CrateRoot.name())
+ .chain(
+ crate_root.into_iter()
+ .chain(components.iter().cloned())
+ .map(Symbol::intern)
+ ).map(hir::PathSegment::from_name).collect::<Vec<_>>();
+
+ if let Some(args) = args {
+ let name = segments.last().unwrap().name;
+ *segments.last_mut().unwrap() = hir::PathSegment {
+ name,
+ args: Some(args),
+ infer_types: true,
+ };
+ }
+
let mut path = hir::Path {
span,
def: Def::Err,
- segments: iter::once(keywords::CrateRoot.name()).chain({
- crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
- }).map(hir::PathSegment::from_name).collect(),
+ segments: segments.into(),
};
self.resolve_hir_path(&mut path, is_value);
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
// as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
- ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
+ ctxt.marks().into_iter().find(|&mark| mark.transparency() != Transparency::Opaque)
} else {
ctxt = ctxt.modern();
ctxt.adjust(Mark::root())
ItemKind::Ty(_, ref generics) |
ItemKind::Struct(_, ref generics) |
ItemKind::Union(_, ref generics) |
- ItemKind::Fn(.., ref generics, _) => {
+ ItemKind::Fn(_, _, ref generics, _) => {
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
- |this| visit::walk_item(this, item));
+ |this| visit::walk_item(this, item));
}
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
- walk_list!(this, visit_ty_param_bound, bounds);
+ walk_list!(this, visit_param_bound, bounds);
for trait_item in trait_items {
this.check_proc_macro_attrs(&trait_item.attrs);
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
- walk_list!(this, visit_ty_param_bound, bounds);
+ walk_list!(this, visit_param_bound, bounds);
});
});
}
HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = FxHashMap();
- for param in &generics.params {
- if let GenericParam::Type(ref type_parameter) = *param {
- let ident = type_parameter.ident.modern();
- debug!("with_type_parameter_rib: {}", type_parameter.id);
+ generics.params.iter().for_each(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { .. } => {
+ let ident = param.ident.modern();
+ debug!("with_type_parameter_rib: {}", param.id);
if seen_bindings.contains_key(&ident) {
let span = seen_bindings.get(&ident).unwrap();
ident.name,
span,
);
- resolve_error(self, type_parameter.ident.span, err);
+ resolve_error(self, param.ident.span, err);
}
- seen_bindings.entry(ident).or_insert(type_parameter.ident.span);
+ seen_bindings.entry(ident).or_insert(param.ident.span);
- // plain insert (no renaming)
- let def_id = self.definitions.local_def_id(type_parameter.id);
- let def = Def::TyParam(def_id);
+ // Plain insert (no renaming).
+ let def = Def::TyParam(self.definitions.local_def_id(param.id));
function_type_rib.bindings.insert(ident, def);
- self.record_def(type_parameter.id, PathResolution::new(def));
+ self.record_def(param.id, PathResolution::new(def));
}
- }
+ });
self.ribs[TypeNS].push(function_type_rib);
}
visit::walk_impl_item(this, impl_item)
);
}
- ImplItemKind::Method(_, _) => {
+ ImplItemKind::Method(..) => {
// If this is a trait impl, ensure the method
// exists in trait
this.check_trait_item(impl_item.ident,
visit::walk_expr(self, expr);
self.current_type_ascription.pop();
}
+ // Resolve the body of async exprs inside the async closure to which they desugar
+ ExprKind::Async(_, async_closure_id, ref block) => {
+ let rib_kind = ClosureRibKind(async_closure_id);
+ self.ribs[ValueNS].push(Rib::new(rib_kind));
+ self.label_ribs.push(Rib::new(rib_kind));
+ self.visit_block(&block);
+ self.label_ribs.pop();
+ self.ribs[ValueNS].pop();
+ }
+ // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
+ // resolve the arguments within the proper scopes so that usages of them inside the
+ // closure are detected as upvars rather than normal closure arg usages.
+ ExprKind::Closure(
+ _, IsAsync::Async(inner_closure_id), _, ref fn_decl, ref body, _span) =>
+ {
+ let rib_kind = ClosureRibKind(expr.id);
+ self.ribs[ValueNS].push(Rib::new(rib_kind));
+ self.label_ribs.push(Rib::new(rib_kind));
+ // Resolve arguments:
+ let mut bindings_list = FxHashMap();
+ for argument in &fn_decl.inputs {
+ self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
+ self.visit_ty(&argument.ty);
+ }
+ // No need to resolve return type-- the outer closure return type is
+ // FunctionRetTy::Default
+
+ // Now resolve the inner closure
+ {
+ let rib_kind = ClosureRibKind(inner_closure_id);
+ self.ribs[ValueNS].push(Rib::new(rib_kind));
+ self.label_ribs.push(Rib::new(rib_kind));
+ // No need to resolve arguments: the inner closure has none.
+ // Resolve the return type:
+ visit::walk_fn_ret_ty(self, &fn_decl.output);
+ // Resolve the body
+ self.visit_expr(body);
+ self.label_ribs.pop();
+ self.ribs[ValueNS].pop();
+ }
+ self.label_ribs.pop();
+ self.ribs[ValueNS].pop();
+ }
_ => {
visit::walk_expr(self, expr);
}
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
-use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
-use syntax::ext::hygiene::{self, Mark, MarkKind};
+use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, InvocationKind};
+use syntax::ext::hygiene::{self, Mark, Transparency};
use syntax::ext::placeholders::placeholder;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
self.whitelisted_legacy_custom_derives.contains(&name)
}
- fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
+ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
+ derives: &[Mark]) {
let invocation = self.invocations[&mark];
- self.collect_def_ids(mark, invocation, expansion);
+ self.collect_def_ids(mark, invocation, fragment);
self.current_module = invocation.module.get();
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
legacy_scope: LegacyScope::Invocation(invocation),
expansion: mark,
};
- expansion.visit_with(&mut visitor);
+ fragment.visit_with(&mut visitor);
invocation.expansion.set(visitor.legacy_scope);
}
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
let normal_module_def_id =
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
- self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
+ self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
+ normal_module_def_id);
self.unused_macros.remove(&def_id);
let ext = self.get_macro(def);
if ext.is_modern() {
- invoc.expansion_data.mark.set_kind(MarkKind::Modern);
+ invoc.expansion_data.mark.set_transparency(Transparency::Opaque);
} else if def_id.krate == BUILTIN_MACROS_CRATE {
- invoc.expansion_data.mark.set_kind(MarkKind::Builtin);
+ invoc.expansion_data.mark.set_is_builtin(true);
}
Ok(Some(ext))
}
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
if inert_attrs.contains(&attr_name) {
// FIXME(jseyfried) Avoid `mem::replace` here.
- let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
+ let dummy_item = placeholder(AstFragmentKind::Items, ast::DUMMY_NODE_ID)
.make_items().pop().unwrap();
let dummy_item = Annotatable::Item(dummy_item);
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
let inert_attr = attr.take().unwrap();
attr::mark_known(&inert_attr);
if self.proc_macro_enabled {
- *attr = find_attr_invoc(&mut attrs);
+ *attr = expand::find_attr_invoc(&mut attrs);
}
attrs.push(inert_attr);
attrs
let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
if def != Err(Determinacy::Undetermined) {
// Do not report duplicated errors on every undetermined resolution.
- path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
- self.session.span_err(segment.parameters.as_ref().unwrap().span(),
+ path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
+ self.session.span_err(segment.args.as_ref().unwrap().span(),
"generic arguments in macro path");
});
}
fn collect_def_ids(&mut self,
mark: Mark,
invocation: &'a InvocationData<'a>,
- expansion: &Expansion) {
+ fragment: &AstFragment) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, .. } = *invocation;
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
- expansion.visit_with(def_collector)
+ fragment.visit_with(def_collector)
});
}
id: NodeId,
) {
for param in &generics.params {
- if let ast::GenericParam::Type(ref ty_param) = *param {
- let param_ss = ty_param.ident.span;
- let name = escape(self.span.snippet(param_ss));
- // Append $id to name to make sure each one is unique
- let qualname = format!("{}::{}${}", prefix, name, id);
- if !self.span.filter_generated(Some(param_ss), full_span) {
- let id = ::id_from_node_id(ty_param.id, &self.save_ctxt);
- let span = self.span_from_span(param_ss);
+ match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => {}
+ ast::GenericParamKind::Type { .. } => {
+ let param_ss = param.ident.span;
+ let name = escape(self.span.snippet(param_ss));
+ // Append $id to name to make sure each one is unique.
+ let qualname = format!("{}::{}${}", prefix, name, id);
+ if !self.span.filter_generated(Some(param_ss), full_span) {
+ let id = ::id_from_node_id(param.id, &self.save_ctxt);
+ let span = self.span_from_span(param_ss);
- self.dumper.dump_def(
- &Access {
- public: false,
- reachable: false,
- },
- Def {
- kind: DefKind::Type,
- id,
- span,
- name,
- qualname,
- value: String::new(),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: String::new(),
- sig: None,
- attributes: vec![],
- },
- );
+ self.dumper.dump_def(
+ &Access {
+ public: false,
+ reachable: false,
+ },
+ Def {
+ kind: DefKind::Type,
+ id,
+ span,
+ name,
+ qualname,
+ value: String::new(),
+ parent: None,
+ children: vec![],
+ decl_id: None,
+ docs: String::new(),
+ sig: None,
+ attributes: vec![],
+ },
+ );
+ }
}
}
}
&mut self,
item: &'l ast::Item,
generics: &'l ast::Generics,
- trait_refs: &'l ast::TyParamBounds,
+ trait_refs: &'l ast::GenericBounds,
methods: &'l [ast::TraitItem],
) {
let name = item.ident.to_string();
// super-traits
for super_bound in trait_refs.iter() {
let trait_ref = match *super_bound {
- ast::TraitTyParamBound(ref trait_ref, _) => trait_ref,
- ast::RegionTyParamBound(..) => {
- continue;
- }
+ ast::GenericBound::Trait(ref trait_ref, _) => trait_ref,
+ ast::GenericBound::Outlives(..) => continue,
};
let trait_ref = &trait_ref.trait_ref;
}
self.dump_path_ref(id, path);
- // Type parameters
+ // Type arguments
for seg in &path.segments {
- if let Some(ref params) = seg.parameters {
- match **params {
- ast::PathParameters::AngleBracketed(ref data) => for t in &data.types {
- self.visit_ty(t);
- },
- ast::PathParameters::Parenthesized(ref data) => {
+ if let Some(ref generic_args) = seg.args {
+ match **generic_args {
+ ast::GenericArgs::AngleBracketed(ref data) => {
+ data.args.iter().for_each(|arg| match arg {
+ ast::GenericArg::Type(ty) => self.visit_ty(ty),
+ _ => {}
+ });
+ }
+ ast::GenericArgs::Parenthesized(ref data) => {
for t in &data.inputs {
self.visit_ty(t);
}
}
// Explicit types in the turbo-fish.
- if let Some(ref params) = seg.parameters {
- if let ast::PathParameters::AngleBracketed(ref data) = **params {
- for t in &data.types {
- self.visit_ty(t);
- }
+ if let Some(ref generic_args) = seg.args {
+ if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
+ data.args.iter().for_each(|arg| match arg {
+ ast::GenericArg::Type(ty) => self.visit_ty(ty),
+ _ => {}
+ });
}
}
}
fn visit_generics(&mut self, generics: &'l ast::Generics) {
- for param in &generics.params {
- if let ast::GenericParam::Type(ref ty_param) = *param {
- for bound in ty_param.bounds.iter() {
- if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
+ generics.params.iter().for_each(|param| match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => {}
+ ast::GenericParamKind::Type { ref default, .. } => {
+ for bound in ¶m.bounds {
+ if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
}
}
- if let Some(ref ty) = ty_param.default {
+ if let Some(ref ty) = default {
self.visit_ty(&ty);
}
}
- }
+ });
}
fn visit_ty(&mut self, t: &'l ast::Ty) {
}
}
}
- ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => {
+ ast::ExprKind::Closure(_, _, _, ref decl, ref body, _fn_decl_span) => {
let mut id = String::from("$");
id.push_str(&ex.id.to_string());
if path.segments.len() != 1 {
return false;
}
- if let Some(ref params) = path.segments[0].parameters {
- if let ast::PathParameters::Parenthesized(_) = **params {
+ if let Some(ref generic_args) = path.segments[0].args {
+ if let ast::GenericArgs::Parenthesized(_) = **generic_args {
return true;
}
}
let callsite = span.source_callsite();
let callsite_span = self.span_from_span(callsite);
let callee = span.source_callee()?;
- let callee_span = callee.span?;
+ let callee_span = callee.def_site?;
// Ignore attribute macros, their spans are usually mangled
if let MacroAttribute(_) = callee.format {
let callee_span = self.span_from_span(callee_span);
Some(MacroRef {
span: callsite_span,
- qualname: callee.name().to_string(), // FIXME: generate the real qualname
+ qualname: callee.format.name().to_string(), // FIXME: generate the real qualname
callee_span,
})
}
sig.push_str(&generics
.params
.iter()
- .map(|param| match *param {
- ast::GenericParam::Lifetime(ref l) => l.lifetime.ident.name.to_string(),
- ast::GenericParam::Type(ref t) => t.ident.to_string(),
- })
+ .map(|param| param.ident.to_string())
.collect::<Vec<_>>()
.join(", "));
sig.push_str("> ");
pub fn assoc_type_signature(
id: NodeId,
ident: ast::Ident,
- bounds: Option<&ast::TyParamBounds>,
+ bounds: Option<&ast::GenericBounds>,
default: Option<&ast::Ty>,
scx: &SaveContext,
) -> Option<Signature> {
text.push_str("for<");
text.push_str(&f.generic_params
.iter()
- .filter_map(|p| match *p {
- ast::GenericParam::Lifetime(ref l) => {
- Some(l.lifetime.ident.to_string())
+ .filter_map(|param| match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => {
+ Some(param.ident.to_string())
}
_ => None,
})
Ok(extend_sig(ty, text, defs, vec![]))
}
- ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, _) => {
+ ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
let mut text = String::new();
- if constness.node == ast::Constness::Const {
+ if header.constness.node == ast::Constness::Const {
text.push_str("const ");
}
- if unsafety == ast::Unsafety::Unsafe {
+ if header.asyncness.is_async() {
+ text.push_str("async ");
+ }
+ if header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
- if abi != ::rustc_target::spec::abi::Abi::Rust {
+ if header.abi != ::rustc_target::spec::abi::Abi::Rust {
text.push_str("extern");
- text.push_str(&abi.to_string());
+ text.push_str(&header.abi.to_string());
text.push(' ');
}
text.push_str("fn ");
let mut defs = vec![];
for param in &self.params {
- match *param {
- ast::GenericParam::Lifetime(ref l) => {
- let mut l_text = l.lifetime.ident.to_string();
- defs.push(SigElement {
- id: id_from_node_id(l.lifetime.id, scx),
- start: offset + text.len(),
- end: offset + text.len() + l_text.len(),
- });
-
- if !l.bounds.is_empty() {
- l_text.push_str(": ");
- let bounds = l.bounds
- .iter()
- .map(|l| l.ident.to_string())
+ let mut param_text = param.ident.to_string();
+ defs.push(SigElement {
+ id: id_from_node_id(param.id, scx),
+ start: offset + text.len(),
+ end: offset + text.len() + param_text.len(),
+ });
+ if !param.bounds.is_empty() {
+ param_text.push_str(": ");
+ match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => {
+ let bounds = param.bounds.iter()
+ .map(|bound| match bound {
+ ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
+ _ => panic!(),
+ })
.collect::<Vec<_>>()
.join(" + ");
- l_text.push_str(&bounds);
+ param_text.push_str(&bounds);
// FIXME add lifetime bounds refs.
}
- text.push_str(&l_text);
- text.push(',');
- }
- ast::GenericParam::Type(ref t) => {
- let mut t_text = t.ident.to_string();
- defs.push(SigElement {
- id: id_from_node_id(t.id, scx),
- start: offset + text.len(),
- end: offset + text.len() + t_text.len(),
- });
-
- if !t.bounds.is_empty() {
- t_text.push_str(": ");
- t_text.push_str(&pprust::bounds_to_string(&t.bounds));
+ ast::GenericParamKind::Type { .. } => {
+ param_text.push_str(&pprust::bounds_to_string(¶m.bounds));
// FIXME descend properly into bounds.
}
- text.push_str(&t_text);
- text.push(',');
}
}
+ text.push_str(¶m_text);
+ text.push(',');
}
text.push('>');
fn make_assoc_type_signature(
id: NodeId,
ident: ast::Ident,
- bounds: Option<&ast::TyParamBounds>,
+ bounds: Option<&ast::GenericBounds>,
default: Option<&ast::Ty>,
scx: &SaveContext,
) -> Result {
) -> Result {
// FIXME code dup with function signature
let mut text = String::new();
- if m.constness.node == ast::Constness::Const {
+ if m.header.constness.node == ast::Constness::Const {
text.push_str("const ");
}
- if m.unsafety == ast::Unsafety::Unsafe {
+ if m.header.asyncness.is_async() {
+ text.push_str("async ");
+ }
+ if m.header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
- if m.abi != ::rustc_target::spec::abi::Abi::Rust {
+ if m.header.abi != ::rustc_target::spec::abi::Abi::Rust {
text.push_str("extern");
- text.push_str(&m.abi.to_string());
+ text.push_str(&m.header.abi.to_string());
text.push(' ');
}
text.push_str("fn ");
Canonical, CanonicalVarValues, Canonicalize, QueryRegionConstraint, QueryResult,
};
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::traits::{DomainGoal, ExClauseFold, ExClauseLift, Goal, ProgramClause, QuantifierKind};
+use rustc::traits::{
+ WellFormed,
+ FromEnv,
+ DomainGoal,
+ ExClauseFold,
+ ExClauseLift,
+ Goal,
+ ProgramClause,
+ QuantifierKind
+};
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::subst::Kind;
use rustc::ty::{self, TyCtxt};
_environment: &ty::ParamEnv<'tcx>,
goal: &DomainGoal<'tcx>,
) -> Vec<ProgramClause<'tcx>> {
- use rustc::traits::DomainGoal::*;
- use rustc::traits::WhereClauseAtom::*;
+ use rustc::traits::WhereClause::*;
match goal {
- Holds(Implemented(_trait_predicate)) => {
+ DomainGoal::Holds(Implemented(_trait_predicate)) => {
// These come from:
//
// - Trait definitions (implied bounds)
panic!()
}
- Holds(ProjectionEq(_projection_predicate)) => {
+ DomainGoal::Holds(ProjectionEq(_projection_predicate)) => {
// These come from:
panic!()
}
- WellFormed(Implemented(_trait_predicate)) => {
- // These come from -- the trait decl.
+ DomainGoal::Holds(RegionOutlives(_region_outlives)) => {
panic!()
}
- WellFormed(ProjectionEq(_projection_predicate)) => panic!(),
-
- FromEnv(Implemented(_trait_predicate)) => panic!(),
-
- FromEnv(ProjectionEq(_projection_predicate)) => panic!(),
+ DomainGoal::Holds(TypeOutlives(_type_outlives)) => {
+ panic!()
+ }
- WellFormedTy(_ty) => panic!(),
+ DomainGoal::WellFormed(WellFormed::Trait(_trait_predicate)) => {
+ // These come from -- the trait decl.
+ panic!()
+ }
- FromEnvTy(_ty) => panic!(),
+ DomainGoal::WellFormed(WellFormed::Ty(_ty)) => panic!(),
- RegionOutlives(_region_outlives) => panic!(),
+ DomainGoal::FromEnv(FromEnv::Trait(_trait_predicate)) => panic!(),
- TypeOutlives(_type_outlives) => panic!(),
+ DomainGoal::FromEnv(FromEnv::Ty(_ty)) => panic!(),
- Normalize(_) => panic!(),
+ DomainGoal::Normalize(_) => panic!(),
}
}
use rustc::hir::map::definitions::DefPathData;
use rustc::hir::{self, ImplPolarity};
use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
- WhereClauseAtom};
+ WhereClause, FromEnv, WellFormed};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Slice, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use std::iter;
crate trait Lower<T> {
- /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
+ /// Lower a rustc construct (e.g. `ty::TraitPredicate`) to a chalk-like type.
fn lower(&self) -> T;
}
}
}
-impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
- fn lower(&self) -> WhereClauseAtom<'tcx> {
- WhereClauseAtom::Implemented(*self)
+impl<'tcx> Lower<WhereClause<'tcx>> for ty::TraitPredicate<'tcx> {
+ fn lower(&self) -> WhereClause<'tcx> {
+ WhereClause::Implemented(*self)
}
}
-impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
- fn lower(&self) -> WhereClauseAtom<'tcx> {
- WhereClauseAtom::ProjectionEq(*self)
+impl<'tcx> Lower<WhereClause<'tcx>> for ty::ProjectionPredicate<'tcx> {
+ fn lower(&self) -> WhereClause<'tcx> {
+ WhereClause::ProjectionEq(*self)
}
}
-impl<'tcx, T> Lower<DomainGoal<'tcx>> for T
-where
- T: Lower<WhereClauseAtom<'tcx>>,
-{
- fn lower(&self) -> DomainGoal<'tcx> {
- DomainGoal::Holds(self.lower())
+impl<'tcx> Lower<WhereClause<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
+ fn lower(&self) -> WhereClause<'tcx> {
+ WhereClause::RegionOutlives(*self)
}
}
-impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
- fn lower(&self) -> DomainGoal<'tcx> {
- DomainGoal::RegionOutlives(*self)
+impl<'tcx> Lower<WhereClause<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
+ fn lower(&self) -> WhereClause<'tcx> {
+ WhereClause::TypeOutlives(*self)
}
}
-impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
+impl<'tcx, T> Lower<DomainGoal<'tcx>> for T
+where
+ T: Lower<WhereClause<'tcx>>,
+{
fn lower(&self) -> DomainGoal<'tcx> {
- DomainGoal::TypeOutlives(*self)
+ DomainGoal::Holds(self.lower())
}
}
impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
fn lower(&self) -> PolyDomainGoal<'tcx> {
- use rustc::ty::Predicate::*;
+ use rustc::ty::Predicate;
match self {
- Trait(predicate) => predicate.lower(),
- RegionOutlives(predicate) => predicate.lower(),
- TypeOutlives(predicate) => predicate.lower(),
- Projection(predicate) => predicate.lower(),
- WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)),
- ObjectSafe(..) | ClosureKind(..) | Subtype(..) | ConstEvaluatable(..) => {
+ Predicate::Trait(predicate) => predicate.lower(),
+ Predicate::RegionOutlives(predicate) => predicate.lower(),
+ Predicate::TypeOutlives(predicate) => predicate.lower(),
+ Predicate::Projection(predicate) => predicate.lower(),
+ Predicate::WellFormed(ty) => ty::Binder::dummy(
+ DomainGoal::WellFormed(WellFormed::Ty(*ty))
+ ),
+ Predicate::ObjectSafe(..) |
+ Predicate::ClosureKind(..) |
+ Predicate::Subtype(..) |
+ Predicate::ConstEvaluatable(..) => {
unimplemented!()
}
}
impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
fn into_from_env_goal(self) -> DomainGoal<'tcx> {
- use self::DomainGoal::*;
+ use self::WhereClause::*;
+
match self {
- Holds(wc_atom) => FromEnv(wc_atom),
- WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..)
- | RegionOutlives(..) | TypeOutlives(..) => self,
+ DomainGoal::Holds(Implemented(trait_ref)) => DomainGoal::FromEnv(
+ FromEnv::Trait(trait_ref)
+ ),
+ other => other,
}
}
}
DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
+ DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
+ DefPathData::TypeNs(..) => program_clauses_for_type_def(tcx, def_id),
_ => Slice::empty(),
}
}
substs: Substs::identity_for_item(tcx, def_id),
},
};
- // `FromEnv(Self: Trait<P1..Pn>)`
- let from_env = Goal::from(DomainGoal::FromEnv(trait_pred.lower()));
+
// `Implemented(Self: Trait<P1..Pn>)`
- let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
+ let impl_trait: DomainGoal = trait_pred.lower();
+
+ // `FromEnv(Self: Trait<P1..Pn>)`
+ let from_env_goal = impl_trait.into_from_env_goal().into_goal();
+ let hypotheses = tcx.intern_goals(&[from_env_goal]);
// `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
let implemented_from_env = ProgramClause {
goal: impl_trait,
- hypotheses: tcx.intern_goals(&[from_env]),
+ hypotheses,
};
+
let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
// Rule Implied-Bound-From-Trait
let where_clauses = &tcx.predicates_of(def_id).predicates;
let implied_bound_clauses = where_clauses[1..]
.into_iter()
- .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc));
+ .map(|wc| wc.lower())
- tcx.mk_clauses(clauses.chain(implied_bound_clauses))
-}
+ // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
+ .map(|wc| wc.map_bound(|goal| ProgramClause {
+ goal: goal.into_from_env_goal(),
+ hypotheses,
+ }))
-/// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
-fn implied_bound_from_trait<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- trait_pred: ty::TraitPredicate<'tcx>,
- where_clause: &ty::Predicate<'tcx>,
-) -> Clause<'tcx> {
- // `FromEnv(Self: Trait<P1..Pn>)`
- let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred));
-
- // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
- Clause::ForAll(where_clause.lower().map_bound(|goal| ProgramClause {
- goal: goal.into_from_env_goal(),
- hypotheses: tcx.intern_goals(&[Goal::from(impl_trait)]),
- }))
+ .map(Clause::ForAll);
+
+ tcx.mk_clauses(clauses.chain(implied_bound_clauses))
}
fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> {
// }
// ```
- let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+ let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
+
// `Implemented(A0: Trait<A1..An>)`
let trait_pred = ty::TraitPredicate { trait_ref }.lower();
+
// `WC`
let where_clauses = tcx.predicates_of(def_id).predicates.lower();
tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))])
}
+pub fn program_clauses_for_type_def<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId,
+) -> Clauses<'tcx> {
+
+ // Rule WellFormed-Type
+ //
+ // `struct Ty<P1..Pn> where WC1, ..., WCm`
+ //
+ // ```
+ // forall<P1..Pn> {
+ // WellFormed(Ty<...>) :- WC1, ..., WCm`
+ // }
+ // ```
+
+ // `Ty<...>`
+ let ty = tcx.type_of(def_id);
+
+ // `WC`
+ let where_clauses = tcx.predicates_of(def_id).predicates.lower();
+
+ // `WellFormed(Ty<...>) :- WC1, ..., WCm`
+ let well_formed = ProgramClause {
+ goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
+ hypotheses: tcx.mk_goals(
+ where_clauses.iter().cloned().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
+ ),
+ };
+
+ let well_formed_clause = iter::once(Clause::ForAll(ty::Binder::dummy(well_formed)));
+
+ // Rule FromEnv-Type
+ //
+ // For each where clause `WC`:
+ // ```
+ // forall<P1..Pn> {
+ // FromEnv(WC) :- FromEnv(Ty<...>)
+ // }
+ // ```
+
+ // `FromEnv(Ty<...>)`
+ let from_env_goal = DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal();
+ let hypotheses = tcx.intern_goals(&[from_env_goal]);
+
+ // For each where clause `WC`:
+ let from_env_clauses = where_clauses
+ .into_iter()
+
+ // `FromEnv(WC) :- FromEnv(Ty<...>)`
+ .map(|wc| wc.map_bound(|goal| ProgramClause {
+ goal: goal.into_from_env_goal(),
+ hypotheses,
+ }))
+
+ .map(Clause::ForAll);
+
+ tcx.mk_clauses(well_formed_clause.chain(from_env_clauses))
+}
+
+pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
+ _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ _item_id: DefId,
+) -> Clauses<'tcx> {
+ unimplemented!()
+}
+
pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
item_id: DefId,
//
// ```impl<P0..Pn> Trait<A1..An> for A0
// {
- // type AssocType<Pn+1..Pm> where WC = T;
+ // type AssocType<Pn+1..Pm> = T;
// }```
//
+ // FIXME: For the moment, we don't account for where clauses written on the associated
+ // ty definition (i.e. in the trait def, as in `type AssocType<T> where T: Sized`).
// ```
// forall<P0..Pm> {
// forall<Pn+1..Pm> {
// Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T) :-
- // Implemented(A0: Trait<A1..An>) && WC
+ // Implemented(A0: Trait<A1..An>)
// }
// }
// ```
let item = tcx.associated_item(item_id);
debug_assert_eq!(item.kind, ty::AssociatedKind::Type);
- let impl_id = if let ty::AssociatedItemContainer::ImplContainer(impl_id) = item.container {
- impl_id
- } else {
- bug!()
+ let impl_id = match item.container {
+ ty::AssociatedItemContainer::ImplContainer(impl_id) => impl_id,
+ _ => bug!("not an impl container"),
};
+
// `A0 as Trait<A1..An>`
let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
+
// `T`
let ty = tcx.type_of(item_id);
+
// `Implemented(A0: Trait<A1..An>)`
let trait_implemented = ty::Binder::dummy(ty::TraitPredicate { trait_ref }.lower());
- // `WC`
- let item_where_clauses = tcx.predicates_of(item_id).predicates.lower();
- // `Implemented(A0: Trait<A1..An>) && WC`
- let mut where_clauses = vec![trait_implemented];
- where_clauses.extend(item_where_clauses);
+
+ // `Implemented(A0: Trait<A1..An>)`
+ let hypotheses = vec![trait_implemented];
+
// `<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm>`
let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.name);
+
// `Normalize(<A0 as Trait<A1..An>>::AssocType<Pn+1..Pm> -> T)`
let normalize_goal = DomainGoal::Normalize(ty::ProjectionPredicate { projection_ty, ty });
+
// `Normalize(... -> T) :- ...`
let clause = ProgramClause {
goal: normalize_goal,
hypotheses: tcx.mk_goals(
- where_clauses
+ hypotheses
.into_iter()
.map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
),
//! is parameterized by an instance of `AstConv`.
use rustc_data_structures::accumulate_vec::AccumulateVec;
-use hir;
+use hir::{self, GenericArg};
use hir::def::Def;
use hir::def_id::DefId;
use middle::resolve_lifetime as rl;
{
let (substs, assoc_bindings) =
- item_segment.with_parameters(|parameters| {
+ item_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path(
span,
def_id,
- parameters,
+ generic_args,
item_segment.infer_types,
None)
});
fn create_substs_for_ast_path(&self,
span: Span,
def_id: DefId,
- parameters: &hir::PathParameters,
+ generic_args: &hir::GenericArgs,
infer_types: bool,
self_ty: Option<Ty<'tcx>>)
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
let tcx = self.tcx();
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
- parameters={:?})",
- def_id, self_ty, parameters);
+ generic_args={:?})",
+ def_id, self_ty, generic_args);
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
- let decl_generics = tcx.generics_of(def_id);
- let ty_provided = parameters.types.len();
- let lt_provided = parameters.lifetimes.len();
+ // FIXME(varkor): Separating out the parameters is messy.
+ let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
+ GenericArg::Lifetime(lt) => Some(lt),
+ _ => None,
+ }).collect();
+ let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
+ GenericArg::Type(ty) => Some(ty),
+ _ => None,
+ }).collect();
+ let lt_provided = lifetimes.len();
+ let ty_provided = types.len();
+
+ let decl_generics = tcx.generics_of(def_id);
let mut lt_accepted = 0;
let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &decl_generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
let i = param.index as usize - own_self;
- if let Some(lifetime) = parameters.lifetimes.get(i) {
- self.ast_region_to_region(lifetime, Some(param)).into()
+ if let Some(lt) = lifetimes.get(i) {
+ self.ast_region_to_region(lt, Some(param)).into()
} else {
tcx.types.re_static.into()
}
let i = i - (lt_accepted + own_self);
if i < ty_provided {
// A provided type parameter.
- self.ast_ty_to_ty(¶meters.types[i]).into()
+ self.ast_ty_to_ty(&types[i]).into()
} else if infer_types {
// No type parameters were provided, we can infer all.
if !default_needs_object_self(param) {
}
});
- let assoc_bindings = parameters.bindings.iter().map(|binding| {
+ let assoc_bindings = generic_args.bindings.iter().map(|binding| {
ConvertedBinding {
item_name: binding.name,
ty: self.ast_ty_to_ty(&binding.ty),
self_ty: Ty<'tcx>)
-> ty::TraitRef<'tcx>
{
- self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1);
+ self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
let trait_def_id = self.trait_def_id(trait_ref);
self.ast_path_to_mono_trait_ref(trait_ref.path.span,
debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
- self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1);
+ self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
let (substs, assoc_bindings) =
self.create_substs_for_ast_trait_ref(trait_ref.path.span,
let trait_def = self.tcx().trait_def(trait_def_id);
if !self.tcx().features().unboxed_closures &&
- trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar {
+ trait_segment.with_generic_args(|generic_args| generic_args.parenthesized)
+ != trait_def.paren_sugar {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let msg = if trait_def.paren_sugar {
"the precise format of `Fn`-family traits' type parameters is subject to change. \
span, GateIssue::Language, msg);
}
- trait_segment.with_parameters(|parameters| {
+ trait_segment.with_generic_args(|generic_args| {
self.create_substs_for_ast_path(span,
trait_def_id,
- parameters,
+ generic_args,
trait_segment.infer_types,
Some(self_ty))
})
debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
- self.prohibit_type_params(slice::from_ref(item_segment));
+ self.prohibit_generics(slice::from_ref(item_segment));
// Find the type of the associated item, and the trait where the associated
// item is declared.
let tcx = self.tcx();
let trait_def_id = tcx.parent_def_id(item_def_id).unwrap();
- self.prohibit_type_params(slice::from_ref(item_segment));
+ self.prohibit_generics(slice::from_ref(item_segment));
let self_ty = if let Some(ty) = opt_self_ty {
ty
self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
}
- pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
+ pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) {
for segment in segments {
- segment.with_parameters(|parameters| {
- for typ in ¶meters.types {
- struct_span_err!(self.tcx().sess, typ.span, E0109,
- "type parameters are not allowed on this type")
- .span_label(typ.span, "type parameter not allowed")
- .emit();
- break;
- }
- for lifetime in ¶meters.lifetimes {
- struct_span_err!(self.tcx().sess, lifetime.span, E0110,
- "lifetime parameters are not allowed on this type")
- .span_label(lifetime.span,
- "lifetime parameter not allowed on this type")
- .emit();
- break;
+ segment.with_generic_args(|generic_args| {
+ let (mut err_for_lt, mut err_for_ty) = (false, false);
+ for arg in &generic_args.args {
+ let (mut span_err, span, kind) = match arg {
+ hir::GenericArg::Lifetime(lt) => {
+ if err_for_lt { continue }
+ err_for_lt = true;
+ (struct_span_err!(self.tcx().sess, lt.span, E0110,
+ "lifetime parameters are not allowed on \
+ this type"),
+ lt.span,
+ "lifetime")
+ }
+ hir::GenericArg::Type(ty) => {
+ if err_for_ty { continue }
+ err_for_ty = true;
+ (struct_span_err!(self.tcx().sess, ty.span, E0109,
+ "type parameters are not allowed on this type"),
+ ty.span,
+ "type")
+ }
+ };
+ span_err.span_label(span, format!("{} parameter not allowed", kind))
+ .emit();
+ if err_for_lt && err_for_ty {
+ break;
+ }
}
- for binding in ¶meters.bindings {
+ for binding in &generic_args.bindings {
self.prohibit_projection(binding.span);
break;
}
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
Def::Union(did) | Def::TyForeign(did) => {
assert_eq!(opt_self_ty, None);
- self.prohibit_type_params(path.segments.split_last().unwrap().1);
+ 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 => {
// 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_type_params(path.segments.split_last().unwrap().1);
+ 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())
}
Def::TyParam(did) => {
assert_eq!(opt_self_ty, None);
- self.prohibit_type_params(&path.segments);
+ self.prohibit_generics(&path.segments);
let node_id = tcx.hir.as_local_node_id(did).unwrap();
let item_id = tcx.hir.get_parent_node(node_id);
// Self in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
- self.prohibit_type_params(&path.segments);
+ self.prohibit_generics(&path.segments);
tcx.at(span).type_of(def_id)
}
Def::SelfTy(Some(_), None) => {
// Self in trait.
assert_eq!(opt_self_ty, None);
- self.prohibit_type_params(&path.segments);
+ self.prohibit_generics(&path.segments);
tcx.mk_self_type()
}
Def::AssociatedTy(def_id) => {
- self.prohibit_type_params(&path.segments[..path.segments.len()-2]);
+ self.prohibit_generics(&path.segments[..path.segments.len()-2]);
self.qpath_to_ty(span,
opt_self_ty,
def_id,
}
Def::PrimTy(prim_ty) => {
assert_eq!(opt_self_ty, None);
- self.prohibit_type_params(&path.segments);
+ self.prohibit_generics(&path.segments);
match prim_ty {
hir::TyBool => tcx.types.bool,
hir::TyChar => tcx.types.char,
fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
let t_cast = self.cast_ty;
let t_expr = self.expr_ty;
- if t_cast.is_numeric() && t_expr.is_numeric() {
- fcx.tcx.lint_node(
- lint::builtin::TRIVIAL_NUMERIC_CASTS,
- self.expr.id,
- self.span,
- &format!("trivial numeric cast: `{}` as `{}`. Cast can be \
- replaced by coercion, this might require type \
- ascription or a temporary variable",
- fcx.ty_to_string(t_expr),
- fcx.ty_to_string(t_cast)));
+ let type_asc_or = if fcx.tcx.features().type_ascription {
+ "type ascription or "
} else {
- fcx.tcx.lint_node(
- lint::builtin::TRIVIAL_CASTS,
- self.expr.id,
- self.span,
- &format!("trivial cast: `{}` as `{}`. Cast can be \
- replaced by coercion, this might require type \
- ascription or a temporary variable",
- fcx.ty_to_string(t_expr),
- fcx.ty_to_string(t_cast)));
- }
-
+ ""
+ };
+ let (adjective, lint) = if t_cast.is_numeric() && t_expr.is_numeric() {
+ ("numeric ", lint::builtin::TRIVIAL_NUMERIC_CASTS)
+ } else {
+ ("", lint::builtin::TRIVIAL_CASTS)
+ };
+ let mut err = fcx.tcx.struct_span_lint_node(
+ lint,
+ self.expr.id,
+ self.span,
+ &format!("trivial {}cast: `{}` as `{}`",
+ adjective,
+ fcx.ty_to_string(t_expr),
+ fcx.ty_to_string(t_cast)));
+ err.help(&format!("cast can be replaced by coercion; this might \
+ require {}a temporary variable", type_asc_or));
+ err.emit();
}
pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rustc::hir::{self, ImplItemKind, TraitItemKind};
+use rustc::hir::{self, GenericParamKind, ImplItemKind, TraitItemKind};
use rustc::infer::{self, InferOk};
use rustc::ty::{self, TyCtxt, GenericParamDefKind};
use rustc::ty::util::ExplicitSelf;
let mut error_found = false;
let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
- let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| {
- match param.kind {
- GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
- GenericParamDefKind::Lifetime => None,
- }
+ let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
+ GenericParamDefKind::Lifetime => None,
});
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
match param.kind {
}
let span = visitor.0?;
- let param = impl_m.generics.params.iter().filter_map(|param| {
- match param {
- hir::GenericParam::Type(param) => {
+ let bounds = impl_m.generics.params.iter().find_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => None,
+ GenericParamKind::Type { .. } => {
if param.id == impl_node_id {
- Some(param)
+ Some(¶m.bounds)
} else {
None
}
- },
- hir::GenericParam::Lifetime(..) => None,
+ }
}
- }).next()?;
- let bounds = param.bounds.first()?.span().to(param.bounds.last()?.span());
+ })?;
+ let bounds = bounds.first()?.span().to(bounds.last()?.span());
let bounds = tcx
.sess
.codemap()
use astconv::AstConv;
use check::{FnCtxt, PlaceOp, callee, Needs};
+use hir::GenericArg;
use hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
"confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
unadjusted_self_ty,
pick,
- segment.parameters,
+ segment.args,
);
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
let method_generics = self.tcx.generics_of(pick.item.def_id);
let mut fn_segment = Some((segment, method_generics));
let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment);
- self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, supress_mismatch);
+ self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch);
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
assert_eq!(method_generics.parent_count, parent_substs.len());
- let provided = &segment.parameters;
+ let provided = &segment.args;
let own_counts = method_generics.own_counts();
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
- let i = param.index as usize;
+ let mut i = param.index as usize;
if i < parent_substs.len() {
parent_substs[i]
} else {
- match param.kind {
- GenericParamDefKind::Lifetime => {
- if let Some(lifetime) = provided.as_ref().and_then(|p| {
- p.lifetimes.get(i - parent_substs.len())
- }) {
- return AstConv::ast_region_to_region(
- self.fcx, lifetime, Some(param)).into();
- }
- }
- GenericParamDefKind::Type {..} => {
- if let Some(ast_ty) = provided.as_ref().and_then(|p| {
- p.types.get(i - parent_substs.len() - own_counts.lifetimes)
- }) {
- return self.to_ty(ast_ty).into();
+ let (is_lt, is_ty) = match param.kind {
+ GenericParamDefKind::Lifetime => (true, false),
+ GenericParamDefKind::Type { .. } => (false, true),
+ };
+ provided.as_ref().and_then(|data| {
+ for arg in &data.args {
+ match arg {
+ GenericArg::Lifetime(lt) if is_lt => {
+ if i == parent_substs.len() {
+ return Some(AstConv::ast_region_to_region(
+ self.fcx, lt, Some(param)).into());
+ }
+ i -= 1;
+ }
+ GenericArg::Lifetime(_) => {}
+ GenericArg::Type(ty) if is_ty => {
+ if i == parent_substs.len() + own_counts.lifetimes {
+ return Some(self.to_ty(ty).into());
+ }
+ i -= 1;
+ }
+ GenericArg::Type(_) => {}
}
}
- }
- self.var_for_def(self.span, param)
+ None
+ }).unwrap_or_else(|| self.var_for_def(self.span, param))
}
})
}
use syntax::ast;
use syntax::util::lev_distance::find_best_match_for_name;
use errors::DiagnosticBuilder;
-use syntax_pos::Span;
+use syntax_pos::{Span, FileName};
+
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::hir;
out_of_scope_traits,
lev_candidate,
mode,
- ..
}) => {
let tcx = self.tcx;
let span = tcx.hir.span(node_id);
let snippet = tcx.sess.codemap().span_to_snippet(span)
.unwrap();
- err.span_suggestion(span,
- &format!("you must specify a type for \
- this binding, like `{}`",
- concrete_type),
- format!("{}: {}",
- snippet,
- concrete_type));
+ let filename = tcx.sess.codemap().span_to_filename(span);
+
+ let parent_node = self.tcx.hir.get(
+ self.tcx.hir.get_parent_node(node_id),
+ );
+ let msg = format!(
+ "you must specify a type for this binding, like `{}`",
+ concrete_type,
+ );
+
+ match (filename, parent_node) {
+ (FileName::Real(_), hir_map::NodeLocal(hir::Local {
+ source: hir::LocalSource::Normal,
+ ty,
+ ..
+ })) => {
+ err.span_suggestion(
+ // account for `let x: _ = 42;`
+ // ^^^^
+ span.to(ty.as_ref().map(|ty| ty.span)
+ .unwrap_or(span)),
+ &msg,
+ format!("{}: {}", snippet, concrete_type),
+ );
+ }
+ _ => {
+ err.span_label(span, msg);
+ }
+ }
}
}
}
use self::TupleArgumentsFlag::*;
use astconv::AstConv;
+use hir::GenericArg;
use hir::def::Def;
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use std::slice;
}
if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) {
- if let Item_::ItemFn(_, _, _, _, ref generics, _) = item.node {
+ if let Item_::ItemFn(_, _, ref generics, _) = item.node {
if !generics.params.is_empty() {
fcx.tcx.sess.span_err(
span,
hir::ItemUnion(..) => {
check_union(tcx, it.id, it.span);
}
- hir::ItemTy(_, ref generics) => {
+ hir::ItemTy(..) => {
let def_id = tcx.hir.local_def_id(it.id);
let pty_ty = tcx.type_of(def_id);
- check_bounds_are_used(tcx, generics, pty_ty);
+ let generics = tcx.generics_of(def_id);
+ check_bounds_are_used(tcx, &generics, pty_ty);
}
hir::ItemForeignMod(ref m) => {
check_abi(tcx, it.span, m.abi);
hir::ExprRepeat(..) |
hir::ExprArray(..) |
hir::ExprBreak(..) |
- hir::ExprAgain(..) |
+ hir::ExprContinue(..) |
hir::ExprRet(..) |
hir::ExprWhile(..) |
hir::ExprLoop(..) |
let tcx = self.tcx;
let id = expr.id;
match expr.node {
- hir::ExprBox(ref subexpr) => {
- let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| {
- match ty.sty {
- ty::TyAdt(def, _) if def.is_box()
- => Expectation::rvalue_hint(self, ty.boxed_ty()),
- _ => NoExpectation
- }
- });
- let referent_ty = self.check_expr_with_expectation(subexpr, expected_inner);
- tcx.mk_box(referent_ty)
- }
-
- hir::ExprLit(ref lit) => {
- self.check_lit(&lit, expected)
- }
- hir::ExprBinary(op, ref lhs, ref rhs) => {
- self.check_binop(expr, op, lhs, rhs)
- }
- hir::ExprAssignOp(op, ref lhs, ref rhs) => {
- self.check_binop_assign(expr, op, lhs, rhs)
- }
- hir::ExprUnary(unop, ref oprnd) => {
- let expected_inner = match unop {
- hir::UnNot | hir::UnNeg => {
- expected
- }
- hir::UnDeref => {
- NoExpectation
- }
- };
- let needs = match unop {
- hir::UnDeref => needs,
- _ => Needs::None
- };
- let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd,
- expected_inner,
- needs);
+ hir::ExprBox(ref subexpr) => {
+ let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| {
+ match ty.sty {
+ ty::TyAdt(def, _) if def.is_box()
+ => Expectation::rvalue_hint(self, ty.boxed_ty()),
+ _ => NoExpectation
+ }
+ });
+ let referent_ty = self.check_expr_with_expectation(subexpr, expected_inner);
+ tcx.mk_box(referent_ty)
+ }
- if !oprnd_t.references_error() {
- oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
- match unop {
+ hir::ExprLit(ref lit) => {
+ self.check_lit(&lit, expected)
+ }
+ hir::ExprBinary(op, ref lhs, ref rhs) => {
+ self.check_binop(expr, op, lhs, rhs)
+ }
+ hir::ExprAssignOp(op, ref lhs, ref rhs) => {
+ self.check_binop_assign(expr, op, lhs, rhs)
+ }
+ hir::ExprUnary(unop, ref oprnd) => {
+ let expected_inner = match unop {
+ hir::UnNot | hir::UnNeg => {
+ expected
+ }
hir::UnDeref => {
- if let Some(mt) = oprnd_t.builtin_deref(true) {
- oprnd_t = mt.ty;
- } else if let Some(ok) = self.try_overloaded_deref(
- expr.span, oprnd_t, needs) {
- let method = self.register_infer_ok_obligations(ok);
- if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty {
- let mutbl = match mutbl {
- hir::MutImmutable => AutoBorrowMutability::Immutable,
- hir::MutMutable => AutoBorrowMutability::Mutable {
- // (It shouldn't actually matter for unary ops whether
- // we enable two-phase borrows or not, since a unary
- // op has no additional operands.)
- allow_two_phase_borrow: AllowTwoPhase::No,
- }
- };
- self.apply_adjustments(oprnd, vec![Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
- target: method.sig.inputs()[0]
- }]);
+ NoExpectation
+ }
+ };
+ let needs = match unop {
+ hir::UnDeref => needs,
+ _ => Needs::None
+ };
+ let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd,
+ expected_inner,
+ needs);
+
+ if !oprnd_t.references_error() {
+ oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
+ match unop {
+ hir::UnDeref => {
+ if let Some(mt) = oprnd_t.builtin_deref(true) {
+ oprnd_t = mt.ty;
+ } else if let Some(ok) = self.try_overloaded_deref(
+ expr.span, oprnd_t, needs) {
+ let method = self.register_infer_ok_obligations(ok);
+ if let ty::TyRef(region, _, mutbl) = method.sig.inputs()[0].sty {
+ let mutbl = match mutbl {
+ hir::MutImmutable => AutoBorrowMutability::Immutable,
+ hir::MutMutable => AutoBorrowMutability::Mutable {
+ // (It shouldn't actually matter for unary ops whether
+ // we enable two-phase borrows or not, since a unary
+ // op has no additional operands.)
+ allow_two_phase_borrow: AllowTwoPhase::No,
+ }
+ };
+ self.apply_adjustments(oprnd, vec![Adjustment {
+ kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
+ target: method.sig.inputs()[0]
+ }]);
+ }
+ oprnd_t = self.make_overloaded_place_return_type(method).ty;
+ self.write_method_call(expr.hir_id, method);
+ } else {
+ type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614,
+ "type `{}` cannot be dereferenced",
+ oprnd_t).emit();
+ oprnd_t = tcx.types.err;
}
- oprnd_t = self.make_overloaded_place_return_type(method).ty;
- self.write_method_call(expr.hir_id, method);
- } else {
- type_error_struct!(tcx.sess, expr.span, oprnd_t, E0614,
- "type `{}` cannot be dereferenced",
- oprnd_t).emit();
- oprnd_t = tcx.types.err;
}
- }
- hir::UnNot => {
- let result = self.check_user_unop(expr, oprnd_t, unop);
- // If it's builtin, we can reuse the type, this helps inference.
- if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
- oprnd_t = result;
+ hir::UnNot => {
+ let result = self.check_user_unop(expr, oprnd_t, unop);
+ // If it's builtin, we can reuse the type, this helps inference.
+ if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
+ oprnd_t = result;
+ }
+ }
+ hir::UnNeg => {
+ let result = self.check_user_unop(expr, oprnd_t, unop);
+ // If it's builtin, we can reuse the type, this helps inference.
+ if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
+ oprnd_t = result;
+ }
}
}
- hir::UnNeg => {
- let result = self.check_user_unop(expr, oprnd_t, unop);
- // If it's builtin, we can reuse the type, this helps inference.
- if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
- oprnd_t = result;
+ }
+ oprnd_t
+ }
+ hir::ExprAddrOf(mutbl, ref oprnd) => {
+ let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
+ match ty.sty {
+ ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
+ if self.is_place_expr(&oprnd) {
+ // Places may legitimately have unsized types.
+ // For example, dereferences of a fat pointer and
+ // the last field of a struct can be unsized.
+ ExpectHasType(ty)
+ } else {
+ Expectation::rvalue_hint(self, ty)
+ }
}
+ _ => NoExpectation
}
+ });
+ let needs = Needs::maybe_mut_place(mutbl);
+ let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);
+
+ let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
+ if tm.ty.references_error() {
+ tcx.types.err
+ } else {
+ // Note: at this point, we cannot say what the best lifetime
+ // is to use for resulting pointer. We want to use the
+ // shortest lifetime possible so as to avoid spurious borrowck
+ // errors. Moreover, the longest lifetime will depend on the
+ // precise details of the value whose address is being taken
+ // (and how long it is valid), which we don't know yet until type
+ // inference is complete.
+ //
+ // Therefore, here we simply generate a region variable. The
+ // region inferencer will then select the ultimate value.
+ // Finally, borrowck is charged with guaranteeing that the
+ // value whose address was taken can actually be made to live
+ // as long as it needs to live.
+ let region = self.next_region_var(infer::AddrOfRegion(expr.span));
+ tcx.mk_ref(region, tm)
}
}
- oprnd_t
- }
- hir::ExprAddrOf(mutbl, ref oprnd) => {
- let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
- match ty.sty {
- ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
- if self.is_place_expr(&oprnd) {
- // Places may legitimately have unsized types.
- // For example, dereferences of a fat pointer and
- // the last field of a struct can be unsized.
- ExpectHasType(ty)
+ hir::ExprPath(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)
+ } else {
+ self.set_tainted_by_errors();
+ tcx.types.err
+ };
+
+ // We always require that the type provided as the value for
+ // a type parameter outlives the moment of instantiation.
+ let substs = self.tables.borrow().node_substs(expr.hir_id);
+ self.add_wf_bounds(substs, expr);
+
+ ty
+ }
+ hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
+ for output in outputs {
+ self.check_expr(output);
+ }
+ for input in inputs {
+ self.check_expr(input);
+ }
+ tcx.mk_nil()
+ }
+ hir::ExprBreak(destination, ref expr_opt) => {
+ if let Ok(target_id) = destination.target_id {
+ let (e_ty, cause);
+ if let Some(ref e) = *expr_opt {
+ // If this is a break with a value, we need to type-check
+ // the expression. Get an expected type from the loop context.
+ let opt_coerce_to = {
+ let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+ enclosing_breakables.find_breakable(target_id)
+ .coerce
+ .as_ref()
+ .map(|coerce| coerce.expected_ty())
+ };
+
+ // If the loop context is not a `loop { }`, then break with
+ // a value is illegal, and `opt_coerce_to` will be `None`.
+ // Just set expectation to error in that case.
+ let coerce_to = opt_coerce_to.unwrap_or(tcx.types.err);
+
+ // Recurse without `enclosing_breakables` borrowed.
+ e_ty = self.check_expr_with_hint(e, coerce_to);
+ cause = self.misc(e.span);
+ } else {
+ // Otherwise, this is a break *without* a value. That's
+ // always legal, and is equivalent to `break ()`.
+ e_ty = tcx.mk_nil();
+ cause = self.misc(expr.span);
+ }
+
+ // Now that we have type-checked `expr_opt`, borrow
+ // the `enclosing_loops` field and let's coerce the
+ // type of `expr_opt` into what is expected.
+ let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+ let ctxt = enclosing_breakables.find_breakable(target_id);
+ if let Some(ref mut coerce) = ctxt.coerce {
+ if let Some(ref e) = *expr_opt {
+ coerce.coerce(self, &cause, e, e_ty);
} else {
- Expectation::rvalue_hint(self, ty)
+ assert!(e_ty.is_nil());
+ coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
}
+ } else {
+ // If `ctxt.coerce` is `None`, we can just ignore
+ // the type of the expresison. This is because
+ // either this was a break *without* a value, in
+ // which case it is always a legal type (`()`), or
+ // else an error would have been flagged by the
+ // `loops` pass for using break with an expression
+ // where you are not supposed to.
+ assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0);
}
- _ => NoExpectation
+
+ ctxt.may_break = true;
+
+ // the type of a `break` is always `!`, since it diverges
+ tcx.types.never
+ } else {
+ // Otherwise, we failed to find the enclosing loop;
+ // this can only happen if the `break` was not
+ // inside a loop at all, which is caught by the
+ // loop-checking pass.
+ assert!(self.tcx.sess.err_count() > 0);
+
+ // We still need to assign a type to the inner expression to
+ // prevent the ICE in #43162.
+ if let Some(ref e) = *expr_opt {
+ self.check_expr_with_hint(e, tcx.types.err);
+
+ // ... except when we try to 'break rust;'.
+ // ICE this expression in particular (see #43162).
+ if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = e.node {
+ if path.segments.len() == 1 && path.segments[0].name == "rust" {
+ fatally_break_rust(self.tcx.sess);
+ }
+ }
+ }
+ // There was an error, make typecheck fail
+ tcx.types.err
}
- });
- let needs = Needs::maybe_mut_place(mutbl);
- let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);
- let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
- if tm.ty.references_error() {
- tcx.types.err
- } else {
- // Note: at this point, we cannot say what the best lifetime
- // is to use for resulting pointer. We want to use the
- // shortest lifetime possible so as to avoid spurious borrowck
- // errors. Moreover, the longest lifetime will depend on the
- // precise details of the value whose address is being taken
- // (and how long it is valid), which we don't know yet until type
- // inference is complete.
- //
- // Therefore, here we simply generate a region variable. The
- // region inferencer will then select the ultimate value.
- // Finally, borrowck is charged with guaranteeing that the
- // value whose address was taken can actually be made to live
- // as long as it needs to live.
- let region = self.next_region_var(infer::AddrOfRegion(expr.span));
- tcx.mk_ref(region, tm)
}
- }
- hir::ExprPath(ref qpath) => {
- let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(qpath,
- expr.id, expr.span);
- let ty = if def != Def::Err {
- self.instantiate_value_path(segments, opt_ty, def, expr.span, id)
- } else {
- self.set_tainted_by_errors();
- tcx.types.err
- };
-
- // We always require that the type provided as the value for
- // a type parameter outlives the moment of instantiation.
- let substs = self.tables.borrow().node_substs(expr.hir_id);
- self.add_wf_bounds(substs, expr);
-
- ty
- }
- hir::ExprInlineAsm(_, ref outputs, ref inputs) => {
- for output in outputs {
- self.check_expr(output);
- }
- for input in inputs {
- self.check_expr(input);
- }
- tcx.mk_nil()
- }
- hir::ExprBreak(destination, ref expr_opt) => {
- if let Ok(target_id) = destination.target_id {
- let (e_ty, cause);
- if let Some(ref e) = *expr_opt {
- // If this is a break with a value, we need to type-check
- // the expression. Get an expected type from the loop context.
- let opt_coerce_to = {
- let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
- enclosing_breakables.find_breakable(target_id)
- .coerce
- .as_ref()
- .map(|coerce| coerce.expected_ty())
- };
-
- // If the loop context is not a `loop { }`, then break with
- // a value is illegal, and `opt_coerce_to` will be `None`.
- // Just set expectation to error in that case.
- let coerce_to = opt_coerce_to.unwrap_or(tcx.types.err);
-
- // Recurse without `enclosing_breakables` borrowed.
- e_ty = self.check_expr_with_hint(e, coerce_to);
- cause = self.misc(e.span);
- } else {
- // Otherwise, this is a break *without* a value. That's
- // always legal, and is equivalent to `break ()`.
- e_ty = tcx.mk_nil();
- cause = self.misc(expr.span);
- }
-
- // Now that we have type-checked `expr_opt`, borrow
- // the `enclosing_loops` field and let's coerce the
- // type of `expr_opt` into what is expected.
- let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
- let ctxt = enclosing_breakables.find_breakable(target_id);
- if let Some(ref mut coerce) = ctxt.coerce {
- if let Some(ref e) = *expr_opt {
- coerce.coerce(self, &cause, e, e_ty);
- } else {
- assert!(e_ty.is_nil());
- coerce.coerce_forced_unit(self, &cause, &mut |_| (), true);
- }
- } else {
- // If `ctxt.coerce` is `None`, we can just ignore
- // the type of the expresison. This is because
- // either this was a break *without* a value, in
- // which case it is always a legal type (`()`), or
- // else an error would have been flagged by the
- // `loops` pass for using break with an expression
- // where you are not supposed to.
- assert!(expr_opt.is_none() || self.tcx.sess.err_count() > 0);
- }
-
- ctxt.may_break = true;
-
- // the type of a `break` is always `!`, since it diverges
- tcx.types.never
- } else {
- // Otherwise, we failed to find the enclosing loop;
- // this can only happen if the `break` was not
- // inside a loop at all, which is caught by the
- // loop-checking pass.
- assert!(self.tcx.sess.err_count() > 0);
-
- // We still need to assign a type to the inner expression to
- // prevent the ICE in #43162.
- if let Some(ref e) = *expr_opt {
- self.check_expr_with_hint(e, tcx.types.err);
-
- // ... except when we try to 'break rust;'.
- // ICE this expression in particular (see #43162).
- if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = e.node {
- if path.segments.len() == 1 && path.segments[0].name == "rust" {
- fatally_break_rust(self.tcx.sess);
- }
- }
- }
- // There was an error, make typecheck fail
- tcx.types.err
- }
-
- }
- hir::ExprAgain(_) => { tcx.types.never }
- hir::ExprRet(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();
- } else if let Some(ref e) = *expr_opt {
- self.check_return_expr(e);
- } else {
- let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
- let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
- coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+ hir::ExprContinue(destination) => {
+ if let Ok(_) = destination.target_id {
+ tcx.types.never
+ } else {
+ // There was an error, make typecheck fail
+ tcx.types.err
+ }
}
- tcx.types.never
- }
- hir::ExprAssign(ref lhs, ref rhs) => {
- let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
+ hir::ExprRet(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();
+ } else if let Some(ref e) = *expr_opt {
+ self.check_return_expr(e);
+ } else {
+ let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
+ let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
+ coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+ }
+ tcx.types.never
+ }
+ hir::ExprAssign(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);
+ let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
- match expected {
- ExpectIfCondition => {
- self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\
- expected error elsehwere");
- }
- _ => {
- // Only check this if not in an `if` condition, as the
- // mistyped comparison help is more appropriate.
- if !self.is_place_expr(&lhs) {
- struct_span_err!(self.tcx.sess, expr.span, E0070,
- "invalid left-hand side expression")
- .span_label(expr.span, "left-hand of expression not valid")
- .emit();
+ match expected {
+ ExpectIfCondition => {
+ self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\
+ expected error elsehwere");
+ }
+ _ => {
+ // Only check this if not in an `if` condition, as the
+ // mistyped comparison help is more appropriate.
+ if !self.is_place_expr(&lhs) {
+ struct_span_err!(self.tcx.sess, expr.span, E0070,
+ "invalid left-hand side expression")
+ .span_label(expr.span, "left-hand of expression not valid")
+ .emit();
+ }
}
}
+
+ self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
+
+ if lhs_ty.references_error() || rhs_ty.references_error() {
+ tcx.types.err
+ } else {
+ tcx.mk_nil()
+ }
+ }
+ hir::ExprIf(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::ExprWhile(ref cond, ref body, _) => {
+ let ctxt = BreakableCtxt {
+ // cannot use break with a value from a while loop
+ coerce: None,
+ may_break: false, // Will get updated if/when we find a `break`.
+ };
- self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
+ let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
+ self.check_expr_has_type_or_error(&cond, tcx.types.bool);
+ let cond_diverging = self.diverges.get();
+ self.check_block_no_value(&body);
- if lhs_ty.references_error() || rhs_ty.references_error() {
- tcx.types.err
- } else {
- tcx.mk_nil()
+ // We may never reach the body so it diverging means nothing.
+ self.diverges.set(cond_diverging);
+ });
+
+ if ctxt.may_break {
+ // No way to know whether it's diverging because
+ // of a `break` or an outer `break` or `return`.
+ self.diverges.set(Diverges::Maybe);
+ }
+
+ self.tcx.mk_nil()
}
- }
- hir::ExprIf(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::ExprWhile(ref cond, ref body, _) => {
- let ctxt = BreakableCtxt {
- // cannot use break with a value from a while loop
- coerce: None,
- may_break: false, // Will get updated if/when we find a `break`.
- };
-
- let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
- self.check_expr_has_type_or_error(&cond, tcx.types.bool);
- let cond_diverging = self.diverges.get();
- self.check_block_no_value(&body);
-
- // We may never reach the body so it diverging means nothing.
- self.diverges.set(cond_diverging);
- });
-
- if ctxt.may_break {
- // No way to know whether it's diverging because
- // of a `break` or an outer `break` or `return`.
- self.diverges.set(Diverges::Maybe);
- }
-
- self.tcx.mk_nil()
- }
- hir::ExprLoop(ref body, _, source) => {
- let coerce = match source {
- // you can only use break with a value from a normal `loop { }`
- hir::LoopSource::Loop => {
- let coerce_to = expected.coercion_target_type(self, body.span);
- Some(CoerceMany::new(coerce_to))
- }
-
- hir::LoopSource::WhileLet |
- hir::LoopSource::ForLoop => {
- None
- }
- };
-
- let ctxt = BreakableCtxt {
- coerce,
- may_break: false, // Will get updated if/when we find a `break`.
- };
-
- let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
- self.check_block_no_value(&body);
- });
-
- if ctxt.may_break {
- // No way to know whether it's diverging because
- // of a `break` or an outer `break` or `return`.
- self.diverges.set(Diverges::Maybe);
- }
-
- // If we permit break with a value, then result type is
- // the LUB of the breaks (possibly ! if none); else, it
- // is nil. This makes sense because infinite loops
- // (which would have type !) are only possible iff we
- // permit break with a value [1].
- assert!(ctxt.coerce.is_some() || ctxt.may_break); // [1]
- ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil())
- }
- hir::ExprMatch(ref discrim, ref arms, match_src) => {
- self.check_match(expr, &discrim, arms, expected, match_src)
- }
- hir::ExprClosure(capture, ref decl, body_id, _, gen) => {
- self.check_expr_closure(expr, capture, &decl, body_id, gen, expected)
- }
- hir::ExprBlock(ref body, _) => {
- self.check_block_with_expected(&body, expected)
- }
- hir::ExprCall(ref callee, ref args) => {
- self.check_call(expr, &callee, args, expected)
- }
- hir::ExprMethodCall(ref segment, span, ref args) => {
- self.check_method_call(expr, segment, span, args, expected, needs)
- }
- hir::ExprCast(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(t);
- let t_cast = self.resolve_type_vars_if_possible(&t_cast);
- let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
- let t_cast = self.resolve_type_vars_if_possible(&t_cast);
-
- // Eagerly check for some obvious errors.
- if t_expr.references_error() || t_cast.references_error() {
- tcx.types.err
- } else {
- // Defer other checks until we're done type checking.
- let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
- match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
- Ok(cast_check) => {
- deferred_cast_checks.push(cast_check);
- t_cast
+ hir::ExprLoop(ref body, _, source) => {
+ let coerce = match source {
+ // you can only use break with a value from a normal `loop { }`
+ hir::LoopSource::Loop => {
+ let coerce_to = expected.coercion_target_type(self, body.span);
+ Some(CoerceMany::new(coerce_to))
}
- Err(ErrorReported) => {
- tcx.types.err
+
+ hir::LoopSource::WhileLet |
+ hir::LoopSource::ForLoop => {
+ None
}
+ };
+
+ let ctxt = BreakableCtxt {
+ coerce,
+ may_break: false, // Will get updated if/when we find a `break`.
+ };
+
+ let (ctxt, ()) = self.with_breakable_ctxt(expr.id, ctxt, || {
+ self.check_block_no_value(&body);
+ });
+
+ if ctxt.may_break {
+ // No way to know whether it's diverging because
+ // of a `break` or an outer `break` or `return`.
+ self.diverges.set(Diverges::Maybe);
}
- }
- }
- hir::ExprType(ref e, ref t) => {
- let typ = self.to_ty(&t);
- self.check_expr_eq_type(&e, typ);
- typ
- }
- hir::ExprArray(ref args) => {
- let uty = expected.to_option(self).and_then(|uty| {
- match uty.sty {
- ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
- _ => None
- }
- });
-
- let element_ty = if !args.is_empty() {
- let coerce_to = uty.unwrap_or_else(
- || self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)));
- let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
- assert_eq!(self.diverges.get(), Diverges::Maybe);
- for e in args {
- let e_ty = self.check_expr_with_hint(e, coerce_to);
- let cause = self.misc(e.span);
- coerce.coerce(self, &cause, e, e_ty);
- }
- coerce.complete(self)
- } else {
- self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))
- };
- tcx.mk_array(element_ty, args.len() as u64)
- }
- hir::ExprRepeat(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);
- let instance = ty::Instance::resolve(
- tcx.global_tcx(),
- param_env,
- count_def_id,
- substs,
- ).unwrap();
- let global_id = GlobalId {
- instance,
- promoted: None
- };
- let count = tcx.const_eval(param_env.and(global_id));
- if let Err(ref err) = count {
- err.report_as_error(
- tcx.at(tcx.def_span(count_def_id)),
- "could not evaluate repeat length",
- );
+ // If we permit break with a value, then result type is
+ // the LUB of the breaks (possibly ! if none); else, it
+ // is nil. This makes sense because infinite loops
+ // (which would have type !) are only possible iff we
+ // permit break with a value [1].
+ assert!(ctxt.coerce.is_some() || ctxt.may_break); // [1]
+ ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil())
}
-
- let uty = match expected {
- ExpectHasType(uty) => {
+ hir::ExprMatch(ref discrim, ref arms, match_src) => {
+ self.check_match(expr, &discrim, arms, expected, match_src)
+ }
+ hir::ExprClosure(capture, ref decl, body_id, _, gen) => {
+ self.check_expr_closure(expr, capture, &decl, body_id, gen, expected)
+ }
+ hir::ExprBlock(ref body, _) => {
+ self.check_block_with_expected(&body, expected)
+ }
+ hir::ExprCall(ref callee, ref args) => {
+ self.check_call(expr, &callee, args, expected)
+ }
+ hir::ExprMethodCall(ref segment, span, ref args) => {
+ self.check_method_call(expr, segment, span, args, expected, needs)
+ }
+ hir::ExprCast(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(t);
+ let t_cast = self.resolve_type_vars_if_possible(&t_cast);
+ let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
+ let t_cast = self.resolve_type_vars_if_possible(&t_cast);
+
+ // Eagerly check for some obvious errors.
+ if t_expr.references_error() || t_cast.references_error() {
+ tcx.types.err
+ } else {
+ // Defer other checks until we're done type checking.
+ let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
+ match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
+ Ok(cast_check) => {
+ deferred_cast_checks.push(cast_check);
+ t_cast
+ }
+ Err(ErrorReported) => {
+ tcx.types.err
+ }
+ }
+ }
+ }
+ hir::ExprType(ref e, ref t) => {
+ let ty = self.to_ty(&t);
+ self.check_expr_eq_type(&e, ty);
+ ty
+ }
+ hir::ExprArray(ref args) => {
+ let uty = expected.to_option(self).and_then(|uty| {
match uty.sty {
ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
_ => None
}
- }
- _ => None
- };
+ });
- let (element_ty, t) = match uty {
- Some(uty) => {
- self.check_expr_coercable_to_type(&element, uty);
- (uty, uty)
- }
- None => {
- let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
- let element_ty = self.check_expr_has_type_or_error(&element, t);
- (element_ty, t)
- }
- };
+ let element_ty = if !args.is_empty() {
+ let coerce_to = uty.unwrap_or_else(
+ || self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)));
+ let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
+ assert_eq!(self.diverges.get(), Diverges::Maybe);
+ for e in args {
+ let e_ty = self.check_expr_with_hint(e, coerce_to);
+ let cause = self.misc(e.span);
+ coerce.coerce(self, &cause, e, e_ty);
+ }
+ coerce.complete(self)
+ } else {
+ self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))
+ };
+ tcx.mk_array(element_ty, args.len() as u64)
+ }
+ hir::ExprRepeat(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);
+ let instance = ty::Instance::resolve(
+ tcx.global_tcx(),
+ param_env,
+ count_def_id,
+ substs,
+ ).unwrap();
+ let global_id = GlobalId {
+ instance,
+ promoted: None
+ };
+ let count = tcx.const_eval(param_env.and(global_id));
- if let Ok(count) = count {
- let zero_or_one = count.assert_usize(tcx).map_or(false, |count| count <= 1);
- if !zero_or_one {
- // For [foo, ..n] where n > 1, `foo` must have
- // Copy type:
- let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);
- self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item);
+ if let Err(ref err) = count {
+ err.report_as_error(
+ tcx.at(tcx.def_span(count_def_id)),
+ "could not evaluate repeat length",
+ );
}
- }
- if element_ty.references_error() {
- tcx.types.err
- } else if let Ok(count) = count {
- tcx.mk_ty(ty::TyArray(t, count))
- } else {
- tcx.types.err
- }
- }
- hir::ExprTup(ref elts) => {
- let flds = expected.only_has_type(self).and_then(|ty| {
- let ty = self.resolve_type_vars_with_obligations(ty);
- match ty.sty {
- ty::TyTuple(ref flds) => Some(&flds[..]),
+ let uty = match expected {
+ ExpectHasType(uty) => {
+ match uty.sty {
+ ty::TyArray(ty, _) | ty::TySlice(ty) => Some(ty),
+ _ => None
+ }
+ }
_ => None
- }
- });
+ };
- let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| {
- let t = match flds {
- Some(ref fs) if i < fs.len() => {
- let ety = fs[i];
- self.check_expr_coercable_to_type(&e, ety);
- ety
+ let (element_ty, t) = match uty {
+ Some(uty) => {
+ self.check_expr_coercable_to_type(&element, uty);
+ (uty, uty)
}
- _ => {
- self.check_expr_with_expectation(&e, NoExpectation)
+ None => {
+ let ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
+ let element_ty = self.check_expr_has_type_or_error(&element, ty);
+ (element_ty, ty)
}
};
- t
- });
- let tuple = tcx.mk_tup(elt_ts_iter);
- if tuple.references_error() {
- tcx.types.err
- } else {
- self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
- tuple
+
+ if let Ok(count) = count {
+ let zero_or_one = count.assert_usize(tcx).map_or(false, |count| count <= 1);
+ if !zero_or_one {
+ // For [foo, ..n] where n > 1, `foo` must have
+ // Copy type:
+ let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem);
+ self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item);
+ }
+ }
+
+ if element_ty.references_error() {
+ tcx.types.err
+ } else if let Ok(count) = count {
+ tcx.mk_ty(ty::TyArray(t, count))
+ } else {
+ tcx.types.err
+ }
}
- }
- hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
- self.check_expr_struct(expr, expected, qpath, fields, base_expr)
- }
- hir::ExprField(ref base, field) => {
- self.check_field(expr, needs, &base, field)
- }
- hir::ExprIndex(ref base, ref idx) => {
- let base_t = self.check_expr_with_needs(&base, needs);
- let idx_t = self.check_expr(&idx);
-
- if base_t.references_error() {
- base_t
- } else if idx_t.references_error() {
- idx_t
- } else {
- let base_t = self.structurally_resolved_type(base.span, base_t);
- match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
- Some((index_ty, element_ty)) => {
- // two-phase not needed because index_ty is never mutable
- self.demand_coerce(idx, idx_t, index_ty, AllowTwoPhase::No);
- element_ty
- }
- None => {
- let mut err = type_error_struct!(tcx.sess, expr.span, base_t, E0608,
- "cannot index into a value of type `{}`",
- base_t);
- // Try to give some advice about indexing tuples.
- if let ty::TyTuple(..) = base_t.sty {
- let mut needs_note = true;
- // If the index is an integer, we can show the actual
- // fixed expression:
- if let hir::ExprLit(ref lit) = idx.node {
- if let ast::LitKind::Int(i,
+ hir::ExprTup(ref elts) => {
+ let flds = expected.only_has_type(self).and_then(|ty| {
+ let ty = self.resolve_type_vars_with_obligations(ty);
+ match ty.sty {
+ ty::TyTuple(ref flds) => Some(&flds[..]),
+ _ => None
+ }
+ });
+
+ let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| {
+ let t = match flds {
+ Some(ref fs) if i < fs.len() => {
+ let ety = fs[i];
+ self.check_expr_coercable_to_type(&e, ety);
+ ety
+ }
+ _ => {
+ self.check_expr_with_expectation(&e, NoExpectation)
+ }
+ };
+ t
+ });
+ let tuple = tcx.mk_tup(elt_ts_iter);
+ if tuple.references_error() {
+ tcx.types.err
+ } else {
+ self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
+ tuple
+ }
+ }
+ hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
+ self.check_expr_struct(expr, expected, qpath, fields, base_expr)
+ }
+ hir::ExprField(ref base, field) => {
+ self.check_field(expr, needs, &base, field)
+ }
+ hir::ExprIndex(ref base, ref idx) => {
+ let base_t = self.check_expr_with_needs(&base, needs);
+ let idx_t = self.check_expr(&idx);
+
+ if base_t.references_error() {
+ base_t
+ } else if idx_t.references_error() {
+ idx_t
+ } else {
+ let base_t = self.structurally_resolved_type(base.span, base_t);
+ match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
+ Some((index_ty, element_ty)) => {
+ // two-phase not needed because index_ty is never mutable
+ self.demand_coerce(idx, idx_t, index_ty, AllowTwoPhase::No);
+ element_ty
+ }
+ None => {
+ let mut err =
+ type_error_struct!(tcx.sess, expr.span, base_t, E0608,
+ "cannot index into a value of type `{}`",
+ base_t);
+ // Try to give some advice about indexing tuples.
+ if let ty::TyTuple(..) = base_t.sty {
+ let mut needs_note = true;
+ // If the index is an integer, we can show the actual
+ // fixed expression:
+ if let hir::ExprLit(ref lit) = idx.node {
+ if let ast::LitKind::Int(i,
ast::LitIntType::Unsuffixed) = lit.node {
- let snip = tcx.sess.codemap().span_to_snippet(base.span);
- if let Ok(snip) = snip {
- err.span_suggestion(expr.span,
- "to access tuple elements, use",
- format!("{}.{}", snip, i));
- needs_note = false;
- }
- }
- }
- if needs_note {
- err.help("to access tuple elements, use tuple indexing \
+ let snip = tcx.sess.codemap().span_to_snippet(base.span);
+ if let Ok(snip) = snip {
+ err.span_suggestion(expr.span,
+ "to access tuple elements, use",
+ format!("{}.{}", snip, i));
+ needs_note = false;
+ }
+ }
+ }
+ if needs_note {
+ err.help("to access tuple elements, use tuple indexing \
syntax (e.g. `tuple.0`)");
- }
- }
- err.emit();
- self.tcx.types.err
- }
- }
- }
- }
- hir::ExprYield(ref value) => {
- match self.yield_ty {
- Some(ty) => {
- self.check_expr_coercable_to_type(&value, ty);
+ }
+ }
+ err.emit();
+ self.tcx.types.err
+ }
+ }
}
- None => {
- struct_span_err!(self.tcx.sess, expr.span, E0627,
- "yield statement outside of generator literal").emit();
+ }
+ hir::ExprYield(ref value) => {
+ match self.yield_ty {
+ Some(ty) => {
+ self.check_expr_coercable_to_type(&value, ty);
+ }
+ None => {
+ struct_span_err!(self.tcx.sess, expr.span, E0627,
+ "yield statement outside of generator literal").emit();
+ }
}
+ tcx.mk_nil()
}
- tcx.mk_nil()
- }
}
}
Def::Fn(def_id) |
Def::Const(def_id) |
Def::Static(def_id, _) => {
- fn_segment = Some((segments.last().unwrap(),
- self.tcx.generics_of(def_id)));
+ fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id)));
}
// Case 3. Reference to a method or associated const.
// errors if type parameters are provided in an inappropriate place.
let poly_segments = type_segment.is_some() as usize +
fn_segment.is_some() as usize;
- AstConv::prohibit_type_params(self, &segments[..segments.len() - poly_segments]);
+ AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]);
match def {
Def::Local(nid) | Def::Upvar(nid, ..) => {
// to add defaults. If the user provided *too many* types, that's
// a problem.
let supress_mismatch = self.check_impl_trait(span, fn_segment);
- self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch);
- self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch);
+ self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch);
+ self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch);
let (fn_start, has_self) = match (type_segment, fn_segment) {
(_, Some((_, generics))) => {
}
(None, None) => (0, false)
};
+ // FIXME(varkor): Separating out the parameters is messy.
+ let mut lifetimes_type_seg = vec![];
+ let mut types_type_seg = vec![];
+ let mut infer_types_type_seg = true;
+ if let Some((seg, _)) = type_segment {
+ if let Some(ref data) = seg.args {
+ for arg in &data.args {
+ match arg {
+ GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt),
+ GenericArg::Type(ty) => types_type_seg.push(ty),
+ }
+ }
+ }
+ infer_types_type_seg = seg.infer_types;
+ }
+
+ let mut lifetimes_fn_seg = vec![];
+ let mut types_fn_seg = vec![];
+ let mut infer_types_fn_seg = true;
+ if let Some((seg, _)) = fn_segment {
+ if let Some(ref data) = seg.args {
+ for arg in &data.args {
+ match arg {
+ GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt),
+ GenericArg::Type(ty) => types_fn_seg.push(ty),
+ }
+ }
+ }
+ infer_types_fn_seg = seg.infer_types;
+ }
+
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
let mut i = param.index as usize;
- let segment = if i < fn_start {
- if let GenericParamDefKind::Type {..} = param.kind {
+ let (segment, lifetimes, types, infer_types) = if i < fn_start {
+ if let GenericParamDefKind::Type { .. } = param.kind {
// Handle Self first, so we can adjust the index to match the AST.
if has_self && i == 0 {
return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
}
}
i -= has_self as usize;
- type_segment
+ (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg)
} else {
i -= fn_start;
- fn_segment
+ (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg)
};
match param.kind {
GenericParamDefKind::Lifetime => {
- let lifetimes = segment.map_or(&[][..], |(s, _)| {
- s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
- });
-
if let Some(lifetime) = lifetimes.get(i) {
AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
} else {
self.re_infer(span, Some(param)).unwrap().into()
}
}
- GenericParamDefKind::Type {..} => {
- let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
- (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
- });
-
+ GenericParamDefKind::Type { .. } => {
// Skip over the lifetimes in the same segment.
if let Some((_, generics)) = segment {
i -= generics.own_counts().lifetimes;
}
/// Report errors if the provided parameters are too few or too many.
- fn check_path_parameter_count(&self,
- span: Span,
- segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
- is_method_call: bool,
- supress_mismatch_error: bool) {
+ fn check_generic_arg_count(&self,
+ span: Span,
+ segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
+ is_method_call: bool,
+ supress_mismatch_error: bool) {
let (lifetimes, types, infer_types, bindings) = segment.map_or(
- (&[][..], &[][..], true, &[][..]),
- |(s, _)| s.parameters.as_ref().map_or(
- (&[][..], &[][..], s.infer_types, &[][..]),
- |p| (&p.lifetimes[..], &p.types[..],
- s.infer_types, &p.bindings[..])));
- let infer_lifetimes = lifetimes.len() == 0;
-
- let count_lifetime_params = |n| {
- format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
- };
- let count_type_params = |n| {
- format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
- };
+ (vec![], vec![], true, &[][..]),
+ |(s, _)| {
+ s.args.as_ref().map_or(
+ (vec![], vec![], s.infer_types, &[][..]),
+ |data| {
+ let (mut lifetimes, mut types) = (vec![], vec![]);
+ data.args.iter().for_each(|arg| match arg {
+ GenericArg::Lifetime(lt) => lifetimes.push(lt),
+ GenericArg::Type(ty) => types.push(ty),
+ });
+ (lifetimes, types, s.infer_types, &data.bindings[..])
+ }
+ )
+ });
// Check provided parameters.
let ((ty_required, ty_accepted), lt_accepted) =
let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &generics.params {
match param.kind {
- GenericParamDefKind::Lifetime => {
- lt_accepted += 1;
- }
+ GenericParamDefKind::Lifetime => lt_accepted += 1,
GenericParamDefKind::Type { has_default, .. } => {
ty_params.accepted += 1;
if !has_default {
((ty_params.required, ty_params.accepted), lt_accepted)
});
- if types.len() > ty_accepted {
- let span = types[ty_accepted].span;
- let expected_text = count_type_params(ty_accepted);
- let actual_text = count_type_params(types.len());
- struct_span_err!(self.tcx.sess, span, E0087,
- "too many type parameters provided: \
- expected at most {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
-
+ let count_type_params = |n| {
+ format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
+ };
+ let expected_text = count_type_params(ty_accepted);
+ let actual_text = count_type_params(types.len());
+ if let Some((mut err, span)) = if types.len() > ty_accepted {
// To prevent derived errors to accumulate due to extra
// type parameters, we force instantiate_value_path to
// use inference variables instead of the provided types.
*segment = None;
+ let span = types[ty_accepted].span;
+ Some((struct_span_err!(self.tcx.sess, span, E0087,
+ "too many type parameters provided: \
+ expected at most {}, found {}",
+ expected_text, actual_text), span))
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
- let expected_text = count_type_params(ty_required);
- let actual_text = count_type_params(types.len());
- struct_span_err!(self.tcx.sess, span, E0089,
- "too few type parameters provided: \
- expected {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
+ Some((struct_span_err!(self.tcx.sess, span, E0089,
+ "too few type parameters provided: \
+ expected {}, found {}",
+ expected_text, actual_text), span))
+ } else {
+ None
+ } {
+ err.span_label(span, format!("expected {}", expected_text)).emit();
}
if !bindings.is_empty() {
AstConv::prohibit_projection(self, bindings[0].span);
}
+ let infer_lifetimes = lifetimes.len() == 0;
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
let has_late_bound_lifetime_defs =
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
return;
}
- if lifetimes.len() > lt_accepted {
+ let count_lifetime_params = |n| {
+ format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
+ };
+ let expected_text = count_lifetime_params(lt_accepted);
+ let actual_text = count_lifetime_params(lifetimes.len());
+ if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
let span = lifetimes[lt_accepted].span;
- let expected_text = count_lifetime_params(lt_accepted);
- let actual_text = count_lifetime_params(lifetimes.len());
- struct_span_err!(self.tcx.sess, span, E0088,
- "too many lifetime parameters provided: \
- expected at most {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
+ Some((struct_span_err!(self.tcx.sess, span, E0088,
+ "too many lifetime parameters provided: \
+ expected at most {}, found {}",
+ expected_text, actual_text), span))
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
- let expected_text = count_lifetime_params(lt_accepted);
- let actual_text = count_lifetime_params(lifetimes.len());
- struct_span_err!(self.tcx.sess, span, E0090,
- "too few lifetime parameters provided: \
- expected {}, found {}",
- expected_text, actual_text)
- .span_label(span, format!("expected {}", expected_text))
- .emit();
+ Some((struct_span_err!(self.tcx.sess, span, E0090,
+ "too few lifetime parameters provided: \
+ expected {}, found {}",
+ expected_text, actual_text), span))
+ } else {
+ None
+ } {
+ err.span_label(span, format!("expected {}", expected_text)).emit();
}
}
-> bool {
let segment = segment.map(|(path_segment, generics)| {
let explicit = !path_segment.infer_types;
- let impl_trait = generics.params.iter().any(|param| {
- match param.kind {
- ty::GenericParamDefKind::Type {
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
- } => true,
- _ => false,
- }
+ let impl_trait = generics.params.iter().any(|param| match param.kind {
+ ty::GenericParamDefKind::Type {
+ synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+ } => true,
+ _ => false,
});
if explicit && impl_trait {
}
pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- generics: &hir::Generics,
+ generics: &ty::Generics,
ty: Ty<'tcx>) {
- debug!("check_bounds_are_used(n_tps={}, ty={:?})",
- generics.ty_params().count(), ty);
-
- // make a vector of booleans initially false, set to true when used
- if generics.ty_params().next().is_none() { return; }
- let mut tps_used = vec![false; generics.ty_params().count()];
+ let own_counts = generics.own_counts();
+ debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
- let lifetime_count = generics.lifetimes().count();
+ if own_counts.types == 0 {
+ return;
+ }
+ // Make a vector of booleans initially false, set to true when used.
+ let mut types_used = vec![false; own_counts.types];
for leaf_ty in ty.walk() {
- if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty {
+ if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
- tps_used[idx as usize - lifetime_count] = true;
+ types_used[idx as usize - own_counts.lifetimes] = true;
} else if let ty::TyError = leaf_ty.sty {
- // If there already another error, do not emit an error for not using a type Parameter
+ // If there is already another error, do not emit
+ // an error for not using a type Parameter.
assert!(tcx.sess.err_count() > 0);
return;
}
}
- for (&used, param) in tps_used.iter().zip(generics.ty_params()) {
+ let types = generics.params.iter().filter(|param| match param.kind {
+ ty::GenericParamDefKind::Type { .. } => true,
+ _ => false,
+ });
+ for (&used, param) in types_used.iter().zip(types) {
if !used {
- struct_span_err!(tcx.sess, param.span, E0091,
- "type parameter `{}` is unused",
- param.name)
- .span_label(param.span, "unused type parameter")
+ let id = tcx.hir.as_local_node_id(param.def_id).unwrap();
+ let span = tcx.hir.span(id);
+ struct_span_err!(tcx.sess, span, E0091, "type parameter `{}` is unused", param.name)
+ .span_label(span, "unused type parameter")
.emit();
}
}
let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
+ ty::TyError => {
+ // #51714: skip analysis when we have already encountered type errors
+ return;
+ }
ref t => {
span_bug!(
span,
}
fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- item: &hir::Item,
- ast_generics: &hir::Generics)
+ item: &hir::Item,
+ hir_generics: &hir::Generics)
{
let item_def_id = tcx.hir.local_def_id(item.id);
let ty = tcx.type_of(item_def_id);
continue;
}
- let (span, name) = match ast_generics.params[index] {
- hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
- hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
- };
- report_bivariance(tcx, span, name);
+ let param = &hir_generics.params[index];
+ report_bivariance(tcx, param.span, param.name.name());
}
}
fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
let generics = tcx.generics_of(def_id);
let parent = tcx.generics_of(generics.parent.unwrap());
- let impl_params: FxHashMap<_, _> =
- parent.params.iter()
- .flat_map(|param| {
- match param.kind {
- GenericParamDefKind::Lifetime => None,
- GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
- }
- })
- .collect();
-
- for method_param in generics.params.iter() {
+ let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
+ GenericParamDefKind::Lifetime => None,
+ GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
+ }).collect();
+
+ for method_param in &generics.params {
match method_param.kind {
// Shadowing is checked in resolve_lifetime.
GenericParamDefKind::Lifetime => continue,
Some(trait_ref) => {
let trait_def = self.tcx.trait_def(trait_ref.def_id);
- let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr());
+ let unsafe_attr = impl_generics.and_then(|generics| {
+ generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
+ });
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
span_err!(self.tcx.sess,
trait_ref);
}
- (Unsafety::Normal, Some(g), Unsafety::Normal, hir::ImplPolarity::Positive) =>
+ (Unsafety::Normal, Some(attr_name), Unsafety::Normal,
+ hir::ImplPolarity::Positive) =>
{
span_err!(self.tcx.sess,
item.span,
E0569,
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
- g.attr_name());
+ attr_name);
}
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {
use syntax_pos::{Span, DUMMY_SP};
use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety};
+use rustc::hir::GenericParamKind;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
- for param in generics.ty_params() {
- if param.default.is_some() {
- let def_id = self.tcx.hir.local_def_id(param.id);
- self.tcx.type_of(def_id);
+ for param in &generics.params {
+ match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {}
+ hir::GenericParamKind::Type { default: Some(_), .. } => {
+ let def_id = self.tcx.hir.local_def_id(param.id);
+ self.tcx.type_of(def_id);
+ }
+ hir::GenericParamKind::Type { .. } => {}
}
}
intravisit::walk_generics(self, generics);
-> Vec<ty::Predicate<'tcx>>
{
let from_ty_params =
- ast_generics.ty_params()
- .filter(|p| p.id == param_id)
- .flat_map(|p| p.bounds.iter())
+ ast_generics.params.iter()
+ .filter_map(|param| match param.kind {
+ GenericParamKind::Type { .. } if param.id == param_id => Some(¶m.bounds),
+ _ => None
+ })
+ .flat_map(|bounds| bounds.iter())
.flat_map(|b| predicates_from_bound(self, ty, b));
let from_where_clauses =
outer_index: ty::INNERMOST,
has_late_bound_regions: None,
};
- for lifetime in generics.lifetimes() {
- let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id);
- if tcx.is_late_bound(hir_id) {
- return Some(lifetime.lifetime.span);
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let hir_id = tcx.hir.node_to_hir_id(param.id);
+ if tcx.is_late_bound(hir_id) {
+ return Some(param.span);
+ }
+ }
+ _ => {},
}
}
visitor.visit_fn_decl(decl);
let mut params: Vec<_> = opt_self.into_iter().collect();
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
- params.extend(early_lifetimes.enumerate().map(|(i, l)| {
+ params.extend(early_lifetimes.enumerate().map(|(i, param)| {
ty::GenericParamDef {
- name: l.lifetime.name.name().as_interned_str(),
+ name: param.name.name().as_interned_str(),
index: own_start + i as u32,
- def_id: tcx.hir.local_def_id(l.lifetime.id),
- pure_wrt_drop: l.pure_wrt_drop,
+ def_id: tcx.hir.local_def_id(param.id),
+ pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Lifetime,
}
}));
// Now create the real type parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
- params.extend(ast_generics.ty_params().enumerate().map(|(i, p)| {
- if p.name == keywords::SelfType.name() {
- span_bug!(p.span, "`Self` should not be the name of a regular parameter");
- }
-
- if !allow_defaults && p.default.is_some() {
- if !tcx.features().default_type_parameter_fallback {
- tcx.lint_node(
- lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
- p.id,
- p.span,
- &format!("defaults for type parameters are only allowed in `struct`, \
- `enum`, `type`, or `trait` definitions."));
+ let mut i = 0;
+ params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Type { ref default, synthetic, .. } => {
+ if param.name.name() == keywords::SelfType.name() {
+ span_bug!(param.span, "`Self` should not be the name of a regular parameter");
}
- }
- ty::GenericParamDef {
- index: type_start + i as u32,
- name: p.name.as_interned_str(),
- def_id: tcx.hir.local_def_id(p.id),
- pure_wrt_drop: p.pure_wrt_drop,
- kind: ty::GenericParamDefKind::Type {
- has_default: p.default.is_some(),
- object_lifetime_default:
- object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
- synthetic: p.synthetic,
- },
+ if !allow_defaults && default.is_some() {
+ if !tcx.features().default_type_parameter_fallback {
+ tcx.lint_node(
+ lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+ param.id,
+ param.span,
+ &format!("defaults for type parameters are only allowed in \
+ `struct`, `enum`, `type`, or `trait` definitions."));
+ }
+ }
+
+ let ty_param = ty::GenericParamDef {
+ index: type_start + i as u32,
+ name: param.name.name().as_interned_str(),
+ def_id: tcx.hir.local_def_id(param.id),
+ pure_wrt_drop: param.pure_wrt_drop,
+ kind: ty::GenericParamDefKind::Type {
+ has_default: default.is_some(),
+ object_lifetime_default:
+ object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
+ synthetic,
+ },
+ };
+ i += 1;
+ Some(ty_param)
}
+ _ => None,
}));
// provide junk type parameter defs - the only place that
ItemExistential(hir::ExistTy { impl_trait_fn: None, .. }) => unimplemented!(),
// existential types desugared from impl Trait
ItemExistential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => {
- tcx.typeck_tables_of(owner).concrete_existential_types[&def_id]
+ tcx.typeck_tables_of(owner).concrete_existential_types
+ .get(&def_id)
+ .cloned()
+ .unwrap_or_else(|| {
+ // This can occur if some error in the
+ // owner fn prevented us from populating
+ // the `concrete_existential_types` table.
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ &format!(
+ "owner {:?} has no existential type for {:?} in its tables",
+ owner,
+ def_id,
+ ),
+ );
+
+ tcx.types.err
+ })
},
ItemTrait(..) | ItemTraitAlias(..) |
ItemMod(..) |
}
},
- NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
- icx.to_ty(ty)
+ NodeGenericParam(param) => {
+ match param.kind {
+ hir::GenericParamKind::Type { default: Some(ref ty), .. } => {
+ icx.to_ty(ty)
+ }
+ _ => bug!("unexpected non-type NodeGenericParam"),
+ }
}
x => {
let icx = ItemCtxt::new(tcx, def_id);
match tcx.hir.get(node_id) {
- NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) |
- NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => {
- AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl)
+ NodeTraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. }) |
+ NodeImplItem(hir::ImplItem { node: ImplItemKind::Method(sig, _), .. }) => {
+ AstConv::ty_of_fn(&icx, sig.header.unsafety, sig.header.abi, &sig.decl)
}
- NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => {
- AstConv::ty_of_fn(&icx, unsafety, abi, decl)
+ NodeItem(hir::Item { node: ItemFn(decl, header, _, _), .. }) => {
+ AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl)
}
NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => {
// Is it marked with ?Sized
fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
- ast_bounds: &[hir::TyParamBound],
+ ast_bounds: &[hir::GenericBound],
span: Span) -> bool
{
let tcx = astconv.tcx();
// Try to find an unbound in bounds.
let mut unbound = None;
for ab in ast_bounds {
- if let &hir::TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+ if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
if unbound.is_none() {
unbound = Some(ptr.trait_ref.clone());
} else {
/// `resolve_lifetime::early_bound_lifetimes`.
fn early_bound_lifetimes_from_generics<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- ast_generics: &'a hir::Generics)
- -> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx>
+ generics: &'a hir::Generics)
+ -> impl Iterator<Item=&'a hir::GenericParam> + Captures<'tcx>
{
- ast_generics
- .lifetimes()
- .filter(move |l| {
- let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id);
+ generics.params.iter().filter(move |param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let hir_id = tcx.hir.node_to_hir_id(param.id);
!tcx.is_late_bound(hir_id)
- })
+ }
+ _ => false,
+ })
}
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut index = parent_count + has_own_self as u32;
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
- def_id: tcx.hir.local_def_id(param.lifetime.id),
+ def_id: tcx.hir.local_def_id(param.id),
index,
- name: param.lifetime.name.name().as_interned_str(),
+ name: param.name.name().as_interned_str(),
}));
index += 1;
- for bound in ¶m.bounds {
- let bound_region = AstConv::ast_region_to_region(&icx, bound, None);
- let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
- predicates.push(outlives.to_predicate());
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ param.bounds.iter().for_each(|bound| match bound {
+ hir::GenericBound::Outlives(lt) => {
+ let bound = AstConv::ast_region_to_region(&icx, <, None);
+ let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound));
+ predicates.push(outlives.to_predicate());
+ }
+ _ => bug!(),
+ });
+ },
+ _ => bug!(),
}
}
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
- for param in ast_generics.ty_params() {
- let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx);
- index += 1;
-
- let bounds = compute_bounds(&icx,
- param_ty,
- ¶m.bounds,
- SizedByDefault::Yes,
- param.span);
- predicates.extend(bounds.predicates(tcx, param_ty));
+ for param in &ast_generics.params {
+ match param.kind {
+ GenericParamKind::Type { .. } => {
+ let name = param.name.name().as_interned_str();
+ let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
+ index += 1;
+
+ let sized = SizedByDefault::Yes;
+ let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span);
+ predicates.extend(bounds.predicates(tcx, param_ty));
+ }
+ _ => {}
+ }
}
// Add in the bounds that appear in the where-clause
for bound in bound_pred.bounds.iter() {
match bound {
- &hir::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
+ &hir::GenericBound::Trait(ref poly_trait_ref, _) => {
let mut projections = Vec::new();
let trait_ref =
}
}
- &hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
+ &hir::GenericBound::Outlives(ref lifetime) => {
let region = AstConv::ast_region_to_region(&icx,
lifetime,
None);
&hir::WherePredicate::RegionPredicate(ref region_pred) => {
let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None);
for bound in ®ion_pred.bounds {
- let r2 = AstConv::ast_region_to_region(&icx, bound, None);
+ let r2 = match bound {
+ hir::GenericBound::Outlives(lt) => {
+ AstConv::ast_region_to_region(&icx, lt, None)
+ }
+ _ => bug!(),
+ };
let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
predicates.push(ty::Predicate::RegionOutlives(pred))
}
/// built-in trait (formerly known as kind): Send.
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty: Ty<'tcx>,
- ast_bounds: &[hir::TyParamBound],
+ ast_bounds: &[hir::GenericBound],
sized_by_default: SizedByDefault,
span: Span)
-> Bounds<'tcx>
let mut trait_bounds = vec![];
for ast_bound in ast_bounds {
match *ast_bound {
- hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
- trait_bounds.push(b);
- }
- hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
- hir::RegionTyParamBound(ref l) => {
- region_bounds.push(l);
- }
+ hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b),
+ hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
+ hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
}
}
let mut projection_bounds = vec![];
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
- astconv.instantiate_poly_trait_ref(bound,
- param_ty,
- &mut projection_bounds)
+ astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds)
}).collect();
let region_bounds = region_bounds.into_iter().map(|r| {
}
}
-/// Converts a specific TyParamBound from the AST into a set of
+/// Converts a specific GenericBound from the AST into a set of
/// predicates that apply to the self-type. A vector is returned
/// because this can be anywhere from 0 predicates (`T:?Sized` adds no
/// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
/// and `<T as Bar>::X == i32`).
fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
param_ty: Ty<'tcx>,
- bound: &hir::TyParamBound)
+ bound: &hir::GenericBound)
-> Vec<ty::Predicate<'tcx>>
{
match *bound {
- hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
+ hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
let mut projections = Vec::new();
let pred = astconv.instantiate_poly_trait_ref(tr,
param_ty,
.chain(Some(pred.to_predicate()))
.collect()
}
- hir::RegionTyParamBound(ref lifetime) => {
+ hir::GenericBound::Outlives(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime, None);
let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
vec![ty::Predicate::TypeOutlives(pred)]
}
- hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {
- Vec::new()
- }
+ hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![],
}
}
}
});
} else if attr.check_name("export_name") {
- if let s @ Some(_) = attr.value_str() {
- codegen_fn_attrs.export_name = s;
+ if let Some(s) = attr.value_str() {
+ if s.as_str().contains("\0") {
+ // `#[export_name = ...]` will be converted to a null-terminated string,
+ // so it may not contain any null characters.
+ struct_span_err!(tcx.sess, attr.span, E0648,
+ "`export_name` may not contain null characters")
+ .emit();
+ }
+ codegen_fn_attrs.export_name = Some(s);
} else {
struct_span_err!(tcx.sess, attr.span, E0558,
- "export_name attribute has invalid format")
+ "`export_name` attribute has invalid format")
.span_label(attr.span, "did you mean #[export_name=\"*\"]?")
.emit();
}
"##,
E0131: r##"
-It is not possible to define `main` with type parameters, or even with function
-parameters. When `main` is present, it must take no arguments and return `()`.
+It is not possible to define `main` with generic parameters.
+When `main` is present, it must take no arguments and return `()`.
Erroneous code example:
```compile_fail,E0131
-fn main<T>() { // error: main function is not allowed to have type parameters
+fn main<T>() { // error: main function is not allowed to have generic parameters
}
```
"##,
Erroneous code example:
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#[export_name] // error: export_name attribute has invalid format
+#[export_name] // error: `export_name` attribute has invalid format
pub fn something() {}
fn main() {}
```
"##,
+E0648: r##"
+`export_name` attributes may not contain null characters (`\0`).
+
+```compile_fail,E0648
+#[export_name="\0foo"] // error: `export_name` may not contain null characters
+pub fn bar() {}
+```
+"##,
+
E0689: r##"
This error indicates that the numeric value for the method being passed exists
but the type of the numeric value or binding could not be identified.
#![feature(crate_visibility_modifier)]
#![feature(from_ref)]
#![feature(exhaustive_patterns)]
+#![feature(iterator_find_map)]
#![feature(quote)]
#![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)]
hir::ItemFn(.., ref generics, _) => {
let mut error = false;
if !generics.params.is_empty() {
- let param_type = if generics.is_lt_parameterized() {
- "lifetime"
- } else {
- "type"
- };
- let msg =
- format!("`main` function is not allowed to have {} parameters",
- param_type);
- let label =
- format!("`main` cannot have {} parameters", param_type);
+ let msg = format!("`main` function is not allowed to have generic \
+ parameters");
+ let label = format!("`main` cannot have generic parameters");
struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
.span_label(generics.span, label)
.emit();
[dependencies]
pulldown-cmark = { version = "0.1.2", default-features = false }
-minifier = "0.0.11"
+minifier = "0.0.14"
tempfile = "3"
None
}
- fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
- let mut lifetimes = vec![];
- let mut types = vec![];
+ fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs {
+ let mut args = vec![];
for param in generics.params.iter() {
match param.kind {
ty::GenericParamDefKind::Lifetime => {
let name = if param.name == "" {
- hir::LifetimeName::Static
+ hir::ParamName::Plain(keywords::StaticLifetime.name())
} else {
- hir::LifetimeName::Name(param.name.as_symbol())
+ hir::ParamName::Plain(param.name.as_symbol())
};
- lifetimes.push(hir::Lifetime {
+ args.push(hir::GenericArg::Lifetime(hir::Lifetime {
id: ast::DUMMY_NODE_ID,
span: DUMMY_SP,
- name,
- });
+ name: hir::LifetimeName::Param(name),
+ }));
}
ty::GenericParamDefKind::Type {..} => {
- types.push(P(self.ty_param_to_ty(param.clone())));
+ args.push(hir::GenericArg::Type(P(self.ty_param_to_ty(param.clone()))));
}
}
}
- hir::PathParameters {
- lifetimes: HirVec::from_vec(lifetimes),
- types: HirVec::from_vec(types),
+ hir::GenericArgs {
+ args: HirVec::from_vec(args),
bindings: HirVec::new(),
parenthesized: false,
}
.iter()
.flat_map(|(name, lifetime)| {
let empty = Vec::new();
- let bounds: FxHashSet<Lifetime> = finished
- .get(name)
- .unwrap_or(&empty)
- .iter()
- .map(|region| self.get_lifetime(region, names_map))
+ let bounds: FxHashSet<GenericBound> = finished.get(name).unwrap_or(&empty).iter()
+ .map(|region| GenericBound::Outlives(self.get_lifetime(region, names_map)))
.collect();
if bounds.is_empty() {
// We only care about late bound regions, as we need to add them
// to the 'for<>' section
&ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
- Some(GenericParamDef::Lifetime(Lifetime(name.to_string())))
+ Some(GenericParamDef {
+ name: name.to_string(),
+ kind: GenericParamDefKind::Lifetime,
+ })
}
&ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
_ => panic!("Unexpected region type {:?}", r),
fn make_final_bounds<'b, 'c, 'cx>(
&self,
- ty_to_bounds: FxHashMap<Type, FxHashSet<TyParamBound>>,
+ ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)>,
- lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<Lifetime>>,
+ lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>,
) -> Vec<WherePredicate> {
ty_to_bounds
.into_iter()
let mut new_path = path.clone();
let last_segment = new_path.segments.pop().unwrap();
- let (old_input, old_output) = match last_segment.params {
- PathParameters::AngleBracketed { types, .. } => (types, None),
- PathParameters::Parenthesized { inputs, output, .. } => {
+ let (old_input, old_output) = match last_segment.args {
+ GenericArgs::AngleBracketed { types, .. } => (types, None),
+ GenericArgs::Parenthesized { inputs, output, .. } => {
(inputs, output)
}
};
);
}
- let new_params = PathParameters::Parenthesized {
+ let new_params = GenericArgs::Parenthesized {
inputs: old_input,
output,
};
new_path.segments.push(PathSegment {
name: last_segment.name,
- params: new_params,
+ args: new_params,
});
Type::ResolvedPath {
}
_ => panic!("Unexpected data: {:?}, {:?}", ty, data),
};
- bounds.insert(TyParamBound::TraitBound(
+ bounds.insert(GenericBound::TraitBound(
PolyTrait {
trait_: new_ty,
generic_params: poly_trait.generic_params,
.filter(|&(_, ref bounds)| !bounds.is_empty())
.map(|(lifetime, bounds)| {
let mut bounds_vec = bounds.into_iter().collect();
- self.sort_where_lifetimes(&mut bounds_vec);
+ self.sort_where_bounds(&mut bounds_vec);
WherePredicate::RegionPredicate {
lifetime,
bounds: bounds_vec,
// later
let is_fn = match &mut b {
- &mut TyParamBound::TraitBound(ref mut p, _) => {
+ &mut GenericBound::TraitBound(ref mut p, _) => {
// Insert regions into the for_generics hash map first, to ensure
// that we don't end up with duplicate bounds (e.g. for<'b, 'b>)
for_generics.extend(p.generic_params.clone());
// FIXME: Remove this scope when NLL lands
{
- let params =
- &mut new_trait_path.segments.last_mut().unwrap().params;
+ let args =
+ &mut new_trait_path.segments.last_mut().unwrap().args;
- match params {
+ match args {
// Convert somethiung like '<T as Iterator::Item> = u8'
// to 'T: Iterator<Item=u8>'
- &mut PathParameters::AngleBracketed {
+ &mut GenericArgs::AngleBracketed {
ref mut bindings,
..
} => {
ty: rhs,
});
}
- &mut PathParameters::Parenthesized { .. } => {
+ &mut GenericArgs::Parenthesized { .. } => {
existing_predicates.push(
WherePredicate::EqPredicate {
lhs: lhs.clone(),
.entry(*ty.clone())
.or_insert_with(|| FxHashSet());
- bounds.insert(TyParamBound::TraitBound(
+ bounds.insert(GenericBound::TraitBound(
PolyTrait {
trait_: Type::ResolvedPath {
path: new_trait_path,
// that we don't see a
// duplicate bound like `T: Iterator + Iterator<Item=u8>`
// on the docs page.
- bounds.remove(&TyParamBound::TraitBound(
+ bounds.remove(&GenericBound::TraitBound(
PolyTrait {
trait_: *trait_.clone(),
generic_params: Vec::new(),
existing_predicates.extend(final_bounds);
- for p in generic_params.iter_mut() {
- match p {
- &mut GenericParamDef::Type(ref mut ty) => {
- // We never want something like 'impl<T=Foo>'
- ty.default.take();
-
- let generic_ty = Type::Generic(ty.name.clone());
-
+ for param in generic_params.iter_mut() {
+ match param.kind {
+ GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
+ // We never want something like `impl<T=Foo>`.
+ default.take();
+ let generic_ty = Type::Generic(param.name.clone());
if !has_sized.contains(&generic_ty) {
- ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx));
+ bounds.insert(0, GenericBound::maybe_sized(self.cx));
}
}
- GenericParamDef::Lifetime(_) => {}
+ GenericParamDefKind::Lifetime => {}
}
}
// both for visual consistency between 'rustdoc' runs, and to
// make writing tests much easier
#[inline]
- fn sort_where_bounds(&self, mut bounds: &mut Vec<TyParamBound>) {
- // We should never have identical bounds - and if we do,
- // they're visually identical as well. Therefore, using
- // an unstable sort is fine.
- self.unstable_debug_sort(&mut bounds);
- }
-
- #[inline]
- fn sort_where_lifetimes(&self, mut bounds: &mut Vec<Lifetime>) {
+ fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
// We should never have identical bounds - and if we do,
// they're visually identical as well. Therefore, using
// an unstable sort is fine.
// to end users, it makes writing tests much more difficult, as predicates
// can appear in any order in the final result.
//
- // To solve this problem, we sort WherePredicates and TyParamBounds
+ // To solve this problem, we sort WherePredicates and GenericBounds
// by their Debug string. The thing to keep in mind is that we don't really
// care what the final order is - we're synthesizing an impl or bound
// ourselves, so any order can be considered equally valid. By sorting the
// Using the Debug impementation for sorting prevents us from needing to
// write quite a bit of almost entirely useless code (e.g. how should two
// Types be sorted relative to each other). It also allows us to solve the
- // problem for both WherePredicates and TyParamBounds at the same time. This
+ // problem for both WherePredicates and GenericBounds at the same time. This
// approach is probably somewhat slower, but the small number of items
// involved (impls rarely have more than a few bounds) means that it
// shouldn't matter in practice.
clean::Function {
decl: (did, sig).clean(cx),
generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
- unsafety: sig.unsafety(),
- constness,
- abi: sig.abi(),
+ header: hir::FnHeader {
+ unsafety: sig.unsafety(),
+ abi: sig.abi(),
+ constness,
+ asyncness: hir::IsAsync::NotAsync,
+ }
}
}
let polarity = tcx.impl_polarity(did);
let trait_ = associated_trait.clean(cx).map(|bound| {
match bound {
- clean::TraitBound(polyt, _) => polyt.trait_,
- clean::RegionBound(..) => unreachable!(),
+ clean::GenericBound::TraitBound(polyt, _) => polyt.trait_,
+ clean::GenericBound::Outlives(..) => unreachable!(),
}
});
if trait_.def_id() == tcx.lang_items().deref_trait() {
let provided = trait_.def_id().map(|did| {
tcx.provided_trait_methods(did)
- .into_iter()
- .map(|meth| meth.name.to_string())
- .collect()
+ .into_iter()
+ .map(|meth| meth.name.to_string())
+ .collect()
}).unwrap_or(FxHashSet());
ret.push(clean::Item {
} if *s == "Self" => {
bounds.retain(|bound| {
match *bound {
- clean::TyParamBound::TraitBound(clean::PolyTrait {
+ clean::GenericBound::TraitBound(clean::PolyTrait {
trait_: clean::ResolvedPath { did, .. },
..
}, _) => did != trait_did,
/// the metadata for a crate, so we want to separate those out and create a new
/// list of explicit supertrait bounds to render nicely.
fn separate_supertrait_bounds(mut g: clean::Generics)
- -> (clean::Generics, Vec<clean::TyParamBound>) {
+ -> (clean::Generics, Vec<clean::GenericBound>) {
let mut ty_bounds = Vec::new();
g.where_predicates.retain(|pred| {
match *pred {
pub use self::Type::*;
pub use self::Mutability::*;
pub use self::ItemEnum::*;
-pub use self::TyParamBound::*;
pub use self::SelfTy::*;
pub use self::FunctionRetTy::*;
pub use self::Visibility::{Public, Inherited};
-use syntax;
use rustc_target::spec::abi::Abi;
+use syntax;
use syntax::ast::{self, AttrStyle, NodeId, Ident};
use syntax::attr;
use syntax::codemap::{dummy_spanned, Spanned};
use rustc::ty::fold::TypeFolder;
use rustc::middle::lang_items;
use rustc::mir::interpret::GlobalId;
-use rustc::hir::{self, HirVec};
+use rustc::hir::{self, GenericArg, HirVec};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::def_id::DefIndexAddressSpace;
use rustc::ty::subst::Substs;
-use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount};
+use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::middle::stability;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_typeck::hir_ty_to_ty;
MacroItem(Macro),
PrimitiveItem(PrimitiveType),
AssociatedConstItem(Type, Option<String>),
- AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
+ AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
/// An item that has been stripped by a rustdoc pass
StrippedItem(Box<ItemEnum>),
KeywordItem(String),
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
-pub struct TyParam {
- pub name: String,
- pub did: DefId,
- pub bounds: Vec<TyParamBound>,
- pub default: Option<Type>,
- pub synthetic: Option<hir::SyntheticTyParamKind>,
-}
-
-impl Clean<TyParam> for hir::TyParam {
- fn clean(&self, cx: &DocContext) -> TyParam {
- TyParam {
- name: self.name.clean(cx),
- did: cx.tcx.hir.local_def_id(self.id),
- bounds: self.bounds.clean(cx),
- default: self.default.clean(cx),
- synthetic: self.synthetic,
- }
- }
-}
-
-impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
- fn clean(&self, cx: &DocContext) -> TyParam {
- cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
- let has_default = match self.kind {
- ty::GenericParamDefKind::Type { has_default, .. } => has_default,
- _ => panic!("tried to convert a non-type GenericParamDef as a type")
- };
- TyParam {
- name: self.name.clean(cx),
- did: self.def_id,
- bounds: vec![], // these are filled in from the where-clauses
- default: if has_default {
- Some(cx.tcx.type_of(self.def_id).clean(cx))
- } else {
- None
- },
- synthetic: None,
- }
- }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
-pub enum TyParamBound {
- RegionBound(Lifetime),
- TraitBound(PolyTrait, hir::TraitBoundModifier)
+pub enum GenericBound {
+ TraitBound(PolyTrait, hir::TraitBoundModifier),
+ Outlives(Lifetime),
}
-impl TyParamBound {
- fn maybe_sized(cx: &DocContext) -> TyParamBound {
+impl GenericBound {
+ fn maybe_sized(cx: &DocContext) -> GenericBound {
let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait);
- TraitBound(PolyTrait {
+ GenericBound::TraitBound(PolyTrait {
trait_: ResolvedPath {
path,
typarams: None,
fn is_sized_bound(&self, cx: &DocContext) -> bool {
use rustc::hir::TraitBoundModifier as TBM;
- if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
+ if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
return true;
}
}
fn get_poly_trait(&self) -> Option<PolyTrait> {
- if let TyParamBound::TraitBound(ref p, _) = *self {
+ if let GenericBound::TraitBound(ref p, _) = *self {
return Some(p.clone())
}
None
fn get_trait_type(&self) -> Option<Type> {
- if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
+ if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
return Some(trait_.clone());
}
None
}
}
-impl Clean<TyParamBound> for hir::TyParamBound {
- fn clean(&self, cx: &DocContext) -> TyParamBound {
+impl Clean<GenericBound> for hir::GenericBound {
+ fn clean(&self, cx: &DocContext) -> GenericBound {
match *self {
- hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
- hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
+ hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
+ hir::GenericBound::Trait(ref t, modifier) => {
+ GenericBound::TraitBound(t.clean(cx), modifier)
+ }
}
}
}
-fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
- bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters {
+fn external_generic_args(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
+ bindings: Vec<TypeBinding>, substs: &Substs) -> GenericArgs {
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
let inputs = match types[0].sty {
ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
_ => {
- return PathParameters::AngleBracketed {
+ return GenericArgs::AngleBracketed {
lifetimes,
types: types.clean(cx),
bindings,
// ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
// _ => Some(types[1].clean(cx))
// };
- PathParameters::Parenthesized {
+ GenericArgs::Parenthesized {
inputs,
output,
}
},
_ => {
- PathParameters::AngleBracketed {
+ GenericArgs::AngleBracketed {
lifetimes,
types: types.clean(cx),
bindings,
def: Def::Err,
segments: vec![PathSegment {
name: name.to_string(),
- params: external_path_params(cx, trait_did, has_self, bindings, substs)
+ args: external_generic_args(cx, trait_did, has_self, bindings, substs)
}],
}
}
-impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
- fn clean(&self, cx: &DocContext) -> TyParamBound {
+impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
+ fn clean(&self, cx: &DocContext) -> GenericBound {
let (trait_ref, ref bounds) = *self;
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
if let ty::TyRef(ref reg, _, _) = ty_s.sty {
if let &ty::RegionKind::ReLateBound(..) = *reg {
debug!(" hit an ReLateBound {:?}", reg);
- if let Some(lt) = reg.clean(cx) {
- late_bounds.push(GenericParamDef::Lifetime(lt));
+ if let Some(Lifetime(name)) = reg.clean(cx) {
+ late_bounds.push(GenericParamDef {
+ name,
+ kind: GenericParamDefKind::Lifetime,
+ });
}
}
}
}
}
- TraitBound(
+ GenericBound::TraitBound(
PolyTrait {
trait_: ResolvedPath {
path,
}
}
-impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
- fn clean(&self, cx: &DocContext) -> TyParamBound {
+impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
+ fn clean(&self, cx: &DocContext) -> GenericBound {
(self, vec![]).clean(cx)
}
}
-impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
- fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
+impl<'tcx> Clean<Option<Vec<GenericBound>>> for Substs<'tcx> {
+ fn clean(&self, cx: &DocContext) -> Option<Vec<GenericBound>> {
let mut v = Vec::new();
- v.extend(self.regions().filter_map(|r| r.clean(cx))
- .map(RegionBound));
- v.extend(self.types().map(|t| TraitBound(PolyTrait {
+ v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
+ v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
trait_: t.clean(cx),
generic_params: Vec::new(),
}, hir::TraitBoundModifier::None)));
}
}
-impl Clean<Lifetime> for hir::LifetimeDef {
+impl Clean<Lifetime> for hir::GenericParam {
fn clean(&self, _: &DocContext) -> Lifetime {
- if self.bounds.len() > 0 {
- let mut s = format!("{}: {}",
- self.lifetime.name.name(),
- self.bounds[0].name.name());
- for bound in self.bounds.iter().skip(1) {
- s.push_str(&format!(" + {}", bound.name.name()));
+ match self.kind {
+ hir::GenericParamKind::Lifetime { .. } => {
+ if self.bounds.len() > 0 {
+ let mut bounds = self.bounds.iter().map(|bound| match bound {
+ hir::GenericBound::Outlives(lt) => lt,
+ _ => panic!(),
+ });
+ let name = bounds.next().unwrap().name.name();
+ let mut s = format!("{}: {}", self.name.name(), name);
+ for bound in bounds {
+ s.push_str(&format!(" + {}", bound.name.name()));
+ }
+ Lifetime(s)
+ } else {
+ Lifetime(self.name.name().to_string())
+ }
}
- Lifetime(s)
- } else {
- Lifetime(self.lifetime.name.name().to_string())
+ _ => panic!(),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum WherePredicate {
- BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
- RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
+ BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
+ RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
EqPredicate { lhs: Type, rhs: Type },
}
let ty::OutlivesPredicate(ref a, ref b) = *self;
WherePredicate::RegionPredicate {
lifetime: a.clean(cx).unwrap(),
- bounds: vec![b.clean(cx).unwrap()]
+ bounds: vec![GenericBound::Outlives(b.clean(cx).unwrap())]
}
}
}
WherePredicate::BoundPredicate {
ty: ty.clean(cx),
- bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
+ bounds: vec![GenericBound::Outlives(lt.clean(cx).unwrap())]
}
}
}
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &DocContext) -> Type {
let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
- TyParamBound::TraitBound(t, _) => t.trait_,
- TyParamBound::RegionBound(_) => {
- panic!("cleaning a trait got a region")
- }
+ GenericBound::TraitBound(t, _) => t.trait_,
+ GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
};
Type::QPath {
name: cx.tcx.associated_item(self.item_def_id).name.clean(cx),
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
-pub enum GenericParamDef {
- Lifetime(Lifetime),
- Type(TyParam),
+pub enum GenericParamDefKind {
+ Lifetime,
+ Type {
+ did: DefId,
+ bounds: Vec<GenericBound>,
+ default: Option<Type>,
+ synthetic: Option<hir::SyntheticTyParamKind>,
+ },
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+pub struct GenericParamDef {
+ pub name: String,
+
+ pub kind: GenericParamDefKind,
}
impl GenericParamDef {
pub fn is_synthetic_type_param(&self) -> bool {
- match self {
- GenericParamDef::Type(ty) => ty.synthetic.is_some(),
- GenericParamDef::Lifetime(_) => false,
+ match self.kind {
+ GenericParamDefKind::Lifetime => false,
+ GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
+ }
+ }
+}
+
+impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
+ fn clean(&self, cx: &DocContext) -> GenericParamDef {
+ let (name, kind) = match self.kind {
+ ty::GenericParamDefKind::Lifetime => {
+ (self.name.to_string(), GenericParamDefKind::Lifetime)
+ }
+ ty::GenericParamDefKind::Type { has_default, .. } => {
+ cx.renderinfo.borrow_mut().external_typarams
+ .insert(self.def_id, self.name.clean(cx));
+ let default = if has_default {
+ Some(cx.tcx.type_of(self.def_id).clean(cx))
+ } else {
+ None
+ };
+ (self.name.clean(cx), GenericParamDefKind::Type {
+ did: self.def_id,
+ bounds: vec![], // These are filled in from the where-clauses.
+ default,
+ synthetic: None,
+ })
+ }
+ };
+
+ GenericParamDef {
+ name,
+ kind,
}
}
}
impl Clean<GenericParamDef> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> GenericParamDef {
- match *self {
- hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)),
- hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)),
+ let (name, kind) = match self.kind {
+ hir::GenericParamKind::Lifetime { .. } => {
+ let name = if self.bounds.len() > 0 {
+ let mut bounds = self.bounds.iter().map(|bound| match bound {
+ hir::GenericBound::Outlives(lt) => lt,
+ _ => panic!(),
+ });
+ let name = bounds.next().unwrap().name.name();
+ let mut s = format!("{}: {}", self.name.name(), name);
+ for bound in bounds {
+ s.push_str(&format!(" + {}", bound.name.name()));
+ }
+ s
+ } else {
+ self.name.name().to_string()
+ };
+ (name, GenericParamDefKind::Lifetime)
+ }
+ hir::GenericParamKind::Type { ref default, synthetic, .. } => {
+ (self.name.name().clean(cx), GenericParamDefKind::Type {
+ did: cx.tcx.hir.local_def_id(self.id),
+ bounds: self.bounds.clean(cx),
+ default: default.clean(cx),
+ synthetic: synthetic,
+ })
+ }
+ };
+
+ GenericParamDef {
+ name,
+ kind,
}
}
}
// In order for normal parameters to be able to refer to synthetic ones,
// scans them first.
fn is_impl_trait(param: &hir::GenericParam) -> bool {
- if let hir::GenericParam::Type(ref tp) = param {
- tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
- } else {
- false
+ match param.kind {
+ hir::GenericParamKind::Type { synthetic, .. } => {
+ synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
+ }
+ _ => false,
}
}
let impl_trait_params = self.params
.iter()
- .filter(|p| is_impl_trait(p))
- .map(|p| {
- let p = p.clean(cx);
- if let GenericParamDef::Type(ref tp) = p {
- cx.impl_trait_bounds
- .borrow_mut()
- .insert(tp.did, tp.bounds.clone());
- } else {
- unreachable!()
+ .filter(|param| is_impl_trait(param))
+ .map(|param| {
+ let param: GenericParamDef = param.clean(cx);
+ match param.kind {
+ GenericParamDefKind::Lifetime => unreachable!(),
+ GenericParamDefKind::Type { did, ref bounds, .. } => {
+ cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
+ }
}
- p
+ param
})
.collect::<Vec<_>>();
}
params.extend(impl_trait_params);
- let mut g = Generics {
+ let mut generics = Generics {
params,
- where_predicates: self.where_clause.predicates.clean(cx)
+ where_predicates: self.where_clause.predicates.clean(cx),
};
// Some duplicates are generated for ?Sized bounds between type params and where
// predicates. The point in here is to move the bounds definitions from type params
// to where predicates when such cases occur.
- for where_pred in &mut g.where_predicates {
+ for where_pred in &mut generics.where_predicates {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
if bounds.is_empty() {
- for param in &mut g.params {
- if let GenericParamDef::Type(ref mut type_param) = *param {
- if &type_param.name == name {
- mem::swap(bounds, &mut type_param.bounds);
- break
+ for param in &mut generics.params {
+ match param.kind {
+ GenericParamDefKind::Lifetime => {}
+ GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
+ if ¶m.name == name {
+ mem::swap(bounds, ty_bounds);
+ break
+ }
}
}
}
_ => continue,
}
}
- g
+ generics
}
}
// Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove
// them.
- let stripped_typarams = gens.params.iter().filter_map(|param| {
- if let ty::GenericParamDefKind::Type {..} = param.kind {
+ let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
+ ty::GenericParamDefKind::Lifetime => None,
+ ty::GenericParamDefKind::Type { .. } => {
if param.name == keywords::SelfType.name().as_str() {
assert_eq!(param.index, 0);
- None
- } else {
- Some(param.clean(cx))
+ return None;
}
- } else {
- None
+ Some(param.clean(cx))
}
- }).collect::<Vec<TyParam>>();
+ }).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.to_vec().clean(cx);
if !sized_params.contains(&tp.name) {
where_predicates.push(WP::BoundPredicate {
ty: Type::Generic(tp.name.clone()),
- bounds: vec![TyParamBound::maybe_sized(cx)],
+ bounds: vec![GenericBound::maybe_sized(cx)],
})
}
}
Generics {
params: gens.params
.iter()
- .flat_map(|param| {
- if let ty::GenericParamDefKind::Lifetime = param.kind {
- Some(GenericParamDef::Lifetime(param.clean(cx)))
- } else {
- None
- }
- }).chain(
- simplify::ty_params(stripped_typarams)
- .into_iter()
- .map(|tp| GenericParamDef::Type(tp))
- )
+ .flat_map(|param| match param.kind {
+ ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
+ ty::GenericParamDefKind::Type { .. } => None,
+ }).chain(simplify::ty_params(stripped_typarams).into_iter())
.collect(),
where_predicates: simplify::where_clauses(cx, where_predicates),
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Method {
pub generics: Generics,
- pub unsafety: hir::Unsafety,
- pub constness: hir::Constness,
pub decl: FnDecl,
- pub abi: Abi,
+ pub header: hir::FnHeader,
}
impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) {
Method {
decl,
generics,
- unsafety: self.0.unsafety,
- constness: self.0.constness,
- abi: self.0.abi
+ header: self.0.header,
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TyMethod {
- pub unsafety: hir::Unsafety,
+ pub header: hir::FnHeader,
pub decl: FnDecl,
pub generics: Generics,
- pub abi: Abi,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Function {
pub decl: FnDecl,
pub generics: Generics,
- pub unsafety: hir::Unsafety,
- pub constness: hir::Constness,
- pub abi: Abi,
+ pub header: hir::FnHeader,
}
impl Clean<Item> for doctree::Function {
inner: FunctionItem(Function {
decl,
generics,
- unsafety: self.unsafety,
- constness: self.constness,
- abi: self.abi,
+ header: self.header,
}),
}
}
pub unsafety: hir::Unsafety,
pub items: Vec<Item>,
pub generics: Generics,
- pub bounds: Vec<TyParamBound>,
+ pub bounds: Vec<GenericBound>,
pub is_spotlight: bool,
pub is_auto: bool,
}
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
});
TyMethodItem(TyMethod {
- unsafety: sig.unsafety.clone(),
+ header: sig.header,
decl,
generics,
- abi: sig.abi
})
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
hir::Constness::NotConst
};
MethodItem(Method {
- unsafety: sig.unsafety(),
generics,
decl,
- abi: sig.abi(),
- constness,
+ header: hir::FnHeader {
+ unsafety: sig.unsafety(),
+ abi: sig.abi(),
+ constness,
+ asyncness: hir::IsAsync::NotAsync,
+ }
})
} else {
TyMethodItem(TyMethod {
- unsafety: sig.unsafety(),
generics,
decl,
- abi: sig.abi(),
+ header: hir::FnHeader {
+ unsafety: sig.unsafety(),
+ abi: sig.abi(),
+ constness: hir::Constness::NotConst,
+ asyncness: hir::IsAsync::NotAsync,
+ }
})
}
}
// at the end.
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
Some(i) => { bounds.remove(i); }
- None => bounds.push(TyParamBound::maybe_sized(cx)),
+ None => bounds.push(GenericBound::maybe_sized(cx)),
}
let ty = if self.defaultness.has_value() {
/// structs/enums/traits (most that'd be an hir::TyPath)
ResolvedPath {
path: Path,
- typarams: Option<Vec<TyParamBound>>,
+ typarams: Option<Vec<GenericBound>>,
did: DefId,
/// true if is a `T::Name` path for associated types
is_generic: bool,
Infer,
// impl TraitA+TraitB
- ImplTrait(Vec<TyParamBound>),
+ ImplTrait(Vec<GenericBound>),
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
match *self {
ResolvedPath { ref path, .. } => {
path.segments.last().and_then(|seg| {
- if let PathParameters::AngleBracketed { ref types, .. } = seg.params {
+ if let GenericArgs::AngleBracketed { ref types, .. } = seg.args {
Some(&**types)
} else {
None
let provided_params = &path.segments.last().unwrap();
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
- provided_params.with_parameters(|provided_params| {
- let mut indices = GenericParamCount {
+ provided_params.with_generic_args(|generic_args| {
+ let mut indices = ty::GenericParamCount {
lifetimes: 0,
types: 0
};
for param in generics.params.iter() {
- match param {
- hir::GenericParam::Lifetime(lt_param) => {
- if let Some(lt) = provided_params.lifetimes
- .get(indices.lifetimes).cloned() {
+ match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {
+ let mut j = 0;
+ let lifetime = generic_args.args.iter().find_map(|arg| {
+ match arg {
+ GenericArg::Lifetime(lt) => {
+ if indices.lifetimes == j {
+ return Some(lt);
+ }
+ j += 1;
+ None
+ }
+ _ => None,
+ }
+ });
+ if let Some(lt) = lifetime.cloned() {
if !lt.is_elided() {
let lt_def_id =
- cx.tcx.hir.local_def_id(lt_param.lifetime.id);
+ cx.tcx.hir.local_def_id(param.id);
lt_substs.insert(lt_def_id, lt.clean(cx));
}
}
indices.lifetimes += 1;
}
- hir::GenericParam::Type(ty_param) => {
+ hir::GenericParamKind::Type { ref default, .. } => {
let ty_param_def =
- Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
- if let Some(ty) = provided_params.types
- .get(indices.types).cloned() {
+ Def::TyParam(cx.tcx.hir.local_def_id(param.id));
+ let mut j = 0;
+ let type_ = generic_args.args.iter().find_map(|arg| {
+ match arg {
+ GenericArg::Type(ty) => {
+ if indices.types == j {
+ return Some(ty);
+ }
+ j += 1;
+ None
+ }
+ _ => None,
+ }
+ });
+ if let Some(ty) = type_.cloned() {
ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
- } else if let Some(default) = ty_param.default.clone() {
+ } else if let Some(default) = default.clone() {
ty_substs.insert(ty_param_def,
default.into_inner().clean(cx));
}
TyTraitObject(ref bounds, ref lifetime) => {
match bounds[0].clean(cx).trait_ {
ResolvedPath { path, typarams: None, did, is_generic } => {
- let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| {
- TraitBound(bound.clean(cx), hir::TraitBoundModifier::None)
+ let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
+ self::GenericBound::TraitBound(bound.clean(cx),
+ hir::TraitBoundModifier::None)
}).collect();
if !lifetime.is_elided() {
- bounds.push(RegionBound(lifetime.clean(cx)));
- }
- ResolvedPath {
- path,
- typarams: Some(bounds),
- did,
- is_generic,
+ bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
}
+ ResolvedPath { path, typarams: Some(bounds), did, is_generic, }
}
_ => Infer // shouldn't happen
}
inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut typarams = vec![];
- reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
+ reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b)));
for did in obj.auto_traits() {
let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait);
- let bound = TraitBound(PolyTrait {
+ let bound = GenericBound::TraitBound(PolyTrait {
trait_: ResolvedPath {
path,
typarams: None,
tr
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
// these should turn up at the end
- pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r)));
+ pred.skip_binder().1.clean(cx).map(|r| {
+ regions.push(GenericBound::Outlives(r))
+ });
return None;
} else {
return None;
}
}
-
let bounds = bounds.predicates.iter().filter_map(|pred|
if let ty::Predicate::Projection(proj) = *pred {
let proj = proj.skip_binder();
}).collect::<Vec<_>>();
bounds.extend(regions);
if !has_sized && !bounds.is_empty() {
- bounds.insert(0, TyParamBound::maybe_sized(cx));
+ bounds.insert(0, GenericBound::maybe_sized(cx));
}
ImplTrait(bounds)
}
def: Def::Err,
segments: vec![PathSegment {
name,
- params: PathParameters::AngleBracketed {
+ args: GenericArgs::AngleBracketed {
lifetimes: Vec::new(),
types: Vec::new(),
bindings: Vec::new(),
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
-pub enum PathParameters {
+pub enum GenericArgs {
AngleBracketed {
lifetimes: Vec<Lifetime>,
types: Vec<Type>,
}
}
-impl Clean<PathParameters> for hir::PathParameters {
- fn clean(&self, cx: &DocContext) -> PathParameters {
+impl Clean<GenericArgs> for hir::GenericArgs {
+ fn clean(&self, cx: &DocContext) -> GenericArgs {
if self.parenthesized {
let output = self.bindings[0].ty.clean(cx);
- PathParameters::Parenthesized {
+ GenericArgs::Parenthesized {
inputs: self.inputs().clean(cx),
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
}
} else {
- PathParameters::AngleBracketed {
- lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
- vec![]
- } else {
- self.lifetimes.clean(cx)
- },
- types: self.types.clean(cx),
+ let (mut lifetimes, mut types) = (vec![], vec![]);
+ let mut elided_lifetimes = true;
+ for arg in &self.args {
+ match arg {
+ GenericArg::Lifetime(lt) => {
+ if !lt.is_elided() {
+ elided_lifetimes = false;
+ }
+ lifetimes.push(lt.clean(cx));
+ }
+ GenericArg::Type(ty) => {
+ types.push(ty.clean(cx));
+ }
+ }
+ }
+ GenericArgs::AngleBracketed {
+ lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
+ types,
bindings: self.bindings.clean(cx),
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub struct PathSegment {
pub name: String,
- pub params: PathParameters,
+ pub args: GenericArgs,
}
impl Clean<PathSegment> for hir::PathSegment {
fn clean(&self, cx: &DocContext) -> PathSegment {
PathSegment {
name: self.name.clean(cx),
- params: self.with_parameters(|parameters| parameters.clean(cx))
+ args: self.with_generic_args(|generic_args| generic_args.clean(cx))
}
}
}
let segments = path.segments.iter().map(|s| {
PathSegment {
name: s.name.clone(),
- params: PathParameters::AngleBracketed {
+ args: GenericArgs::AngleBracketed {
lifetimes: Vec::new(),
types: Vec::new(),
bindings: Vec::new(),
});
BareFunctionDecl {
unsafety: self.unsafety,
+ abi: self.abi,
decl,
generic_params,
- abi: self.abi,
}
}
}
let mut items = self.items.clean(cx);
for item in &mut items {
if let ForeignFunctionItem(ref mut f) = item.inner {
- f.abi = self.abi;
+ f.header.abi = self.abi;
}
}
items
ForeignFunctionItem(Function {
decl,
generics,
- unsafety: hir::Unsafety::Unsafe,
- abi: Abi::Rust,
- constness: hir::Constness::NotConst,
+ header: hir::FnHeader {
+ unsafety: hir::Unsafety::Unsafe,
+ abi: Abi::Rust,
+ constness: hir::Constness::NotConst,
+ asyncness: hir::IsAsync::NotAsync,
+ },
})
}
hir::ForeignItemStatic(ref ty, mutbl) => {
def: def_ctor(def_id),
segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment {
name: ast::Name::intern(&s),
- parameters: None,
+ args: None,
infer_types: false,
}).collect())
}
#[derive(Eq, PartialEq, Hash, Debug)]
enum SimpleBound {
- RegionBound(Lifetime),
- TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier)
+ TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
+ Outlives(Lifetime),
}
enum AutoTraitResult {
}
}
-impl From<TyParamBound> for SimpleBound {
- fn from(bound: TyParamBound) -> Self {
+impl From<GenericBound> for SimpleBound {
+ fn from(bound: GenericBound) -> Self {
match bound.clone() {
- TyParamBound::RegionBound(l) => SimpleBound::RegionBound(l),
- TyParamBound::TraitBound(t, mod_) => match t.trait_ {
+ GenericBound::Outlives(l) => SimpleBound::Outlives(l),
+ GenericBound::TraitBound(t, mod_) => match t.trait_ {
Type::ResolvedPath { path, typarams, .. } => {
SimpleBound::TraitBound(path.segments,
typarams
use rustc::hir::def_id::DefId;
use rustc::ty;
-use clean::PathParameters as PP;
+use clean::GenericArgs as PP;
use clean::WherePredicate as WP;
use clean;
use core::DocContext;
};
!bounds.iter_mut().any(|b| {
let trait_ref = match *b {
- clean::TraitBound(ref mut tr, _) => tr,
- clean::RegionBound(..) => return false,
+ clean::GenericBound::TraitBound(ref mut tr, _) => tr,
+ clean::GenericBound::Outlives(..) => return false,
};
let (did, path) = match trait_ref.trait_ {
clean::ResolvedPath { did, ref mut path, ..} => (did, path),
return false
}
let last = path.segments.last_mut().unwrap();
- match last.params {
+ match last.args {
PP::AngleBracketed { ref mut bindings, .. } => {
bindings.push(clean::TypeBinding {
name: name.clone(),
clauses
}
-pub fn ty_params(mut params: Vec<clean::TyParam>) -> Vec<clean::TyParam> {
+pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericParamDef> {
for param in &mut params {
- param.bounds = ty_bounds(mem::replace(&mut param.bounds, Vec::new()));
+ match param.kind {
+ clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
+ *bounds = ty_bounds(mem::replace(bounds, Vec::new()));
+ }
+ _ => panic!("expected only type parameters"),
+ }
}
params
}
-fn ty_bounds(bounds: Vec<clean::TyParamBound>) -> Vec<clean::TyParamBound> {
+fn ty_bounds(bounds: Vec<clean::GenericBound>) -> Vec<clean::GenericBound> {
bounds
}
/// Table node id of lifetime parameter definition -> substituted lifetime
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
/// Table DefId of `impl Trait` in argument position -> bounds
- pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::TyParamBound>>>,
+ pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
pub send_trait: Option<DefId>,
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
pub use self::StructType::*;
pub use self::TypeBound::*;
-use rustc_target::spec::abi;
use syntax::ast;
use syntax::ast::{Name, NodeId};
use syntax::attr;
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub unsafety: hir::Unsafety,
- pub constness: hir::Constness,
+ pub header: hir::FnHeader,
pub whence: Span,
pub generics: hir::Generics,
- pub abi: abi::Abi,
pub body: hir::BodyId,
}
pub name: Name,
pub items: hir::HirVec<hir::TraitItem>,
pub generics: hir::Generics,
- pub bounds: hir::HirVec<hir::TyParamBound>,
+ pub bounds: hir::HirVec<hir::GenericBound>,
pub attrs: hir::HirVec<ast::Attribute>,
pub id: ast::NodeId,
pub whence: Span,
/// with a space after it.
#[derive(Copy, Clone)]
pub struct ConstnessSpace(pub hir::Constness);
+/// Similarly to VisSpace, this structure is used to render a function asyncness
+/// with a space after it.
+#[derive(Copy, Clone)]
+pub struct AsyncSpace(pub hir::IsAsync);
/// Similar to VisSpace, but used for mutability
#[derive(Copy, Clone)]
pub struct MutableSpace(pub clean::Mutability);
#[derive(Copy, Clone)]
pub struct RawMutableSpace(pub clean::Mutability);
/// Wrapper struct for emitting type parameter bounds.
-pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
+pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]);
/// Wrapper struct for emitting a comma-separated list of items
pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
pub struct AbiSpace(pub Abi);
}
}
-impl<'a> fmt::Display for TyParamBounds<'a> {
+impl<'a> fmt::Display for GenericBounds<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let &TyParamBounds(bounds) = self;
+ let &GenericBounds(bounds) = self;
for (i, bound) in bounds.iter().enumerate() {
if i > 0 {
f.write_str(" + ")?;
impl fmt::Display for clean::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp),
- clean::GenericParamDef::Type(ref tp) => {
- f.write_str(&tp.name)?;
+ match self.kind {
+ clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
+ clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
+ f.write_str(&self.name)?;
- if !tp.bounds.is_empty() {
+ if !bounds.is_empty() {
if f.alternate() {
- write!(f, ": {:#}", TyParamBounds(&tp.bounds))?;
+ write!(f, ": {:#}", GenericBounds(bounds))?;
} else {
- write!(f, ": {}", TyParamBounds(&tp.bounds))?;
+ write!(f, ": {}", GenericBounds(bounds))?;
}
}
- if let Some(ref ty) = tp.default {
+ if let Some(ref ty) = default {
if f.alternate() {
write!(f, " = {:#}", ty)?;
} else {
&clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
let bounds = bounds;
if f.alternate() {
- clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds)));
+ clause.push_str(&format!("{:#}: {:#}", ty, GenericBounds(bounds)));
} else {
- clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds)));
+ clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds)));
}
}
&clean::WherePredicate::RegionPredicate { ref lifetime,
}
}
-impl fmt::Display for clean::TyParamBound {
+impl fmt::Display for clean::GenericBound {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
- clean::RegionBound(ref lt) => {
+ clean::GenericBound::Outlives(ref lt) => {
write!(f, "{}", *lt)
}
- clean::TraitBound(ref ty, modifier) => {
+ clean::GenericBound::TraitBound(ref ty, modifier) => {
let modifier_str = match modifier {
hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?",
}
}
-impl fmt::Display for clean::PathParameters {
+impl fmt::Display for clean::GenericArgs {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
- clean::PathParameters::AngleBracketed {
+ clean::GenericArgs::AngleBracketed {
ref lifetimes, ref types, ref bindings
} => {
if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
}
}
}
- clean::PathParameters::Parenthesized { ref inputs, ref output } => {
+ clean::GenericArgs::Parenthesized { ref inputs, ref output } => {
f.write_str("(")?;
let mut comma = false;
for ty in inputs {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&self.name)?;
if f.alternate() {
- write!(f, "{:#}", self.params)
+ write!(f, "{:#}", self.args)
} else {
- write!(f, "{}", self.params)
+ write!(f, "{}", self.args)
}
}
}
}
}
if w.alternate() {
- write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
+ write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?;
} else {
let path = if use_absolute {
match href(did) {
} else {
format!("{}", HRef::new(did, &last.name))
};
- write!(w, "{}{}", path, last.params)?;
+ write!(w, "{}{}", path, last.args)?;
}
Ok(())
}
/// Helper to render type parameters
fn tybounds(w: &mut fmt::Formatter,
- typarams: &Option<Vec<clean::TyParamBound>>) -> fmt::Result {
+ typarams: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
match *typarams {
Some(ref params) => {
for param in params {
}
}
clean::ImplTrait(ref bounds) => {
- write!(f, "impl {}", TyParamBounds(bounds))
+ write!(f, "impl {}", GenericBounds(bounds))
}
clean::QPath { ref name, ref self_type, ref trait_ } => {
let should_show_cast = match *trait_ {
clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => {
let last = path.segments.last().unwrap();
fmt::Display::fmt(&last.name, f)?;
- fmt::Display::fmt(&last.params, f)?;
+ fmt::Display::fmt(&last.args, f)?;
}
_ => unreachable!(),
}
}
}
+impl fmt::Display for AsyncSpace {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {
+ hir::IsAsync::Async => write!(f, "async "),
+ hir::IsAsync::NotAsync => Ok(()),
+ }
+ }
+}
+
impl fmt::Display for clean::Import {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
use std::default::Default;
use std::error;
use std::fmt::{self, Display, Formatter, Write as FmtWrite};
+use std::ffi::OsStr;
use std::fs::{self, File, OpenOptions};
use std::io::prelude::*;
use std::io::{self, BufWriter, BufReader};
use rustc::hir;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::flock;
-use rustc_target::spec::abi;
use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability};
use doctree;
use fold::DocFolder;
use html::escape::Escape;
-use html::format::{ConstnessSpace};
-use html::format::{TyParamBounds, WhereClause, href, AbiSpace};
+use html::format::{AsyncSpace, ConstnessSpace};
+use html::format::{GenericBounds, WhereClause, href, AbiSpace};
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
use html::format::fmt_impl_for_trait_page;
use html::item_type::ItemType;
// Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date.
- write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/rustdoc.css"))?;
- write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/settings.css"))?;
+ write_minify(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
+ include_str!("static/rustdoc.css"),
+ enable_minification)?;
+ write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
+ include_str!("static/settings.css"),
+ enable_minification)?;
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
// then we'll run over the "official" styles.
include_bytes!("static/brush.svg"))?;
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
include_bytes!("static/wheel.svg"))?;
- write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/themes/light.css"))?;
+ write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
+ include_str!("static/themes/light.css"),
+ enable_minification)?;
themes.insert("light".to_owned());
- write(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/themes/dark.css"))?;
+ write_minify(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
+ include_str!("static/themes/dark.css"),
+ enable_minification)?;
themes.insert("dark".to_owned());
let mut themes: Vec<&String> = themes.iter().collect();
if let Some(ref css) = cx.shared.css_file_extension {
let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix));
- try_err!(fs::copy(css, out), css);
+ if !enable_minification {
+ try_err!(fs::copy(css, out), css);
+ } else {
+ let mut f = try_err!(File::open(css), css);
+ let mut buffer = String::with_capacity(1000);
+
+ try_err!(f.read_to_string(&mut buffer), css);
+ write_minify(out, &buffer, enable_minification)?;
+ }
}
- write(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/normalize.css"))?;
+ write_minify(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
+ include_str!("static/normalize.css"),
+ enable_minification)?;
write(cx.dst.join("FiraSans-Regular.woff"),
include_bytes!("static/FiraSans-Regular.woff"))?;
write(cx.dst.join("FiraSans-Medium.woff"),
fn write_minify(dst: PathBuf, contents: &str, enable_minification: bool) -> Result<(), Error> {
if enable_minification {
- write(dst, minifier::js::minify(contents).as_bytes())
+ if dst.extension() == Some(&OsStr::new("css")) {
+ let res = try_none!(minifier::css::minify(contents).ok(), &dst);
+ write(dst, res.as_bytes())
+ } else {
+ write(dst, minifier::js::minify(contents).as_bytes())
+ }
} else {
write(dst, contents.as_bytes())
}
impl<'a> Cache {
fn generics(&mut self, generics: &clean::Generics) {
for param in &generics.params {
- match *param {
- clean::GenericParamDef::Type(ref typ) => {
- self.typarams.insert(typ.did, typ.name.clone());
+ match param.kind {
+ clean::GenericParamDefKind::Lifetime => {}
+ clean::GenericParamDefKind::Type { did, .. } => {
+ self.typarams.insert(did, param.name.clone());
}
- clean::GenericParamDef::Lifetime(_) => {}
}
}
}
let unsafety_flag = match myitem.inner {
clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func)
- if func.unsafety == hir::Unsafety::Unsafe => {
+ if func.header.unsafety == hir::Unsafety::Unsafe => {
"<a title='unsafe function' href='#'><sup>⚠</sup></a>"
}
_ => "",
fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
f: &clean::Function) -> fmt::Result {
- let name_len = format!("{}{}{}{:#}fn {}{:#}",
+ let name_len = format!("{}{}{}{}{:#}fn {}{:#}",
VisSpace(&it.visibility),
- ConstnessSpace(f.constness),
- UnsafetySpace(f.unsafety),
- AbiSpace(f.abi),
+ ConstnessSpace(f.header.constness),
+ UnsafetySpace(f.header.unsafety),
+ AsyncSpace(f.header.asyncness),
+ AbiSpace(f.header.abi),
it.name.as_ref().unwrap(),
f.generics).len();
write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it)?)?;
render_attributes(w, it)?;
write!(w,
- "{vis}{constness}{unsafety}{abi}fn {name}{generics}{decl}{where_clause}</pre>",
+ "{vis}{constness}{unsafety}{asyncness}{abi}fn \
+ {name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(&it.visibility),
- constness = ConstnessSpace(f.constness),
- unsafety = UnsafetySpace(f.unsafety),
- abi = AbiSpace(f.abi),
+ constness = ConstnessSpace(f.header.constness),
+ unsafety = UnsafetySpace(f.header.unsafety),
+ asyncness = AsyncSpace(f.header.asyncness),
+ abi = AbiSpace(f.header.abi),
name = it.name.as_ref().unwrap(),
generics = f.generics,
where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
}
fn assoc_type<W: fmt::Write>(w: &mut W, it: &clean::Item,
- bounds: &Vec<clean::TyParamBound>,
+ bounds: &Vec<clean::GenericBound>,
default: Option<&clean::Type>,
link: AssocItemLink) -> fmt::Result {
write!(w, "type <a href='{}' class=\"type\">{}</a>",
naive_assoc_href(it, link),
it.name.as_ref().unwrap())?;
if !bounds.is_empty() {
- write!(w, ": {}", TyParamBounds(bounds))?
+ write!(w, ": {}", GenericBounds(bounds))?
}
if let Some(default) = default {
write!(w, " = {}", default)?;
parent: ItemType) -> fmt::Result {
fn method(w: &mut fmt::Formatter,
meth: &clean::Item,
- unsafety: hir::Unsafety,
- constness: hir::Constness,
- abi: abi::Abi,
+ header: hir::FnHeader,
g: &clean::Generics,
d: &clean::FnDecl,
link: AssocItemLink,
href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
}
};
- let mut head_len = format!("{}{}{}{:#}fn {}{:#}",
+ let mut head_len = format!("{}{}{}{}{:#}fn {}{:#}",
VisSpace(&meth.visibility),
- ConstnessSpace(constness),
- UnsafetySpace(unsafety),
- AbiSpace(abi),
+ ConstnessSpace(header.constness),
+ UnsafetySpace(header.unsafety),
+ AsyncSpace(header.asyncness),
+ AbiSpace(header.abi),
name,
*g).len();
let (indent, end_newline) = if parent == ItemType::Trait {
(0, true)
};
render_attributes(w, meth)?;
- write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
+ write!(w, "{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
{generics}{decl}{where_clause}",
VisSpace(&meth.visibility),
- ConstnessSpace(constness),
- UnsafetySpace(unsafety),
- AbiSpace(abi),
+ ConstnessSpace(header.constness),
+ UnsafetySpace(header.unsafety),
+ AsyncSpace(header.asyncness),
+ AbiSpace(header.abi),
href = href,
name = name,
generics = *g,
match item.inner {
clean::StrippedItem(..) => Ok(()),
clean::TyMethodItem(ref m) => {
- method(w, item, m.unsafety, hir::Constness::NotConst,
- m.abi, &m.generics, &m.decl, link, parent)
+ method(w, item, m.header, &m.generics, &m.decl, link, parent)
}
clean::MethodItem(ref m) => {
- method(w, item, m.unsafety, m.constness,
- m.abi, &m.generics, &m.decl, link, parent)
+ method(w, item, m.header, &m.generics, &m.decl, link, parent)
}
clean::AssociatedConstItem(ref ty, ref default) => {
assoc_const(w, item, ty, default.as_ref(), link)
.content table:not(.table-display) {
border-spacing: 0 5px;
- border-collapse: separate;
}
.content td { vertical-align: top; }
.content td:first-child { padding-right: 20px; }
.content td p:first-child { margin-top: 0; }
.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; }
+.content tr:first-child td { border-top: 0; }
.docblock table {
- border: 1px solid;
margin: .5em 0;
- border-collapse: collapse;
width: 100%;
}
.docblock table td {
padding: .5em;
- border-top: 1px dashed;
- border-bottom: 1px dashed;
+ border: 1px dashed;
}
.docblock table th {
padding: .5em;
text-align: left;
- border-top: 1px solid;
- border-bottom: 1px solid;
+ border: 1px solid;
}
.fields + table {
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(fs_read_write)]
+#![feature(iterator_find_map)]
#![feature(set_stdio)]
#![feature(slice_sort_by_cached_key)]
#![feature(test)]
use std::mem;
-use rustc_target::spec::abi;
use syntax::ast;
use syntax::attr;
use syntax_pos::Span;
pub fn visit_fn(&mut self, item: &hir::Item,
name: ast::Name, fd: &hir::FnDecl,
- unsafety: &hir::Unsafety,
- constness: hir::Constness,
- abi: &abi::Abi,
+ header: hir::FnHeader,
gen: &hir::Generics,
body: hir::BodyId) -> Function {
debug!("Visiting fn");
name,
whence: item.span,
generics: gen.clone(),
- unsafety: *unsafety,
- constness,
- abi: *abi,
+ header,
body,
}
}
om.structs.push(self.visit_variant_data(item, name, sd, gen)),
hir::ItemUnion(ref sd, ref gen) =>
om.unions.push(self.visit_union_data(item, name, sd, gen)),
- hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) =>
- om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
- constness, abi, gen, body)),
+ hir::ItemFn(ref fd, header, ref gen, body) =>
+ om.fns.push(self.visit_fn(item, name, &**fd, header, gen, body)),
hir::ItemTy(ref ty, ref gen) => {
let t = Typedef {
ty: ty.clone(),
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Asynchronous values.
+
+use core::cell::Cell;
+use core::marker::Unpin;
+use core::mem::PinMut;
+use core::option::Option;
+use core::ptr::NonNull;
+use core::task::{self, Poll};
+use core::ops::{Drop, Generator, GeneratorState};
+
+#[doc(inline)]
+pub use core::future::*;
+
+/// Wrap a future in a generator.
+///
+/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
+/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
+#[unstable(feature = "gen_future", issue = "50547")]
+pub fn from_generator<T: Generator<Yield = ()>>(x: T) -> impl Future<Output = T::Return> {
+ GenFuture(x)
+}
+
+/// A wrapper around generators used to implement `Future` for `async`/`await` code.
+#[unstable(feature = "gen_future", issue = "50547")]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+struct GenFuture<T: Generator<Yield = ()>>(T);
+
+// We rely on the fact that async/await futures are immovable in order to create
+// self-referential borrows in the underlying generator.
+impl<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
+ type Output = T::Return;
+ fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+ set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
+ GeneratorState::Yielded(()) => Poll::Pending,
+ GeneratorState::Complete(x) => Poll::Ready(x),
+ })
+ }
+}
+
+thread_local! {
+ static TLS_CX: Cell<Option<NonNull<task::Context<'static>>>> = Cell::new(None);
+}
+
+struct SetOnDrop(Option<NonNull<task::Context<'static>>>);
+
+impl Drop for SetOnDrop {
+ fn drop(&mut self) {
+ TLS_CX.with(|tls_cx| {
+ tls_cx.set(self.0.take());
+ });
+ }
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Sets the thread-local task context used by async/await futures.
+pub fn set_task_cx<F, R>(cx: &mut task::Context, f: F) -> R
+where
+ F: FnOnce() -> R
+{
+ let old_cx = TLS_CX.with(|tls_cx| {
+ tls_cx.replace(NonNull::new(
+ cx
+ as *mut task::Context
+ as *mut ()
+ as *mut task::Context<'static>
+ ))
+ });
+ let _reset_cx = SetOnDrop(old_cx);
+ f()
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Retrieves the thread-local task context used by async/await futures.
+///
+/// This function acquires exclusive access to the task context.
+///
+/// Panics if no task has been set or if the task context has already been
+/// retrived by a surrounding call to get_task_cx.
+pub fn get_task_cx<F, R>(f: F) -> R
+where
+ F: FnOnce(&mut task::Context) -> R
+{
+ let cx_ptr = TLS_CX.with(|tls_cx| {
+ // Clear the entry so that nested `with_get_cx` calls
+ // will fail or set their own value.
+ tls_cx.replace(None)
+ });
+ let _reset_cx = SetOnDrop(cx_ptr);
+
+ let mut cx_ptr = cx_ptr.expect(
+ "TLS task::Context not set. This is a rustc bug. \
+ Please file an issue on https://github.com/rust-lang/rust.");
+ unsafe { f(cx_ptr.as_mut()) }
+}
+
+#[unstable(feature = "gen_future", issue = "50547")]
+/// Polls a future in the current thread-local task context.
+pub fn poll_in_task_cx<F>(f: &mut PinMut<F>) -> Poll<F::Output>
+where
+ F: Future
+{
+ get_task_cx(|cx| f.reborrow().poll(cx))
+}
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(futures_api)]
+#![feature(generator_trait)]
#![feature(hashmap_internals)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]
#[stable(feature = "core_hint", since = "1.27.0")]
pub use core::hint;
-#[unstable(feature = "futures_api",
- reason = "futures in libcore are unstable",
- issue = "50547")]
-pub mod task {
- //! Types and Traits for working with asynchronous tasks.
- #[doc(inline)]
- pub use core::task::*;
- #[doc(inline)]
- pub use alloc_crate::task::*;
-}
-
-#[unstable(feature = "futures_api",
- reason = "futures in libcore are unstable",
- issue = "50547")]
-pub use core::future;
-
pub mod f32;
pub mod f64;
pub mod sync;
pub mod time;
+#[unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+pub mod task {
+ //! Types and Traits for working with asynchronous tasks.
+ #[doc(inline)]
+ pub use core::task::*;
+ #[doc(inline)]
+ pub use alloc_crate::task::*;
+}
+
+#[unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+pub mod future;
+
// Platform-abstraction modules
#[macro_use]
mod sys_common;
/// The multi-argument form of this macro panics with a string and has the
/// [`format!`] syntax for building a string.
///
+/// See also the macro [`compile_error!`], for raising errors during compilation.
+///
/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
/// [`Result`]: ../std/result/enum.Result.html
/// [`format!`]: ../std/macro.format.html
+/// [`compile_error!`]: ../std/macro.compile_error.html
/// [book]: ../book/second-edition/ch09-01-unrecoverable-errors-with-panic.html
///
/// # Current implementation
($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*));
}
+#[macro_export]
+#[unstable(feature = "await_macro", issue = "50547")]
+#[allow_internal_unstable]
+#[allow_internal_unsafe]
+macro_rules! await {
+ ($e:expr) => { {
+ let mut pinned = $e;
+ let mut pinned = unsafe { $crate::mem::PinMut::new_unchecked(&mut pinned) };
+ loop {
+ match $crate::future::poll_in_task_cx(&mut pinned) {
+ // FIXME(cramertj) prior to stabilizing await, we have to ensure that this
+ // can't be used to create a generator on stable via `|| await!()`.
+ $crate::task::Poll::Pending => yield,
+ $crate::task::Poll::Ready(x) => break x,
+ }
+ }
+ } }
+}
+
/// A macro to select an event from a number of receivers.
///
/// This macro is used to wait for the first event to occur on a number of
/// Unconditionally causes compilation to fail with the given error message when encountered.
///
/// This macro should be used when a crate uses a conditional compilation strategy to provide
- /// better error messages for erroneous conditions.
+ /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
+ /// which emits an error at *runtime*, rather than during compilation.
///
/// # Examples
///
/// Two such examples are macros and `#[cfg]` environments.
///
- /// Emit better compiler error if a macro is passed invalid values.
+ /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
+ /// the compiler would still emit an error, but the error's message would not mention the two
+ /// valid values.
///
/// ```compile_fail
/// macro_rules! give_me_foo_or_bar {
/// #[cfg(not(any(feature = "foo", feature = "bar")))]
/// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
/// ```
+ ///
+ /// [`panic!`]: ../std/macro.panic.html
#[stable(feature = "compile_error_macro", since = "1.20.0")]
#[macro_export]
macro_rules! compile_error {
///
/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
- across an unwind boundary"]
+#[rustc_on_unimplemented(
+ message="the type `{Self}` may not be safely transferred across an unwind boundary",
+ label="`{Self}` may not be safely transferred across an unwind boundary",
+)]
pub auto trait UnwindSafe {}
/// A marker trait representing types where a shared reference is considered
/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html
/// [`UnwindSafe`]: ./trait.UnwindSafe.html
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[rustc_on_unimplemented = "the type {Self} may contain interior mutability \
- and a reference may not be safely transferrable \
- across a catch_unwind boundary"]
+#[rustc_on_unimplemented(
+ message="the type `{Self}` may contain interior mutability and a reference may not be safely \
+ transferrable across a catch_unwind boundary",
+ label="`{Self}` may contain interior mutability and a reference may not be safely \
+ transferrable across a catch_unwind boundary",
+)]
pub auto trait RefUnwindSafe {}
/// A simple wrapper around a type to assert that it is unwind safe.
impl<'a, F: Future> Future for AssertUnwindSafe<F> {
type Output = F::Output;
- fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
- unsafe {
- let pinned_field = PinMut::new_unchecked(
- &mut PinMut::get_mut(self.reborrow()).0
- );
-
- pinned_field.poll(cx)
- }
+ fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+ let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
+ pinned_field.poll(cx)
}
}
// (missing things in `libc` which is empty) so just omit everything
// with an empty module
#[unstable(issue = "0", feature = "std_internals")]
+ #[allow(missing_docs)]
pub mod unix_ext {}
} else {
// On other platforms like Windows document the bare bones of unix
cfg_if! {
if #[cfg(windows)] {
// 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"))] {
// On CloudABI and wasm right now the shim below doesn't compile, so
// just omit it
#[unstable(issue = "0", feature = "std_internals")]
+ #[allow(missing_docs)]
pub mod windows_ext {}
} else {
// On all other platforms (aka linux/osx/etc) then pull in a "minimal"
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "l4re"))]
use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
+#[cfg(any(target_os = "linux", target_os = "emscripten"))]
+use libc::fstatat64;
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
-use libc::{fstatat, dirfd};
+use libc::dirfd;
#[cfg(target_os = "android")]
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek64,
+use libc::{stat as stat64, fstat as fstat64, fstatat as fstatat64, lstat as lstat64, lseek64,
dirent as dirent64, open as open64};
#[cfg(not(any(target_os = "linux",
target_os = "emscripten",
}
#[derive(Clone)]
-pub struct ReadDir(Arc<InnerReadDir>);
+pub struct ReadDir {
+ inner: Arc<InnerReadDir>,
+ end_of_stream: bool,
+}
struct Dir(*mut libc::DIR);
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
// Thus the result will be e g 'ReadDir("/home")'
- fmt::Debug::fmt(&*self.0.root, f)
+ fmt::Debug::fmt(&*self.inner.root, f)
}
}
// is safe to use in threaded applications and it is generally preferred
// over the readdir_r(3C) function.
super::os::set_errno(0);
- let entry_ptr = libc::readdir(self.0.dirp.0);
+ let entry_ptr = libc::readdir(self.inner.dirp.0);
if entry_ptr.is_null() {
// NULL can mean either the end is reached or an error occurred.
// So we had to clear errno beforehand to check for an error now.
#[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ if self.end_of_stream {
+ return None;
+ }
+
unsafe {
let mut ret = DirEntry {
entry: mem::zeroed(),
};
let mut entry_ptr = ptr::null_mut();
loop {
- if readdir64_r(self.0.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+ if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+ if entry_ptr.is_null() {
+ // We encountered an error (which will be returned in this iteration), but
+ // we also reached the end of the directory stream. The `end_of_stream`
+ // flag is enabled to make sure that we return `None` in the next iteration
+ // (instead of looping forever)
+ self.end_of_stream = true;
+ }
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
impl DirEntry {
pub fn path(&self) -> PathBuf {
- self.dir.0.root.join(OsStr::from_bytes(self.name_bytes()))
+ self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
}
pub fn file_name(&self) -> OsString {
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
pub fn metadata(&self) -> io::Result<FileAttr> {
- let fd = cvt(unsafe {dirfd(self.dir.0.dirp.0)})?;
+ let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- fstatat(fd,
- self.entry.d_name.as_ptr(),
- &mut stat as *mut _ as *mut _,
- libc::AT_SYMLINK_NOFOLLOW)
+ fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
})?;
Ok(FileAttr { stat: stat })
}
Err(Error::last_os_error())
} else {
let inner = InnerReadDir { dirp: Dir(ptr), root };
- Ok(ReadDir(Arc::new(inner)))
+ Ok(ReadDir{
+ inner: Arc::new(inner),
+ end_of_stream: false,
+ })
}
}
}
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ stat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ lstat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
mod imp {
#[link(name = "zircon")]
extern {
- fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
+ fn zx_cprng_draw_new(buffer: *mut u8, len: usize) -> i32;
}
fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
unsafe {
- let mut actual = 0;
- let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
+ let status = zx_cprng_draw_new(buf.as_mut_ptr(), buf.len());
if status == 0 {
- Ok(actual)
+ Ok(buf.len())
} else {
Err(status)
}
// The Rust abstract syntax tree.
-pub use self::TyParamBound::*;
pub use self::UnsafeSource::*;
-pub use self::PathParameters::*;
+pub use self::GenericArgs::*;
pub use symbol::{Ident, Symbol as Name};
pub use util::ThinVec;
pub use util::parser::ExprPrecedence;
use syntax_pos::{Span, DUMMY_SP};
-use codemap::{respan, Spanned};
+use codemap::{dummy_spanned, respan, Spanned};
use rustc_target::spec::abi::Abi;
use ext::hygiene::{Mark, SyntaxContext};
use print::pprust;
}
}
-/// A lifetime definition, e.g. `'a: 'b+'c+'d`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct LifetimeDef {
- pub attrs: ThinVec<Attribute>,
- pub lifetime: Lifetime,
- pub bounds: Vec<Lifetime>
-}
-
/// A "Path" is essentially Rust's notion of a name.
///
/// It's represented as a sequence of identifiers,
/// `Some` means that parameter list is supplied (`Path<X, Y>`)
/// but it can be empty (`Path<>`).
/// `P` is used as a size optimization for the common case with no parameters.
- pub parameters: Option<P<PathParameters>>,
+ pub args: Option<P<GenericArgs>>,
}
impl PathSegment {
pub fn from_ident(ident: Ident) -> Self {
- PathSegment { ident, parameters: None }
+ PathSegment { ident, args: None }
}
pub fn crate_root(span: Span) -> Self {
PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span))
}
}
-/// Parameters of a path segment.
+/// Arguments of a path segment.
///
/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum PathParameters {
+pub enum GenericArgs {
/// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
- AngleBracketed(AngleBracketedParameterData),
+ AngleBracketed(AngleBracketedArgs),
/// The `(A,B)` and `C` in `Foo(A,B) -> C`
- Parenthesized(ParenthesizedParameterData),
+ Parenthesized(ParenthesisedArgs),
}
-impl PathParameters {
+impl GenericArgs {
pub fn span(&self) -> Span {
match *self {
AngleBracketed(ref data) => data.span,
}
}
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum GenericArg {
+ Lifetime(Lifetime),
+ Type(P<Ty>),
+}
+
/// A path like `Foo<'a, T>`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
-pub struct AngleBracketedParameterData {
+pub struct AngleBracketedArgs {
/// Overall span
pub span: Span,
- /// The lifetime parameters for this path segment.
- pub lifetimes: Vec<Lifetime>,
- /// The type parameters for this path segment, if present.
- pub types: Vec<P<Ty>>,
+ /// The arguments for this path segment.
+ pub args: Vec<GenericArg>,
/// Bindings (equality constraints) on associated types, if present.
///
/// E.g., `Foo<A=Bar>`.
pub bindings: Vec<TypeBinding>,
}
-impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
- fn into(self) -> Option<P<PathParameters>> {
- Some(P(PathParameters::AngleBracketed(self)))
+impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs {
+ fn into(self) -> Option<P<GenericArgs>> {
+ Some(P(GenericArgs::AngleBracketed(self)))
}
}
-impl Into<Option<P<PathParameters>>> for ParenthesizedParameterData {
- fn into(self) -> Option<P<PathParameters>> {
- Some(P(PathParameters::Parenthesized(self)))
+impl Into<Option<P<GenericArgs>>> for ParenthesisedArgs {
+ fn into(self) -> Option<P<GenericArgs>> {
+ Some(P(GenericArgs::Parenthesized(self)))
}
}
/// A path like `Foo(A,B) -> C`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ParenthesizedParameterData {
+pub struct ParenthesisedArgs {
/// Overall span
pub span: Span,
/// small, positive ids.
pub const DUMMY_NODE_ID: NodeId = NodeId(!0);
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitBoundModifier {
+ None,
+ Maybe,
+}
+
/// The AST represents all type param bounds as types.
/// typeck::collect::compute_bounds matches these against
/// the "special" built-in traits (see middle::lang_items) and
/// detects Copy, Send and Sync.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TyParamBound {
- TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
- RegionTyParamBound(Lifetime)
+pub enum GenericBound {
+ Trait(PolyTraitRef, TraitBoundModifier),
+ Outlives(Lifetime)
}
-impl TyParamBound {
+impl GenericBound {
pub fn span(&self) -> Span {
match self {
- &TraitTyParamBound(ref t, ..) => t.span,
- &RegionTyParamBound(ref l) => l.ident.span,
+ &GenericBound::Trait(ref t, ..) => t.span,
+ &GenericBound::Outlives(ref l) => l.ident.span,
}
}
}
-/// A modifier on a bound, currently this is only used for `?Sized`, where the
-/// modifier is `Maybe`. Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitBoundModifier {
- None,
- Maybe,
-}
-
-pub type TyParamBounds = Vec<TyParamBound>;
+pub type GenericBounds = Vec<GenericBound>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TyParam {
- pub attrs: ThinVec<Attribute>,
- pub ident: Ident,
- pub id: NodeId,
- pub bounds: TyParamBounds,
- pub default: Option<P<Ty>>,
+pub enum GenericParamKind {
+ /// A lifetime definition, e.g. `'a: 'b+'c+'d`.
+ Lifetime,
+ Type {
+ default: Option<P<Ty>>,
+ }
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum GenericParam {
- Lifetime(LifetimeDef),
- Type(TyParam),
-}
-
-impl GenericParam {
- pub fn is_lifetime_param(&self) -> bool {
- match *self {
- GenericParam::Lifetime(_) => true,
- _ => false,
- }
- }
+pub struct GenericParam {
+ pub id: NodeId,
+ pub ident: Ident,
+ pub attrs: ThinVec<Attribute>,
+ pub bounds: GenericBounds,
- pub fn is_type_param(&self) -> bool {
- match *self {
- GenericParam::Type(_) => true,
- _ => false,
- }
- }
+ pub kind: GenericParamKind,
}
/// Represents lifetime, type and const parameters attached to a declaration of
pub span: Span,
}
-impl Generics {
- pub fn is_lt_parameterized(&self) -> bool {
- self.params.iter().any(|param| param.is_lifetime_param())
- }
-
- pub fn is_type_parameterized(&self) -> bool {
- self.params.iter().any(|param| param.is_type_param())
- }
-
- pub fn is_parameterized(&self) -> bool {
- !self.params.is_empty()
- }
-
- pub fn span_for_name(&self, name: &str) -> Option<Span> {
- for param in &self.params {
- if let GenericParam::Type(ref t) = *param {
- if t.ident.name == name {
- return Some(t.ident.span);
- }
- }
- }
- None
- }
-}
-
impl Default for Generics {
/// Creates an instance of `Generics`.
fn default() -> Generics {
/// The type being bounded
pub bounded_ty: P<Ty>,
/// Trait and lifetime bounds (`Clone+Send+'static`)
- pub bounds: TyParamBounds,
+ pub bounds: GenericBounds,
}
/// A lifetime predicate.
pub struct WhereRegionPredicate {
pub span: Span,
pub lifetime: Lifetime,
- pub bounds: Vec<Lifetime>,
+ pub bounds: GenericBounds,
}
/// An equality predicate (unsupported).
}
}
- fn to_bound(&self) -> Option<TyParamBound> {
+ fn to_bound(&self) -> Option<GenericBound> {
match &self.node {
ExprKind::Path(None, path) =>
- Some(TraitTyParamBound(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
- TraitBoundModifier::None)),
+ Some(GenericBound::Trait(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
+ TraitBoundModifier::None)),
_ => None,
}
}
ExprKind::Closure(..) => ExprPrecedence::Closure,
ExprKind::Block(..) => ExprPrecedence::Block,
ExprKind::Catch(..) => ExprPrecedence::Catch,
+ ExprKind::Async(..) => ExprPrecedence::Async,
ExprKind::Assign(..) => ExprPrecedence::Assign,
ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
ExprKind::Field(..) => ExprPrecedence::Field,
/// A closure (for example, `move |a, b, c| a + b + c`)
///
/// The final span is the span of the argument block `|...|`
- Closure(CaptureBy, Movability, P<FnDecl>, P<Expr>, Span),
+ Closure(CaptureBy, IsAsync, Movability, P<FnDecl>, P<Expr>, Span),
/// A block (`'label: { ... }`)
Block(P<Block>, Option<Label>),
+ /// An async block (`async move { ... }`)
+ ///
+ /// The `NodeId` is the `NodeId` for the closure that results from
+ /// desugaring an async block, just like the NodeId field in the
+ /// `IsAsync` enum. This is necessary in order to create a def for the
+ /// closure which can be used as a parent of any child defs. Defs
+ /// created during lowering cannot be made the parent of any other
+ /// preexisting defs.
+ Async(CaptureBy, NodeId, P<Block>),
/// A catch block (`catch { ... }`)
Catch(P<Block>),
/// or in an implementation.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MethodSig {
- pub unsafety: Unsafety,
- pub constness: Spanned<Constness>,
- pub abi: Abi,
+ pub header: FnHeader,
pub decl: P<FnDecl>,
}
pub enum TraitItemKind {
Const(P<Ty>, Option<P<Expr>>),
Method(MethodSig, Option<P<Block>>),
- Type(TyParamBounds, Option<P<Ty>>),
+ Type(GenericBounds, Option<P<Ty>>),
Macro(Mac),
}
Path(Option<QSelf>, Path),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
- TraitObject(TyParamBounds, TraitObjectSyntax),
+ TraitObject(GenericBounds, TraitObjectSyntax),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
- ImplTrait(TyParamBounds),
+ ImplTrait(GenericBounds),
/// No-op; kept solely so that we can pretty-print faithfully
Paren(P<Ty>),
/// Unused for now
Normal,
}
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAsync {
+ Async(NodeId),
+ NotAsync,
+}
+
+impl IsAsync {
+ pub fn is_async(self) -> bool {
+ if let IsAsync::Async(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Constness {
Const,
pub tokens: Option<TokenStream>,
}
+/// A function header
+///
+/// All the information between the visibility & the name of the function is
+/// included in this struct (e.g. `async unsafe fn` or `const extern "C" fn`)
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct FnHeader {
+ pub unsafety: Unsafety,
+ pub asyncness: IsAsync,
+ pub constness: Spanned<Constness>,
+ pub abi: Abi,
+}
+
+impl Default for FnHeader {
+ fn default() -> FnHeader {
+ FnHeader {
+ unsafety: Unsafety::Normal,
+ asyncness: IsAsync::NotAsync,
+ constness: dummy_spanned(Constness::NotConst),
+ abi: Abi::Rust,
+ }
+ }
+}
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum ItemKind {
/// An `extern crate` item, with optional *original* crate name if the crate was renamed.
/// A function declaration (`fn` or `pub fn`).
///
/// E.g. `fn foo(bar: usize) -> usize { .. }`
- Fn(P<FnDecl>, Unsafety, Spanned<Constness>, Abi, Generics, P<Block>),
+ Fn(P<FnDecl>, FnHeader, Generics, P<Block>),
/// A module declaration (`mod` or `pub mod`).
///
/// E.g. `mod foo;` or `mod foo { .. }`
/// A Trait declaration (`trait` or `pub trait`).
///
/// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
- Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
+ Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
/// Trait alias
///
/// E.g. `trait Foo = Bar + Quux;`
- TraitAlias(Generics, TyParamBounds),
+ TraitAlias(Generics, GenericBounds),
/// An implementation.
///
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
impl HasAttrs for GenericParam {
fn attrs(&self) -> &[ast::Attribute] {
- match self {
- GenericParam::Lifetime(lifetime) => lifetime.attrs(),
- GenericParam::Type(ty) => ty.attrs(),
- }
+ &self.attrs
}
- fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
- match self {
- GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
- GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
- }
+ fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(mut self, f: F) -> Self {
+ self.attrs = self.attrs.map_attrs(f);
+ self
}
}
derive_has_attrs! {
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
- ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
+ ast::Field, ast::FieldPat, ast::Variant_
}
pub use syntax_pos::*;
-pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan};
+pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo};
pub use self::ExpnFormat::*;
use rustc_data_structures::fx::FxHashMap;
E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
E0693, // incorrect `repr(align)` attribute format
E0694, // an unknown tool name found in scoped attributes
+ E0703, // invalid ABI
+ E0704, // incorrect visibility restriction
}
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use edition::Edition;
use errors::{DiagnosticBuilder, DiagnosticId};
-use ext::expand::{self, Expansion, Invocation};
+use ext::expand::{self, AstFragment, Invocation};
use ext::hygiene::{self, Mark, SyntaxContext};
use fold::{self, Folder};
use parse::{self, parser, DirectoryOwnership};
MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
/// A function-like procedural macro. TokenStream -> TokenStream.
- ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>, Edition),
+ ProcMacro(
+ /* expander: */ Box<ProcMacro + sync::Sync + sync::Send>,
+ /* allow_internal_unstable: */ bool,
+ /* edition: */ Edition,
+ ),
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
/// The first TokenSteam is the attribute, the second is the annotated item.
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
- fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
+ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
+ derives: &[Mark]);
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
fn resolve_imports(&mut self);
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
- fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
+ fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
+ _derives: &[Mark]) {}
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
fn resolve_imports(&mut self) {}
let mut last_macro = None;
loop {
if ctxt.outer().expn_info().map_or(None, |info| {
- if info.callee.name() == "include" {
+ if info.format.name() == "include" {
// Stop going up the backtrace once include! is encountered
return None;
}
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path;
fn path_all(&self, sp: Span,
global: bool,
- idents: Vec<ast::Ident> ,
- lifetimes: Vec<ast::Lifetime>,
- types: Vec<P<ast::Ty>>,
- bindings: Vec<ast::TypeBinding> )
+ idents: Vec<ast::Ident>,
+ args: Vec<ast::GenericArg>,
+ bindings: Vec<ast::TypeBinding>)
-> ast::Path;
fn qpath(&self, self_type: P<ast::Ty>,
fn qpath_all(&self, self_type: P<ast::Ty>,
trait_path: ast::Path,
ident: ast::Ident,
- lifetimes: Vec<ast::Lifetime>,
- types: Vec<P<ast::Ty>>,
+ args: Vec<ast::GenericArg>,
bindings: Vec<ast::TypeBinding>)
-> (ast::QSelf, ast::Path);
span: Span,
id: ast::Ident,
attrs: Vec<ast::Attribute>,
- bounds: ast::TyParamBounds,
- default: Option<P<ast::Ty>>) -> ast::TyParam;
+ bounds: ast::GenericBounds,
+ default: Option<P<ast::Ty>>) -> ast::GenericParam;
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef;
- fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
+ fn trait_bound(&self, path: ast::Path) -> ast::GenericBound;
fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime;
fn lifetime_def(&self,
span: Span,
ident: ast::Ident,
attrs: Vec<ast::Attribute>,
- bounds: Vec<ast::Lifetime>)
- -> ast::LifetimeDef;
+ bounds: ast::GenericBounds)
+ -> ast::GenericParam;
// statements
fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt;
impl<'a> AstBuilder for ExtCtxt<'a> {
fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
- self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
+ self.path_all(span, false, strs, vec![], vec![])
}
fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
self.path(span, vec![id])
}
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
- self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
+ self.path_all(span, true, strs, vec![], vec![])
}
fn path_all(&self,
span: Span,
global: bool,
mut idents: Vec<ast::Ident> ,
- lifetimes: Vec<ast::Lifetime>,
- types: Vec<P<ast::Ty>>,
+ args: Vec<ast::GenericArg>,
bindings: Vec<ast::TypeBinding> )
-> ast::Path {
let last_ident = idents.pop().unwrap();
- let mut segments: Vec<ast::PathSegment> = Vec::new();
+ let mut segments: Vec<ast::PathSegment> = vec![];
segments.extend(idents.into_iter().map(|ident| {
ast::PathSegment::from_ident(ident.with_span_pos(span))
}));
- let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
- ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
+ let args = if !args.is_empty() || !bindings.is_empty() {
+ ast::AngleBracketedArgs { args, bindings, span }.into()
} else {
None
};
- segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), parameters });
+ segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args });
let mut path = ast::Path { span, segments };
if global {
if let Some(seg) = path.make_root() {
trait_path: ast::Path,
ident: ast::Ident)
-> (ast::QSelf, ast::Path) {
- self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
+ self.qpath_all(self_type, trait_path, ident, vec![], vec![])
}
/// Constructs a qualified path.
self_type: P<ast::Ty>,
trait_path: ast::Path,
ident: ast::Ident,
- lifetimes: Vec<ast::Lifetime>,
- types: Vec<P<ast::Ty>>,
+ args: Vec<ast::GenericArg>,
bindings: Vec<ast::TypeBinding>)
-> (ast::QSelf, ast::Path) {
let mut path = trait_path;
- let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
- ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into()
+ let args = if !args.is_empty() || !bindings.is_empty() {
+ ast::AngleBracketedArgs { args, bindings, span: ident.span }.into()
} else {
None
};
- path.segments.push(ast::PathSegment { ident, parameters });
+ path.segments.push(ast::PathSegment { ident, args });
(ast::QSelf {
ty: self_type,
self.path_all(DUMMY_SP,
true,
self.std_path(&["option", "Option"]),
- Vec::new(),
- vec![ ty ],
+ vec![ast::GenericArg::Type(ty)],
Vec::new()))
}
span: Span,
ident: ast::Ident,
attrs: Vec<ast::Attribute>,
- bounds: ast::TyParamBounds,
- default: Option<P<ast::Ty>>) -> ast::TyParam {
- ast::TyParam {
+ bounds: ast::GenericBounds,
+ default: Option<P<ast::Ty>>) -> ast::GenericParam {
+ ast::GenericParam {
ident: ident.with_span_pos(span),
id: ast::DUMMY_NODE_ID,
attrs: attrs.into(),
bounds,
- default,
+ kind: ast::GenericParamKind::Type {
+ default,
+ }
}
}
}
}
- fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
- ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None)
+ fn trait_bound(&self, path: ast::Path) -> ast::GenericBound {
+ ast::GenericBound::Trait(self.poly_trait_ref(path.span, path),
+ ast::TraitBoundModifier::None)
}
fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
span: Span,
ident: ast::Ident,
attrs: Vec<ast::Attribute>,
- bounds: Vec<ast::Lifetime>)
- -> ast::LifetimeDef {
- ast::LifetimeDef {
+ bounds: ast::GenericBounds)
+ -> ast::GenericParam {
+ let lifetime = self.lifetime(span, ident);
+ ast::GenericParam {
+ ident: lifetime.ident,
+ id: lifetime.id,
attrs: attrs.into(),
- lifetime: self.lifetime(span, ident),
bounds,
+ kind: ast::GenericParamKind::Lifetime,
}
}
fn_decl_span: Span) // span of the `|...|` part
-> P<ast::Expr> {
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
+ ast::IsAsync::NotAsync,
ast::Movability::Movable,
fn_decl,
body,
// the entire lambda body. Probably we should extend the API
// here, but that's not entirely clear.
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
+ ast::IsAsync::NotAsync,
ast::Movability::Movable,
fn_decl,
body,
name,
Vec::new(),
ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
- ast::Unsafety::Normal,
- dummy_spanned(ast::Constness::NotConst),
- Abi::Rust,
+ ast::FnHeader {
+ unsafety: ast::Unsafety::Normal,
+ asyncness: ast::IsAsync::NotAsync,
+ constness: dummy_spanned(ast::Constness::NotConst),
+ abi: Abi::Rust,
+ },
generics,
body))
}
use attr::HasAttrs;
use ast;
-use codemap::{hygiene, ExpnInfo, NameAndSpan, ExpnFormat};
+use codemap::{hygiene, ExpnInfo, ExpnFormat};
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use parse::parser::PathStyle;
cx.current_expansion.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- },
+ def_site: None,
+ format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let span = span.with_ctxt(cx.backtrace());
use ast::{self, Block, Ident, NodeId, PatKind, Path};
use ast::{MacStmtStyle, StmtKind, ItemKind};
use attr::{self, HasAttrs};
-use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, dummy_spanned, respan};
+use codemap::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
use config::{is_test_or_bench, StripUnconfigured};
use errors::{Applicability, FatalError};
use ext::base::*;
use std::rc::Rc;
use std::path::PathBuf;
-macro_rules! expansions {
- ($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
- $(.$fold:ident)* $(lift .$fold_elt:ident)*,
- $(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
+macro_rules! ast_fragments {
+ (
+ $($Kind:ident($AstTy:ty) {
+ $kind_name:expr;
+ $(one fn $fold_ast:ident; fn $visit_ast:ident;)?
+ $(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)?
+ fn $make_ast:ident;
+ })*
+ ) => {
+ /// A fragment of AST that can be produced by a single macro expansion.
+ /// Can also serve as an input and intermediate result for macro expansion operations.
+ pub enum AstFragment {
+ OptExpr(Option<P<ast::Expr>>),
+ $($Kind($AstTy),)*
+ }
+
+ /// "Discriminant" of an AST fragment.
#[derive(Copy, Clone, PartialEq, Eq)]
- pub enum ExpansionKind { OptExpr, $( $kind, )* }
- pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
+ pub enum AstFragmentKind {
+ OptExpr,
+ $($Kind,)*
+ }
- impl ExpansionKind {
+ impl AstFragmentKind {
pub fn name(self) -> &'static str {
match self {
- ExpansionKind::OptExpr => "expression",
- $( ExpansionKind::$kind => $kind_name, )*
+ AstFragmentKind::OptExpr => "expression",
+ $(AstFragmentKind::$Kind => $kind_name,)*
}
}
- fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<Expansion> {
+ fn make_from<'a>(self, result: Box<MacResult + 'a>) -> Option<AstFragment> {
match self {
- ExpansionKind::OptExpr => result.make_expr().map(Some).map(Expansion::OptExpr),
- $( ExpansionKind::$kind => result.$make().map(Expansion::$kind), )*
+ AstFragmentKind::OptExpr =>
+ result.make_expr().map(Some).map(AstFragment::OptExpr),
+ $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
}
- impl Expansion {
+ impl AstFragment {
pub fn make_opt_expr(self) -> Option<P<ast::Expr>> {
match self {
- Expansion::OptExpr(expr) => expr,
- _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
+ AstFragment::OptExpr(expr) => expr,
+ _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
}
- $( pub fn $make(self) -> $ty {
+
+ $(pub fn $make_ast(self) -> $AstTy {
match self {
- Expansion::$kind(ast) => ast,
- _ => panic!("Expansion::make_* called on the wrong kind of expansion"),
+ AstFragment::$Kind(ast) => ast,
+ _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
}
- } )*
+ })*
pub fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
- use self::Expansion::*;
match self {
- OptExpr(expr) => OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
- $($( $kind(ast) => $kind(folder.$fold(ast)), )*)*
- $($( $kind(ast) => {
- $kind(ast.into_iter().flat_map(|ast| folder.$fold_elt(ast)).collect())
- }, )*)*
+ AstFragment::OptExpr(expr) =>
+ AstFragment::OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
+ $($(AstFragment::$Kind(ast) =>
+ AstFragment::$Kind(folder.$fold_ast(ast)),)?)*
+ $($(AstFragment::$Kind(ast) =>
+ AstFragment::$Kind(ast.into_iter()
+ .flat_map(|ast| folder.$fold_ast_elt(ast))
+ .collect()),)?)*
}
}
pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
match *self {
- Expansion::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
- Expansion::OptExpr(None) => {}
- $($( Expansion::$kind(ref ast) => visitor.$visit(ast), )*)*
- $($( Expansion::$kind(ref ast) => for ast in &ast[..] {
- visitor.$visit_elt(ast);
- }, )*)*
+ AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
+ AstFragment::OptExpr(None) => {}
+ $($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
+ $($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
+ visitor.$visit_ast_elt(ast_elt);
+ })?)*
}
}
}
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
- self.expand(Expansion::OptExpr(Some(expr))).make_opt_expr()
+ self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr()
}
- $($(fn $fold(&mut self, node: $ty) -> $ty {
- self.expand(Expansion::$kind(node)).$make()
- })*)*
- $($(fn $fold_elt(&mut self, node: $ty_elt) -> $ty {
- self.expand(Expansion::$kind(SmallVector::one(node))).$make()
- })*)*
+ $($(fn $fold_ast(&mut self, ast: $AstTy) -> $AstTy {
+ self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
+ })?)*
+ $($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
+ self.expand_fragment(AstFragment::$Kind(SmallVector::one(ast_elt))).$make_ast()
+ })?)*
}
impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
- $(fn $make(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$ty> {
- Some(self.make(ExpansionKind::$kind).$make())
+ $(fn $make_ast(self: Box<::ext::tt::macro_rules::ParserAnyMacro<'a>>)
+ -> Option<$AstTy> {
+ Some(self.make(AstFragmentKind::$Kind).$make_ast())
})*
}
}
}
-expansions! {
- Expr: P<ast::Expr> [], "expression", .make_expr, .fold_expr, .visit_expr;
- Pat: P<ast::Pat> [], "pattern", .make_pat, .fold_pat, .visit_pat;
- Ty: P<ast::Ty> [], "type", .make_ty, .fold_ty, .visit_ty;
- Stmts: SmallVector<ast::Stmt> [SmallVector, ast::Stmt],
- "statement", .make_stmts, lift .fold_stmt, lift .visit_stmt;
- Items: SmallVector<P<ast::Item>> [SmallVector, P<ast::Item>],
- "item", .make_items, lift .fold_item, lift .visit_item;
- TraitItems: SmallVector<ast::TraitItem> [SmallVector, ast::TraitItem],
- "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
- ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
- "impl item", .make_impl_items, lift .fold_impl_item, lift .visit_impl_item;
- ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
- "foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
+ast_fragments! {
+ Expr(P<ast::Expr>) { "expression"; one fn fold_expr; fn visit_expr; fn make_expr; }
+ Pat(P<ast::Pat>) { "pattern"; one fn fold_pat; fn visit_pat; fn make_pat; }
+ Ty(P<ast::Ty>) { "type"; one fn fold_ty; fn visit_ty; fn make_ty; }
+ Stmts(SmallVector<ast::Stmt>) { "statement"; many fn fold_stmt; fn visit_stmt; fn make_stmts; }
+ Items(SmallVector<P<ast::Item>>) { "item"; many fn fold_item; fn visit_item; fn make_items; }
+ TraitItems(SmallVector<ast::TraitItem>) {
+ "trait item"; many fn fold_trait_item; fn visit_trait_item; fn make_trait_items;
+ }
+ ImplItems(SmallVector<ast::ImplItem>) {
+ "impl item"; many fn fold_impl_item; fn visit_impl_item; fn make_impl_items;
+ }
+ ForeignItems(SmallVector<ast::ForeignItem>) {
+ "foreign item"; many fn fold_foreign_item; fn visit_foreign_item; fn make_foreign_items;
+ }
}
-impl ExpansionKind {
- fn dummy(self, span: Span) -> Option<Expansion> {
+impl AstFragmentKind {
+ fn dummy(self, span: Span) -> Option<AstFragment> {
self.make_from(DummyResult::any(span))
}
- fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I) -> Expansion {
+ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
+ -> AstFragment {
let mut items = items.into_iter();
match self {
- ExpansionKind::Items =>
- Expansion::Items(items.map(Annotatable::expect_item).collect()),
- ExpansionKind::ImplItems =>
- Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
- ExpansionKind::TraitItems =>
- Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
- ExpansionKind::ForeignItems =>
- Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
- ExpansionKind::Stmts => Expansion::Stmts(items.map(Annotatable::expect_stmt).collect()),
- ExpansionKind::Expr => Expansion::Expr(
+ AstFragmentKind::Items =>
+ AstFragment::Items(items.map(Annotatable::expect_item).collect()),
+ AstFragmentKind::ImplItems =>
+ AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
+ AstFragmentKind::TraitItems =>
+ AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
+ AstFragmentKind::ForeignItems =>
+ AstFragment::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
+ AstFragmentKind::Stmts =>
+ AstFragment::Stmts(items.map(Annotatable::expect_stmt).collect()),
+ AstFragmentKind::Expr => AstFragment::Expr(
items.next().expect("expected exactly one expression").expect_expr()
),
- ExpansionKind::OptExpr =>
- Expansion::OptExpr(items.next().map(Annotatable::expect_expr)),
- ExpansionKind::Pat | ExpansionKind::Ty =>
+ AstFragmentKind::OptExpr =>
+ AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)),
+ AstFragmentKind::Pat | AstFragmentKind::Ty =>
panic!("patterns and types aren't annotatable"),
}
}
pub struct Invocation {
pub kind: InvocationKind,
- expansion_kind: ExpansionKind,
+ fragment_kind: AstFragmentKind,
pub expansion_data: ExpansionData,
}
let orig_mod_span = krate.module.inner;
- let krate_item = Expansion::Items(SmallVector::one(P(ast::Item {
+ let krate_item = AstFragment::Items(SmallVector::one(P(ast::Item {
attrs: krate.attrs,
span: krate.span,
node: ast::ItemKind::Mod(krate.module),
tokens: None,
})));
- match self.expand(krate_item).make_items().pop().map(P::into_inner) {
+ match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) {
Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => {
krate.attrs = attrs;
krate.module = module;
krate
}
- // Fully expand all the invocations in `expansion`.
- fn expand(&mut self, expansion: Expansion) -> Expansion {
+ // Fully expand all macro invocations in this AST fragment.
+ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone();
self.cx.current_expansion.depth = 0;
- let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
+ // Collect all macro invocations and replace them with placeholders.
+ let (fragment_with_placeholders, mut invocations)
+ = self.collect_invocations(input_fragment, &[]);
+
+ // Optimization: if we resolve all imports now,
+ // we'll be able to immediately resolve most of imported macros.
self.resolve_imports();
- invocations.reverse();
- let mut expansions = Vec::new();
+ // Resolve paths in all invocations and produce ouput expanded fragments for them, but
+ // do not insert them into our input AST fragment yet, only store in `expanded_fragments`.
+ // The output fragments also go through expansion recursively until no invocations are left.
+ // Unresolved macros produce dummy outputs as a recovery measure.
+ invocations.reverse();
+ let mut expanded_fragments = Vec::new();
let mut derives = HashMap::new();
let mut undetermined_invocations = Vec::new();
let (mut progress, mut force) = (false, !self.monotonic);
self.cx.current_expansion.mark = scope;
// FIXME(jseyfried): Refactor out the following logic
- let (expansion, new_invocations) = if let Some(ext) = ext {
+ let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
if let Some(ext) = ext {
- let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
- let expansion = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
- self.collect_invocations(expansion, &[])
+ let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
+ let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
+ self.collect_invocations(fragment, &[])
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
if !item.derive_allowed() {
let attr = attr::find_by_name(item.attrs(), "derive")
};
invocations.push(Invocation {
kind: InvocationKind::Derive { path: path.clone(), item: item },
- expansion_kind: invoc.expansion_kind,
+ fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
mark,
..invoc.expansion_data.clone()
},
});
}
- let expansion = invoc.expansion_kind
+ let fragment = invoc.fragment_kind
.expect_from_annotatables(::std::iter::once(item_with_markers));
- self.collect_invocations(expansion, derives)
+ self.collect_invocations(fragment, derives)
} else {
unreachable!()
}
} else {
- self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
+ self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
};
- if expansions.len() < depth {
- expansions.push(Vec::new());
+ if expanded_fragments.len() < depth {
+ expanded_fragments.push(Vec::new());
}
- expansions[depth - 1].push((mark, expansion));
+ expanded_fragments[depth - 1].push((mark, expanded_fragment));
if !self.cx.ecfg.single_step {
invocations.extend(new_invocations.into_iter().rev());
}
self.cx.current_expansion = orig_expansion_data;
+ // Finally incorporate all the expanded macros into the input AST fragment.
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
- while let Some(expansions) = expansions.pop() {
- for (mark, expansion) in expansions.into_iter().rev() {
+ while let Some(expanded_fragments) = expanded_fragments.pop() {
+ for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() {
let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
- placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
+ placeholder_expander.add(NodeId::placeholder_from_mark(mark),
+ expanded_fragment, derives);
}
}
-
- expansion.fold_with(&mut placeholder_expander)
+ fragment_with_placeholders.fold_with(&mut placeholder_expander)
}
fn resolve_imports(&mut self) {
}
}
- fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
- -> (Expansion, Vec<Invocation>) {
- let result = {
+ /// Collect all macro invocations reachable at this time in this AST fragment, and replace
+ /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s.
+ /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and
+ /// prepares data for resolving paths of macro invocations.
+ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
+ -> (AstFragment, Vec<Invocation>) {
+ let (fragment_with_placeholders, invocations) = {
let mut collector = InvocationCollector {
cfg: StripUnconfigured {
should_test: self.cx.ecfg.should_test,
invocations: Vec::new(),
monotonic: self.monotonic,
};
- (expansion.fold_with(&mut collector), collector.invocations)
+ (fragment.fold_with(&mut collector), collector.invocations)
};
if self.monotonic {
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
let mark = self.cx.current_expansion.mark;
- self.cx.resolver.visit_expansion(mark, &result.0, derives);
+ self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
+ derives);
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
}
- result
+ (fragment_with_placeholders, invocations)
}
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
}
}
- fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<Expansion> {
+ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
let result = match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
let mut err = self.cx.struct_span_err(info.call_site,
&format!("recursion limit reached while expanding the macro `{}`",
- info.callee.name()));
+ info.format.name()));
err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
suggested_limit));
fn expand_attr_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let Invocation { expansion_kind: kind, .. } = invoc;
+ -> Option<AstFragment> {
let (attr, item) = match invoc.kind {
InvocationKind::Attr { attr, item, .. } => (attr?, item),
_ => unreachable!(),
attr::mark_used(&attr);
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: attr.span,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
- span: None,
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition: ext.edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
+ allow_internal_unstable: false,
+ allow_internal_unsafe: false,
+ edition: ext.edition(),
});
match *ext {
let meta = attr.parse_meta(self.cx.parse_sess)
.map_err(|mut e| { e.emit(); }).ok()?;
let item = mac.expand(self.cx, attr.span, &meta, item);
- Some(kind.expect_from_annotatables(item))
+ Some(invoc.fragment_kind.expect_from_annotatables(item))
}
MultiDecorator(ref mac) => {
let mut items = Vec::new();
.expect("derive meta should already have been parsed");
mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
items.push(item);
- Some(kind.expect_from_annotatables(items))
+ Some(invoc.fragment_kind.expect_from_annotatables(items))
}
AttrProcMacro(ref mac, ..) => {
self.gate_proc_macro_attr_item(attr.span, &item);
})).into();
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
- let res = self.parse_expansion(tok_result, kind, &attr.path, attr.span);
+ let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
+ &attr.path, attr.span);
self.gate_proc_macro_expansion(attr.span, &res);
res
}
ProcMacroDerive(..) | BuiltinDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
self.cx.trace_macros_diag();
- kind.dummy(attr.span)
+ invoc.fragment_kind.dummy(attr.span)
}
_ => {
let msg = &format!("macro `{}` may not be used in attributes", attr.path);
self.cx.span_err(attr.span, msg);
self.cx.trace_macros_diag();
- kind.dummy(attr.span)
+ invoc.fragment_kind.dummy(attr.span)
}
}
}
);
}
- fn gate_proc_macro_expansion(&self, span: Span, expansion: &Option<Expansion>) {
+ fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
if self.cx.ecfg.proc_macro_gen() {
return
}
- let expansion = match expansion {
- Some(expansion) => expansion,
+ let fragment = match fragment {
+ Some(fragment) => fragment,
None => return,
};
- expansion.visit_with(&mut DisallowModules {
+ fragment.visit_with(&mut DisallowModules {
span,
parse_sess: self.cx.parse_sess,
});
}
}
- /// Expand a macro invocation. Returns the result of expansion.
+ /// Expand a macro invocation. Returns the resulting expanded AST fragment.
fn expand_bang_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
+ -> Option<AstFragment> {
+ let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
let (mac, ident, span) = match invoc.kind {
InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
_ => unreachable!(),
}
mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- span: def_site_span,
- allow_internal_unstable,
- allow_internal_unsafe,
- edition,
- },
+ def_site: def_site_span,
+ format: macro_bang_format(path),
+ allow_internal_unstable,
+ allow_internal_unsafe,
+ edition,
});
Ok(())
};
} else {
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- span: tt_span,
- allow_internal_unstable,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: tt_span,
+ format: macro_bang_format(path),
+ allow_internal_unstable,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let input: Vec<_> = mac.node.stream().into_trees().collect();
kind.dummy(span)
}
- ProcMacro(ref expandfun, edition) => {
+ ProcMacro(ref expandfun, allow_internal_unstable, edition) => {
if ident.name != keywords::Invalid.name() {
let msg =
format!("macro {}! expects no ident argument, given '{}'", path, ident);
self.gate_proc_macro_expansion_kind(span, kind);
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: macro_bang_format(path),
- // FIXME procedural macros do not have proper span info
- // yet, when they do, we should use it here.
- span: None,
- // FIXME probably want to follow macro_rules macros here.
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition,
- },
+ // FIXME procedural macros do not have proper span info
+ // yet, when they do, we should use it here.
+ def_site: None,
+ format: macro_bang_format(path),
+ // FIXME probably want to follow macro_rules macros here.
+ allow_internal_unstable,
+ allow_internal_unsafe: false,
+ edition,
});
let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
- let result = self.parse_expansion(tok_result, kind, path, span);
+ let result = self.parse_ast_fragment(tok_result, kind, path, span);
self.gate_proc_macro_expansion(span, &result);
result
}
}
}
- fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) {
+ fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
- ExpansionKind::Expr => "expressions",
- ExpansionKind::OptExpr => "expressions",
- ExpansionKind::Pat => "patterns",
- ExpansionKind::Ty => "types",
- ExpansionKind::Stmts => "statements",
- ExpansionKind::Items => return,
- ExpansionKind::TraitItems => return,
- ExpansionKind::ImplItems => return,
- ExpansionKind::ForeignItems => return,
+ AstFragmentKind::Expr => "expressions",
+ AstFragmentKind::OptExpr => "expressions",
+ AstFragmentKind::Pat => "patterns",
+ AstFragmentKind::Ty => "types",
+ AstFragmentKind::Stmts => "statements",
+ AstFragmentKind::Items => return,
+ AstFragmentKind::TraitItems => return,
+ AstFragmentKind::ImplItems => return,
+ AstFragmentKind::ForeignItems => return,
};
if self.cx.ecfg.proc_macro_non_items() {
return
);
}
- /// Expand a derive invocation. Returns the result of expansion.
+ /// Expand a derive invocation. Returns the resulting expanded AST fragment.
fn expand_derive_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
- -> Option<Expansion> {
- let Invocation { expansion_kind: kind, .. } = invoc;
+ -> Option<AstFragment> {
let (path, item) = match invoc.kind {
InvocationKind::Derive { path, item } => (path, item),
_ => unreachable!(),
let mut expn_info = ExpnInfo {
call_site: span,
- callee: NameAndSpan {
- format: MacroAttribute(pretty_name),
- span: None,
- allow_internal_unstable: false,
- allow_internal_unsafe: false,
- edition: ext.edition(),
- }
+ def_site: None,
+ format: MacroAttribute(pretty_name),
+ allow_internal_unstable: false,
+ allow_internal_unsafe: false,
+ edition: ext.edition(),
};
match *ext {
node: ast::MetaItemKind::Word,
};
let items = ext.expand(self.cx, span, &dummy, item);
- Some(kind.expect_from_annotatables(items))
+ Some(invoc.fragment_kind.expect_from_annotatables(items))
}
BuiltinDerive(func) => {
- expn_info.callee.allow_internal_unstable = true;
+ expn_info.allow_internal_unstable = true;
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let mut items = Vec::new();
func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
- Some(kind.expect_from_annotatables(items))
+ Some(invoc.fragment_kind.expect_from_annotatables(items))
}
_ => {
let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
self.cx.span_err(span, msg);
self.cx.trace_macros_diag();
- kind.dummy(span)
+ invoc.fragment_kind.dummy(span)
}
}
}
- fn parse_expansion(&mut self,
- toks: TokenStream,
- kind: ExpansionKind,
- path: &Path,
- span: Span)
- -> Option<Expansion> {
+ fn parse_ast_fragment(&mut self,
+ toks: TokenStream,
+ kind: AstFragmentKind,
+ path: &Path,
+ span: Span)
+ -> Option<AstFragment> {
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
- match parser.parse_expansion(kind, false) {
- Ok(expansion) => {
+ match parser.parse_ast_fragment(kind, false) {
+ Ok(fragment) => {
parser.ensure_complete_parse(path, kind.name(), span);
- Some(expansion)
+ Some(fragment)
}
Err(mut err) => {
err.set_span(span);
}
impl<'a> Parser<'a> {
- pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bool)
- -> PResult<'a, Expansion> {
+ pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool)
+ -> PResult<'a, AstFragment> {
Ok(match kind {
- ExpansionKind::Items => {
+ AstFragmentKind::Items => {
let mut items = SmallVector::new();
while let Some(item) = self.parse_item()? {
items.push(item);
}
- Expansion::Items(items)
+ AstFragment::Items(items)
}
- ExpansionKind::TraitItems => {
+ AstFragmentKind::TraitItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
items.push(self.parse_trait_item(&mut false)?);
}
- Expansion::TraitItems(items)
+ AstFragment::TraitItems(items)
}
- ExpansionKind::ImplItems => {
+ AstFragmentKind::ImplItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
items.push(self.parse_impl_item(&mut false)?);
}
- Expansion::ImplItems(items)
+ AstFragment::ImplItems(items)
}
- ExpansionKind::ForeignItems => {
+ AstFragmentKind::ForeignItems => {
let mut items = SmallVector::new();
while self.token != token::Eof {
if let Some(item) = self.parse_foreign_item()? {
items.push(item);
}
}
- Expansion::ForeignItems(items)
+ AstFragment::ForeignItems(items)
}
- ExpansionKind::Stmts => {
+ AstFragmentKind::Stmts => {
let mut stmts = SmallVector::new();
while self.token != token::Eof &&
// won't make progress on a `}`
stmts.push(stmt);
}
}
- Expansion::Stmts(stmts)
+ AstFragment::Stmts(stmts)
}
- ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
- ExpansionKind::OptExpr => {
+ AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?),
+ AstFragmentKind::OptExpr => {
if self.token != token::Eof {
- Expansion::OptExpr(Some(self.parse_expr()?))
+ AstFragment::OptExpr(Some(self.parse_expr()?))
} else {
- Expansion::OptExpr(None)
+ AstFragment::OptExpr(None)
}
},
- ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
- ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
+ AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
+ AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?),
})
}
}
impl<'a, 'b> InvocationCollector<'a, 'b> {
- fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
+ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
let mark = Mark::fresh(self.cx.current_expansion.mark);
self.invocations.push(Invocation {
kind,
- expansion_kind,
+ fragment_kind,
expansion_data: ExpansionData {
mark,
depth: self.cx.current_expansion.depth + 1,
..self.cx.current_expansion.clone()
},
});
- placeholder(expansion_kind, NodeId::placeholder_from_mark(mark))
+ placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
}
- fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
+ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
}
attr: Option<ast::Attribute>,
traits: Vec<Path>,
item: Annotatable,
- kind: ExpansionKind)
- -> Expansion {
+ kind: AstFragmentKind)
+ -> AstFragment {
self.collect(kind, InvocationKind::Attr { attr, traits, item })
}
// expansion will eat the attribute so it won't error later
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
- // ExpansionKind::Expr requires the macro to emit an expression
- return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::Expr)
- .make_expr();
+ // AstFragmentKind::Expr requires the macro to emit an expression
+ return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
+ AstFragmentKind::Expr).make_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
self.check_attributes(&expr.attrs);
- self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
+ self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
} else {
P(noop_fold_expr(expr, self))
}
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
- ExpansionKind::OptExpr)
+ AstFragmentKind::OptExpr)
.make_opt_expr();
}
if let ast::ExprKind::Mac(mac) = expr.node {
self.check_attributes(&expr.attrs);
- self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
+ self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
} else {
Some(P(noop_fold_expr(expr, self)))
}
}
pat.and_then(|pat| match pat.node {
- PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
+ PatKind::Mac(mac) => self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat(),
_ => unreachable!(),
})
}
if attr.is_some() || !derives.is_empty() {
return self.collect_attr(attr, derives,
- Annotatable::Stmt(P(stmt_)), ExpansionKind::Stmts)
+ Annotatable::Stmt(P(stmt_)), AstFragmentKind::Stmts)
.make_stmts();
}
if let StmtKind::Mac(mac) = stmt.node {
let (mac, style, attrs) = mac.into_inner();
self.check_attributes(&attrs);
- let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts)
+ let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts)
.make_stmts();
// If this is a macro invocation with a semicolon, then apply that
let (attr, traits, mut item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::Item(item);
- return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
+ return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
}
match item.node {
self.check_attributes(&item.attrs);
item.and_then(|item| match item.node {
ItemKind::Mac(mac) => {
- self.collect(ExpansionKind::Items, InvocationKind::Bang {
+ self.collect(AstFragmentKind::Items, InvocationKind::Bang {
mac,
ident: Some(item.ident),
span: item.span,
let (attr, traits, item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::TraitItem(P(item));
- return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::TraitItems)
.make_trait_items()
}
ast::TraitItemKind::Macro(mac) => {
let ast::TraitItem { attrs, span, .. } = item;
self.check_attributes(&attrs);
- self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
+ self.collect_bang(mac, span, AstFragmentKind::TraitItems).make_trait_items()
}
_ => fold::noop_fold_trait_item(item, self),
}
let (attr, traits, item) = self.classify_item(item);
if attr.is_some() || !traits.is_empty() {
let item = Annotatable::ImplItem(P(item));
- return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::ImplItems)
.make_impl_items();
}
ast::ImplItemKind::Macro(mac) => {
let ast::ImplItem { attrs, span, .. } = item;
self.check_attributes(&attrs);
- self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
+ self.collect_bang(mac, span, AstFragmentKind::ImplItems).make_impl_items()
}
_ => fold::noop_fold_impl_item(item, self),
}
};
match ty.node {
- ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
+ ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty(),
_ => unreachable!(),
}
}
}
let item = Annotatable::ForeignItem(P(foreign_item));
- return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
+ return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
.make_foreign_items();
}
GateIssue::Language, explain);
}
- return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
+ return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
.make_foreign_items();
}
pub struct Marker(pub Mark);
impl Folder for Marker {
- fn fold_ident(&mut self, mut ident: Ident) -> Ident {
- ident.span = ident.span.apply_mark(self.0);
- ident
- }
-
fn new_span(&mut self, span: Span) -> Span {
span.apply_mark(self.0)
}
use ast::{self, NodeId};
use codemap::{DUMMY_SP, dummy_spanned};
use ext::base::ExtCtxt;
-use ext::expand::{Expansion, ExpansionKind};
+use ext::expand::{AstFragment, AstFragmentKind};
use ext::hygiene::Mark;
use tokenstream::TokenStream;
use fold::*;
use std::collections::HashMap;
-pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
+pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
fn mac_placeholder() -> ast::Mac {
dummy_spanned(ast::Mac_ {
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
});
match kind {
- ExpansionKind::Expr => Expansion::Expr(expr_placeholder()),
- ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())),
- ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item {
+ AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
+ AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
+ AstFragmentKind::Items => AstFragment::Items(SmallVector::one(P(ast::Item {
id, span, ident, vis, attrs,
node: ast::ItemKind::Mac(mac_placeholder()),
tokens: None,
}))),
- ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem {
+ AstFragmentKind::TraitItems => AstFragment::TraitItems(SmallVector::one(ast::TraitItem {
id, span, ident, attrs, generics,
node: ast::TraitItemKind::Macro(mac_placeholder()),
tokens: None,
})),
- ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem {
+ AstFragmentKind::ImplItems => AstFragment::ImplItems(SmallVector::one(ast::ImplItem {
id, span, ident, vis, attrs, generics,
node: ast::ImplItemKind::Macro(mac_placeholder()),
defaultness: ast::Defaultness::Final,
tokens: None,
})),
- ExpansionKind::ForeignItems => Expansion::ForeignItems(SmallVector::one(ast::ForeignItem {
- id, span, ident, vis, attrs,
- node: ast::ForeignItemKind::Macro(mac_placeholder()),
- })),
- ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
+ AstFragmentKind::ForeignItems =>
+ AstFragment::ForeignItems(SmallVector::one(ast::ForeignItem {
+ id, span, ident, vis, attrs,
+ node: ast::ForeignItemKind::Macro(mac_placeholder()),
+ })),
+ AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
id, span, node: ast::PatKind::Mac(mac_placeholder()),
})),
- ExpansionKind::Ty => Expansion::Ty(P(ast::Ty {
+ AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
id, span, node: ast::TyKind::Mac(mac_placeholder()),
})),
- ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({
+ AstFragmentKind::Stmts => AstFragment::Stmts(SmallVector::one({
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new()));
ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
})),
}
pub struct PlaceholderExpander<'a, 'b: 'a> {
- expansions: HashMap<ast::NodeId, Expansion>,
+ expanded_fragments: HashMap<ast::NodeId, AstFragment>,
cx: &'a mut ExtCtxt<'b>,
monotonic: bool,
}
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
PlaceholderExpander {
cx,
- expansions: HashMap::new(),
+ expanded_fragments: HashMap::new(),
monotonic,
}
}
- pub fn add(&mut self, id: ast::NodeId, expansion: Expansion, derives: Vec<Mark>) {
- let mut expansion = expansion.fold_with(self);
- if let Expansion::Items(mut items) = expansion {
+ pub fn add(&mut self, id: ast::NodeId, fragment: AstFragment, derives: Vec<Mark>) {
+ let mut fragment = fragment.fold_with(self);
+ if let AstFragment::Items(mut items) = fragment {
for derive in derives {
match self.remove(NodeId::placeholder_from_mark(derive)) {
- Expansion::Items(derived_items) => items.extend(derived_items),
+ AstFragment::Items(derived_items) => items.extend(derived_items),
_ => unreachable!(),
}
}
- expansion = Expansion::Items(items);
+ fragment = AstFragment::Items(items);
}
- self.expansions.insert(id, expansion);
+ self.expanded_fragments.insert(id, fragment);
}
- fn remove(&mut self, id: ast::NodeId) -> Expansion {
- self.expansions.remove(&id).unwrap()
+ fn remove(&mut self, id: ast::NodeId) -> AstFragment {
+ self.expanded_fragments.remove(&id).unwrap()
}
}
}
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
- let (style, mut expansion) = match stmt.node {
+ let (style, mut stmts) = match stmt.node {
ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
_ => return noop_fold_stmt(stmt, self),
};
if style == ast::MacStmtStyle::Semicolon {
- if let Some(stmt) = expansion.pop() {
- expansion.push(stmt.add_trailing_semicolon());
+ if let Some(stmt) = stmts.pop() {
+ stmts.push(stmt.add_trailing_semicolon());
}
}
- expansion
+ stmts
}
fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
use edition::Edition;
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{NormalTT, TTMacroExpander};
-use ext::expand::{Expansion, ExpansionKind};
+use ext::expand::{AstFragment, AstFragmentKind};
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::{parse, parse_failure_msg};
}
impl<'a> ParserAnyMacro<'a> {
- pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion {
+ pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment {
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
- let expansion = panictry!(parser.parse_expansion(kind, true));
+ let fragment = panictry!(parser.parse_ast_fragment(kind, true));
// We allow semicolons at the end of expressions -- e.g. the semicolon in
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
// but `m!()` is allowed in expression positions (c.f. issue #34706).
- if kind == ExpansionKind::Expr && parser.token == token::Semi {
+ if kind == AstFragmentKind::Expr && parser.token == token::Semi {
parser.bump();
}
// Make sure we don't have any tokens left to parse so we don't silently drop anything.
let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
parser.ensure_complete_parse(&path, kind.name(), site_span);
- expansion
+ fragment
}
}
use ast::{self, NodeId, PatKind, RangeEnd};
use attr;
use edition::{ALL_EDITIONS, Edition};
-use codemap::Spanned;
use syntax_pos::{Span, DUMMY_SP};
use errors::{DiagnosticBuilder, Handler, FatalError};
use visit::{self, FnKind, Visitor};
// Declarative macros 2.0 (`macro`).
(active, decl_macro, "1.17.0", Some(39412), None),
- // Allows #[link(kind="static-nobundle"...]
+ // Allows #[link(kind="static-nobundle"...)]
(active, static_nobundle, "1.16.0", Some(37403), None),
// `extern "msp430-interrupt" fn()`
// Scoped attributes
(active, tool_attributes, "1.25.0", Some(44690), None),
+ // allow irrefutable patterns in if-let and while-let statements (RFC 2086)
+ (active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
+
// Allows use of the :literal macro fragment specifier (RFC 1576)
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
// 'a: { break 'a; }
(active, label_break_value, "1.28.0", Some(48594), None),
-
// #[panic_implementation]
(active, panic_implementation, "1.28.0", Some(44489), None),
// #[doc(keyword = "...")]
(active, doc_keyword, "1.28.0", Some(51315), None),
+
+ // Allows async and await syntax
+ (active, async_await, "1.28.0", Some(50547), None),
);
declare_features! (
"labels on blocks are unstable");
}
}
+ ast::ExprKind::Closure(_, ast::IsAsync::Async(_), ..) => {
+ gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
+ }
+ ast::ExprKind::Async(..) => {
+ gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
+ }
_ => {}
}
visit::walk_expr(self, e);
fn_decl: &'a ast::FnDecl,
span: Span,
_node_id: NodeId) {
- // check for const fn declarations
- if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) =
- fn_kind {
- gate_feature_post!(&self, const_fn, span, "const fn is unstable");
- }
- // stability of const fn methods are covered in
- // visit_trait_item and visit_impl_item below; this is
- // because default methods don't pass through this
- // point.
-
match fn_kind {
- FnKind::ItemFn(_, _, _, abi, _, _) |
- FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
- self.check_abi(abi, span);
+ FnKind::ItemFn(_, header, _, _) => {
+ // check for const fn and async fn declarations
+ if header.asyncness.is_async() {
+ gate_feature_post!(&self, async_await, span, "async fn is unstable");
+ }
+ if header.constness.node == ast::Constness::Const {
+ gate_feature_post!(&self, const_fn, span, "const fn is unstable");
+ }
+ // stability of const fn methods are covered in
+ // visit_trait_item and visit_impl_item below; this is
+ // because default methods don't pass through this
+ // point.
+
+ self.check_abi(header.abi, span);
+ }
+ FnKind::Method(_, sig, _, _) => {
+ self.check_abi(sig.header.abi, span);
}
_ => {}
}
match ti.node {
ast::TraitItemKind::Method(ref sig, ref block) => {
if block.is_none() {
- self.check_abi(sig.abi, ti.span);
+ self.check_abi(sig.header.abi, ti.span);
}
- if sig.constness.node == ast::Constness::Const {
+ if sig.header.constness.node == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
}
}
gate_feature_post!(&self, associated_type_defaults, ti.span,
"associated type defaults are unstable");
}
- if ti.generics.is_parameterized() {
+ if !ti.generics.params.is_empty() {
gate_feature_post!(&self, generic_associated_types, ti.span,
"generic associated types are unstable");
}
match ii.node {
ast::ImplItemKind::Method(ref sig, _) => {
- if sig.constness.node == ast::Constness::Const {
+ if sig.header.constness.node == ast::Constness::Const {
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
}
}
- ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => {
+ ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => {
gate_feature_post!(&self, generic_associated_types, ii.span,
"generic associated types are unstable");
}
noop_fold_item_simple(i, self)
}
+ fn fold_fn_header(&mut self, header: FnHeader) -> FnHeader {
+ noop_fold_fn_header(header, self)
+ }
+
fn fold_struct_field(&mut self, sf: StructField) -> StructField {
noop_fold_struct_field(sf, self)
}
noop_fold_exprs(es, self)
}
+ fn fold_generic_arg(&mut self, arg: GenericArg) -> GenericArg {
+ match arg {
+ GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.fold_lifetime(lt)),
+ GenericArg::Type(ty) => GenericArg::Type(self.fold_ty(ty)),
+ }
+ }
+
fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
noop_fold_ty(t, self)
}
+ fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
+ noop_fold_lifetime(l, self)
+ }
+
fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding {
noop_fold_ty_binding(t, self)
}
noop_fold_qpath(qs, p, self)
}
- fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
- noop_fold_path_parameters(p, self)
+ fn fold_generic_args(&mut self, p: GenericArgs) -> GenericArgs {
+ noop_fold_generic_args(p, self)
}
- fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
- -> AngleBracketedParameterData
+ fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedArgs)
+ -> AngleBracketedArgs
{
noop_fold_angle_bracketed_parameter_data(p, self)
}
- fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
- -> ParenthesizedParameterData
+ fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs)
+ -> ParenthesisedArgs
{
noop_fold_parenthesized_parameter_data(p, self)
}
noop_fold_variant_data(vdata, self)
}
- fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
- noop_fold_ty_param(tp, self)
- }
-
fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam {
noop_fold_generic_param(param, self)
}
noop_fold_interpolated(nt, self)
}
- fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>)
- -> Option<TyParamBounds> {
+ fn fold_opt_bounds(&mut self, b: Option<GenericBounds>) -> Option<GenericBounds> {
noop_fold_opt_bounds(b, self)
}
- fn fold_bounds(&mut self, b: TyParamBounds)
- -> TyParamBounds {
+ fn fold_bounds(&mut self, b: GenericBounds) -> GenericBounds {
noop_fold_bounds(b, self)
}
- fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
- noop_fold_ty_param_bound(tpb, self)
+ fn fold_param_bound(&mut self, tpb: GenericBound) -> GenericBound {
+ noop_fold_param_bound(tpb, self)
}
fn fold_mt(&mut self, mt: MutTy) -> MutTy {
TyKind::Typeof(fld.fold_anon_const(expr))
}
TyKind::TraitObject(bounds, syntax) => {
- TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax)
+ TyKind::TraitObject(bounds.move_map(|b| fld.fold_param_bound(b)), syntax)
}
TyKind::ImplTrait(bounds) => {
- TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+ TyKind::ImplTrait(bounds.move_map(|b| fld.fold_param_bound(b)))
}
TyKind::Mac(mac) => {
TyKind::Mac(fld.fold_mac(mac))
pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
Path {
- segments: segments.move_map(|PathSegment {ident, parameters}| PathSegment {
+ segments: segments.move_map(|PathSegment { ident, args }| PathSegment {
ident: fld.fold_ident(ident),
- parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
+ args: args.map(|args| args.map(|args| fld.fold_generic_args(args))),
}),
span: fld.new_span(span)
}
(qself, fld.fold_path(path))
}
-pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
- -> PathParameters
+pub fn noop_fold_generic_args<T: Folder>(generic_args: GenericArgs, fld: &mut T) -> GenericArgs
{
- match path_parameters {
- PathParameters::AngleBracketed(data) =>
- PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)),
- PathParameters::Parenthesized(data) =>
- PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)),
+ match generic_args {
+ GenericArgs::AngleBracketed(data) => {
+ GenericArgs::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data))
+ }
+ GenericArgs::Parenthesized(data) => {
+ GenericArgs::Parenthesized(fld.fold_parenthesized_parameter_data(data))
+ }
}
}
-pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
+pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedArgs,
fld: &mut T)
- -> AngleBracketedParameterData
+ -> AngleBracketedArgs
{
- let AngleBracketedParameterData { lifetimes, types, bindings, span } = data;
- AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)),
- types: types.move_map(|ty| fld.fold_ty(ty)),
- bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
- span: fld.new_span(span) }
+ let AngleBracketedArgs { args, bindings, span } = data;
+ AngleBracketedArgs {
+ args: args.move_map(|arg| fld.fold_generic_arg(arg)),
+ bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
+ span: fld.new_span(span)
+ }
}
-pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
+pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesisedArgs,
fld: &mut T)
- -> ParenthesizedParameterData
+ -> ParenthesisedArgs
{
- let ParenthesizedParameterData { inputs, output, span } = data;
- ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
- output: output.map(|ty| fld.fold_ty(ty)),
- span: fld.new_span(span) }
+ let ParenthesisedArgs { inputs, output, span } = data;
+ ParenthesisedArgs {
+ inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
+ output: output.map(|ty| fld.fold_ty(ty)),
+ span: fld.new_span(span)
+ }
}
pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
})
}
-pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
- -> TyParamBound
- where T: Folder {
- match tpb {
- TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
- RegionTyParamBound(lifetime) => RegionTyParamBound(noop_fold_lifetime(lifetime, fld)),
- }
-}
-
-pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
- let TyParam {attrs, id, ident, bounds, default} = tp;
- let attrs: Vec<_> = attrs.into();
- TyParam {
- attrs: attrs.into_iter()
- .flat_map(|x| fld.fold_attribute(x).into_iter())
- .collect::<Vec<_>>()
- .into(),
- id: fld.new_id(id),
- ident: fld.fold_ident(ident),
- bounds: fld.fold_bounds(bounds),
- default: default.map(|x| fld.fold_ty(x)),
+pub fn noop_fold_param_bound<T>(pb: GenericBound, fld: &mut T) -> GenericBound where T: Folder {
+ match pb {
+ GenericBound::Trait(ty, modifier) => {
+ GenericBound::Trait(fld.fold_poly_trait_ref(ty), modifier)
+ }
+ GenericBound::Outlives(lifetime) => {
+ GenericBound::Outlives(noop_fold_lifetime(lifetime, fld))
+ }
}
}
pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam {
- match param {
- GenericParam::Lifetime(l) => {
- let attrs: Vec<_> = l.attrs.into();
- GenericParam::Lifetime(LifetimeDef {
- attrs: attrs.into_iter()
+ let attrs: Vec<_> = param.attrs.into();
+ GenericParam {
+ ident: fld.fold_ident(param.ident),
+ id: fld.new_id(param.id),
+ attrs: attrs.into_iter()
.flat_map(|x| fld.fold_attribute(x).into_iter())
.collect::<Vec<_>>()
.into(),
- lifetime: Lifetime {
- id: fld.new_id(l.lifetime.id),
- ident: fld.fold_ident(l.lifetime.ident),
- },
- bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)),
- })
+ bounds: param.bounds.move_map(|l| noop_fold_param_bound(l, fld)),
+ kind: match param.kind {
+ GenericParamKind::Lifetime => GenericParamKind::Lifetime,
+ GenericParamKind::Type { default } => GenericParamKind::Type {
+ default: default.map(|ty| fld.fold_ty(ty))
+ }
}
- GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)),
}
}
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
bound_generic_params: fld.fold_generic_params(bound_generic_params),
bounded_ty: fld.fold_ty(bounded_ty),
- bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
+ bounds: bounds.move_map(|x| fld.fold_param_bound(x)),
span: fld.new_span(span)
})
}
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
span: fld.new_span(span),
lifetime: noop_fold_lifetime(lifetime, fld),
- bounds: bounds.move_map(|bound| noop_fold_lifetime(bound, fld))
+ bounds: bounds.move_map(|bound| noop_fold_param_bound(bound, fld))
})
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
}
}
-pub fn noop_fold_opt_bounds<T: Folder>(b: Option<TyParamBounds>, folder: &mut T)
- -> Option<TyParamBounds> {
+pub fn noop_fold_opt_bounds<T: Folder>(b: Option<GenericBounds>, folder: &mut T)
+ -> Option<GenericBounds> {
b.map(|bounds| folder.fold_bounds(bounds))
}
-fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
- -> TyParamBounds {
- bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
+fn noop_fold_bounds<T: Folder>(bounds: GenericBounds, folder: &mut T)
+ -> GenericBounds {
+ bounds.move_map(|bound| folder.fold_param_bound(bound))
}
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
ItemKind::Const(t, e) => {
ItemKind::Const(folder.fold_ty(t), folder.fold_expr(e))
}
- ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
+ ItemKind::Fn(decl, header, generics, body) => {
let generics = folder.fold_generics(generics);
+ let header = folder.fold_fn_header(header);
let decl = folder.fold_fn_decl(decl);
let body = folder.fold_block(body);
- ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
+ ItemKind::Fn(decl, header, generics, body)
}
ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
})
}
+pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> FnHeader {
+ header.asyncness = match header.asyncness {
+ IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
+ IsAsync::NotAsync => IsAsync::NotAsync,
+ };
+ header
+}
+
pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
Mod {
inner: folder.new_span(inner),
pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
MethodSig {
- abi: sig.abi,
- unsafety: sig.unsafety,
- constness: sig.constness,
+ header: folder.fold_fn_header(sig.header),
decl: folder.fold_fn_decl(sig.decl)
}
}
ExprKind::MethodCall(
PathSegment {
ident: folder.fold_ident(seg.ident),
- parameters: seg.parameters.map(|ps| {
- ps.map(|ps| folder.fold_path_parameters(ps))
+ args: seg.args.map(|args| {
+ args.map(|args| folder.fold_generic_args(args))
}),
},
folder.fold_exprs(args))
ExprKind::Match(folder.fold_expr(expr),
arms.move_map(|x| folder.fold_arm(x)))
}
- ExprKind::Closure(capture_clause, movability, decl, body, span) => {
+ ExprKind::Closure(capture_clause, asyncness, movability, decl, body, span) => {
+ let asyncness = match asyncness {
+ IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)),
+ IsAsync::NotAsync => IsAsync::NotAsync,
+ };
ExprKind::Closure(capture_clause,
+ asyncness,
movability,
folder.fold_fn_decl(decl),
folder.fold_expr(body),
ExprKind::Block(folder.fold_block(blk),
opt_label.map(|label| folder.fold_label(label)))
}
+ ExprKind::Async(capture_clause, node_id, body) => {
+ ExprKind::Async(capture_clause, folder.new_id(node_id), folder.fold_block(body))
+ }
ExprKind::Assign(el, er) => {
ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er))
}
html_root_url = "https://doc.rust-lang.org/nightly/",
test(attr(deny(warnings))))]
-#![feature(unicode_internals)]
-#![feature(rustc_diagnostic_macros)]
-#![feature(slice_sort_by_cached_key)]
#![feature(const_atomic_usize_new)]
+#![feature(crate_visibility_modifier)]
+#![feature(macro_at_most_once_rep)]
#![feature(rustc_attrs)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(slice_sort_by_cached_key)]
#![feature(str_escape)]
-#![feature(crate_visibility_modifier)]
+#![feature(unicode_internals)]
#![recursion_limit="256"]
/// Parse a string representing a string literal into its final form. Does
/// unescaping.
-fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
+pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
debug!("str_lit: given {}", lit.escape_default());
let mut res = String::with_capacity(lit.len());
output: ast::FunctionRetTy::Default(sp(15, 15)),
variadic: false
}),
- ast::Unsafety::Normal,
- Spanned {
- span: sp(0,2),
- node: ast::Constness::NotConst,
+ ast::FnHeader {
+ unsafety: ast::Unsafety::Normal,
+ asyncness: ast::IsAsync::NotAsync,
+ constness: Spanned {
+ span: sp(0,2),
+ node: ast::Constness::NotConst,
+ },
+ abi: Abi::Rust,
},
- Abi::Rust,
ast::Generics{
params: Vec::new(),
where_clause: ast::WhereClause {
// except according to those terms.
use rustc_target::spec::abi::{self, Abi};
-use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
-use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
+use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
+use ast::{GenericBound, TraitBoundModifier};
use ast::Unsafety;
use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
use ast::Block;
use ast::Defaultness;
use ast::EnumDef;
use ast::{Expr, ExprKind, RangeLimits};
-use ast::{Field, FnDecl};
+use ast::{Field, FnDecl, FnHeader};
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
-use ast::GenericParam;
-use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
-use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind};
+use ast::{GenericParam, GenericParamKind};
+use ast::GenericArg;
+use ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind};
+use ast::{Label, Lifetime, Lit, LitKind};
use ast::Local;
use ast::MacStmtStyle;
use ast::{Mac, Mac_, MacDelimiter};
use ast::StrStyle;
use ast::SelfKind;
use ast::{TraitItem, TraitRef, TraitObjectSyntax};
-use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
+use ast::{Ty, TyKind, TypeBinding, GenericBounds};
use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar};
use ast::{UseTree, UseTreeKind};
use ast::{BinOpKind, UnOp};
use ast::{RangeEnd, RangeSyntax};
use {ast, attr};
use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP};
+use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, DUMMY_SP, edition::Edition};
use errors::{self, Applicability, DiagnosticBuilder};
use parse::{self, SeqSep, classify, token};
use parse::lexer::TokenAndSpan;
let mut err = self.fatal(&format!("expected `{}`, found `{}`",
token_str,
this_token_str));
- err.span_label(self.span, format!("expected `{}`", token_str));
+
+ let sp = if self.token == token::Token::Eof {
+ // EOF, don't want to point at the following char, but rather the last token
+ self.prev_span
+ } else {
+ self.sess.codemap().next_point(self.prev_span)
+ };
+ let label_exp = format!("expected `{}`", token_str);
+ let cm = self.sess.codemap();
+ match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
+ (Ok(ref a), Ok(ref b)) if a.line == b.line => {
+ // When the spans are in the same line, it means that the only content
+ // between them is whitespace, point only at the found token.
+ err.span_label(self.span, label_exp);
+ }
+ _ => {
+ err.span_label(sp, label_exp);
+ err.span_label(self.span, "unexpected token");
+ }
+ }
Err(err)
}
} else {
err.span_label(self.span, format!("expected identifier, found {}", token_descr));
} else {
err.span_label(self.span, "expected identifier");
+ if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
+ err.span_suggestion(self.span, "remove this comma", "".into());
+ }
}
err
}
/// Parse a sequence, not including the closing delimiter. The function
/// f must consume tokens until reaching the next separator or
/// closing bracket.
- fn parse_seq_to_before_end<T, F>(&mut self,
+ pub fn parse_seq_to_before_end<T, F>(&mut self,
ket: &token::Token,
sep: SeqSep,
f: F)
fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
err.span_err(sp, self.diagnostic())
}
- fn span_fatal_help<S: Into<MultiSpan>>(&self,
- sp: S,
- m: &str,
- help: &str) -> DiagnosticBuilder<'a> {
- let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m);
- err.help(help);
- err
- }
fn bug(&self, m: &str) -> ! {
self.sess.span_diagnostic.span_bug(self.span, m)
}
}
/// parse a TyKind::BareFn type:
- fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>)
- -> PResult<'a, TyKind> {
+ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
/*
[unsafe] [extern "ABI"] fn (S) -> T
})))
}
+ /// Parse asyncness: `async` or nothing
+ fn parse_asyncness(&mut self) -> IsAsync {
+ if self.eat_keyword(keywords::Async) {
+ IsAsync::Async(ast::DUMMY_NODE_ID)
+ } else {
+ IsAsync::NotAsync
+ }
+ }
+
/// Parse unsafety: `unsafe` or nothing.
fn parse_unsafety(&mut self) -> Unsafety {
if self.eat_keyword(keywords::Unsafe) {
let lo = self.span;
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
- let (generics, TyParam {ident, bounds, default, ..}) =
- self.parse_trait_item_assoc_ty(vec![])?;
- (ident, TraitItemKind::Type(bounds, default), generics)
+ self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() {
self.expect_keyword(keywords::Const)?;
let ident = self.parse_ident()?;
// trait item macro.
(keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
} else {
- let (constness, unsafety, abi) = self.parse_fn_front_matter()?;
+ let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
let sig = ast::MethodSig {
- unsafety,
- constness,
+ header: FnHeader {
+ unsafety,
+ constness,
+ abi,
+ asyncness,
+ },
decl: d,
- abi,
};
let body = match self.token {
TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
let path = match bounds[0] {
- TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(),
+ GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
_ => self.bug("unexpected lifetime bound"),
};
self.parse_remaining_bounds(Vec::new(), path, lo, true)?
}
} else if self.eat_keyword(keywords::Impl) {
// Always parse bounds greedily for better error recovery.
- let bounds = self.parse_ty_param_bounds()?;
+ let bounds = self.parse_generic_bounds()?;
impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
TyKind::ImplTrait(bounds)
} else if self.check_keyword(keywords::Dyn) &&
!can_continue_type_after_non_fn_ident(t)) {
self.bump(); // `dyn`
// Always parse bounds greedily for better error recovery.
- let bounds = self.parse_ty_param_bounds()?;
+ let bounds = self.parse_generic_bounds()?;
impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
} else if self.check(&token::Question) ||
self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
// Bound list (trait object type)
- TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?,
+ TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus)?,
TraitObjectSyntax::None)
} else if self.eat_lt() {
// Qualified path
fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
- let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)];
+ let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
if parse_plus {
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
- bounds.append(&mut self.parse_ty_param_bounds()?);
+ bounds.append(&mut self.parse_generic_bounds()?);
}
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
}
}
self.bump(); // `+`
- let bounds = self.parse_ty_param_bounds()?;
+ let bounds = self.parse_generic_bounds()?;
let sum_span = ty.span.to(self.prev_span);
let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178,
s.print_mutability(mut_ty.mutbl)?;
s.popen()?;
s.print_type(&mut_ty.ty)?;
- s.print_bounds(" +", &bounds)?;
+ s.print_type_bounds(" +", &bounds)?;
s.pclose()
});
err.span_suggestion_with_applicability(
-> PResult<'a, ast::Path> {
maybe_whole!(self, NtPath, |path| {
if style == PathStyle::Mod &&
- path.segments.iter().any(|segment| segment.parameters.is_some()) {
+ path.segments.iter().any(|segment| segment.args.is_some()) {
self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
}
path
.span_label(self.prev_span, "try removing `::`").emit();
}
- let parameters = if self.eat_lt() {
+ let args = if self.eat_lt() {
// `<'a, T, A = U>`
- let (lifetimes, types, bindings) = self.parse_generic_args()?;
+ let (args, bindings) = self.parse_generic_args()?;
self.expect_gt()?;
let span = lo.to(self.prev_span);
- AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
+ AngleBracketedArgs { args, bindings, span }.into()
} else {
// `(T, U) -> R`
self.bump(); // `(`
None
};
let span = lo.to(self.prev_span);
- ParenthesizedParameterData { inputs, output, span }.into()
+ ParenthesisedArgs { inputs, output, span }.into()
};
- PathSegment { ident, parameters }
+ PathSegment { ident, args }
} else {
// Generic arguments are not found.
PathSegment::from_ident(ident)
ExprKind::AssignOp(binop, lhs, rhs)
}
- fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
+ pub fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
P(Expr {
id: ast::DUMMY_NODE_ID,
node: ExprKind::Mac(codemap::Spanned {node: m, span: span}),
hi = path.span;
return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
}
+ if self.span.edition() >= Edition::Edition2018 &&
+ self.check_keyword(keywords::Async)
+ {
+ if self.is_async_block() { // check for `async {` and `async move {`
+ return self.parse_async_block(attrs);
+ } else {
+ return self.parse_lambda_expr(attrs);
+ }
+ }
if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) {
return self.parse_lambda_expr(attrs);
}
Err(mut e) => {
e.span_label(struct_sp, "while parsing this struct");
e.emit();
- self.recover_stmt();
- break;
+
+ // If the next token is a comma, then try to parse
+ // what comes next as additional fields, rather than
+ // bailing out until next `}`.
+ if self.token != token::Comma {
+ self.recover_stmt();
+ break;
+ }
}
}
}
_ => {
// Field access `expr.f`
- if let Some(parameters) = segment.parameters {
- self.span_err(parameters.span(),
+ if let Some(args) = segment.args {
+ self.span_err(args.span(),
"field expressions may not have generic arguments");
}
} else {
Movability::Movable
};
+ let asyncness = if self.span.edition() >= Edition::Edition2018
+ && self.eat_keyword(keywords::Async)
+ {
+ IsAsync::Async(ast::DUMMY_NODE_ID)
+ } else {
+ IsAsync::NotAsync
+ };
let capture_clause = if self.eat_keyword(keywords::Move) {
CaptureBy::Value
} else {
Ok(self.mk_expr(
lo.to(body.span),
- ExprKind::Closure(capture_clause, movability, decl, body, lo.to(decl_hi)),
+ ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
attrs))
}
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
}
+ /// Parse an `async move {...}` expression
+ pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
+ -> PResult<'a, P<Expr>>
+ {
+ let span_lo = self.span;
+ self.expect_keyword(keywords::Async)?;
+ let capture_clause = if self.eat_keyword(keywords::Move) {
+ CaptureBy::Value
+ } else {
+ CaptureBy::Ref
+ };
+ let (iattrs, body) = self.parse_inner_attrs_and_block()?;
+ attrs.extend(iattrs);
+ Ok(self.mk_expr(
+ span_lo.to(body.span),
+ ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs))
+ }
+
/// Parse a `do catch {...}` expression (`do catch` token already eaten)
fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
-> PResult<'a, P<Expr>>
})
}
+ fn is_async_block(&mut self) -> bool {
+ self.token.is_keyword(keywords::Async) &&
+ (
+ ( // `async move {`
+ self.look_ahead(1, |t| t.is_keyword(keywords::Move)) &&
+ self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))
+ ) || ( // `async {`
+ self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace))
+ )
+ )
+ }
+
fn is_catch_expr(&mut self) -> bool {
self.token.is_keyword(keywords::Do) &&
self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
if macro_legacy_warnings && self.token != token::Semi {
self.warn_missing_semicolon();
} else {
- self.expect_one_of(&[token::Semi], &[])?;
+ self.expect_one_of(&[], &[token::Semi])?;
}
}
_ => {}
fn err_dotdotdot_syntax(&self, span: Span) {
self.diagnostic().struct_span_err(span, {
- "`...` syntax cannot be used in expressions"
- }).help({
- "Use `..` if you need an exclusive range (a < b)"
- }).help({
- "or `..=` if you need an inclusive range (a <= b)"
- }).emit();
+ "unexpected token: `...`"
+ }).span_suggestion_with_applicability(
+ span, "use `..` for an exclusive range", "..".to_owned(),
+ Applicability::MaybeIncorrect
+ ).span_suggestion_with_applicability(
+ span, "or `..=` for an inclusive range", "..=".to_owned(),
+ Applicability::MaybeIncorrect
+ ).emit();
}
// Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
// LT_BOUND = LIFETIME (e.g. `'a`)
// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
- fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> {
+ fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> {
let mut bounds = Vec::new();
loop {
// This needs to be syncronized with `Token::can_begin_bound`.
self.span_err(question_span,
"`?` may only modify trait bounds, not lifetime bounds");
}
- bounds.push(RegionTyParamBound(self.expect_lifetime()));
+ bounds.push(GenericBound::Outlives(self.expect_lifetime()));
if has_parens {
self.expect(&token::CloseDelim(token::Paren))?;
self.span_err(self.prev_span,
} else {
TraitBoundModifier::None
};
- bounds.push(TraitTyParamBound(poly_trait, modifier));
+ bounds.push(GenericBound::Trait(poly_trait, modifier));
}
} else {
break
return Ok(bounds);
}
- fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds> {
- self.parse_ty_param_bounds_common(true)
+ fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
+ self.parse_generic_bounds_common(true)
}
// Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
// BOUND = LT_BOUND (e.g. `'a`)
- fn parse_lt_param_bounds(&mut self) -> Vec<Lifetime> {
+ fn parse_lt_param_bounds(&mut self) -> GenericBounds {
let mut lifetimes = Vec::new();
while self.check_lifetime() {
- lifetimes.push(self.expect_lifetime());
+ lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
if !self.eat_plus() {
break
}
/// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
- fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyParam> {
+ fn parse_ty_param(&mut self,
+ preceding_attrs: Vec<Attribute>)
+ -> PResult<'a, GenericParam> {
let ident = self.parse_ident()?;
// Parse optional colon and param bounds.
let bounds = if self.eat(&token::Colon) {
- self.parse_ty_param_bounds()?
+ self.parse_generic_bounds()?
} else {
Vec::new()
};
None
};
- Ok(TyParam {
- attrs: preceding_attrs.into(),
+ Ok(GenericParam {
ident,
id: ast::DUMMY_NODE_ID,
+ attrs: preceding_attrs.into(),
bounds,
- default,
+ kind: GenericParamKind::Type {
+ default,
+ }
})
}
/// Parses the following grammar:
- /// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
- fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
- -> PResult<'a, (ast::Generics, TyParam)> {
+ /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
+ fn parse_trait_item_assoc_ty(&mut self)
+ -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
// Parse optional colon and param bounds.
let bounds = if self.eat(&token::Colon) {
- self.parse_ty_param_bounds()?
+ self.parse_generic_bounds()?
} else {
Vec::new()
};
};
self.expect(&token::Semi)?;
- Ok((generics, TyParam {
- attrs: preceding_attrs.into(),
- ident,
- id: ast::DUMMY_NODE_ID,
- bounds,
- default,
- }))
+ Ok((ident, TraitItemKind::Type(bounds, default), generics))
}
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
} else {
Vec::new()
};
- params.push(ast::GenericParam::Lifetime(LifetimeDef {
+ params.push(ast::GenericParam {
+ ident: lifetime.ident,
+ id: lifetime.id,
attrs: attrs.into(),
- lifetime,
bounds,
- }));
+ kind: ast::GenericParamKind::Lifetime,
+ });
if seen_ty_param {
self.span_err(self.prev_span,
"lifetime parameters must be declared prior to type parameters");
}
} else if self.check_ident() {
// Parse type parameter.
- params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?));
+ params.push(self.parse_ty_param(attrs)?);
seen_ty_param = true;
} else {
// Check for trailing attributes and stop parsing.
/// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
/// possibly including trailing comma.
- fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<TypeBinding>)> {
- let mut lifetimes = Vec::new();
- let mut types = Vec::new();
+ fn parse_generic_args(&mut self)
+ -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
+ let mut args = Vec::new();
let mut bindings = Vec::new();
let mut seen_type = false;
let mut seen_binding = false;
loop {
if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
// Parse lifetime argument.
- lifetimes.push(self.expect_lifetime());
+ args.push(GenericArg::Lifetime(self.expect_lifetime()));
if seen_type || seen_binding {
self.span_err(self.prev_span,
"lifetime parameters must be declared prior to type parameters");
seen_binding = true;
} else if self.check_type() {
// Parse type argument.
- types.push(self.parse_ty()?);
+ let ty_param = self.parse_ty()?;
if seen_binding {
- self.span_err(types[types.len() - 1].span,
+ self.span_err(ty_param.span,
"type parameters must be declared prior to associated type bindings");
}
+ args.push(GenericArg::Type(ty_param));
seen_type = true;
} else {
break
break
}
}
- Ok((lifetimes, types, bindings))
+ Ok((args, bindings))
}
/// Parses an optional `where` clause and places it in `generics`.
// or with mandatory equality sign and the second type.
let ty = self.parse_ty()?;
if self.eat(&token::Colon) {
- let bounds = self.parse_ty_param_bounds()?;
+ let bounds = self.parse_generic_bounds()?;
where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
ast::WhereBoundPredicate {
span: lo.to(self.prev_span),
/// Parse an item-position function declaration.
fn parse_item_fn(&mut self,
unsafety: Unsafety,
+ asyncness: IsAsync,
constness: Spanned<Constness>,
abi: Abi)
-> PResult<'a, ItemInfo> {
let decl = self.parse_fn_decl(false)?;
generics.where_clause = self.parse_where_clause()?;
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
- Ok((ident, ItemKind::Fn(decl, unsafety, constness, abi, generics, body), Some(inner_attrs)))
+ let header = FnHeader { unsafety, asyncness, constness, abi };
+ Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
}
/// true if we are looking at `const ID`, false for things like `const fn` etc
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
- fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
+ fn parse_fn_front_matter(&mut self)
+ -> PResult<'a, (
+ Spanned<Constness>,
+ Unsafety,
+ IsAsync,
+ Abi
+ )>
+ {
let is_const_fn = self.eat_keyword(keywords::Const);
let const_span = self.prev_span;
let unsafety = self.parse_unsafety();
+ let asyncness = self.parse_asyncness();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
(respan(self.prev_span, Constness::NotConst), unsafety, abi)
};
self.expect_keyword(keywords::Fn)?;
- Ok((constness, unsafety, abi))
+ Ok((constness, unsafety, asyncness, abi))
}
/// Parse an impl item.
- crate fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
+ pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
maybe_whole!(self, NtImplItem, |x| x);
let attrs = self.parse_outer_attributes()?;
let (mut item, tokens) = self.collect_tokens(|this| {
Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
ast::ImplItemKind::Macro(mac)))
} else {
- let (constness, unsafety, abi) = self.parse_fn_front_matter()?;
+ let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?;
generics.where_clause = self.parse_where_clause()?;
*at_end = true;
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
- Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(ast::MethodSig {
- abi,
- unsafety,
- constness,
- decl,
- }, body)))
+ let header = ast::FnHeader { abi, unsafety, constness, asyncness };
+ Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(
+ ast::MethodSig { header, decl },
+ body
+ )))
}
}
// Parse optional colon and supertrait bounds.
let bounds = if self.eat(&token::Colon) {
- self.parse_ty_param_bounds()?
+ self.parse_generic_bounds()?
} else {
Vec::new()
};
if self.eat(&token::Eq) {
// it's a trait alias
- let bounds = self.parse_ty_param_bounds()?;
+ let bounds = self.parse_generic_bounds()?;
tps.where_clause = self.parse_where_clause()?;
self.expect(&token::Semi)?;
if unsafety != Unsafety::Normal {
`pub(super)`: visible only in the current module's parent
`pub(in path::to::module)`: visible only on the specified path"##;
let path = self.parse_path(PathStyle::Mod)?;
- let path_span = self.prev_span;
+ let sp = self.prev_span;
let help_msg = format!("make this visible only to module `{}` with `in`", path);
self.expect(&token::CloseDelim(token::Paren))?; // `)`
- let mut err = self.span_fatal_help(path_span, msg, suggestion);
+ let mut err = struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg);
+ err.help(suggestion);
err.span_suggestion_with_applicability(
- path_span, &help_msg, format!("in {}", path), Applicability::MachineApplicable
+ sp, &help_msg, format!("in {}", path), Applicability::MachineApplicable
);
err.emit(); // emit diagnostic, but continue with public visibility
}
Some(abi) => Ok(Some(abi)),
None => {
let prev_span = self.prev_span;
- self.span_err(
+ let mut err = struct_span_err!(
+ self.sess.span_diagnostic,
prev_span,
- &format!("invalid ABI: expected one of [{}], \
- found `{}`",
- abi::all_names().join(", "),
- s));
+ E0703,
+ "invalid ABI: found `{}`",
+ s);
+ err.span_label(prev_span, "invalid ABI");
+ err.help(&format!("valid ABIs: {}", abi::all_names().join(", ")));
+ err.emit();
Ok(None)
}
}
let abi = opt_abi.unwrap_or(Abi::C);
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal,
+ IsAsync::NotAsync,
respan(fn_span, Constness::NotConst),
abi)?;
let prev_span = self.prev_span;
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
+ IsAsync::NotAsync,
respan(const_span, Constness::Const),
Abi::Rust)?;
let prev_span = self.prev_span;
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
+
+ // `unsafe async fn` or `async fn`
+ if (
+ self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Async))
+ ) || (
+ self.check_keyword(keywords::Async) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+ )
+ {
+ // ASYNC FUNCTION ITEM
+ let unsafety = self.parse_unsafety();
+ self.expect_keyword(keywords::Async)?;
+ self.expect_keyword(keywords::Fn)?;
+ let fn_span = self.prev_span;
+ let (ident, item_, extra_attrs) =
+ self.parse_item_fn(unsafety,
+ IsAsync::Async(ast::DUMMY_NODE_ID),
+ respan(fn_span, Constness::NotConst),
+ Abi::Rust)?;
+ let prev_span = self.prev_span;
+ let item = self.mk_item(lo.to(prev_span),
+ ident,
+ item_,
+ visibility,
+ maybe_append(attrs, extra_attrs));
+ return Ok(Some(item));
+ }
if self.check_keyword(keywords::Unsafe) &&
(self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Normal,
+ IsAsync::NotAsync,
respan(fn_span, Constness::NotConst),
Abi::Rust)?;
let prev_span = self.prev_span;
let fn_span = self.prev_span;
let (ident, item_, extra_attrs) =
self.parse_item_fn(Unsafety::Unsafe,
+ IsAsync::NotAsync,
respan(fn_span, Constness::NotConst),
abi)?;
let prev_span = self.prev_span;
})
}
- fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
+ pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
let ret = match self.token {
token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf),
token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf),
use rustc_target::spec::abi::{self, Abi};
use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
-use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
-use ast::{Attribute, MacDelimiter};
+use ast::{SelfKind, GenericBound, TraitBoundModifier};
+use ast::{Attribute, MacDelimiter, GenericArg};
use util::parser::{self, AssocOp, Fixity};
use attr;
use codemap::{self, CodeMap};
use syntax_pos::{self, BytePos};
-use syntax_pos::hygiene::{Mark, MarkKind, SyntaxContext};
+use syntax_pos::hygiene::{Mark, SyntaxContext};
use parse::token::{self, BinOpToken, Token};
use parse::lexer::comments;
use parse::{self, ParseSess};
to_string(|s| s.print_type(ty))
}
-pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
- to_string(|s| s.print_bounds("", bounds))
+pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
+ to_string(|s| s.print_type_bounds("", bounds))
}
pub fn pat_to_string(pat: &ast::Pat) -> String {
to_string(|s| s.print_expr(e))
}
-pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
- to_string(|s| s.print_lifetime(e))
+pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
+ to_string(|s| s.print_lifetime(*lt))
}
pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
}
pub fn fun_to_string(decl: &ast::FnDecl,
- unsafety: ast::Unsafety,
- constness: ast::Constness,
+ header: ast::FnHeader,
name: ast::Ident,
generics: &ast::Generics)
-> String {
to_string(|s| {
s.head("")?;
- s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
+ s.print_fn(decl, header, Some(name),
generics, &codemap::dummy_spanned(ast::VisibilityKind::Inherited))?;
s.end()?; // Close the head box
s.end() // Close the outer box
fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> {
if let Some(mark) = ctxt.adjust(Mark::root()) {
// Make a best effort to print something that complies
- if mark.kind() == MarkKind::Builtin {
+ if mark.is_builtin() {
if let Some(name) = std_inject::injected_crate_name() {
self.writer().word("::")?;
self.writer().word(name)?;
Ok(())
}
- pub fn print_opt_lifetime(&mut self,
- lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
- if let Some(l) = *lifetime {
- self.print_lifetime(&l)?;
+ pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
+ if let Some(lt) = *lifetime {
+ self.print_lifetime(lt)?;
self.nbsp()?;
}
Ok(())
}
+ pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) -> io::Result<()> {
+ match generic_arg {
+ GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
+ GenericArg::Type(ty) => self.print_type(ty),
+ }
+ }
+
pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
self.maybe_print_comment(ty.span.lo())?;
self.ibox(0)?;
}
ast::TyKind::TraitObject(ref bounds, syntax) => {
let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" };
- self.print_bounds(prefix, &bounds[..])?;
+ self.print_type_bounds(prefix, &bounds[..])?;
}
ast::TyKind::ImplTrait(ref bounds) => {
- self.print_bounds("impl", &bounds[..])?;
+ self.print_type_bounds("impl", &bounds[..])?;
}
ast::TyKind::Array(ref ty, ref length) => {
self.s.word("[")?;
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
self.head("")?;
- self.print_fn(decl, ast::Unsafety::Normal,
- ast::Constness::NotConst,
- Abi::Rust, Some(item.ident),
+ self.print_fn(decl, ast::FnHeader::default(),
+ Some(item.ident),
generics, &item.vis)?;
self.end()?; // end head-ibox
self.s.word(";")?;
fn print_associated_type(&mut self,
ident: ast::Ident,
- bounds: Option<&ast::TyParamBounds>,
+ bounds: Option<&ast::GenericBounds>,
ty: Option<&ast::Ty>)
-> io::Result<()> {
self.word_space("type")?;
self.print_ident(ident)?;
if let Some(bounds) = bounds {
- self.print_bounds(":", bounds)?;
+ self.print_type_bounds(":", bounds)?;
}
if let Some(ty) = ty {
self.s.space()?;
self.s.word(";")?;
self.end()?; // end the outer cbox
}
- ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
+ ast::ItemKind::Fn(ref decl, header, ref typarams, ref body) => {
self.head("")?;
self.print_fn(
decl,
- unsafety,
- constness.node,
- abi,
+ header,
Some(item.ident),
typarams,
&item.vis
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
- if generics.is_parameterized() {
+ if !generics.params.is_empty() {
self.print_generic_params(&generics.params)?;
self.s.space()?;
}
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
- if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
+ if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
real_bounds.push(b.clone());
}
}
- self.print_bounds(":", &real_bounds[..])?;
+ self.print_type_bounds(":", &real_bounds[..])?;
self.print_where_clause(&generics.where_clause)?;
self.s.word(" ")?;
self.bopen()?;
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
- if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
+ if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
}
}
self.nbsp()?;
- self.print_bounds("=", &real_bounds[..])?;
+ self.print_type_bounds("=", &real_bounds[..])?;
self.print_where_clause(&generics.where_clause)?;
self.s.word(";")?;
}
vis: &ast::Visibility)
-> io::Result<()> {
self.print_fn(&m.decl,
- m.unsafety,
- m.constness.node,
- m.abi,
+ m.header,
Some(ident),
&generics,
vis)
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
self.s.word(".")?;
self.print_ident(segment.ident)?;
- if let Some(ref parameters) = segment.parameters {
- self.print_path_parameters(parameters, true)?;
+ if let Some(ref args) = segment.args {
+ self.print_generic_args(args, true)?;
}
self.print_call_post(base_args)
}
}
self.bclose_(expr.span, INDENT_UNIT)?;
}
- ast::ExprKind::Closure(capture_clause, movability, ref decl, ref body, _) => {
+ ast::ExprKind::Closure(
+ capture_clause, asyncness, movability, ref decl, ref body, _) => {
self.print_movability(movability)?;
+ self.print_asyncness(asyncness)?;
self.print_capture_clause(capture_clause)?;
self.print_fn_block_args(decl)?;
self.ibox(0)?;
self.print_block_with_attrs(blk, attrs)?;
}
+ ast::ExprKind::Async(capture_clause, _, ref blk) => {
+ self.word_nbsp("async")?;
+ self.print_capture_clause(capture_clause)?;
+ self.s.space()?;
+ self.print_block_with_attrs(blk, attrs)?;
+ }
ast::ExprKind::Assign(ref lhs, ref rhs) => {
let prec = AssocOp::Assign.precedence() as i8;
self.print_expr_maybe_paren(lhs, prec + 1)?;
if segment.ident.name != keywords::CrateRoot.name() &&
segment.ident.name != keywords::DollarCrate.name() {
self.print_ident(segment.ident)?;
- if let Some(ref parameters) = segment.parameters {
- self.print_path_parameters(parameters, colons_before_params)?;
+ if let Some(ref args) = segment.args {
+ self.print_generic_args(args, colons_before_params)?;
}
} else if segment.ident.name == keywords::DollarCrate.name() {
self.print_dollar_crate(segment.ident.span.ctxt())?;
self.s.word("::")?;
let item_segment = path.segments.last().unwrap();
self.print_ident(item_segment.ident)?;
- match item_segment.parameters {
- Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
+ match item_segment.args {
+ Some(ref args) => self.print_generic_args(args, colons_before_params),
None => Ok(()),
}
}
- fn print_path_parameters(&mut self,
- parameters: &ast::PathParameters,
- colons_before_params: bool)
- -> io::Result<()>
+ fn print_generic_args(&mut self,
+ args: &ast::GenericArgs,
+ colons_before_params: bool)
+ -> io::Result<()>
{
if colons_before_params {
self.s.word("::")?
}
- match *parameters {
- ast::PathParameters::AngleBracketed(ref data) => {
+ match *args {
+ ast::GenericArgs::AngleBracketed(ref data) => {
self.s.word("<")?;
- let mut comma = false;
- for lifetime in &data.lifetimes {
- if comma {
- self.word_space(",")?
- }
- self.print_lifetime(lifetime)?;
- comma = true;
- }
+ self.commasep(Inconsistent, &data.args, |s, generic_arg| {
+ s.print_generic_arg(generic_arg)
+ })?;
- if !data.types.is_empty() {
- if comma {
- self.word_space(",")?
- }
- self.commasep(
- Inconsistent,
- &data.types,
- |s, ty| s.print_type(ty))?;
- comma = true;
- }
+ let mut comma = data.args.len() != 0;
for binding in data.bindings.iter() {
if comma {
self.s.word(">")?
}
- ast::PathParameters::Parenthesized(ref data) => {
+ ast::GenericArgs::Parenthesized(ref data) => {
self.s.word("(")?;
self.commasep(
Inconsistent,
pub fn print_fn(&mut self,
decl: &ast::FnDecl,
- unsafety: ast::Unsafety,
- constness: ast::Constness,
- abi: abi::Abi,
+ header: ast::FnHeader,
name: Option<ast::Ident>,
generics: &ast::Generics,
vis: &ast::Visibility) -> io::Result<()> {
- self.print_fn_header_info(unsafety, constness, abi, vis)?;
+ self.print_fn_header_info(header, vis)?;
if let Some(name) = name {
self.nbsp()?;
}
}
+ pub fn print_asyncness(&mut self, asyncness: ast::IsAsync)
+ -> io::Result<()> {
+ if asyncness.is_async() {
+ self.word_nbsp("async")?;
+ }
+ Ok(())
+ }
+
pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy)
-> io::Result<()> {
match capture_clause {
}
}
- pub fn print_bounds(&mut self,
+ pub fn print_type_bounds(&mut self,
prefix: &str,
- bounds: &[ast::TyParamBound])
+ bounds: &[ast::GenericBound])
-> io::Result<()> {
if !bounds.is_empty() {
self.s.word(prefix)?;
}
match bound {
- TraitTyParamBound(tref, modifier) => {
+ GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
self.s.word("?")?;
}
self.print_poly_trait_ref(tref)?;
}
- RegionTyParamBound(lt) => {
- self.print_lifetime(lt)?;
- }
+ GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
}
}
}
Ok(())
}
- pub fn print_lifetime(&mut self,
- lifetime: &ast::Lifetime)
- -> io::Result<()>
- {
+ pub fn print_lifetime(&mut self, lifetime: ast::Lifetime) -> io::Result<()> {
self.print_name(lifetime.ident.name)
}
- pub fn print_lifetime_bounds(&mut self,
- lifetime: &ast::Lifetime,
- bounds: &[ast::Lifetime])
- -> io::Result<()>
+ pub fn print_lifetime_bounds(&mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds)
+ -> io::Result<()>
{
self.print_lifetime(lifetime)?;
if !bounds.is_empty() {
if i != 0 {
self.s.word(" + ")?;
}
- self.print_lifetime(bound)?;
+ match bound {
+ ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
+ _ => panic!(),
+ }
}
}
Ok(())
self.s.word("<")?;
self.commasep(Inconsistent, &generic_params, |s, param| {
- match *param {
- ast::GenericParam::Lifetime(ref lifetime_def) => {
- s.print_outer_attributes_inline(&lifetime_def.attrs)?;
- s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)
+ match param.kind {
+ ast::GenericParamKind::Lifetime => {
+ s.print_outer_attributes_inline(¶m.attrs)?;
+ let lt = ast::Lifetime { id: param.id, ident: param.ident };
+ s.print_lifetime_bounds(lt, ¶m.bounds)
},
- ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param),
+ ast::GenericParamKind::Type { ref default } => {
+ s.print_outer_attributes_inline(¶m.attrs)?;
+ s.print_ident(param.ident)?;
+ s.print_type_bounds(":", ¶m.bounds)?;
+ match default {
+ Some(ref default) => {
+ s.s.space()?;
+ s.word_space("=")?;
+ s.print_type(default)
+ }
+ _ => Ok(())
+ }
+ }
}
})?;
Ok(())
}
- pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
- self.print_outer_attributes_inline(¶m.attrs)?;
- self.print_ident(param.ident)?;
- self.print_bounds(":", ¶m.bounds)?;
- match param.default {
- Some(ref default) => {
- self.s.space()?;
- self.word_space("=")?;
- self.print_type(default)
- }
- _ => Ok(())
- }
- }
-
pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
-> io::Result<()> {
if where_clause.predicates.is_empty() {
}) => {
self.print_formal_generic_params(bound_generic_params)?;
self.print_type(bounded_ty)?;
- self.print_bounds(":", bounds)?;
+ self.print_type_bounds(":", bounds)?;
}
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
- self.print_lifetime_bounds(lifetime, bounds)?;
+ self.print_lifetime_bounds(*lifetime, bounds)?;
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
span: syntax_pos::DUMMY_SP,
};
self.print_fn(decl,
- unsafety,
- ast::Constness::NotConst,
- abi,
+ ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
name,
&generics,
&codemap::dummy_spanned(ast::VisibilityKind::Inherited))?;
}
pub fn print_fn_header_info(&mut self,
- unsafety: ast::Unsafety,
- constness: ast::Constness,
- abi: Abi,
+ header: ast::FnHeader,
vis: &ast::Visibility) -> io::Result<()> {
self.s.word(&visibility_qualified(vis, ""))?;
- match constness {
+ match header.constness.node {
ast::Constness::NotConst => {}
ast::Constness::Const => self.word_nbsp("const")?
}
- self.print_unsafety(unsafety)?;
+ self.print_asyncness(header.asyncness)?;
+ self.print_unsafety(header.unsafety)?;
- if abi != Abi::Rust {
+ if header.abi != Abi::Rust {
self.word_nbsp("extern")?;
- self.word_nbsp(&abi.to_string())?;
+ self.word_nbsp(&header.abi.to_string())?;
}
self.s.word("fn")
variadic: false
};
let generics = ast::Generics::default();
- assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
- ast::Constness::NotConst,
- abba_ident, &generics),
- "fn abba()");
+ assert_eq!(
+ fun_to_string(
+ &decl,
+ ast::FnHeader {
+ unsafety: ast::Unsafety::Normal,
+ constness: codemap::dummy_spanned(ast::Constness::NotConst),
+ asyncness: ast::IsAsync::NotAsync,
+ abi: Abi::Rust,
+ },
+ abba_ident,
+ &generics
+ ),
+ "fn abba()"
+ );
})
}
use ext::hygiene::{Mark, SyntaxContext};
use symbol::{Symbol, keywords};
use syntax_pos::{DUMMY_SP, Span};
-use codemap::{ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned, hygiene, respan};
+use codemap::{ExpnInfo, MacroAttribute, dummy_spanned, hygiene, respan};
use ptr::P;
use tokenstream::TokenStream;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("std_inject")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("std_inject")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
use attr::{self, HasAttrs};
use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
-use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute, dummy_spanned};
+use codemap::{self, CodeMap, ExpnInfo, MacroAttribute, dummy_spanned};
use errors;
use config;
use entry::{self, EntryPointType};
if is_test_fn(&self.cx, &i) || is_bench_fn(&self.cx, &i) {
match i.node {
- ast::ItemKind::Fn(_, ast::Unsafety::Unsafe, _, _, _, _) => {
- let diag = self.cx.span_diagnostic;
- diag.span_fatal(i.span, "unsafe functions cannot be used for tests").raise();
- }
- _ => {
- debug!("this is a test function");
- let test = Test {
- span: i.span,
- path: self.cx.path.clone(),
- bench: is_bench_fn(&self.cx, &i),
- ignore: is_ignored(&i),
- should_panic: should_panic(&i, &self.cx),
- allow_fail: is_allowed_fail(&i),
- };
- self.cx.testfns.push(test);
- self.tests.push(i.ident);
+ ast::ItemKind::Fn(_, header, _, _) => {
+ if header.unsafety == ast::Unsafety::Unsafe {
+ let diag = self.cx.span_diagnostic;
+ diag.span_fatal(
+ i.span,
+ "unsafe functions cannot be used for tests"
+ ).raise();
+ }
+ if header.asyncness.is_async() {
+ let diag = self.cx.span_diagnostic;
+ diag.span_fatal(
+ i.span,
+ "async functions cannot be used for tests"
+ ).raise();
+ }
}
+ _ => {},
}
+
+ debug!("this is a test function");
+ let test = Test {
+ span: i.span,
+ path: self.cx.path.clone(),
+ bench: is_bench_fn(&self.cx, &i),
+ ignore: is_ignored(&i),
+ should_panic: should_panic(&i, &self.cx),
+ allow_fail: is_allowed_fail(&i),
+ };
+ self.cx.testfns.push(test);
+ self.tests.push(i.ident);
}
let mut item = i.into_inner();
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("test")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("test")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
TestHarnessGenerator {
fn has_test_signature(_cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
match i.node {
- ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
+ ast::ItemKind::Fn(ref decl, _, ref generics, _) => {
// If the termination trait is active, the compiler will check that the output
// type implements the `Termination` trait as `libtest` enforces that.
let has_output = match decl.output {
match (has_output, has_should_panic_attr) {
(true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
- (true, false) => if generics.is_parameterized() {
+ (true, false) => if !generics.params.is_empty() {
No(BadTestSignature::WrongTypeSignature)
} else {
Yes
fn has_bench_signature(_cx: &TestCtxt, i: &ast::Item) -> bool {
match i.node {
- ast::ItemKind::Fn(ref decl, _, _, _, _, _) => {
+ ast::ItemKind::Fn(ref decl, _, _, _) => {
// NB: inadequate check, but we're running
// well before resolve, can't get too deep.
decl.inputs.len() == 1
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
let main_body = ecx.block(sp, vec![call_test_main]);
let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
- ast::Unsafety::Normal,
- dummy_spanned(ast::Constness::NotConst),
- ::rustc_target::spec::abi::Abi::Rust,
+ ast::FnHeader::default(),
ast::Generics::default(),
main_body);
P(ast::Item {
self.count += 1;
walk_trait_ref(self, t)
}
- fn visit_ty_param_bound(&mut self, bounds: &TyParamBound) {
+ fn visit_param_bound(&mut self, bounds: &GenericBound) {
self.count += 1;
- walk_ty_param_bound(self, bounds)
+ walk_param_bound(self, bounds)
}
fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) {
self.count += 1;
self.count += 1;
walk_use_tree(self, use_tree, id)
}
- fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) {
+ fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) {
self.count += 1;
- walk_path_parameters(self, path_span, path_parameters)
+ walk_generic_args(self, path_span, generic_args)
}
fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
self.count += 1;
Block,
Catch,
Struct,
+ Async,
}
impl PartialOrd for ExprPrecedence {
ExprPrecedence::Match |
ExprPrecedence::Block |
ExprPrecedence::Catch |
+ ExprPrecedence::Async |
ExprPrecedence::Struct => PREC_PAREN,
}
}
//! instance, a walker looking for item names in a module will miss all of
//! those that are created by the expansion of a macro.
-use rustc_target::spec::abi::Abi;
use ast::*;
use syntax_pos::Span;
-use codemap::Spanned;
use parse::token::Token;
use tokenstream::{TokenTree, TokenStream};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo()
- ItemFn(Ident, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block),
+ ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
/// fn foo(&self)
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
- fn visit_generic_param(&mut self, param: &'ast GenericParam) { walk_generic_param(self, param) }
+ fn visit_generic_param(&mut self, param: &'ast GenericParam) {
+ walk_generic_param(self, param)
+ }
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) }
fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) }
fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) }
- fn visit_ty_param_bound(&mut self, bounds: &'ast TyParamBound) {
- walk_ty_param_bound(self, bounds)
+ fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
+ walk_param_bound(self, bounds)
}
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
walk_poly_trait_ref(self, t, m)
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
walk_path_segment(self, path_span, path_segment)
}
- fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'ast PathParameters) {
- walk_path_parameters(self, path_span, path_parameters)
+ fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
+ walk_generic_args(self, path_span, generic_args)
+ }
+ fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
+ match generic_arg {
+ GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+ GenericArg::Type(ty) => self.visit_ty(ty),
+ }
}
fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
walk_assoc_type_binding(self, type_binding)
visitor.visit_ty(typ);
visitor.visit_expr(expr);
}
- ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+ ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
visitor.visit_generics(generics);
- visitor.visit_fn(FnKind::ItemFn(item.ident, unsafety,
- constness, abi, &item.vis, body),
+ visitor.visit_fn(FnKind::ItemFn(item.ident, header,
+ &item.vis, body),
declaration,
item.span,
item.id)
}
ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
visitor.visit_generics(generics);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_trait_item, methods);
}
ItemKind::TraitAlias(ref generics, ref bounds) => {
visitor.visit_generics(generics);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
}
ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
}
TyKind::TraitObject(ref bounds, ..) |
TyKind::ImplTrait(ref bounds) => {
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
}
TyKind::Typeof(ref expression) => {
visitor.visit_anon_const(expression)
path_span: Span,
segment: &'a PathSegment) {
visitor.visit_ident(segment.ident);
- if let Some(ref parameters) = segment.parameters {
- visitor.visit_path_parameters(path_span, parameters);
+ if let Some(ref args) = segment.args {
+ visitor.visit_generic_args(path_span, args);
}
}
-pub fn walk_path_parameters<'a, V>(visitor: &mut V,
- _path_span: Span,
- path_parameters: &'a PathParameters)
+pub fn walk_generic_args<'a, V>(visitor: &mut V,
+ _path_span: Span,
+ generic_args: &'a GenericArgs)
where V: Visitor<'a>,
{
- match *path_parameters {
- PathParameters::AngleBracketed(ref data) => {
- walk_list!(visitor, visit_ty, &data.types);
- walk_list!(visitor, visit_lifetime, &data.lifetimes);
+ match *generic_args {
+ GenericArgs::AngleBracketed(ref data) => {
+ walk_list!(visitor, visit_generic_arg, &data.args);
walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
}
- PathParameters::Parenthesized(ref data) => {
+ GenericArgs::Parenthesized(ref data) => {
walk_list!(visitor, visit_ty, &data.inputs);
walk_list!(visitor, visit_ty, &data.output);
}
// Empty!
}
-pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
+pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) {
match *bound {
- TraitTyParamBound(ref typ, ref modifier) => {
- visitor.visit_poly_trait_ref(typ, modifier);
- }
- RegionTyParamBound(ref lifetime) => {
- visitor.visit_lifetime(lifetime);
- }
+ GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier),
+ GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
}
}
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
- match *param {
- GenericParam::Lifetime(ref l) => {
- visitor.visit_ident(l.lifetime.ident);
- walk_list!(visitor, visit_lifetime, &l.bounds);
- walk_list!(visitor, visit_attribute, &*l.attrs);
- }
- GenericParam::Type(ref t) => {
- visitor.visit_ident(t.ident);
- walk_list!(visitor, visit_ty_param_bound, &t.bounds);
- walk_list!(visitor, visit_ty, &t.default);
- walk_list!(visitor, visit_attribute, &*t.attrs);
- }
+ visitor.visit_ident(param.ident);
+ walk_list!(visitor, visit_attribute, param.attrs.iter());
+ walk_list!(visitor, visit_param_bound, ¶m.bounds);
+ match param.kind {
+ GenericParamKind::Lifetime => {}
+ GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
}
}
ref bound_generic_params,
..}) => {
visitor.visit_ty(bounded_ty);
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_generic_param, bound_generic_params);
}
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
visitor.visit_lifetime(lifetime);
- walk_list!(visitor, visit_lifetime, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
}
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
where V: Visitor<'a>,
{
match kind {
- FnKind::ItemFn(_, _, _, _, _, body) => {
+ FnKind::ItemFn(_, _, _, body) => {
walk_fn_decl(visitor, declaration);
visitor.visit_block(body);
}
&sig.decl, trait_item.span, trait_item.id);
}
TraitItemKind::Type(ref bounds, ref default) => {
- walk_list!(visitor, visit_ty_param_bound, bounds);
+ walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, default);
}
TraitItemKind::Macro(ref mac) => {
visitor.visit_expr(subexpression);
walk_list!(visitor, visit_arm, arms);
}
- ExprKind::Closure(_, _, ref function_declaration, ref body, _decl_span) => {
+ ExprKind::Closure(_, _, _, ref function_declaration, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure(body),
function_declaration,
expression.span,
walk_list!(visitor, visit_label, opt_label);
visitor.visit_block(block);
}
+ ExprKind::Async(_, _, ref body) => {
+ visitor.visit_block(body);
+ }
ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => {
visitor.visit_expr(left_hand_expression);
visitor.visit_expr(right_hand_expression);
use deriving::generic::ty::*;
use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData};
+use syntax::ast::GenericArg;
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
ItemKind::Struct(_, Generics { ref params, .. }) |
ItemKind::Enum(_, Generics { ref params, .. }) => {
if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") &&
- !params.iter().any(|param| param.is_type_param())
+ !params.iter().any(|param| match param.kind {
+ ast::GenericParamKind::Type { .. } => true,
+ _ => false,
+ })
{
bounds = vec![];
is_shallow = true;
let span = span.with_ctxt(cx.backtrace());
let assert_path = cx.path_all(span, true,
cx.std_path(&["clone", helper_name]),
- vec![], vec![ty], vec![]);
+ vec![GenericArg::Type(ty)], vec![]);
stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
}
fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &VariantData) {
use deriving::generic::*;
use deriving::generic::ty::*;
-use syntax::ast::{self, Expr, MetaItem};
+use syntax::ast::{self, Expr, MetaItem, GenericArg};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
let span = span.with_ctxt(cx.backtrace());
let assert_path = cx.path_all(span, true,
cx.std_path(&["cmp", helper_name]),
- vec![], vec![ty], vec![]);
+ vec![GenericArg::Type(ty)], vec![]);
stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
}
fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &ast::VariantData) {
use std::vec;
use rustc_target::spec::abi::Abi;
-use syntax::ast::{
- self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
-};
-
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
+use syntax::ast::{VariantData, GenericParamKind, GenericArg};
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
-use syntax::codemap::{self, dummy_spanned, respan};
+use syntax::codemap::{self, respan};
use syntax::util::move_map::MoveMap;
use syntax::ptr::P;
use syntax::symbol::{Symbol, keywords};
ast::ItemKind::Struct(_, ref generics) |
ast::ItemKind::Enum(_, ref generics) |
ast::ItemKind::Union(_, ref generics) => {
- !generics.params.iter().any(|p| p.is_type_param())
+ !generics.params.iter().any(|param| match param.kind {
+ ast::GenericParamKind::Type { .. } => true,
+ _ => false,
+ })
}
_ => {
// Non-ADT derive is an error, but it should have been
.to_generics(cx, self.span, type_ident, generics);
// Create the generic parameters
- params.extend(generics.params.iter().map(|param| {
- match *param {
- ref l @ GenericParam::Lifetime(_) => l.clone(),
- GenericParam::Type(ref ty_param) => {
- // I don't think this can be moved out of the loop, since
- // a TyParamBound requires an ast id
- let mut bounds: Vec<_> =
- // extra restrictions on the generics parameters to the
- // type being derived upon
- self.additional_bounds.iter().map(|p| {
- cx.typarambound(p.to_path(cx, self.span,
- type_ident, generics))
- }).collect();
-
- // require the current trait
- bounds.push(cx.typarambound(trait_path.clone()));
-
- // also add in any bounds from the declaration
- for declared_bound in ty_param.bounds.iter() {
- bounds.push((*declared_bound).clone());
- }
-
- GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None))
+ params.extend(generics.params.iter().map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => param.clone(),
+ GenericParamKind::Type { .. } => {
+ // I don't think this can be moved out of the loop, since
+ // a GenericBound requires an ast id
+ let mut bounds: Vec<_> =
+ // extra restrictions on the generics parameters to the
+ // type being derived upon
+ self.additional_bounds.iter().map(|p| {
+ cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
+ }).collect();
+
+ // require the current trait
+ bounds.push(cx.trait_bound(trait_path.clone()));
+
+ // also add in any bounds from the declaration
+ for declared_bound in ¶m.bounds {
+ bounds.push((*declared_bound).clone());
}
+
+ cx.typaram(self.span, param.ident, vec![], bounds, None)
}
}));
// Extra scope required here so ty_params goes out of scope before params is moved
let mut ty_params = params.iter()
- .filter_map(|param| match *param {
- ast::GenericParam::Type(ref t) => Some(t),
+ .filter_map(|param| match param.kind {
+ ast::GenericParamKind::Type { .. } => Some(param),
_ => None,
})
.peekable();
let mut bounds: Vec<_> = self.additional_bounds
.iter()
.map(|p| {
- cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
+ cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
})
.collect();
// require the current trait
- bounds.push(cx.typarambound(trait_path.clone()));
+ bounds.push(cx.trait_bound(trait_path.clone()));
let predicate = ast::WhereBoundPredicate {
span: self.span,
// Create the reference to the trait.
let trait_ref = cx.trait_ref(trait_path);
- // Create the type parameters on the `self` path.
- let self_ty_params = generics.params
- .iter()
- .filter_map(|param| match *param {
- GenericParam::Type(ref ty_param)
- => Some(cx.ty_ident(self.span, ty_param.ident)),
- _ => None,
- })
- .collect();
-
- let self_lifetimes: Vec<ast::Lifetime> = generics.params
- .iter()
- .filter_map(|param| match *param {
- GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
- _ => None,
- })
- .collect();
+ let self_params: Vec<_> = generics.params.iter().map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ GenericArg::Lifetime(cx.lifetime(self.span, param.ident))
+ }
+ GenericParamKind::Type { .. } => {
+ GenericArg::Type(cx.ty_ident(self.span, param.ident))
+ }
+ }).collect();
// Create the type of `self`.
- let self_type = cx.ty_path(cx.path_all(self.span,
- false,
- vec![type_ident],
- self_lifetimes,
- self_ty_params,
- Vec::new()));
+ let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]);
+ let self_type = cx.ty_path(path);
let attr = cx.attribute(self.span,
cx.meta_word(self.span,
defaultness: ast::Defaultness::Final,
ident: method_ident,
node: ast::ImplItemKind::Method(ast::MethodSig {
- abi,
- unsafety,
- constness:
- dummy_spanned(ast::Constness::NotConst),
+ header: ast::FnHeader {
+ unsafety, abi,
+ ..ast::FnHeader::default()
+ },
decl: fn_decl,
},
body_block),
pub use self::Ty::*;
use syntax::ast;
-use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind};
+use syntax::ast::{Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::codemap::{respan, DUMMY_SP};
-> ast::Path {
let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
let lt = mk_lifetimes(cx, span, &self.lifetime);
- let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
+ let tys: Vec<P<ast::Ty>> =
+ self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
+ let params = lt.into_iter()
+ .map(|lt| GenericArg::Lifetime(lt))
+ .chain(tys.into_iter().map(|ty| GenericArg::Type(ty)))
+ .collect();
match self.kind {
- PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()),
- PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()),
+ PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()),
+ PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
PathKind::Std => {
let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark);
idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site));
- cx.path_all(span, false, idents, lt, tys, Vec::new())
+ cx.path_all(span, false, idents, params, Vec::new())
}
}
cx: &ExtCtxt,
span: Span,
self_ty: Ident,
- self_generics: &Generics)
+ generics: &Generics)
-> ast::Path {
match *self {
Self_ => {
- let self_params = self_generics.params
- .iter()
- .filter_map(|param| match *param {
- GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
- _ => None,
- })
- .collect();
-
- let lifetimes: Vec<ast::Lifetime> = self_generics.params
- .iter()
- .filter_map(|param| match *param {
- GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
- _ => None,
- })
- .collect();
+ let params: Vec<_> = generics.params.iter().map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident })
+ }
+ GenericParamKind::Type { .. } => {
+ GenericArg::Type(cx.ty_ident(span, param.ident))
+ }
+ }).collect();
- cx.path_all(span,
- false,
- vec![self_ty],
- lifetimes,
- self_params,
- Vec::new())
+ cx.path_all(span, false, vec![self_ty], params, vec![])
}
- Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),
+ Literal(ref p) => p.to_path(cx, span, self_ty, generics),
Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
}
bounds: &[Path],
self_ident: Ident,
self_generics: &Generics)
- -> ast::TyParam {
+ -> ast::GenericParam {
let bounds = bounds.iter()
.map(|b| {
let path = b.to_path(cx, span, self_ident, self_generics);
- cx.typarambound(path)
+ cx.trait_bound(path)
})
.collect();
cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
}
-fn mk_generics(params: Vec<GenericParam>, span: Span) -> Generics {
+fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
Generics {
params,
where_clause: ast::WhereClause {
.iter()
.map(|&(lt, ref bounds)| {
let bounds = bounds.iter()
- .map(|b| cx.lifetime(span, Ident::from_str(b)))
- .collect();
- GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds))
+ .map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b))));
+ cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect())
})
.chain(self.bounds
.iter()
.map(|t| {
let (name, ref bounds) = *t;
- GenericParam::Type(mk_ty_param(
- cx, span, name, &[], &bounds, self_ty, self_generics
- ))
+ mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
})
)
.collect();
match item.node {
ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
- for param in params.iter() {
- if let ast::GenericParam::Type(ref ty) = *param{
- typaram.push_str(&ty.ident.as_str());
+ for param in params {
+ match param.kind {
+ ast::GenericParamKind::Type { .. } => {
+ typaram.push_str(¶m.ident.as_str());
+ }
+ _ => {}
}
}
}
intrinsic: &str,
args: Vec<P<ast::Expr>>)
-> P<ast::Expr> {
- if cx.current_expansion.mark.expn_info().unwrap().callee.allow_internal_unstable {
+ if cx.current_expansion.mark.expn_info().unwrap().allow_internal_unstable {
span = span.with_ctxt(cx.backtrace());
} else { // Avoid instability errors with user defined curstom derives, cc #36316
let mut info = cx.current_expansion.mark.expn_info().unwrap();
- info.callee.allow_internal_unstable = true;
+ info.allow_internal_unstable = true;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(info);
span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
// interface.
//
-use syntax::ast::{self, Ident};
+use syntax::ast::{self, Ident, GenericArg};
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
cx.expr_path(cx.path_all(sp,
true,
cx.std_path(&["option", "Option", "None"]),
- Vec::new(),
- vec![cx.ty_rptr(sp,
+ vec![GenericArg::Type(cx.ty_rptr(sp,
cx.ty_ident(sp, Ident::from_str("str")),
Some(lt),
- ast::Mutability::Immutable)],
- Vec::new()))
+ ast::Mutability::Immutable))],
+ vec![]))
}
Ok(s) => {
cx.expr_call_global(sp,
use syntax::ast::{self, Ident, NodeId};
use syntax::attr;
-use syntax::codemap::{ExpnInfo, NameAndSpan, MacroAttribute, hygiene, respan};
+use syntax::codemap::{ExpnInfo, MacroAttribute, hygiene, respan};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
- callee: NameAndSpan {
- format: MacroAttribute(Symbol::intern("proc_macro")),
- span: None,
- allow_internal_unstable: true,
- allow_internal_unsafe: false,
- edition: hygiene::default_edition(),
- }
+ def_site: None,
+ format: MacroAttribute(Symbol::intern("proc_macro")),
+ allow_internal_unstable: true,
+ allow_internal_unsafe: false,
+ edition: hygiene::default_edition(),
});
let span = DUMMY_SP.apply_mark(mark);
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
pub struct SyntaxContext(pub(super) u32);
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub struct SyntaxContextData {
pub outer_mark: Mark,
pub prev_ctxt: SyntaxContext,
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct Mark(u32);
+#[derive(Debug)]
struct MarkData {
parent: Mark,
- kind: MarkKind,
+ transparency: Transparency,
+ is_builtin: bool,
expn_info: Option<ExpnInfo>,
}
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub enum MarkKind {
- Modern,
- Builtin,
- Legacy,
+/// A property of a macro expansion that determines how identifiers
+/// produced by that expansion are resolved.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum Transparency {
+ /// Identifier produced by a transparent expansion is always resolved at call-site.
+ /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
+ /// (Not used yet.)
+ Transparent,
+ /// Identifier produced by a semi-transparent expansion may be resolved
+ /// either at call-site or at definition-site.
+ /// If it's a local variable, label or `$crate` then it's resolved at def-site.
+ /// Otherwise it's resolved at call-site.
+ /// `macro_rules` macros behave like this, built-in macros currently behave like this too,
+ /// but that's an implementation detail.
+ SemiTransparent,
+ /// Identifier produced by an opaque expansion is always resolved at definition-site.
+ /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
+ Opaque,
}
impl Mark {
pub fn fresh(parent: Mark) -> Self {
HygieneData::with(|data| {
- data.marks.push(MarkData { parent: parent, kind: MarkKind::Legacy, expn_info: None });
+ data.marks.push(MarkData {
+ parent,
+ // By default expansions behave like `macro_rules`.
+ transparency: Transparency::SemiTransparent,
+ is_builtin: false,
+ expn_info: None,
+ });
Mark(data.marks.len() as u32 - 1)
})
}
#[inline]
pub fn set_expn_info(self, info: ExpnInfo) {
- HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
+ HygieneData::with(|data| {
+ let old_info = &mut data.marks[self.0 as usize].expn_info;
+ if let Some(old_info) = old_info {
+ panic!("expansion info is reset for the mark {}\nold: {:#?}\nnew: {:#?}",
+ self.0, old_info, info);
+ }
+ *old_info = Some(info);
+ })
}
pub fn modern(mut self) -> Mark {
HygieneData::with(|data| {
- loop {
- if self == Mark::root() || data.marks[self.0 as usize].kind == MarkKind::Modern {
- return self;
- }
+ while data.marks[self.0 as usize].transparency != Transparency::Opaque {
self = data.marks[self.0 as usize].parent;
}
+ self
})
}
#[inline]
- pub fn kind(self) -> MarkKind {
- HygieneData::with(|data| data.marks[self.0 as usize].kind)
+ pub fn transparency(self) -> Transparency {
+ assert_ne!(self, Mark::root());
+ HygieneData::with(|data| data.marks[self.0 as usize].transparency)
}
#[inline]
- pub fn set_kind(self, kind: MarkKind) {
- HygieneData::with(|data| data.marks[self.0 as usize].kind = kind)
+ pub fn set_transparency(self, transparency: Transparency) {
+ assert_ne!(self, Mark::root());
+ HygieneData::with(|data| data.marks[self.0 as usize].transparency = transparency)
+ }
+
+ #[inline]
+ pub fn is_builtin(self) -> bool {
+ HygieneData::with(|data| data.marks[self.0 as usize].is_builtin)
+ }
+
+ #[inline]
+ pub fn set_is_builtin(self, is_builtin: bool) {
+ HygieneData::with(|data| data.marks[self.0 as usize].is_builtin = is_builtin)
}
pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
}
}
+#[derive(Debug)]
pub struct HygieneData {
marks: Vec<MarkData>,
syntax_contexts: Vec<SyntaxContextData>,
HygieneData {
marks: vec![MarkData {
parent: Mark::root(),
- kind: MarkKind::Builtin,
+ // If the root is opaque, then loops searching for an opaque mark
+ // will automatically stop after reaching it.
+ transparency: Transparency::Opaque,
+ is_builtin: true,
expn_info: None,
}],
syntax_contexts: vec![SyntaxContextData {
HygieneData::with(|data| {
data.marks.push(MarkData {
parent: Mark::root(),
- kind: MarkKind::Legacy,
- expn_info: Some(expansion_info)
+ transparency: Transparency::SemiTransparent,
+ is_builtin: false,
+ expn_info: Some(expansion_info),
});
let mark = Mark(data.marks.len() as u32 - 1);
/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
- if mark.kind() == MarkKind::Modern {
+ if mark.transparency() == Transparency::Opaque {
return self.apply_mark_internal(mark);
}
HygieneData::with(|data| {
let syntax_contexts = &mut data.syntax_contexts;
let mut modern = syntax_contexts[self.0 as usize].modern;
- if data.marks[mark.0 as usize].kind == MarkKind::Modern {
+ if data.marks[mark.0 as usize].transparency == Transparency::Opaque {
modern = *data.markings.entry((modern, mark)).or_insert_with(|| {
let len = syntax_contexts.len() as u32;
syntax_contexts.push(SyntaxContextData {
/// call_site span would have its own ExpnInfo, with the call_site
/// pointing to the `foo!` invocation.
pub call_site: Span,
- /// Information about the expansion.
- pub callee: NameAndSpan
-}
-
-#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct NameAndSpan {
+ /// The span of the macro definition itself. The macro may not
+ /// have a sensible definition span (e.g. something defined
+ /// completely inside libsyntax) in which case this is None.
+ /// This span serves only informational purpose and is not used for resolution.
+ pub def_site: Option<Span>,
/// The format with which the macro was invoked.
pub format: ExpnFormat,
/// Whether the macro is allowed to use #[unstable]/feature-gated
pub allow_internal_unsafe: bool,
/// Edition of the crate in which the macro is defined.
pub edition: Edition,
- /// The span of the macro definition itself. The macro may not
- /// have a sensible definition span (e.g. something defined
- /// completely inside libsyntax) in which case this is None.
- pub span: Option<Span>
-}
-
-impl NameAndSpan {
- pub fn name(&self) -> Symbol {
- match self.format {
- ExpnFormat::MacroAttribute(s) |
- ExpnFormat::MacroBang(s) => s,
- ExpnFormat::CompilerDesugaring(ref kind) => kind.as_symbol(),
- }
- }
}
/// The source of expansion.
CompilerDesugaring(CompilerDesugaringKind)
}
+impl ExpnFormat {
+ pub fn name(&self) -> Symbol {
+ match *self {
+ ExpnFormat::MacroBang(name) | ExpnFormat::MacroAttribute(name) => name,
+ ExpnFormat::CompilerDesugaring(kind) => kind.name(),
+ }
+ }
+}
+
/// The kind of compiler desugaring.
-#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CompilerDesugaringKind {
DotFill,
QuestionMark,
/// to an `existential type Foo: Trait;` + replacing the
/// `impl Trait` with `Foo`.
ExistentialReturnType,
+ Async,
}
impl CompilerDesugaringKind {
- pub fn as_symbol(&self) -> Symbol {
- use CompilerDesugaringKind::*;
- let s = match *self {
- DotFill => "...",
- QuestionMark => "?",
- Catch => "do catch",
- ExistentialReturnType => "existental type",
- };
- Symbol::intern(s)
+ pub fn name(self) -> Symbol {
+ Symbol::intern(match self {
+ CompilerDesugaringKind::Async => "async",
+ CompilerDesugaringKind::DotFill => "...",
+ CompilerDesugaringKind::QuestionMark => "?",
+ CompilerDesugaringKind::Catch => "do catch",
+ CompilerDesugaringKind::ExistentialReturnType => "existential type",
+ })
}
}
pub mod edition;
pub mod hygiene;
-pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
+pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind};
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
/// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition {
self.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(),
- |einfo| einfo.callee.edition)
+ |einfo| einfo.edition)
}
/// Return the source callee.
///
- /// Returns None if the supplied span has no expansion trace,
- /// else returns the NameAndSpan for the macro definition
+ /// Returns `None` if the supplied span has no expansion trace,
+ /// else returns the `ExpnInfo` for the macro definition
/// corresponding to the source callsite.
- pub fn source_callee(self) -> Option<NameAndSpan> {
- fn source_callee(info: ExpnInfo) -> NameAndSpan {
+ pub fn source_callee(self) -> Option<ExpnInfo> {
+ fn source_callee(info: ExpnInfo) -> ExpnInfo {
match info.call_site.ctxt().outer().expn_info() {
Some(info) => source_callee(info),
- None => info.callee,
+ None => info,
}
}
self.ctxt().outer().expn_info().map(source_callee)
/// `#[allow_internal_unstable]`).
pub fn allows_unstable(&self) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => info.callee.allow_internal_unstable,
+ Some(info) => info.allow_internal_unstable,
None => false,
}
}
/// Check if this span arises from a compiler desugaring of kind `kind`.
pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => match info.callee.format {
+ Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => k == kind,
_ => false,
},
/// if this span is not from a desugaring.
pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
match self.ctxt().outer().expn_info() {
- Some(info) => match info.callee.format {
+ Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => Some(k),
_ => None
},
// (that is, a macro marked with `#[allow_internal_unsafe]`).
pub fn allows_unsafe(&self) -> bool {
match self.ctxt().outer().expn_info() {
- Some(info) => info.callee.allow_internal_unsafe,
+ Some(info) => info.allow_internal_unsafe,
None => false,
}
}
let mut prev_span = DUMMY_SP;
let mut result = vec![];
while let Some(info) = self.ctxt().outer().expn_info() {
- let (pre, post) = match info.callee.format {
- ExpnFormat::MacroAttribute(..) => ("#[", "]"),
- ExpnFormat::MacroBang(..) => ("", "!"),
- ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
- };
- let macro_decl_name = format!("{}{}{}", pre, info.callee.name(), post);
- let def_site_span = info.callee.span;
-
// Don't print recursive invocations
if !info.call_site.source_equal(&prev_span) {
+ let (pre, post) = match info.format {
+ ExpnFormat::MacroAttribute(..) => ("#[", "]"),
+ ExpnFormat::MacroBang(..) => ("", "!"),
+ ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
+ };
result.push(MacroBacktrace {
call_site: info.call_site,
- macro_decl_name,
- def_site_span,
+ macro_decl_name: format!("{}{}{}", pre, info.format.name(), post),
+ def_site_span: info.def_site,
});
}
}
fn foo<T:Get>(t: T) {
- let x = t.get(); //~ ERROR `<T as Get>::Value: std::marker::Sized` is not
+ let x = t.get(); //~ ERROR the size for value values of type
}
fn main() {
// <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.
+
#![crate_name="lint_stability"]
#![crate_type = "lib"]
#![feature(staged_api)]
#[rustc_deprecated(since = "1.0.0", reason = "text")]
pub fn deprecated_text() {}
+#[stable(feature = "test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "99.99.99", reason = "text")]
+pub fn deprecated_future() {}
+
#[unstable(feature = "test_feature", issue = "0")]
#[rustc_deprecated(since = "1.0.0", reason = "text")]
pub fn deprecated_unstable() {}
// except according to those terms.
fn foo<T:'static>() {
- 1.bar::<T>(); //~ ERROR `T: std::marker::Send` is not satisfied
+ 1.bar::<T>(); //~ ERROR `T` cannot be sent between threads safely
}
trait bar {
pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
//~^ ERROR only auto traits can be used as additional traits in a trait object
- //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
- //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
+ //~| ERROR the size for value values of type
+ //~| ERROR the size for value values of type
}
trait Foo : Send+Sync { }
impl <T: Sync+'static> Foo for (T,) { }
-//~^ ERROR the trait bound `T: std::marker::Send` is not satisfied in `(T,)` [E0277]
+//~^ ERROR `T` cannot be sent between threads safely [E0277]
impl <T: Send> Foo for (T,T) { }
//~^ ERROR `T` cannot be shared between threads safely [E0277]
impl <T:Sync> RequiresShare for X<T> { }
impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
-//~^ ERROR `T: std::marker::Send` is not satisfied
+//~^ ERROR `T` cannot be sent between threads safely [E0277]
fn main() { }
trait Foo : Send { }
impl Foo for std::rc::Rc<i8> { }
-//~^ ERROR `std::rc::Rc<i8>: std::marker::Send` is not satisfied
+//~^ ERROR `std::rc::Rc<i8>` cannot be sent between threads safely
fn main() { }
trait Foo : Send { }
-impl <T: Sync+'static> Foo for T { } //~ ERROR `T: std::marker::Send` is not satisfied
+impl <T: Sync+'static> Foo for T { }
+//~^ ERROR `T` cannot be sent between threads safely
fn main() { }
}
fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
- //~^ ERROR `F: std::marker::Send` is not satisfied
+ //~^ ERROR `F` cannot be sent between threads safely
return X { field: blk };
}
pub fn main() {
let x: Box<Trait> = Box::new(Foo);
let _y: &Trait = x; //~ ERROR E0308
- //~| expected type `&Trait`
- //~| found type `std::boxed::Box<Trait>`
+ //~| expected type `&dyn Trait`
+ //~| found type `std::boxed::Box<dyn Trait>`
}
let &&x = &&(&1isize as &T);
// n == m
- let &x = &1isize as &T; //~ ERROR type `&T` cannot be dereferenced
- let &&x = &(&1isize as &T); //~ ERROR type `&T` cannot be dereferenced
- let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<T>` cannot be dereferenced
+ let &x = &1isize as &T; //~ ERROR type `&dyn T` cannot be dereferenced
+ let &&x = &(&1isize as &T); //~ ERROR type `&dyn T` cannot be dereferenced
+ let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<dyn T>` cannot be dereferenced
// n > m
let &&x = &1isize as &T;
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
let &&&x = &(&1isize as &T);
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
let box box x = box 1isize as Box<T>;
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `std::boxed::Box<_>`
}
let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = *z;
- //~^ ERROR `ToBar: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
+
}
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected type `ToBar`
+ //~| expected type `dyn ToBar`
//~| found type `Bar1`
//~| expected trait ToBar, found struct `Bar1`
- //~| ERROR `ToBar: std::marker::Sized` is not satisfied
+ //~| ERROR the size for value values of type
}
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected type `ToBar`
+ //~| expected type `dyn ToBar`
//~| found type `Bar1`
//~| expected trait ToBar, found struct `Bar1`
- //~| ERROR `ToBar: std::marker::Sized` is not satisfied
+ //~| ERROR the size for value values of type
}
let f: ([isize; 3],) = ([5, 6, 7],);
let g: &([isize],) = &f;
let h: &(([isize],),) = &(*g,);
- //~^ ERROR `[isize]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
let f: Fat<[isize; 3]> = Fat { ptr: [5, 6, 7] };
let g: &Fat<[isize]> = &f;
let h: &Fat<Fat<[isize]>> = &Fat { ptr: *g };
- //~^ ERROR `[isize]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn test1<T: ?Sized + Foo>(t: &T) {
let u: &Foo = t;
- //~^ ERROR `T: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn test2<T: ?Sized + Foo>(t: &T) {
let v: &Foo = t as &Foo;
- //~^ ERROR `T: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn test3() {
let _: &[&Foo] = &["hi"];
- //~^ ERROR `str: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn test4(x: &[u8]) {
let _: &Foo = x as &Foo;
- //~^ ERROR `[u8]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() { }
trait Foo<T> : Sized { fn take(self, x: &T) { } } // Note: T is sized
impl Foo<[isize]> for usize { }
-//~^ ERROR `[isize]: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
impl Foo<isize> for [usize] { }
-//~^ ERROR `[usize]: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
pub fn main() { }
//~^ ERROR `A` cannot be shared between threads safely [E0277]
assert_send::<A>();
- //~^ ERROR the trait bound `A: std::marker::Send` is not satisfied
+ //~^ ERROR `A` cannot be sent between threads safely [E0277]
}
fn main() {
assert_sized::<A>();
- //~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
assert_sized::<Foo>();
- //~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
assert_sized::<Bar<A>>();
- //~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
assert_sized::<Bar<Bar<A>>>();
- //~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
--- /dev/null
+// gate-test-irrefutable_let_patterns
+
+// Copyright 2015 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(irrefutable_let_patterns)]
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR 15:12: 15:13: irrefutable if-let pattern [E0162]
+}
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::FnOnce(isize)>`
+ //~| found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::Fn(isize, isize)>`
+ //~| found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::FnMut() -> isize>`
+ //~| found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
needs_fn(1);
//~^ ERROR : std::ops::Fn<(isize,)>`
impl Foo for Baz {
fn bar(&mut self, other: &Foo) {}
//~^ ERROR method `bar` has an incompatible type for trait
- //~| expected type `fn(&mut Baz, &mut Foo)`
- //~| found type `fn(&mut Baz, &Foo)`
+ //~| expected type `fn(&mut Baz, &mut dyn Foo)`
+ //~| found type `fn(&mut Baz, &dyn Foo)`
}
fn main() {}
fn main() {
let _x = "test" as &::std::any::Any;
-//~^ ERROR `str: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
{
for
&mut something
-//~^ ERROR `[T]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
in arg2
{
}
fn main() {
(|| Box::new(*(&[0][..])))();
- //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn _create_render(_: &()) ->
AbstractRenderer
-//~^ ERROR: `AbstractRenderer + 'static: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
{
match 0 {
_ => unimplemented!()
type FuncType<'f> = Fn(&isize) -> isize + 'f;
fn ho_func(f: Option<FuncType>) {
- //~^ ERROR: `for<'r> std::ops::Fn(&'r isize) -> isize: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: `main` function is not allowed to have type parameters
+// error-pattern: `main` function is not allowed to have generic parameters
fn main<T>() { }
}
trait To {
- fn to<Dst>( //~ ERROR `Self: std::marker::Sized` is not satisfied
+ fn to<Dst>( //~ ERROR the size for value values of type
self
) -> <Dst as From<Self>>::Result where Dst: From<Self> {
From::from(self)
impl The {
fn iceman(c: Vec<[i32]>) {}
- //~^ ERROR the trait bound `[i32]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn changer<'a>(mut things: Box<Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
-//~^ ERROR the trait bound `std::iter::Iterator<Item=&mut u8>: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
}
fn main() {}
trait Foo {}
impl<'a> Foo for Foo+'a {}
-//~^ ERROR the object type `Foo + 'a` automatically implements the trait `Foo`
+//~^ ERROR the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
fn main() {}
fn main() {
foo::<HashMap<Rc<()>, Rc<()>>>();
- //~^ ERROR: `std::rc::Rc<()>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
}
struct Table {
rows: [[String]],
- //~^ ERROR the trait bound `[std::string::String]: std::marker::Sized` is not satisfied [E0277]
+ //~^ ERROR the size for value values of type
}
fn f(table: &Table) -> &[String] {
impl Struct {
pub fn function(funs: Vec<Fn() -> ()>) {}
- //~^ ERROR the trait bound `std::ops::Fn() + 'static: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() {}
fn main() {
static foo: Fn() -> u32 = || -> u32 {
- //~^ ERROR: mismatched types
- //~| ERROR: `std::ops::Fn() -> u32 + 'static: std::marker::Sized` is not satisfied
+ //~^ ERROR mismatched types
+ //~| ERROR the size for value values of type
0
};
}
#[repr(packed)]
pub struct Bad<T: ?Sized> {
- data: T, //~ ERROR `T: std::marker::Sized` is not satisfied
+ data: T, //~ ERROR the size for value values of type
}
fn main() {}
trait Foo {
const BAR: i32;
fn foo(self) -> &'static i32 {
- //~^ ERROR the trait bound `Self: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
&<Self>::BAR
}
}
fn main() {
size_of_copy::<Misc+Copy>();
//~^ ERROR only auto traits can be used as additional traits in a trait object
- //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
+ //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
}
enum E {
V([Box<E>]),
- //~^ ERROR the trait bound `[std::boxed::Box<E>]: std::marker::Sized` is not satisfied [E0277]
+ //~^ ERROR the size for value values of type
}
fn main() {}
// except according to those terms.
fn _test(ref _p: str) {}
-//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277]
+//~^ ERROR the size for value values of type
fn main() { }
fn main() {
let t : &Trait = &get_function()();
- //~^ ERROR cannot move a value of type Trait + 'static
+ //~^ ERROR cannot move a value of type (dyn Trait + 'static)
}
// except according to those terms.
pub fn example(ref s: str) {}
-//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
-//~| `str` does not have a constant size known at compile-time
-//~| the trait `std::marker::Sized` is not implemented for `str`
+//~^ ERROR the size for value values of type
fn main() {}
pub trait Foo {
fn baz(_: Self::Target) where Self: Deref {}
- //~^ ERROR `<Self as std::ops::Deref>::Target: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
pub fn f(_: ToString) {}
-//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
fn main() { }
#![feature(fn_traits)]
trait CallSingle<A, B> {
- fn call(&self, a: A) -> B where Self: Fn(A) -> B;
+ fn call(&self, a: A) -> B where Self: Sized, Self: Fn(A) -> B;
}
impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
fn main() {
(&5isize as &Foo).foo();
- //~^ ERROR: no method named `foo` found for type `&Foo` in the current scope
+ //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
}
}
fn new_struct(r: A+'static)
- -> Struct { //~^ ERROR `A + 'static: std::marker::Sized` is not satisfied
- //~^ ERROR `A + 'static: std::marker::Sized` is not satisfied
+ -> Struct { //~^ ERROR the size for value values of type
+ //~^ ERROR the size for value values of type
Struct { r: r }
}
fn main() {
let a = A {v: box B{v: None} as Box<Foo+Send>};
- //~^ ERROR `std::rc::Rc<std::cell::RefCell<A>>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<std::cell::RefCell<A>>` cannot be sent between threads safely
}
fn f<T>(val: T) {
let t: S<T> = S(marker::PhantomData);
let a = &t as &Gettable<T>;
- //~^ ERROR : std::marker::Send` is not satisfied
- //~^^ ERROR : std::marker::Copy` is not satisfied
+ //~^ ERROR `T` cannot be sent between threads safely
+ //~| ERROR : std::marker::Copy` is not satisfied
}
fn g<T>(val: T) {
let t: S<T> = S(marker::PhantomData);
let a: &Gettable<T> = &t;
- //~^ ERROR : std::marker::Send` is not satisfied
- //~^^ ERROR : std::marker::Copy` is not satisfied
+ //~^ ERROR `T` cannot be sent between threads safely
+ //~| ERROR : std::marker::Copy` is not satisfied
}
fn foo<'a>() {
fn main() {
let x = Rc::new(3);
bar(move|| foo(x));
- //~^ ERROR : std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<usize>` cannot be sent between threads safely
}
fn object_ref_with_static_bound_not_ok() {
assert_send::<&'static (Dummy+'static)>();
- //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn box_object_with_no_bound_not_ok<'a>() {
- assert_send::<Box<Dummy>>(); //~ ERROR : std::marker::Send` is not satisfied
+ assert_send::<Box<Dummy>>();
+ //~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
fn object_with_send_bound_ok() {
// careful with object types, who knows what they close over...
fn test51<'a>() {
assert_send::<&'a Dummy>();
- //~^ ERROR `Dummy + 'a` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
}
fn test52<'a>() {
assert_send::<&'a (Dummy+Sync)>();
// them not ok
fn test_71<'a>() {
assert_send::<Box<Dummy+'a>>();
- //~^ ERROR : std::marker::Send` is not satisfied
+ //~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely
}
fn main() { }
fn test50() {
assert_send::<&'static Dummy>();
- //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn test53() {
- assert_send::<Box<Dummy>>(); //~ ERROR : std::marker::Send` is not satisfied
+ assert_send::<Box<Dummy>>();
+ //~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
// ...unless they are properly bounded
// but not if they own a bad thing
fn test40() {
- assert_send::<Box<*mut u8>>(); //~ ERROR : std::marker::Send` is not satisfied
+ assert_send::<Box<*mut u8>>();
+ //~^ ERROR `*mut u8` cannot be sent between threads safely
}
fn main() { }
fn test71<'a>() {
assert_send::<*mut &'a isize>();
- //~^ ERROR `*mut &'a isize: std::marker::Send` is not satisfied
+ //~^ ERROR `*mut &'a isize` cannot be sent between threads safely
}
fn main() {
<Foo>::trait_deprecated_text(&foo);
<Foo as Trait>::trait_deprecated_text(&foo);
+ deprecated_future(); // Fine; no error.
+
deprecated_unstable();
//~^ ERROR use of unstable library feature
Trait::trait_deprecated_unstable(&foo);
#[rustc_deprecated(since = "1.0.0", reason = "text")]
pub fn deprecated_text() {}
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_deprecated(since = "99.99.99", reason = "text")]
+ pub fn deprecated_future() {}
+
#[unstable(feature = "test_feature", issue = "0")]
pub fn unstable() {}
#[unstable(feature = "test_feature", reason = "text", issue = "0")]
<Foo>::trait_deprecated_text(&foo);
<Foo as Trait>::trait_deprecated_text(&foo);
+ deprecated_future();
+
unstable();
foo.method_unstable();
Foo::method_unstable(&foo);
let x: Box<HashMap<isize, isize>> = box HashMap::new();
let x: Box<Map<isize, isize>> = x;
let y: Box<Map<usize, isize>> = Box::new(x);
- //~^ ERROR `std::boxed::Box<Map<isize, isize>>: Map<usize, isize>` is not satisfied
+ //~^ ERROR `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
}
let x = foo(Port(Rc::new(())));
thread::spawn(move|| {
- //~^ ERROR `std::rc::Rc<()>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
let y = x;
println!("{:?}", y);
});
fn main() {
let x = Foo::A(NoSend);
bar(x);
- //~^ ERROR `NoSend: std::marker::Send` is not satisfied
+ //~^ ERROR `NoSend` cannot be sent between threads safely
}
fn main() {
let x = Rc::new(5);
bar(x);
- //~^ ERROR `std::rc::Rc<{integer}>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<{integer}>` cannot be sent between threads safely
}
fn main() {
let x = Foo { a: 5 };
bar(x);
- //~^ ERROR `Foo: std::marker::Send` is not satisfied
+ //~^ ERROR `Foo` cannot be sent between threads safely
}
pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
intrinsics::atomic_load(p);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
intrinsics::atomic_store(p, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
intrinsics::atomic_xchg(p, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
intrinsics::atomic_cxchg(p, v, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
fn main() {
assert::<Rc<RefCell<i32>>>();
- //~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
- //~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
+ //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+ //~| ERROR the type `std::cell::UnsafeCell<usize>` may contain interior mutability and a
}
fn main() {
assert::<Arc<RefCell<i32>>>();
- //~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
- //~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
+ //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+ //~| ERROR the type `std::cell::UnsafeCell<usize>` may contain interior mutability and a
}
fn main() {
assert::<&RefCell<i32>>();
- //~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
- //~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
+ //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+ //~| ERROR the type `std::cell::UnsafeCell<usize>` may contain interior mutability and a
}
fn main() {
assert::<*mut RefCell<i32>>();
- //~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
- //~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
+ //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
+ //~| ERROR the type `std::cell::UnsafeCell<usize>` may contain interior mutability and a
}
fn assert<T: UnwindSafe + ?Sized>() {}
fn main() {
- assert::<&mut i32>(); //~ ERROR: UnwindSafe` is not satisfied
+ assert::<&mut i32>();
+ //~^ ERROR the type `&mut i32` may not be safely transferred across an unwind boundary
}
trait Foo {}
fn take_foo<F:Foo>(f: F) {}
fn take_object(f: Box<Foo>) { take_foo(f); }
-//~^ ERROR `std::boxed::Box<Foo>: Foo` is not satisfied
+//~^ ERROR `std::boxed::Box<dyn Foo>: Foo` is not satisfied
fn main() {}
}
fn use_bar(t: Box<Bar>) {
- t.bar() //~ ERROR cannot move a value of type Bar
+ t.bar() //~ ERROR cannot move a value of type (dyn Bar + 'static)
}
fn main() { }
pub macro mac1() {
let _: Box<PubTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PubTr<AssocTy=u8> + '<empty>` is private
- //~| ERROR type `priv_trait::PubTr<AssocTy=u8> + '<empty>` is private
+ //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
+ //~| ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PubTr<AssocTy=u8> + 'static` is private
+ //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private
trait InSignatureTr2: PubTr<AssocTy = u8> {}
//~^ ERROR trait `priv_trait::PrivTr` is private
}
pub macro mac2() {
let _: Box<PrivTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PrivTr<AssocTy=u8> + '<empty>` is private
- //~| ERROR type `priv_trait::PrivTr<AssocTy=u8> + '<empty>` is private
+ //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
+ //~| ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PrivTr<AssocTy=u8> + 'static` is private
+ //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private
trait InSignatureTr1: PrivTr<AssocTy = u8> {}
//~^ ERROR trait `priv_trait::PrivTr` is private
}
m::leak_anon2(); //~ ERROR type `m::Priv` is private
m::leak_anon3(); //~ ERROR type `m::Priv` is private
- m::leak_dyn1(); //~ ERROR type `m::Trait + 'static` is private
+ m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private
m::leak_dyn2(); //~ ERROR type `m::Priv` is private
m::leak_dyn3(); //~ ERROR type `m::Priv` is private
// Unsized type.
let arr: &[_] = &[1, 2, 3];
let range = *arr..;
- //~^ ERROR `[{integer}]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
struct AllTheRanges {
a: Range<usize>,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
b: RangeTo<usize>,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
c: RangeFrom<usize>,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
d: RangeFull,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
e: RangeInclusive<usize>,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
f: RangeToInclusive<usize>,
- //~^ ERROR PartialOrd
- //~^^ ERROR Ord
+ //~^ ERROR can't compare
+ //~| ERROR Ord
}
fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+// should-fail-irrefutable_let_patterns
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR irrefutable if-let pattern [E0162]
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(irrefutable_let_patterns)]
+
+// should-fail-irrefutable_let_patterns_with_gate
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR irrefutable if-let pattern [irrefutable_let_patterns]
+}
pub fn main() {
let s: &str = "hello";
- let c: u8 = s[4]; //~ ERROR `str: std::ops::Index<{integer}>` is not satisfied
+ let c: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}`
}
fn mutate(s: &mut str) {
s[1..2] = bot();
- //~^ ERROR `str: std::marker::Sized` is not satisfied
- //~| ERROR `str: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
+ //~| ERROR the size for value values of type
s[1usize] = bot();
- //~^ ERROR `str: std::ops::IndexMut<usize>` is not satisfied
+ //~^ ERROR the type `str` cannot be mutably indexed by `usize`
}
pub fn main() {}
//[normal]~| found type `fn() {foo::<'static>}`
<str as Foo<u8>>::bar;
- //[verbose]~^ ERROR `str: std::marker::Sized` is not satisfied
- //[normal]~^^ ERROR `str: std::marker::Sized` is not satisfied
+ //[verbose]~^ ERROR the size for value values of type
+ //[normal]~^^ ERROR the size for value values of type
}
// This should emit the less confusing error, not the more confusing one.
fn foo(_x: Foo + Send) {
- //~^ ERROR the trait bound `Foo + std::marker::Send + 'static: std::marker::Sized` is not
+ //~^ ERROR the size for value values of type
}
fn main() { }
// A, B, C are resolved as inherent items, their traits don't need to be in scope
C::A; //~ ERROR associated constant `A` is private
//~^ ERROR the trait `assoc_const::C` cannot be made into an object
- //~| ERROR the trait bound `assoc_const::C: assoc_const::A` is not satisfied
+ //~| ERROR the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
- //~^ ERROR the trait bound `assoc_const::C: assoc_const::B` is not satisfied
+ //~^ ERROR the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
C::C; // OK
}
impl !Send for TestType {}
Outer(TestType);
- //~^ ERROR `dummy::TestType: std::marker::Send` is not satisfied
- //~| ERROR `dummy::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `dummy::TestType` cannot be sent between threads safely
+ //~| ERROR `dummy::TestType` cannot be sent between threads safely
}
fn dummy1b() {
impl !Send for TestType {}
is_send(TestType);
- //~^ ERROR `dummy1b::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely
}
fn dummy1c() {
impl !Send for TestType {}
is_send((8, TestType));
- //~^ ERROR `dummy1c::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely
}
fn dummy2() {
impl !Send for TestType {}
is_send(Box::new(TestType));
- //~^ ERROR `dummy2::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `dummy2::TestType` cannot be sent between threads safely
}
fn dummy3() {
impl !Send for TestType {}
is_send(Box::new(Outer2(TestType)));
- //~^ ERROR `dummy3::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `dummy3::TestType` cannot be sent between threads safely
}
fn main() {
// This will complain about a missing Send impl because `Sync` is implement *just*
// for T that are `Send`. Look at #20366 and #19950
is_sync(Outer2(TestType));
- //~^ ERROR `main::TestType: std::marker::Send` is not satisfied
+ //~^ ERROR `main::TestType` cannot be sent between threads safely
}
impl CompareToInts for i64 { }
fn with_obj(c: &CompareToInts) -> bool {
- c.same_as(22) //~ ERROR `CompareToInts: CompareTo<i32>` is not satisfied
+ c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
}
fn with_trait<C:CompareToInts>(c: &C) -> bool {
}
fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
- CompareToInts::same_as(c, 22) //~ ERROR `CompareToInts: CompareTo<i32>` is not satisfied
+ CompareToInts::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
}
fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
// unsize trait
let x: &Bar = &Bar;
- let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo`
- let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo`
+ let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo`
+ let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo`
let _: &Foo = x;
let _: *const Foo = x;
let x: &mut Bar = &mut Bar;
- let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo`
- let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo`
+ let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo`
+ let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo`
let _: &mut Foo = x;
let _: *mut Foo = x;
let x: Box<Bar> = Box::new(Bar);
- let _ = x as Box<Foo>; //~ERROR trivial cast: `std::boxed::Box<Bar>` as `std::boxed::Box<Foo>`
+ let _ = x as Box<Foo>; //~ERROR `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
let x: Box<Bar> = Box::new(Bar);
let _: Box<Foo> = x;
// functions
fn baz(_x: i32) {}
- let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&std::ops::Fn(i32)`
+ let _ = &baz as &Fn(i32); //~ERROR `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
let _: &Fn(i32) = &baz;
let x = |_x: i32| {};
let _ = &x as &Fn(i32); //~ERROR trivial cast
//~^ ERROR mismatched types
//~| Perhaps two different versions of crate `crate_a1`
//~| expected trait `main::a::Bar`
- //~| expected type `std::boxed::Box<main::a::Bar + 'static>`
- //~| found type `std::boxed::Box<main::a::Bar>`
+ //~| expected type `std::boxed::Box<(dyn main::a::Bar + 'static)>`
+ //~| found type `std::boxed::Box<dyn main::a::Bar>`
}
}
let x: i32 = 5;
let y = x as MyAdd<i32>;
//~^ ERROR E0038
- //~| ERROR cast to unsized type: `i32` as `MyAdd<i32>`
+ //~| ERROR cast to unsized type: `i32` as `dyn MyAdd<i32>`
}
fn main() {
is_send::<MySendable>();
is_send::<MyNotSendable>();
- //~^ ERROR `MyNotSendable: std::marker::Send` is not satisfied
+ //~^ ERROR `MyNotSendable` cannot be sent between threads safely
}
#![feature(untagged_unions)]
union U {
- a: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ a: str,
+ //~^ ERROR the size for value values of type
+
b: u8,
}
union W {
a: u8,
- b: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ b: str,
+ //~^ ERROR the size for value values of type
}
fn main() {}
// except according to those terms.
fn bar<T: Sized>() { }
-fn foo<T: ?Sized>() { bar::<T>() } //~ ERROR `T: std::marker::Sized` is not satisfied
+fn foo<T: ?Sized>() { bar::<T>() }
+//~^ ERROR the size for value values of type
fn main() { }
enum Foo<U> { FooSome(U), FooNone }
fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
-//~^ ERROR `T: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
//
// Not OK: `T` is not sized.
struct S5<Y>(Y);
-impl<X: ?Sized> S5<X> { //~ ERROR E0277
+impl<X: ?Sized> S5<X> {
+ //~^ ERROR the size for value values of type
}
fn main() { }
struct Foo<T> { data: T }
fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
-//~^ ERROR `T: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
//
// Not OK: `T` is not sized.
struct Bar<T: ?Sized> { data: T }
fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
-//~^ ERROR `T: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
//
// Not OK: `Bar<T>` is not sized, but it should be.
struct S5<Y>(Y);
-impl<X: ?Sized> T3<X> for S5<X> { //~ ERROR E0277
+impl<X: ?Sized> T3<X> for S5<X> {
+ //~^ ERROR the size for value values of type
}
fn main() { }
}
struct S4<Y: ?Sized>(Box<Y>);
impl<X: ?Sized> T2<X> for S4<X> {
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() { }
// Unbounded.
fn f1<X: ?Sized>(x: &X) {
f2::<X>(x);
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn f2<X>(x: &X) {
}
}
fn f3<X: ?Sized + T>(x: &X) {
f4::<X>(x);
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn f4<X: T>(x: &X) {
}
fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
f5(x1);
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
f6(x2); // ok
}
// Test some tuples.
fn f9<X: ?Sized>(x1: Box<S<X>>) {
f5(&(*x1, 34));
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn f10<X: ?Sized>(x1: Box<S<X>>) {
f5(&(32, *x1));
- //~^ ERROR `X: std::marker::Sized` is not satisfied
- //~| ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
+ //~| ERROR the size for value values of type
}
pub fn main() {
// Test `?Sized` types not allowed in fields (except the last one).
struct S1<X: ?Sized> {
- f1: X, //~ ERROR `X: std::marker::Sized` is not satisfied
+ f1: X,
+ //~^ ERROR the size for value values of type
f2: isize,
}
struct S2<X: ?Sized> {
f: isize,
- g: X, //~ ERROR `X: std::marker::Sized` is not satisfied
+ g: X,
+ //~^ ERROR the size for value values of type
h: isize,
}
struct S3 {
- f: str, //~ ERROR `str: std::marker::Sized` is not satisfied
+ f: str,
+ //~^ ERROR the size for value values of type
g: [usize]
}
struct S4 {
- f: [u8], //~ ERROR `[u8]: std::marker::Sized` is not satisfied
+ f: [u8],
+ //~^ ERROR the size for value values of type
g: usize
}
enum E<X: ?Sized> {
- V1(X, isize), //~ERROR `X: std::marker::Sized` is not satisfied
+ V1(X, isize),
+ //~^ ERROR the size for value values of type
}
enum F<X: ?Sized> {
- V2{f1: X, f: isize}, //~ERROR `X: std::marker::Sized` is not satisfied
+ V2{f1: X, f: isize},
+ //~^ ERROR the size for value values of type
}
pub fn main() {
fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
let _: W; // <-- this is OK, no bindings created, no initializer.
- let _: (isize, (X, isize)); //~ERROR `X: std::marker::Sized` is not satisfie
- let y: Y; //~ERROR `Y: std::marker::Sized` is not satisfied
- let y: (isize, (Z, usize)); //~ERROR `Z: std::marker::Sized` is not satisfied
+ let _: (isize, (X, isize));
+ //~^ ERROR the size for value values of type
+ let y: Y;
+ //~^ ERROR the size for value values of type
+ let y: (isize, (Z, usize));
+ //~^ ERROR the size for value values of type
}
fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
- let y: X; //~ERROR `X: std::marker::Sized` is not satisfied
- let y: (isize, (Y, isize)); //~ERROR `Y: std::marker::Sized` is not satisfied
+ let y: X;
+ //~^ ERROR the size for value values of type
+ let y: (isize, (Y, isize));
+ //~^ ERROR the size for value values of type
}
fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
- let y: X = *x1; //~ERROR `X: std::marker::Sized` is not satisfied
- let y = *x2; //~ERROR `X: std::marker::Sized` is not satisfied
- let (y, z) = (*x3, 4); //~ERROR `X: std::marker::Sized` is not satisfied
+ let y: X = *x1;
+ //~^ ERROR the size for value values of type
+ let y = *x2;
+ //~^ ERROR the size for value values of type
+ let (y, z) = (*x3, 4);
+ //~^ ERROR the size for value values of type
}
fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
- let y: X = *x1; //~ERROR `X: std::marker::Sized` is not satisfied
- let y = *x2; //~ERROR `X: std::marker::Sized` is not satisfied
- let (y, z) = (*x3, 4); //~ERROR `X: std::marker::Sized` is not satisfied
+ let y: X = *x1;
+ //~^ ERROR the size for value values of type
+ let y = *x2;
+ //~^ ERROR the size for value values of type
+ let (y, z) = (*x3, 4);
+ //~^ ERROR the size for value values of type
}
-fn g1<X: ?Sized>(x: X) {} //~ERROR `X: std::marker::Sized` is not satisfied
-fn g2<X: ?Sized + T>(x: X) {} //~ERROR `X: std::marker::Sized` is not satisfied
+fn g1<X: ?Sized>(x: X) {}
+//~^ ERROR the size for value values of type
+fn g2<X: ?Sized + T>(x: X) {}
+//~^ ERROR the size for value values of type
pub fn main() {
}
struct S3<Y: ?Sized>(Box<Y>);
impl<X: ?Sized + T> T1<X> for S3<X> {
- //~^ ERROR `X: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() { }
struct Bar<T:Eq+?Sized> { value: Box<T> }
trait Foo {
- fn bar(&self) where Bar<Self>: Copy;
+ fn bar(&self) where Self: Sized, Bar<Self>: Copy;
//~^ ERROR E0277
//
// Here, Eq ought to be implemented.
// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 {
// let mut _0: i32;
// ...
-// let _2: &'15_0rs D;
+// let _2: &'16_0rs D;
// ...
// let mut _3: i32;
// bb0: {
// StorageLive(_2);
-// _2 = &'15_0rs (*(_1.0: &'19s D));
+// _2 = &'16_0rs (*(_1.0: &'19s D));
// StorageLive(_3);
// _3 = ((*_2).0: i32);
// _0 = move _3;
// StorageDead(_3);
-// EndRegion('15_0rs);
+// EndRegion('16_0rs);
// StorageDead(_2);
// return;
// }
// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 {
// let mut _0: i32;
// ...
-// let _2: &'15_0rs D;
+// let _2: &'16_0rs D;
// ...
// let mut _3: i32;
// bb0: {
// StorageLive(_2);
-// _2 = &'15_0rs (_1.0: D);
+// _2 = &'16_0rs (_1.0: D);
// StorageLive(_3);
// _3 = ((*_2).0: i32);
// _0 = move _3;
// StorageDead(_3);
-// EndRegion('15_0rs);
+// EndRegion('16_0rs);
// StorageDead(_2);
// drop(_1) -> [return: bb2, unwind: bb1];
// }
// bb0: {
// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]);
// StorageLive(_3);
-// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_2): i32]);
+// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))), [(*_2): i32]);
// _3 = &ReErased (*_2);
-// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })) (imm)]);
+// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })) (imm)]);
// StorageLive(_4);
// _4 = (*_3);
// _0 = move _4;
// StorageDead(_4);
-// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })));
+// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })));
// StorageDead(_3);
// return;
// }
// StorageLive(_3);
// StorageLive(_4);
// StorageLive(_5);
-// Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]);
+// Validate(Suspend(ReScope(Node(ItemLocalId(12)))), [(*_2): i32]);
// _5 = &ReErased mut (*_2);
-// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(9)))]);
+// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(12)))]);
// _4 = move _5 as *mut i32 (Misc);
// _3 = move _4;
-// EndRegion(ReScope(Node(ItemLocalId(9))));
+// EndRegion(ReScope(Node(ItemLocalId(12))));
// StorageDead(_4);
// StorageDead(_5);
// Validate(Release, [_0: bool, _3: *mut i32]);
fn foo() {}
#[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or
fn main() {}
impl Foo {
#[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or
fn main() {}
use std::ops::RangeToInclusive;
fn return_range_to() -> RangeToInclusive<i32> {
- return ...1; //~ERROR `...` syntax cannot be used in expressions
- //~^HELP Use `..` if you need an exclusive range (a < b)
- //~^^HELP or `..=` if you need an inclusive range (a <= b)
+ return ...1; //~ERROR unexpected token: `...`
+ //~^HELP use `..` for an exclusive range
+ //~^^HELP or `..=` for an inclusive range
}
pub fn main() {
- let x = ...0; //~ERROR `...` syntax cannot be used in expressions
- //~^HELP Use `..` if you need an exclusive range (a < b)
- //~^^HELP or `..=` if you need an inclusive range (a <= b)
+ let x = ...0; //~ERROR unexpected token: `...`
+ //~^HELP use `..` for an exclusive range
+ //~^^HELP or `..=` for an inclusive range
- let x = 5...5; //~ERROR `...` syntax cannot be used in expressions
- //~^HELP Use `..` if you need an exclusive range (a < b)
- //~^^HELP or `..=` if you need an inclusive range (a <= b)
+ let x = 5...5; //~ERROR unexpected token: `...`
+ //~^HELP use `..` for an exclusive range
+ //~^^HELP or `..=` for an inclusive range
- for _ in 0...1 {} //~ERROR `...` syntax cannot be used in expressions
- //~^HELP Use `..` if you need an exclusive range (a < b)
- //~^^HELP or `..=` if you need an inclusive range (a <= b)
+ for _ in 0...1 {} //~ERROR unexpected token: `...`
+ //~^HELP use `..` for an exclusive range
+ //~^^HELP or `..=` for an inclusive range
}
-
impl S {
static fn f() {}
}
-//~^^ ERROR expected one of `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`
+//~^^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`,
macro_rules! bah {
($a:expr) => ($a)
- //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
+ //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
}
trait bar {
trait Foo {
pub const Foo: u32;
- //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+ //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
}
fn main() {}
trait Foo {
pub type Foo;
- //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+ //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
}
fn main() {}
trait Foo {
pub fn foo();
- //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
+ //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
}
fn main() {}
});
iter_exprs(depth - 1, &mut |e| g(
ExprKind::Closure(CaptureBy::Value,
+ IsAsync::NotAsync,
Movability::Movable,
decl.clone(),
e,
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(irrefutable_let_patterns)]
+
+// must-compile-successfully-irrefutable_let_patterns_with_gate
+#[allow(irrefutable_let_patterns)]
+fn main() {
+ if let _ = 5 {}
+
+ while let _ = 5 {
+ break;
+ }
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition=2018
+
+#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+
+use std::boxed::PinBox;
+use std::mem::PinMut;
+use std::future::Future;
+use std::sync::{
+ Arc,
+ atomic::{self, AtomicUsize},
+};
+use std::task::{
+ Context, Poll, Wake,
+ Executor, TaskObj, SpawnObjError,
+ local_waker_from_nonlocal,
+};
+
+struct Counter {
+ wakes: AtomicUsize,
+}
+
+impl Wake for Counter {
+ fn wake(this: &Arc<Self>) {
+ this.wakes.fetch_add(1, atomic::Ordering::SeqCst);
+ }
+}
+
+struct NoopExecutor;
+impl Executor for NoopExecutor {
+ fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> {
+ Ok(())
+ }
+}
+
+struct WakeOnceThenComplete(bool);
+
+fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
+
+impl Future for WakeOnceThenComplete {
+ type Output = ();
+ fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
+ if self.0 {
+ Poll::Ready(())
+ } else {
+ cx.waker().wake();
+ self.0 = true;
+ Poll::Pending
+ }
+ }
+}
+
+fn async_block(x: u8) -> impl Future<Output = u8> {
+ async move {
+ await!(wake_and_yield_once());
+ x
+ }
+}
+
+fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
+ async move {
+ let future = async {
+ await!(wake_and_yield_once());
+ x
+ };
+ await!(future)
+ }
+}
+
+fn async_closure(x: u8) -> impl Future<Output = u8> {
+ (async move |x: u8| -> u8 {
+ await!(wake_and_yield_once());
+ x
+ })(x)
+}
+
+async fn async_fn(x: u8) -> u8 {
+ await!(wake_and_yield_once());
+ x
+}
+
+async fn async_fn_with_borrow(x: &u8) -> u8 {
+ await!(wake_and_yield_once());
+ *x
+}
+
+fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
+ async move {
+ await!(async_fn_with_borrow(&y))
+ }
+}
+
+unsafe async fn unsafe_async_fn(x: u8) -> u8 {
+ await!(wake_and_yield_once());
+ x
+}
+
+struct Foo;
+
+trait Bar {
+ fn foo() {}
+}
+
+impl Foo {
+ async fn async_method(x: u8) -> u8 {
+ unsafe {
+ await!(unsafe_async_fn(x))
+ }
+ }
+}
+
+fn test_future_yields_once_then_returns<F, Fut>(f: F)
+where
+ F: FnOnce(u8) -> Fut,
+ Fut: Future<Output = u8>,
+{
+ let mut fut = PinBox::new(f(9));
+ let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
+ let waker = local_waker_from_nonlocal(counter.clone());
+ let executor = &mut NoopExecutor;
+ let cx = &mut Context::new(&waker, executor);
+
+ assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Pending, fut.as_pin_mut().poll(cx));
+ assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
+ assert_eq!(Poll::Ready(9), fut.as_pin_mut().poll(cx));
+}
+
+fn main() {
+ macro_rules! test {
+ ($($fn_name:ident,)*) => { $(
+ test_future_yields_once_then_returns($fn_name);
+ )* }
+ }
+
+ test! {
+ async_block,
+ async_nonmove_block,
+ async_closure,
+ async_fn,
+ async_fn_with_internal_borrow,
+ }
+}
std::intrinsics::type_name::<NT>(),
// DST
std::intrinsics::type_name::<DST>()
- )}, ("[u8]", "str", "std::marker::Send", "NT", "DST"));
+ )}, ("[u8]", "str", "dyn std::marker::Send", "NT", "DST"));
}
struct S05_PolyTraitRef(S06_TraitRef);
struct S06_TraitRef(S07_Path);
struct S07_Path(Vec<S08_PathSegment>);
-struct S08_PathSegment(S09_PathParameters);
-struct S09_PathParameters(P<S10_ParenthesizedParameterData>);
+struct S08_PathSegment(S09_GenericArgs);
+struct S09_GenericArgs(P<S10_ParenthesizedParameterData>);
struct S10_ParenthesizedParameterData(Option<P<S11_Ty>>);
struct S11_Ty(P<S12_Expr>);
struct S12_Expr(P<S13_Block>);
+++ /dev/null
-// Copyright 2015 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.
-
-// Test that we do not ICE when a default method implementation has
-// requirements (in this case, `Self : Baz`) that do not hold for some
-// specific impl (in this case, `Foo : Bar`). This causes problems
-// only when building a vtable, because that goes along and
-// instantiates all the methods, even those that could not otherwise
-// be called.
-
-// pretty-expanded FIXME #23616
-
-struct Foo {
- x: i32
-}
-
-trait Bar {
- fn bar(&self) where Self : Baz { self.baz(); }
-}
-
-trait Baz {
- fn baz(&self);
-}
-
-impl Bar for Foo {
-}
-
-fn main() {
- let x: &Bar = &Foo { x: 22 };
-}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+const PATH_DOT: &[u8] = &[b'.'];
+
+fn match_slice(element: &[u8]) {
+ match element {
+ &[] => {}
+ PATH_DOT => {}
+ _ => {}
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that it is possible to create a global allocator in a submodule, rather than in the crate
+// root.
+
+#![feature(alloc, allocator_api, global_allocator)]
+
+extern crate alloc;
+
+use std::{
+ alloc::{GlobalAlloc, Layout},
+ ptr,
+};
+
+struct MyAlloc;
+
+unsafe impl GlobalAlloc for MyAlloc {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ ptr::null_mut()
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {}
+}
+
+mod submod {
+ use super::MyAlloc;
+
+ #[global_allocator]
+ static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
+}
+
+fn main() {}
--- /dev/null
+error: `global_allocator` cannot be used in submodules
+ --> $DIR/allocator-submodule.rs:37:5
+ |
+LL | static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch
| ^^ -------------- found signature of `fn((), ()) -> _`
| |
- | expected signature of `for<'r> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>) -> _`
+ | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _`
|
note: required by `g1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:33:1
LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch
| ^^ -------------- found signature of `fn((), ()) -> _`
| |
- | expected signature of `for<'s> fn(&'s (), std::boxed::Box<for<'r> std::ops::Fn(&'r ()) + 'static>) -> _`
+ | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
|
note: required by `g3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
| ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
| |
- | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<for<'t0> std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
+ | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
|
note: required by `h1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:39:1
LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
| ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
| |
- | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
+ | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
|
note: required by `h2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
| ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo` has a non-standard `self` type
- = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<Foo>>` for `std::boxed::Box<usize>`
+ = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
error: aborting due to 2 previous errors
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition=2018
+
+#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+
+use std::ops::Add;
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+//~^ ERROR multiple different lifetimes used in arguments of `async fn`
+
+async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
+ _: impl for<'a> Add<&'a u8>,
+ _: impl for<'b> Add<&'b u8>,
+ _: &'c u8,
+) {}
+
+async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+//~^ ERROR multiple elided lifetimes used
+//~^^ ERROR missing lifetime specifier
+
+fn main() {}
--- /dev/null
+error[E0709]: multiple different lifetimes used in arguments of `async fn`
+ --> $DIR/async-fn-multiple-lifetimes.rs:17:49
+ |
+LL | async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+ | --^^^^^^^^^-- different lifetime here
+ | |
+ | first lifetime here
+ |
+ = help: `async fn` can only accept borrowed values with identical lifetimes
+
+error[E0707]: multiple elided lifetimes used in arguments of `async fn`
+ --> $DIR/async-fn-multiple-lifetimes.rs:26:39
+ |
+LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+ | -^^^^^^^- different lifetime here
+ | |
+ | first lifetime here
+ |
+ = help: consider giving these arguments named lifetimes
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/async-fn-multiple-lifetimes.rs:26:39
+ |
+LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+ | ^ expected lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_` or `_`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0106, E0707, E0709.
+For more information about an error, try `rustc --explain E0106`.
LL | let _y = a.y; //~ ERROR use of moved
| ^^^ value used here after move
|
- = note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `a.y`
--> $DIR/borrowck-box-insensitivity.rs:108:14
LL | let _y = a.y; //~ ERROR use of collaterally moved
| ^^^ value used here after move
|
- = note: move occurs because `a.y` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+ = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
//~| ERROR use of moved value: `(maybe as std::prelude::v1::Some).0` (Ast) [E0382]
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
//~| ERROR use of moved value: `maybe` (Mir) [E0382]
- //~| ERROR use of moved value: `maybe.0` (Mir) [E0382]
+ //~| ERROR use of moved value (Mir) [E0382]
//~| ERROR borrow of moved value: `maybe` (Mir) [E0382]
}
}
LL | | }
| |_________^ value used here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:9
LL | | }
| |_________^ value borrowed here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
| | value moved here
| value used here after move
|
- = note: move occurs because `maybe` has type `std::option::Option<std::vec::Vec<bool>>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
-error[E0382]: use of moved value: `maybe.0` (Mir)
+error[E0382]: use of moved value (Mir)
--> $DIR/issue-41962.rs:17:21
|
LL | if let Some(thing) = maybe {
| ^^^^^ value moved here in previous iteration of loop
|
- = note: move occurs because `maybe.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+ = note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/issue-51415.rs:16:47
+ |
+LL | let opt = a.iter().enumerate().find(|(_, &s)| {
+ | ^ cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// Copyright 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.
+
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+ let a = vec![String::from("a")];
+ let opt = a.iter().enumerate().find(|(_, &s)| {
+ //~^ ERROR cannot move out
+ *s == String::from("d")
+ }).map(|(i, _)| i);
+ println!("{:?}", opt);
+}
--- /dev/null
+error[E0507]: cannot move out of borrowed content
+ --> $DIR/issue-51415.rs:16:46
+ |
+LL | let opt = a.iter().enumerate().find(|(_, &s)| {
+ | ^-
+ | ||
+ | |hint: to prevent move, use `ref s` or `ref mut s`
+ | cannot move out of borrowed content
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
-error[E0620]: cast to unsized type: `&{integer}` as `std::marker::Send`
+error[E0620]: cast to unsized type: `&{integer}` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:12:5
|
LL | &1 as Send; //~ ERROR cast to unsized
| |
| help: try casting to a reference instead: `&Send`
-error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `std::marker::Send`
+error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:13:5
|
LL | Box::new(1) as Send; //~ ERROR cast to unsized
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+struct Foo<T> where Box<T>: Clone {
+ _x: std::marker::PhantomData<T>,
+}
+
+fn main() { }
--- /dev/null
+error: program clause dump
+ --> $DIR/lower_struct.rs:13:1
+ |
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: FromEnv(T: std::marker::Sized) :- FromEnv(Foo<T>).
+ = note: FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<T>).
+ = note: WellFormed(Foo<T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone).
+
+error: aborting due to previous error
+
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
= note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
= note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
= note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
+ = note: ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
+
+ while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
+
+ while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
+}
--- /dev/null
+error[E0268]: `continue` outside of loop
+ --> $DIR/closure-array-break-length.rs:12:13
+ |
+LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
+ | ^^^^^^^^ cannot break outside of a loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+ --> $DIR/closure-array-break-length.rs:14:19
+ |
+LL | while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
+ | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+ --> $DIR/closure-array-break-length.rs:16:19
+ |
+LL | while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
+ | ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0268, E0590.
+For more information about an error, try `rustc --explain E0268`.
-error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
+error[E0703]: invalid ABI: found `路濫狼á́́`
--> $DIR/unicode.rs:11:8
|
LL | extern "路濫狼á́́" fn foo() {} //~ ERROR invalid ABI
- | ^^^^^^^^^
+ | ^^^^^^^^^ invalid ABI
+ |
+ = help: valid ABIs: cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0703`.
use std::fmt::Debug;
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
-//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
const CONST_FOO: str = *"foo";
-//~^ ERROR `str: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
-//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
static STATIC_BAR: str = *"bar";
-//~^ ERROR `str: std::marker::Sized` is not satisfied
+//~^ ERROR the size for value values of type
fn main() {
println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-error[E0277]: the trait bound `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:13:29
|
LL | const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
- | ^^^^^^^^^^^^^^^^^^^^^^ `std::fmt::Debug + std::marker::Sync + 'static` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Sync + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/const-unsized.rs:16:24
|
LL | const CONST_FOO: str = *"foo";
- | ^^^^^^ `str` does not have a constant size known at compile-time
+ | ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
-error[E0277]: the trait bound `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:19:31
|
LL | static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
- | ^^^^^^^^^^^^^^^^^^^^^^ `std::fmt::Debug + std::marker::Sync + 'static` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Sync + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/const-unsized.rs:22:26
|
LL | static STATIC_BAR: str = *"bar";
- | ^^^^^^ `str` does not have a constant size known at compile-time
+ | ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
error: aborting due to 4 previous errors
LL | type G = 'static + (Send)::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
|
- = note: specify the type using the syntax `<std::marker::Send + 'static as Trait>::AssocTy`
+ = note: specify the type using the syntax `<(dyn std::marker::Send + 'static) as Trait>::AssocTy`
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:43:10
LL | type H = Fn(u8) -> (u8)::Output;
| ^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
|
- = note: specify the type using the syntax `<std::ops::Fn(u8) -> u8 + 'static as Trait>::Output`
+ = note: specify the type using the syntax `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output`
error: aborting due to 15 previous errors
LL | | Z = { 2 + 3 }; //~ ERROR expected one of
| |____^ missing `fn`, `type`, or `const`
-error: expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
--> $DIR/issue-40006.rs:23:18
|
LL | Z = { 2 + 3 }; //~ ERROR expected one of
- | ^ expected one of `const`, `extern`, `fn`, `type`, `unsafe`, or `}` here
+ | ^ expected one of 7 possible tokens here
error: expected one of `!` or `::`, found `(`
--> $DIR/issue-40006.rs:24:9
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
- if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
+ if passes_ident!(async) == 1 {}
if passes_ident!(r#async) == 1 {} // OK
module::async(); //~ ERROR expected identifier, found reserved keyword `async`
module::r#async(); // OK
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
-error: expected expression, found reserved keyword `async`
- --> $DIR/edition-keywords-2018-2015-parsing.rs:28:22
+error: expected one of `move`, `|`, or `||`, found `<eof>`
+ --> <passes_ident macros>:1:22
|
-LL | if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
- | ^^^^^ expected expression
+LL | ( $ i : ident ) => ( $ i )
+ | ^^^ expected one of `move`, `|`, or `||` here
error: aborting due to 5 previous errors
r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
r#async = consumes_async_raw!(r#async); // OK
- if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
+ if passes_ident!(async) == 1 {}
if passes_ident!(r#async) == 1 {} // OK
module::async(); //~ ERROR expected identifier, found reserved keyword `async`
module::r#async(); // OK
LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async`
| ^^^^^
-error: expected expression, found reserved keyword `async`
- --> $DIR/edition-keywords-2018-2018-parsing.rs:28:22
+error: expected one of `move`, `|`, or `||`, found `<eof>`
+ --> <passes_ident macros>:1:22
|
-LL | if passes_ident!(async) == 1 {} //~ ERROR expected expression, found reserved keyword `async`
- | ^^^^^ expected expression
+LL | ( $ i : ident ) => ( $ i )
+ | ^^^ expected one of `move`, `|`, or `||` here
error: aborting due to 5 previous errors
|
= note: method `foo` has no receiver
-error[E0033]: type `&SomeTrait` cannot be dereferenced
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033-teach.rs:23:9
|
LL | let &invalid = trait_obj;
- | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced
+ | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
|
= note: This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer.
|
= note: method `foo` has no receiver
-error[E0033]: type `&SomeTrait` cannot be dereferenced
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033.rs:21:9
|
LL | let &invalid = trait_obj;
- | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced
+ | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
error: aborting due to 3 previous errors
--> $DIR/E0110.rs:11:14
|
LL | type X = u32<'static>; //~ ERROR E0110
- | ^^^^^^^ lifetime parameter not allowed on this type
+ | ^^^^^^^ lifetime parameter not allowed
error: aborting due to previous error
-error[E0131]: `main` function is not allowed to have type parameters
+error[E0131]: `main` function is not allowed to have generic parameters
--> $DIR/E0131.rs:11:8
|
LL | fn main<T>() {
- | ^^^ `main` cannot have type parameters
+ | ^^^ `main` cannot have generic parameters
error: aborting due to previous error
fn main() {
is_send::<Foo>();
- //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
+ //~^ ERROR `*const u8` cannot be sent between threads safely
}
-error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
+error[E0277]: `*const u8` cannot be sent between threads safely
--> $DIR/E0277-2.rs:26:5
|
LL | is_send::<Foo>();
}
fn f(p: Path) { }
-//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
+//~^ ERROR the size for value values of type
fn main() {
some_func(5i32);
-error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
+error[E0277]: the size for value values of type `[u8]` cannot be known at compilation time
--> $DIR/E0277.rs:23:6
|
LL | fn f(p: Path) { }
- | ^ `[u8]` does not have a constant size known at compile-time
+ | ^ doesn't have a size known at compile-time
|
= help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `std::path::Path`
= note: all local variables must have a statically known size
-error[E0558]: export_name attribute has invalid format
+error[E0558]: `export_name` attribute has invalid format
--> $DIR/E0558.rs:11:1
|
LL | #[export_name]
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[export_name="\0foo"] //~ ERROR E0648
+pub fn bar() {}
+
+fn main() {}
--- /dev/null
+error[E0648]: `export_name` may not contain null characters
+ --> $DIR/E0648.rs:11:1
+ |
+LL | #[export_name="/0foo"] //~ ERROR E0648
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0648`.
-> Box<for<'a> Id<impl Lt<'a>>>
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
{
- ()
+ () //~ ERROR mismatched types
}
struct Foo;
-> Box<for<'a> Id<impl Lt<'a>>>
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
{
- ()
+ () //~ ERROR mismatched types
}
}
LL | -> Box<for<'a> Id<impl Lt<'a>>>
| ^^
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/E0657.rs:22:5
+ |
+LL | () //~ ERROR mismatched types
+ | ^^ expected struct `std::boxed::Box`, found ()
+ |
+ = note: expected type `std::boxed::Box<(dyn Id<_> + 'static)>`
+ found type `()`
+
+error[E0308]: mismatched types
+ --> $DIR/E0657.rs:31:9
+ |
+LL | () //~ ERROR mismatched types
+ | ^^ expected struct `std::boxed::Box`, found ()
+ |
+ = note: expected type `std::boxed::Box<(dyn Id<_> + 'static)>`
+ found type `()`
+
+error: aborting due to 4 previous errors
-For more information about this error, try `rustc --explain E0657`.
+Some errors occurred: E0308, E0657.
+For more information about an error, try `rustc --explain E0308`.
LL | q as *const [i32]; //~ ERROR cannot cast
| ^^^^^^^^^^^^^^^^^
-error[E0606]: casting `usize` as `*mut Trait + 'static` is invalid
+error[E0606]: casting `usize` as `*mut (dyn Trait + 'static)` is invalid
--> $DIR/fat-ptr-cast.rs:32:37
|
LL | let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR casting
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition=2015
+
+#![feature(futures_api)]
+
+async fn foo() {} //~ ERROR async fn is unstable
+
+fn main() {
+ let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
+ let _ = async || {}; //~ ERROR cannot find value `async` in this scope
+}
--- /dev/null
+error[E0422]: cannot find struct, variant or union type `async` in this scope
+ --> $DIR/feature-gate-async-await-2015-edition.rs:18:13
+ |
+LL | let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
+ | ^^^^^ not found in this scope
+
+error[E0425]: cannot find value `async` in this scope
+ --> $DIR/feature-gate-async-await-2015-edition.rs:19:13
+ |
+LL | let _ = async || {}; //~ ERROR cannot find value `async` in this scope
+ | ^^^^^ not found in this scope
+
+error[E0658]: async fn is unstable (see issue #50547)
+ --> $DIR/feature-gate-async-await-2015-edition.rs:15:1
+ |
+LL | async fn foo() {} //~ ERROR async fn is unstable
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(async_await)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0422, E0425, E0658.
+For more information about an error, try `rustc --explain E0422`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition=2018
+#![feature(futures_api)]
+
+async fn foo() {} //~ ERROR async fn is unstable
+
+fn main() {
+ let _ = async {}; //~ ERROR async blocks are unstable
+ let _ = async || {}; //~ ERROR async closures are unstable
+}
--- /dev/null
+error[E0658]: async fn is unstable (see issue #50547)
+ --> $DIR/feature-gate-async-await.rs:14:1
+ |
+LL | async fn foo() {} //~ ERROR async fn is unstable
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(async_await)] to the crate attributes to enable
+
+error[E0658]: async blocks are unstable (see issue #50547)
+ --> $DIR/feature-gate-async-await.rs:17:13
+ |
+LL | let _ = async {}; //~ ERROR async blocks are unstable
+ | ^^^^^^^^
+ |
+ = help: add #![feature(async_await)] to the crate attributes to enable
+
+error[E0658]: async closures are unstable (see issue #50547)
+ --> $DIR/feature-gate-async-await.rs:18:13
+ |
+LL | let _ = async || {}; //~ ERROR async closures are unstable
+ | ^^^^^^^^^^^
+ |
+ = help: add #![feature(async_await)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/feature-gate-trivial_bounds.rs:62:1
|
LL | struct TwoStrs(str, str) where str: Sized; //~ ERROR
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `str` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: the trait bound `A + 'static: std::marker::Sized` is not satisfied in `Dst<A + 'static>`
+error[E0277]: the size for value values of type `(dyn A + 'static)` cannot be known at compilation time
--> $DIR/feature-gate-trivial_bounds.rs:65:1
|
LL | / fn unsized_local() where Dst<A>: Sized { //~ ERROR
LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
LL | | }
- | |_^ `A + 'static` does not have a constant size known at compile-time
+ | |_^ doesn't have a size known at compile-time
|
- = help: within `Dst<A + 'static>`, the trait `std::marker::Sized` is not implemented for `A + 'static`
- = note: required because it appears within the type `Dst<A + 'static>`
+ = help: within `Dst<(dyn A + 'static)>`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
+ = note: required because it appears within the type `Dst<(dyn A + 'static)>`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/feature-gate-trivial_bounds.rs:69:1
|
LL | / fn return_str() -> str where str: Sized { //~ ERROR
LL | | *"Sized".to_string().into_boxed_str()
LL | | }
- | |_^ `str` does not have a constant size known at compile-time
+ | |_^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/send-sync.rs:18:5
|
LL | send(format_args!("{:?}", c)); //~ ERROR E0277
- | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+ | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
- = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static`
- = note: required because it appears within the type `std::marker::PhantomData<*mut std::ops::Fn() + 'static>`
+ = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+ = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
LL | fn send<T: Send>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/send-sync.rs:19:5
|
LL | sync(format_args!("{:?}", c)); //~ ERROR E0277
- | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+ | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
- = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static`
- = note: required because it appears within the type `std::marker::PhantomData<*mut std::ops::Fn() + 'static>`
+ = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+ = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
fn main() {
let s = String::from("foo");
- let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ let mut gen = move || {
+ //~^ ERROR the size for value values of type
yield s[..];
};
- unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ unsafe { gen.resume(); }
+ //~^ ERROR the size for value values of type
}
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/sized-yield.rs:17:26
|
-LL | let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+LL | let mut gen = move || {
| __________________________^
+LL | | //~^ ERROR the size for value values of type
LL | | yield s[..];
LL | | };
- | |____^ `str` does not have a constant size known at compile-time
+ | |____^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: the yield type of a generator must have a statically known size
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
- --> $DIR/sized-yield.rs:20:17
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
+ --> $DIR/sized-yield.rs:21:17
|
-LL | unsafe { gen.resume(); } //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
- | ^^^^^^ `str` does not have a constant size known at compile-time
+LL | unsafe { gen.resume(); }
+ | ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
error: aborting due to 2 previous errors
//~^ ERROR cycle detected
//~| ERROR cycle detected
send(cycle2().clone());
- //~^ ERROR Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<std::string::String>` cannot be sent between threads safely
Rc::new(Cell::new(5))
}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle
-error[E0277]: the trait bound `std::rc::Rc<std::string::String>: std::marker::Send` is not satisfied in `impl std::clone::Clone`
+error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
--> $DIR/auto-trait-leak.rs:27:5
|
LL | send(cycle2().clone());
fn main() {
send(before());
- //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
send(after());
- //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+ //~^ ERROR `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
}
// Deferred path, main has to wait until typeck finishes,
-error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
+error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
--> $DIR/auto-trait-leak2.rs:25:5
|
LL | send(before());
LL | fn send<T: Send>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied in `impl std::ops::Fn<(i32,)>`
+error[E0277]: `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
--> $DIR/auto-trait-leak2.rs:28:5
|
LL | send(after());
fn projection_with_named_trait_inside_path_is_disallowed()
-> <::std::ops::Range<impl Debug> as Iterator>::Item
//~^ ERROR `impl Trait` is not allowed in path parameters
-{
- (1i32..100).next().unwrap()
+//~| ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
+{ //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
+ (1i32..100).next().unwrap() //~ ERROR mismatched types
}
fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
| ^^^^^^^^^^
error[E0667]: `impl Trait` is not allowed in path parameters
- --> $DIR/impl_trait_projections.rs:42:29
+ --> $DIR/impl_trait_projections.rs:43:29
|
LL | -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
| ^^^^^^^^^^
|
= note: specify the type using the syntax `<impl std::iter::Iterator as Trait>::Item`
-error: aborting due to 5 previous errors
+error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
+ --> $DIR/impl_trait_projections.rs:38:1
+ |
+LL | / { //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
+LL | | (1i32..100).next().unwrap() //~ ERROR mismatched types
+LL | | }
+ | |_^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug`
+ |
+ = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<impl std::fmt::Debug>`
+
+error[E0308]: mismatched types
+ --> $DIR/impl_trait_projections.rs:39:5
+ |
+LL | (1i32..100).next().unwrap() //~ ERROR mismatched types
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected anonymized type, found i32
+ |
+ = note: expected type `impl std::fmt::Debug`
+ found type `i32`
+
+error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
+ --> $DIR/impl_trait_projections.rs:35:8
+ |
+LL | -> <::std::ops::Range<impl Debug> as Iterator>::Item
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug`
+ |
+ = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<impl std::fmt::Debug>`
+
+error: aborting due to 8 previous errors
-Some errors occurred: E0223, E0667.
+Some errors occurred: E0223, E0277, E0308, E0667.
For more information about an error, try `rustc --explain E0223`.
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
- expected std::boxed::Box<std::fmt::Debug>
- found std::boxed::Box<std::fmt::Debug + 'a>
+ expected std::boxed::Box<dyn std::fmt::Debug>
+ found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the types are compatible:
expected StaticTrait
| |_____^
= note: ...but the lifetime must also be valid for the static lifetime...
= note: ...so that the method type is compatible with trait:
- expected fn(&Struct) -> &Trait + 'static
- found fn(&Struct) -> &Trait
+ expected fn(&Struct) -> &(dyn Trait + 'static)
+ found fn(&Struct) -> &dyn Trait
error: aborting due to previous error
use std::panic::catch_unwind;
fn main() {
let mut x = Cell::new(22);
- catch_unwind(|| { x.set(23); }); //~ ERROR the trait bound
+ catch_unwind(|| { x.set(23); });
+ //~^ ERROR the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a
}
-error[E0277]: the trait bound `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied in `std::cell::Cell<i32>`
+error[E0277]: the type `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
--> $DIR/interior-mutability.rs:15:5
|
-LL | catch_unwind(|| { x.set(23); }); //~ ERROR the trait bound
- | ^^^^^^^^^^^^ the type std::cell::UnsafeCell<i32> may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+LL | catch_unwind(|| { x.set(23); });
+ | ^^^^^^^^^^^^ `std::cell::UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
|
= help: within `std::cell::Cell<i32>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<i32>`
= note: required because it appears within the type `std::cell::Cell<i32>`
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
let _bar = Box::new(1_usize) as std::fmt::Debug;
- //~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `std::fmt::Debug`
+ //~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
let _baz = 1_usize as std::fmt::Debug;
- //~^ ERROR cast to unsized type: `usize` as `std::fmt::Debug`
+ //~^ ERROR cast to unsized type: `usize` as `dyn std::fmt::Debug`
let _quux = [1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`
LL | let _foo = &[1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `std::fmt::Debug`
+error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:15:16
|
LL | let _bar = Box::new(1_usize) as std::fmt::Debug;
| |
| help: try casting to a `Box` instead: `Box<std::fmt::Debug>`
-error[E0620]: cast to unsized type: `usize` as `std::fmt::Debug`
+error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:18:16
|
LL | let _baz = 1_usize as std::fmt::Debug;
--- /dev/null
+// 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.
+
+// run-pass
+// run-rustfix
+
+#![allow(non_snake_case)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[derive(Copy, Clone)]
+enum Foo {
+ Bar,
+ Baz
+}
+
+impl Foo {
+ fn foo(&self) {
+ match self {
+ &
+Foo::Bar if true
+//~^ WARN pattern binding `Bar` is named the same as one of the variants of the type `Foo`
+=> println!("bar"),
+ &
+Foo::Baz if false
+//~^ WARN pattern binding `Baz` is named the same as one of the variants of the type `Foo`
+=> println!("baz"),
+_ => ()
+ }
+ }
+}
+
+fn main() {}
// except according to those terms.
// run-pass
+// run-rustfix
#![allow(non_snake_case)]
#![allow(dead_code)]
warning[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo`
- --> $DIR/issue-19100.rs:27:1
+ --> $DIR/issue-19100.rs:28:1
|
LL | Bar if true
- | ^^^
- |
- = help: if you meant to match on a variant, consider making the path in the pattern qualified: `Foo::Bar`
+ | ^^^ help: to match on the variant, qualify the path: `Foo::Bar`
warning[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo`
- --> $DIR/issue-19100.rs:31:1
+ --> $DIR/issue-19100.rs:32:1
|
LL | Baz if false
- | ^^^
- |
- = help: if you meant to match on a variant, consider making the path in the pattern qualified: `Foo::Baz`
+ | ^^^ help: to match on the variant, qualify the path: `Foo::Baz`
| ^ the trait `Array` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
- = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&Array>` for `&T`
+ = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
error: aborting due to 2 previous errors
--> $DIR/issue-30302.rs:23:9
|
LL | Nil => true,
- | ^^^
- |
- = help: if you meant to match on a variant, consider making the path in the pattern qualified: `Stack::Nil`
+ | ^^^ help: to match on the variant, qualify the path: `Stack::Nil`
error: unreachable pattern
--> $DIR/issue-30302.rs:25:9
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ enum Foo {
+ Drop = assert_eq!(1, 1)
+ }
+}
--- /dev/null
+error[E0317]: if may be missing an else clause
+ --> $DIR/issue-50577.rs:13:16
+ |
+LL | Drop = assert_eq!(1, 1)
+ | ^^^^^^^^^^^^^^^^ expected (), found isize
+ |
+ = note: expected type `()`
+ found type `isize`
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ |y: Vec<[(); for x in 0..2 {}]>| {};
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-50585.rs:12:18
+ |
+LL | fn main() {
+ | - expected `()` because of default return type
+LL | |y: Vec<[(); for x in 0..2 {}]>| {};
+ | ^^^^^^^^^^^^^^^^ expected usize, found ()
+ |
+ = note: expected type `usize`
+ found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(where_clauses_object_safety)]
+
+trait Trait {}
+
+trait X {
+ fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object
+ //~^ WARN this was previously accepted by the compiler but is being phased out
+}
+
+impl X for () {
+ fn foo(&self) {}
+}
+
+impl Trait for dyn X {}
+
+pub fn main() {
+ // Check that this does not segfault.
+ <X as X>::foo(&());
+}
--- /dev/null
+error: the trait `X` cannot be made into an object
+ --> $DIR/issue-50781.rs:16:5
+ |
+LL | fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/issue-50781.rs:11:9
+ |
+LL | #![deny(where_clauses_object_safety)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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 #51443 <https://github.com/rust-lang/rust/issues/51443>
+ = note: method `foo` references the `Self` type in where clauses
+
+error: aborting due to previous error
+
// except according to those terms.
fn main<'a>() { }
- //~^ ERROR `main` function is not allowed to have lifetime parameters [E0131]
+ //~^ ERROR `main` function is not allowed to have generic parameters [E0131]
-error[E0131]: `main` function is not allowed to have lifetime parameters
+error[E0131]: `main` function is not allowed to have generic parameters
--> $DIR/issue-51022.rs:11:8
|
LL | fn main<'a>() { }
- | ^^^^ `main` cannot have lifetime parameters
+ | ^^^^ `main` cannot have generic parameters
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ |_: [_; return || {}] | {}
+ //~^ ERROR return statement outside of function body
+}
+
+fn foo() {
+ [(); return || {}];
+ //~^ ERROR return statement outside of function body
+}
--- /dev/null
+error[E0572]: return statement outside of function body
+ --> $DIR/issue-51714.rs:12:14
+ |
+LL | |_: [_; return || {}] | {}
+ | ^^^^^^^^^^^^
+
+error[E0572]: return statement outside of function body
+ --> $DIR/issue-51714.rs:17:10
+ |
+LL | [(); return || {}];
+ | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0572`.
pub fn char_type(p: char); //~ ERROR uses type `char`
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
- pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
+ pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
LL | pub fn u128_type(p: u128); //~ ERROR uses type `u128`
| ^^^^
-error: `extern` block uses type `std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
+error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
--> $DIR/lint-ctypes.rs:62:26
|
-LL | pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
+LL | pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
| ^^^^^^
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(trivial_casts, trivial_numeric_casts)]
+#![feature(type_ascription)]
+
+fn main() {
+ let lugubrious = 12i32 as i32;
+ //~^ ERROR trivial numeric cast
+ let haunted: &u32 = &99;
+ let _ = haunted as *const u32;
+ //~^ ERROR trivial cast
+}
--- /dev/null
+error: trivial numeric cast: `i32` as `i32`
+ --> $DIR/trivial-casts-featuring-type-ascription.rs:15:22
+ |
+LL | let lugubrious = 12i32 as i32;
+ | ^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/trivial-casts-featuring-type-ascription.rs:11:24
+ |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
+
+error: trivial cast: `&u32` as `*const u32`
+ --> $DIR/trivial-casts-featuring-type-ascription.rs:18:13
+ |
+LL | let _ = haunted as *const u32;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/trivial-casts-featuring-type-ascription.rs:11:9
+ |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+ | ^^^^^^^^^^^^^
+ = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(trivial_casts, trivial_numeric_casts)]
+
+fn main() {
+ let lugubrious = 12i32 as i32;
+ //~^ ERROR trivial numeric cast
+ let haunted: &u32 = &99;
+ let _ = haunted as *const u32;
+ //~^ ERROR trivial cast
+}
--- /dev/null
+error: trivial numeric cast: `i32` as `i32`
+ --> $DIR/trivial-casts.rs:14:22
+ |
+LL | let lugubrious = 12i32 as i32;
+ | ^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/trivial-casts.rs:11:24
+ |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: trivial cast: `&u32` as `*const u32`
+ --> $DIR/trivial-casts.rs:17:13
+ |
+LL | let _ = haunted as *const u32;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/trivial-casts.rs:11:9
+ |
+LL | #![deny(trivial_casts, trivial_numeric_casts)]
+ | ^^^^^^^^^^^^^
+ = help: cast can be replaced by coercion; this might require a temporary variable
+
+error: aborting due to 2 previous errors
+
LL | | };
| |_____^ expected bound lifetime parameter 'a, found concrete lifetime
|
- = note: expected type `&for<'a, 'b> Foo<&'a u8, &'b u8>`
- found type `&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>`
= note: this was previously accepted by the compiler but has been phased out
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
2 as usize - Some(1); //~ ERROR cannot subtract `std::option::Option<{integer}>` from `usize`
3 * (); //~ ERROR cannot multiply `()` to `{integer}`
4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
- 5 < String::new(); //~ ERROR is not satisfied
- 6 == Ok(1); //~ ERROR is not satisfied
+ 5 < String::new(); //~ ERROR can't compare `{integer}` with `std::string::String`
+ 6 == Ok(1); //~ ERROR can't compare `{integer}` with `std::result::Result<{integer}, _>`
}
|
= help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
-error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
+error[E0277]: can't compare `{integer}` with `std::string::String`
--> $DIR/binops.rs:16:7
|
-LL | 5 < String::new(); //~ ERROR is not satisfied
- | ^ can't compare `{integer}` with `std::string::String`
+LL | 5 < String::new(); //~ ERROR can't compare `{integer}` with `std::string::String`
+ | ^ no implementation for `{integer} < std::string::String` and `{integer} > std::string::String`
|
= help: the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
-error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
+error[E0277]: can't compare `{integer}` with `std::result::Result<{integer}, _>`
--> $DIR/binops.rs:17:7
|
-LL | 6 == Ok(1); //~ ERROR is not satisfied
- | ^^ can't compare `{integer}` with `std::result::Result<{integer}, _>`
+LL | 6 == Ok(1); //~ ERROR can't compare `{integer}` with `std::result::Result<{integer}, _>`
+ | ^^ no implementation for `{integer} == std::result::Result<{integer}, _>`
|
= help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
let _ = 42usize as *const [u8]; //~ ERROR is invalid
let _ = v as *const [u8]; //~ ERROR cannot cast
- let _ = fat_v as *const Foo; //~ ERROR is not satisfied
+ let _ = fat_v as *const Foo; //~ ERROR the size for value values of type
let _ = foo as *const str; //~ ERROR is invalid
let _ = foo as *mut str; //~ ERROR is invalid
let _ = main as *mut str; //~ ERROR is invalid
let _ = fat_sv as usize; //~ ERROR is invalid
let a : *const str = "hello";
- let _ = a as *const Foo; //~ ERROR is not satisfied
+ let _ = a as *const Foo; //~ ERROR the size for value values of type
// check no error cascade
let _ = main.f as *const u32; //~ ERROR no field
LL | let _ = v as *const [u8]; //~ ERROR cannot cast
| ^^^^^^^^^^^^^^^^
-error[E0606]: casting `&Foo` as `*const str` is invalid
+error[E0606]: casting `&dyn Foo` as `*const str` is invalid
--> $DIR/cast-rfc0401.rs:64:13
|
LL | let _ = foo as *const str; //~ ERROR is invalid
| ^^^^^^^^^^^^^^^^^
-error[E0606]: casting `&Foo` as `*mut str` is invalid
+error[E0606]: casting `&dyn Foo` as `*mut str` is invalid
--> $DIR/cast-rfc0401.rs:65:13
|
LL | let _ = foo as *mut str; //~ ERROR is invalid
|
= help: cast through a thin pointer first
-error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const dyn Foo` as `*const [u16]` is invalid
--> $DIR/cast-rfc0401.rs:78:13
|
LL | let _ = cf as *const [u16]; //~ ERROR is invalid
|
= note: vtable kinds may not match
-error[E0606]: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid
--> $DIR/cast-rfc0401.rs:79:13
|
LL | let _ = cf as *const Bar; //~ ERROR is invalid
|
= note: vtable kinds may not match
-error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `[u8]` cannot be known at compilation time
--> $DIR/cast-rfc0401.rs:63:13
|
-LL | let _ = fat_v as *const Foo; //~ ERROR is not satisfied
- | ^^^^^ `[u8]` does not have a constant size known at compile-time
+LL | let _ = fat_v as *const Foo; //~ ERROR the size for value values of type
+ | ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
- = note: required for the cast to the object type `Foo`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
+ = note: required for the cast to the object type `dyn Foo`
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/cast-rfc0401.rs:72:13
|
-LL | let _ = a as *const Foo; //~ ERROR is not satisfied
- | ^ `str` does not have a constant size known at compile-time
+LL | let _ = a as *const Foo; //~ ERROR the size for value values of type
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
- = note: required for the cast to the object type `Foo`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
+ = note: required for the cast to the object type `dyn Foo`
error[E0606]: casting `&{float}` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:81:30
--> $DIR/issue-19109.rs:14:5
|
LL | fn function(t: &mut Trait) {
- | - help: try adding a return type: `-> *mut Trait`
+ | - help: try adding a return type: `-> *mut dyn Trait`
LL | t as *mut Trait
| ^^^^^^^^^^^^^^^ expected (), found *-ptr
|
= note: expected type `()`
- found type `*mut Trait`
+ found type `*mut dyn Trait`
error: aborting due to previous error
LL | a(x); //~ ERROR mismatched types [E0308]
| ^ expected trait `Foo + std::marker::Send`, found trait `Foo`
|
- = note: expected type `std::boxed::Box<Foo + std::marker::Send + 'static>`
- found type `std::boxed::Box<Foo + 'static>`
+ = note: expected type `std::boxed::Box<(dyn Foo + std::marker::Send + 'static)>`
+ found type `std::boxed::Box<(dyn Foo + 'static)>`
error: aborting due to previous error
LL | touch(&x); //~ ERROR use of partially moved value: `x`
| ^^ value borrowed here after move
|
- = note: move occurs because `x` has type `Foo<std::string::String>`, which does not implement the `Copy` trait
+ = note: move occurs because `x.f` has type `std::string::String`, which does not implement the `Copy` trait
error: aborting due to previous error
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+#![feature(nll)]
+
+fn main() {
+ let range = 0..1;
+ let r = range;
+ let x = range.start;
+ //~^ ERROR use of moved value: `range.start` [E0382]
+}
--- /dev/null
+error[E0382]: use of moved value: `range.start`
+ --> $DIR/issue-51512.rs:17:13
+ |
+LL | let r = range;
+ | ----- value moved here
+LL | let x = range.start;
+ | ^^^^^^^^^^^ value used here after move
+ |
+ = note: move occurs because `range` has type `std::ops::Range<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
]
= note: number of external vids: 3
= note: where <T as std::iter::Iterator>::Item: '_#2r
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
]
= note: number of external vids: 3
= note: where <T as std::iter::Iterator>::Item: '_#2r
'_#2r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
]
= note: number of external vids: 4
= note: where <T as std::iter::Iterator>::Item: '_#3r
'_#2r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
]
= note: number of external vids: 4
= note: where <T as std::iter::Iterator>::Item: '_#3r
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<std::fmt::Debug + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>
]
= note: number of external vids: 3
= note: where T: '_#2r
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --edition=2018
+
+#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]
+
+fn main() {
+ let _ = async |x: u8| {};
+ //~^ ERROR `async` non-`move` closures with arguments are not currently supported
+}
--- /dev/null
+error[E0708]: `async` non-`move` closures with arguments are not currently supported
+ --> $DIR/no-args-non-move-async-closure.rs:16:13
+ |
+LL | let _ = async |x: u8| {};
+ | ^^^^^^^^^^^^^
+ |
+ = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0708`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that two closures cannot simultaneously have mutable
+// access to the variable, whether that mutable access be used
+// for direct assignment or for taking mutable ref. Issue #6801.
+
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented(
+ message="the message"
+ label="the label"
+)]
+trait T {}
+//~^^^ ERROR expected one of `)` or `,`, found `label`
--- /dev/null
+error: expected one of `)` or `,`, found `label`
+ --> $DIR/expected-comma-found-token.rs:19:5
+ |
+LL | message="the message"
+ | - expected one of `)` or `,` here
+LL | label="the label"
+ | ^^^^^ unexpected token
+
+error: aborting due to previous error
+
-error[E0277]: the trait bound `&T: std::cmp::PartialEq<T>` is not satisfied
+error[E0277]: can't compare `&T` with `T`
--> $DIR/partialeq_help.rs:12:7
|
LL | a == b; //~ ERROR E0277
- | ^^ can't compare `&T` with `T`
+ | ^^ no implementation for `&T == T`
|
= help: the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
= help: consider adding a `where &T: std::cmp::PartialEq<T>` bound
-error: incorrect visibility restriction
+error[E0704]: incorrect visibility restriction
--> $DIR/pub-restricted.rs:15:6
|
LL | pub (a) fn afn() {} //~ incorrect visibility restriction
`pub(super)`: visible only in the current module's parent
`pub(in path::to::module)`: visible only on the specified path
-error: incorrect visibility restriction
+error[E0704]: incorrect visibility restriction
--> $DIR/pub-restricted.rs:16:6
|
LL | pub (b) fn bfn() {} //~ incorrect visibility restriction
`pub(super)`: visible only in the current module's parent
`pub(in path::to::module)`: visible only on the specified path
-error: incorrect visibility restriction
+error[E0704]: incorrect visibility restriction
--> $DIR/pub-restricted.rs:32:14
|
LL | pub (a) invalid: usize, //~ incorrect visibility restriction
`pub(super)`: visible only in the current module's parent
`pub(in path::to::module)`: visible only on the specified path
-error: incorrect visibility restriction
+error[E0704]: incorrect visibility restriction
--> $DIR/pub-restricted.rs:41:6
|
LL | pub (xyz) fn xyz() {} //~ incorrect visibility restriction
error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0704`.
trait I {}
type K = I+'static;
-fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
+fn foo(_x: K) {}
+//~^ ERROR the size for value values of type
fn main() {}
-error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `(dyn I + 'static)` cannot be known at compilation time
--> $DIR/issue-5035-2.rs:14:8
|
-LL | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
- | ^^ `I + 'static` does not have a constant size known at compile-time
+LL | fn foo(_x: K) {}
+ | ^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: all local variables must have a statically known size
error: aborting due to previous error
--> $DIR/collections.rs:33:50
|
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
- | ^^^^^ lifetime parameter not allowed on this type
+ | ^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/collections.rs:59:50
|
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
- | ^^^^^ lifetime parameter not allowed on this type
+ | ^^^^^ lifetime parameter not allowed
error: aborting due to 5 previous errors
--> $DIR/construct_with_other_type.rs:26:46
|
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/construct_with_other_type.rs:26:63
|
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/construct_with_other_type.rs:34:40
|
LL | type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error: aborting due to 3 previous errors
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47
|
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
|
LL | + Deref<Target = Self::Item<'b>>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
- | ^^^^^^^^^^^ lifetime parameter not allowed on this type
+ | ^^^^^^^^^^^ lifetime parameter not allowed
error: aborting due to 5 previous errors
--> $DIR/iterable.rs:20:47
|
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:49:53
|
LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:54:60
|
LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:23:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:32:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:43:41
|
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error: aborting due to 6 previous errors
+error[E0110]: lifetime parameters are not allowed on this type
+ --> $DIR/parameter_number_and_kind.rs:26:27
+ |
+LL | type FOk<T> = Self::E<'static, T>;
+ | ^^^^^^^ lifetime parameter not allowed
+
error[E0109]: type parameters are not allowed on this type
--> $DIR/parameter_number_and_kind.rs:26:36
|
| ^ type parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:26:27
+ --> $DIR/parameter_number_and_kind.rs:29:26
|
-LL | type FOk<T> = Self::E<'static, T>;
- | ^^^^^^^ lifetime parameter not allowed on this type
+LL | type FErr1 = Self::E<'static, 'static>; // Error
+ | ^^^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:29:26
+ --> $DIR/parameter_number_and_kind.rs:31:29
|
-LL | type FErr1 = Self::E<'static, 'static>; // Error
- | ^^^^^^^ lifetime parameter not allowed on this type
+LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
+ | ^^^^^^^ lifetime parameter not allowed
error[E0109]: type parameters are not allowed on this type
--> $DIR/parameter_number_and_kind.rs:31:38
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
| ^ type parameter not allowed
-error[E0110]: lifetime parameters are not allowed on this type
- --> $DIR/parameter_number_and_kind.rs:31:29
- |
-LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
- | ^^^^^^^ lifetime parameter not allowed on this type
-
error: aborting due to 5 previous errors
Some errors occurred: E0109, E0110.
--> $DIR/streaming_iterator.rs:27:41
|
LL | bar: <T as StreamingIterator>::Item<'static>,
- | ^^^^^^^ lifetime parameter not allowed on this type
+ | ^^^^^^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/streaming_iterator.rs:35:64
|
LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/streaming_iterator.rs:21:48
|
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/streaming_iterator.rs:47:37
|
LL | type Item<'a> = (usize, I::Item<'a>);
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/streaming_iterator.rs:49:48
|
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
- | ^^ lifetime parameter not allowed on this type
+ | ^^ lifetime parameter not allowed
error: aborting due to 5 previous errors
--> $DIR/fn-types.rs:19:10
|
LL | a: for<'a> fn(&'a u32), //~ ERROR `'a` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/fn-types.rs:11:9
|
LL | fn a(x: &'a u32, y: &'b u32) {
| ^^
+ | |
+ | this lifetime...
+ | ...is used only here
|
note: lint level defined here
--> $DIR/one-use-in-fn-argument-in-band.rs:12:9
|
LL | fn a(x: &'a u32, y: &'b u32) {
| ^^
+ | |
+ | this lifetime...
+ | ...is used only here
error: aborting due to 2 previous errors
--> $DIR/one-use-in-fn-argument.rs:18:6
|
LL | fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/one-use-in-fn-argument.rs:11:9
--> $DIR/one-use-in-inherent-impl-header.rs:24:6
|
LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/one-use-in-inherent-impl-header.rs:11:9
--> $DIR/one-use-in-inherent-method-argument.rs:22:19
|
LL | fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/one-use-in-inherent-method-argument.rs:11:9
--> $DIR/one-use-in-inherent-method-argument.rs:21:6
|
LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
error: aborting due to 2 previous errors
--> $DIR/one-use-in-inherent-method-return.rs:22:6
|
LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/one-use-in-inherent-method-return.rs:11:9
--> $DIR/one-use-in-trait-method-argument.rs:25:13
|
LL | fn next<'g>(&'g mut self) -> Option<Self::Item> { //~ ERROR `'g` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/one-use-in-trait-method-argument.rs:14:9
--> $DIR/two-uses-in-inherent-method-argument-and-return.rs:22:6
|
LL | impl<'f> Foo<'f> { //~ ERROR `'f` only used once
- | ^^
+ | ^^ -- ...is used only here
+ | |
+ | this lifetime...
|
note: lint level defined here
--> $DIR/two-uses-in-inherent-method-argument-and-return.rs:14:9
--> $DIR/borrowck-object-mutability.rs:19:5
|
LL | fn borrowed_receiver(x: &Foo) {
- | ---- help: consider changing this to be a mutable reference: `&mut Foo`
+ | ---- help: consider changing this to be a mutable reference: `&mut dyn Foo`
LL | x.borrowed();
LL | x.borrowed_mut(); //~ ERROR cannot borrow
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+// Issue #50974
+
+struct Foo {
+ a: u8,
+ b: u8
+}
+
+fn main() {
+ let bar = Foo {
+ a: 0,,
+ //~^ ERROR expected identifier
+ b: 42
+ };
+}
+
--- /dev/null
+error: expected identifier, found `,`
+ --> $DIR/struct-duplicate-comma.rs:22:14
+ |
+LL | let bar = Foo {
+ | --- while parsing this struct
+LL | a: 0,,
+ | ^
+ | |
+ | expected identifier
+ | help: remove this comma
+
+error: aborting due to previous error
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! mac {
+ ($ident:ident) => { let $ident = 42; }
+}
|
= help: did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`?
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<std::boxed::FnBox<(), Output=u32> + 'static>>` in the current scope
+error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output=u32> + 'static)>>` in the current scope
--> $DIR/issue-2392.rs:72:24
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let _redemptive = 1...21;
+ //~^ ERROR unexpected token
+}
--- /dev/null
+error: unexpected token: `...`
+ --> $DIR/dotdotdot-expr.rs:12:24
+ |
+LL | let _redemptive = 1...21;
+ | ^^^
+help: use `..` for an exclusive range
+ |
+LL | let _redemptive = 1..21;
+ | ^^
+help: or `..=` for an inclusive range
+ |
+LL | let _redemptive = 1..=21;
+ | ^^^
+
+error: aborting due to previous error
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// aux-build:macro-in-other-crate.rs
+
+#[macro_use] extern crate macro_in_other_crate;
+
+macro_rules! local_mac {
+ ($ident:ident) => { let $ident = 42; }
+}
+
fn main() {
let x = 2.0.neg();
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
+
let y = 2.0;
let x = y.neg();
//~^ ERROR can't call method `neg` on ambiguous numeric type `{float}`
println!("{:?}", x);
+
+ for i in 0..100 {
+ println!("{}", i.pow(2));
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+ }
+
+ local_mac!(local_bar);
+ local_bar.pow(2);
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
+}
+
+fn qux() {
+ mac!(bar);
+ bar.pow(2);
+ //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}`
}
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
- --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
+ --> $DIR/method-on-ambiguous-numeric-type.rs:20:17
|
LL | let x = 2.0.neg();
| ^^^
| ^^^^^^^
error[E0689]: can't call method `neg` on ambiguous numeric type `{float}`
- --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
+ --> $DIR/method-on-ambiguous-numeric-type.rs:24:15
|
LL | let x = y.neg();
| ^^^
LL | let y: f32 = 2.0;
| ^^^^^^
-error: aborting due to 2 previous errors
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:29:26
+ |
+LL | for i in 0..100 {
+ | - you must specify a type for this binding, like `i32`
+LL | println!("{}", i.pow(2));
+ | ^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:34:15
+ |
+LL | local_bar.pow(2);
+ | ^^^
+help: you must specify a type for this binding, like `i32`
+ |
+LL | ($ident:ident) => { let $ident: i32 = 42; }
+ | ^^^^^^^^^^^
+
+error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}`
+ --> $DIR/method-on-ambiguous-numeric-type.rs:40:9
+ |
+LL | mac!(bar);
+ | ---------- you must specify a type for this binding, like `i32`
+LL | bar.pow(2);
+ | ^^^
+ |
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0689`.
let u: &str = if true { s[..2] } else { s };
//~^ ERROR mismatched types
let v = s[..2];
- //~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
let w: &str = s[..2];
//~^ ERROR mismatched types
}
= note: expected type `&str`
found type `str`
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/str-array-assignment.rs:17:7
|
LL | let v = s[..2];
| ^ ------ help: consider borrowing here: `&s[..2]`
| |
- | `str` does not have a constant size known at compile-time
+ | doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: all local variables must have a statically known size
error[E0308]: mismatched types
-error: expected one of `(`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}`
+error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}`
--> $DIR/issue-41155.rs:13:1
|
LL | pub
- | - expected one of 7 possible tokens here
+ | - expected one of 8 possible tokens here
LL | } //~ ERROR expected one of
| ^ unexpected token
fn check<T: Iterator, U: ?Sized>() {
// suggest a where-clause, if needed
mem::size_of::<U>();
- //~^ ERROR `U: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
mem::size_of::<Misc<U>>();
- //~^ ERROR `U: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
// ... even if T occurs as a type parameter
// ... and also not if the error is not related to the type
mem::size_of::<[T]>();
- //~^ ERROR `[T]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
mem::size_of::<[&U]>();
- //~^ ERROR `[&U]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
fn main() {
-error[E0277]: the trait bound `U: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `U` cannot be known at compilation time
--> $DIR/trait-suggest-where-clause.rs:17:5
|
LL | mem::size_of::<U>();
- | ^^^^^^^^^^^^^^^^^ `U` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `U`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where U: std::marker::Sized` bound
= note: required by `std::mem::size_of`
-error[E0277]: the trait bound `U: std::marker::Sized` is not satisfied in `Misc<U>`
+error[E0277]: the size for value values of type `U` cannot be known at compilation time
--> $DIR/trait-suggest-where-clause.rs:20:5
|
LL | mem::size_of::<Misc<U>>();
- | ^^^^^^^^^^^^^^^^^^^^^^^ `U` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where U: std::marker::Sized` bound
= note: required because it appears within the type `Misc<U>`
= note: required by `std::mem::size_of`
|
= note: required by `std::convert::From::from`
-error[E0277]: the trait bound `[T]: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `[T]` cannot be known at compilation time
--> $DIR/trait-suggest-where-clause.rs:38:5
|
LL | mem::size_of::<[T]>();
- | ^^^^^^^^^^^^^^^^^^^ `[T]` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[T]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required by `std::mem::size_of`
-error[E0277]: the trait bound `[&U]: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `[&U]` cannot be known at compilation time
--> $DIR/trait-suggest-where-clause.rs:41:5
|
LL | mem::size_of::<[&U]>();
- | ^^^^^^^^^^^^^^^^^^^^ `[&U]` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[&U]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required by `std::mem::size_of`
error: aborting due to 7 previous errors
|
= note: #[warn(trivial_bounds)] on by default
-warning: Trait bound for<'a> T<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:26:1
|
LL | / fn unsized_local() where for<'a> T<A + 'a>: Sized {
LL | struct TwoStrs(str, str) where str: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: Trait bound for<'a> Dst<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:65:1
|
LL | / fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/trivial-bounds-leak.rs:22:25
|
LL | fn cant_return_str() -> str { //~ ERROR
- | ^^^ `str` does not have a constant size known at compile-time
+ | ^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: the return type of a function must have a statically known size
error[E0599]: no method named `test` found for type `i32` in the current scope
struct Foo<T, U: FromIterator<T>>(T, U);
struct WellFormed<Z = Foo<i32, i32>>(Z);
-//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
+//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
-//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
+//~^ ERROR a collection of type `i32` cannot be built from an iterator over elements of type `i32`
struct Bounds<T:Copy=String>(T);
-//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
struct WhereClause<T=String>(T) where T: Copy;
-//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
trait TraitBound<T:Copy=String> {}
-//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
trait Super<T: Copy> { }
trait Base<T = String>: Super<T> { }
-//~^ error: the trait bound `T: std::marker::Copy` is not satisfied [E0277]
+//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied [E0277]
trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
-//~^ error: cannot add `u8` to `i32` [E0277]
+//~^ ERROR cannot add `u8` to `i32` [E0277]
fn main() { }
-error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
+error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
--> $DIR/type-check-defaults.rs:16:19
|
LL | struct WellFormed<Z = Foo<i32, i32>>(Z);
- | ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+ | ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
note: required by `Foo`
LL | struct Foo<T, U: FromIterator<T>>(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
+error[E0277]: a collection of type `i32` cannot be built from an iterator over elements of type `i32`
--> $DIR/type-check-defaults.rs:18:27
|
LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
- | ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+ | ^ a collection of type `i32` cannot be built from `std::iter::Iterator<Item=i32>`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
note: required by `Foo`
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
- expected std::boxed::Box<std::iter::Iterator<Item=&T> + 'static>
- found std::boxed::Box<std::iter::Iterator<Item=&T>>
+ expected std::boxed::Box<(dyn std::iter::Iterator<Item=&T> + 'static)>
+ found std::boxed::Box<dyn std::iter::Iterator<Item=&T>>
error: aborting due to previous error
#![feature(untagged_unions)]
union Foo<T: ?Sized> {
- value: T, //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
+ value: T,
+ //~^ ERROR the size for value values of type
}
struct Foo2<T: ?Sized> {
- value: T, //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
+ value: T,
+ //~^ ERROR the size for value values of type
t: u32,
}
enum Foo3<T: ?Sized> {
- Value(T), //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
+ Value(T),
+ //~^ ERROR the size for value values of type
}
fn main() {}
-error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `T` cannot be known at compilation time
--> $DIR/union-sized-field.rs:14:5
|
-LL | value: T, //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
- | ^^^^^^^^ `T` does not have a constant size known at compile-time
+LL | value: T,
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where T: std::marker::Sized` bound
= note: no field of a union may have a dynamically sized type
-error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
- --> $DIR/union-sized-field.rs:18:5
+error[E0277]: the size for value values of type `T` cannot be known at compilation time
+ --> $DIR/union-sized-field.rs:19:5
|
-LL | value: T, //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
- | ^^^^^^^^ `T` does not have a constant size known at compile-time
+LL | value: T,
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where T: std::marker::Sized` bound
= note: only the last field of a struct may have a dynamically sized type
-error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
- --> $DIR/union-sized-field.rs:23:11
+error[E0277]: the size for value values of type `T` cannot be known at compilation time
+ --> $DIR/union-sized-field.rs:25:11
|
-LL | Value(T), //~ ERROR the trait bound `T: std::marker::Sized` is not satisfied
- | ^ `T` does not have a constant size known at compile-time
+LL | Value(T),
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `T`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where T: std::marker::Sized` bound
= note: no field of an enum variant may have a dynamically sized type
enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
// parameter
- VA(W), //~ ERROR `W: std::marker::Sized` is not satisfied
- VB{x: X}, //~ ERROR `X: std::marker::Sized` is not satisfied
- VC(isize, Y), //~ ERROR `Y: std::marker::Sized` is not satisfied
- VD{u: isize, x: Z}, //~ ERROR `Z: std::marker::Sized` is not satisfied
+ VA(W),
+ //~^ ERROR the size for value values of type
+ VB{x: X},
+ //~^ ERROR the size for value values of type
+ VC(isize, Y),
+ //~^ ERROR the size for value values of type
+ VD{u: isize, x: Z},
+ //~^ ERROR the size for value values of type
// slice / str
- VE([u8]), //~ ERROR `[u8]: std::marker::Sized` is not satisfied
- VF{x: str}, //~ ERROR `str: std::marker::Sized` is not satisfied
- VG(isize, [f32]), //~ ERROR `[f32]: std::marker::Sized` is not satisfied
- VH{u: isize, x: [u32]}, //~ ERROR `[u32]: std::marker::Sized` is not satisfied
+ VE([u8]),
+ //~^ ERROR the size for value values of type
+ VF{x: str},
+ //~^ ERROR the size for value values of type
+ VG(isize, [f32]),
+ //~^ ERROR the size for value values of type
+ VH{u: isize, x: [u32]},
+ //~^ ERROR the size for value values of type
// unsized struct
- VI(Path1), //~ ERROR `PathHelper1 + 'static: std::marker::Sized` is not satisfied
- VJ{x: Path2}, //~ ERROR `PathHelper2 + 'static: std::marker::Sized` is not satisfied
- VK(isize, Path3), //~ ERROR `PathHelper3 + 'static: std::marker::Sized` is not satisfied
- VL{u: isize, x: Path4}, //~ ERROR `PathHelper4 + 'static: std::marker::Sized` is not satisfied
+ VI(Path1),
+ //~^ ERROR the size for value values of type
+ VJ{x: Path2},
+ //~^ ERROR the size for value values of type
+ VK(isize, Path3),
+ //~^ ERROR the size for value values of type
+ VL{u: isize, x: Path4},
+ //~^ ERROR the size for value values of type
// plain trait
- VM(Foo), //~ ERROR `Foo + 'static: std::marker::Sized` is not satisfied
- VN{x: Bar}, //~ ERROR `Bar + 'static: std::marker::Sized` is not satisfied
- VO(isize, FooBar), //~ ERROR `FooBar + 'static: std::marker::Sized` is not satisfied
- VP{u: isize, x: BarFoo}, //~ ERROR `BarFoo + 'static: std::marker::Sized` is not satisfied
+ VM(Foo),
+ //~^ ERROR the size for value values of type
+ VN{x: Bar},
+ //~^ ERROR the size for value values of type
+ VO(isize, FooBar),
+ //~^ ERROR the size for value values of type
+ VP{u: isize, x: BarFoo},
+ //~^ ERROR the size for value values of type
// projected
- VQ(<&'static [i8] as Deref>::Target), //~ ERROR `[i8]: std::marker::Sized` is not satisfied
+ VQ(<&'static [i8] as Deref>::Target),
+ //~^ ERROR the size for value values of type
VR{x: <&'static [char] as Deref>::Target},
- //~^ ERROR `[char]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
VS(isize, <&'static [f64] as Deref>::Target),
- //~^ ERROR `[f64]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
VT{u: isize, x: <&'static [i32] as Deref>::Target},
- //~^ ERROR `[i32]: std::marker::Sized` is not satisfied
+ //~^ ERROR the size for value values of type
}
-error[E0277]: the trait bound `W: std::marker::Sized` is not satisfied
+error[E0277]: the size for value values of type `W` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:33:8
|
-LL | VA(W), //~ ERROR `W: std::marker::Sized` is not satisfied
- | ^ `W` does not have a constant size known at compile-time
+LL | VA(W),
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `W`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where W: std::marker::Sized` bound
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `X: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:34:8
+error[E0277]: the size for value values of type `X` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:35:8
|
-LL | VB{x: X}, //~ ERROR `X: std::marker::Sized` is not satisfied
- | ^^^^ `X` does not have a constant size known at compile-time
+LL | VB{x: X},
+ | ^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `X`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where X: std::marker::Sized` bound
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `Y: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:35:15
+error[E0277]: the size for value values of type `Y` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:37:15
|
-LL | VC(isize, Y), //~ ERROR `Y: std::marker::Sized` is not satisfied
- | ^ `Y` does not have a constant size known at compile-time
+LL | VC(isize, Y),
+ | ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Y`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where Y: std::marker::Sized` bound
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `Z: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:36:18
+error[E0277]: the size for value values of type `Z` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:39:18
|
-LL | VD{u: isize, x: Z}, //~ ERROR `Z: std::marker::Sized` is not satisfied
- | ^^^^ `Z` does not have a constant size known at compile-time
+LL | VD{u: isize, x: Z},
+ | ^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Z`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= help: consider adding a `where Z: std::marker::Sized` bound
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:39:8
+error[E0277]: the size for value values of type `[u8]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:43:8
|
-LL | VE([u8]), //~ ERROR `[u8]: std::marker::Sized` is not satisfied
- | ^^^^ `[u8]` does not have a constant size known at compile-time
+LL | VE([u8]),
+ | ^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:40:8
+error[E0277]: the size for value values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:45:8
|
-LL | VF{x: str}, //~ ERROR `str: std::marker::Sized` is not satisfied
- | ^^^^^^ `str` does not have a constant size known at compile-time
+LL | VF{x: str},
+ | ^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[f32]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:41:15
+error[E0277]: the size for value values of type `[f32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:47:15
|
-LL | VG(isize, [f32]), //~ ERROR `[f32]: std::marker::Sized` is not satisfied
- | ^^^^^ `[f32]` does not have a constant size known at compile-time
+LL | VG(isize, [f32]),
+ | ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[f32]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[u32]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:42:18
+error[E0277]: the size for value values of type `[u32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:49:18
|
-LL | VH{u: isize, x: [u32]}, //~ ERROR `[u32]: std::marker::Sized` is not satisfied
- | ^^^^^^^^ `[u32]` does not have a constant size known at compile-time
+LL | VH{u: isize, x: [u32]},
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `Foo + 'static: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:51:8
+error[E0277]: the size for value values of type `(dyn Foo + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:63:8
|
-LL | VM(Foo), //~ ERROR `Foo + 'static: std::marker::Sized` is not satisfied
- | ^^^ `Foo + 'static` does not have a constant size known at compile-time
+LL | VM(Foo),
+ | ^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `Foo + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `Bar + 'static: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:52:8
+error[E0277]: the size for value values of type `(dyn Bar + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:65:8
|
-LL | VN{x: Bar}, //~ ERROR `Bar + 'static: std::marker::Sized` is not satisfied
- | ^^^^^^ `Bar + 'static` does not have a constant size known at compile-time
+LL | VN{x: Bar},
+ | ^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `Bar + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn Bar + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `FooBar + 'static: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:53:15
+error[E0277]: the size for value values of type `(dyn FooBar + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:67:15
|
-LL | VO(isize, FooBar), //~ ERROR `FooBar + 'static: std::marker::Sized` is not satisfied
- | ^^^^^^ `FooBar + 'static` does not have a constant size known at compile-time
+LL | VO(isize, FooBar),
+ | ^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `FooBar + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn FooBar + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `BarFoo + 'static: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:54:18
+error[E0277]: the size for value values of type `(dyn BarFoo + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:69:18
|
-LL | VP{u: isize, x: BarFoo}, //~ ERROR `BarFoo + 'static: std::marker::Sized` is not satisfied
- | ^^^^^^^^^ `BarFoo + 'static` does not have a constant size known at compile-time
+LL | VP{u: isize, x: BarFoo},
+ | ^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `BarFoo + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn BarFoo + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[i8]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:57:8
+error[E0277]: the size for value values of type `[i8]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:73:8
|
-LL | VQ(<&'static [i8] as Deref>::Target), //~ ERROR `[i8]: std::marker::Sized` is not satisfied
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `[i8]` does not have a constant size known at compile-time
+LL | VQ(<&'static [i8] as Deref>::Target),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[i8]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[char]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:58:8
+error[E0277]: the size for value values of type `[char]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:75:8
|
LL | VR{x: <&'static [char] as Deref>::Target},
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `[char]` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[char]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[f64]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:60:15
+error[E0277]: the size for value values of type `[f64]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:77:15
|
LL | VS(isize, <&'static [f64] as Deref>::Target),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `[f64]` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[f64]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `[i32]: std::marker::Sized` is not satisfied
- --> $DIR/unsized-enum2.rs:62:18
+error[E0277]: the size for value values of type `[i32]` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:79:18
|
LL | VT{u: isize, x: <&'static [i32] as Deref>::Target},
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `[i32]` does not have a constant size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[i32]`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `PathHelper1 + 'static: std::marker::Sized` is not satisfied in `Path1`
- --> $DIR/unsized-enum2.rs:45:8
+error[E0277]: the size for value values of type `(dyn PathHelper1 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:53:8
|
-LL | VI(Path1), //~ ERROR `PathHelper1 + 'static: std::marker::Sized` is not satisfied
- | ^^^^^ `PathHelper1 + 'static` does not have a constant size known at compile-time
+LL | VI(Path1),
+ | ^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path1`, the trait `std::marker::Sized` is not implemented for `PathHelper1 + 'static`
+ = help: within `Path1`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper1 + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path1`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `PathHelper2 + 'static: std::marker::Sized` is not satisfied in `Path2`
- --> $DIR/unsized-enum2.rs:46:8
+error[E0277]: the size for value values of type `(dyn PathHelper2 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:55:8
|
-LL | VJ{x: Path2}, //~ ERROR `PathHelper2 + 'static: std::marker::Sized` is not satisfied
- | ^^^^^^^^ `PathHelper2 + 'static` does not have a constant size known at compile-time
+LL | VJ{x: Path2},
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path2`, the trait `std::marker::Sized` is not implemented for `PathHelper2 + 'static`
+ = help: within `Path2`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper2 + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path2`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `PathHelper3 + 'static: std::marker::Sized` is not satisfied in `Path3`
- --> $DIR/unsized-enum2.rs:47:15
+error[E0277]: the size for value values of type `(dyn PathHelper3 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:57:15
|
-LL | VK(isize, Path3), //~ ERROR `PathHelper3 + 'static: std::marker::Sized` is not satisfied
- | ^^^^^ `PathHelper3 + 'static` does not have a constant size known at compile-time
+LL | VK(isize, Path3),
+ | ^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path3`, the trait `std::marker::Sized` is not implemented for `PathHelper3 + 'static`
+ = help: within `Path3`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper3 + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path3`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the trait bound `PathHelper4 + 'static: std::marker::Sized` is not satisfied in `Path4`
- --> $DIR/unsized-enum2.rs:48:18
+error[E0277]: the size for value values of type `(dyn PathHelper4 + 'static)` cannot be known at compilation time
+ --> $DIR/unsized-enum2.rs:59:18
|
-LL | VL{u: isize, x: Path4}, //~ ERROR `PathHelper4 + 'static: std::marker::Sized` is not satisfied
- | ^^^^^^^^ `PathHelper4 + 'static` does not have a constant size known at compile-time
+LL | VL{u: isize, x: Path4},
+ | ^^^^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path4`, the trait `std::marker::Sized` is not implemented for `PathHelper4 + 'static`
+ = help: within `Path4`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper4 + 'static)`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path4`
= note: no field of an enum variant may have a dynamically sized type
cargo_release: String,
rls_release: String,
rustfmt_release: String,
+ llvm_tools_release: String,
input: PathBuf,
output: PathBuf,
cargo_version: Option<String>,
rls_version: Option<String>,
rustfmt_version: Option<String>,
+ llvm_tools_version: Option<String>,
rust_git_commit_hash: Option<String>,
cargo_git_commit_hash: Option<String>,
rls_git_commit_hash: Option<String>,
rustfmt_git_commit_hash: Option<String>,
+ llvm_tools_git_commit_hash: Option<String>,
}
fn main() {
let cargo_release = args.next().unwrap();
let rls_release = args.next().unwrap();
let rustfmt_release = args.next().unwrap();
+ let llvm_tools_release = args.next().unwrap();
let s3_address = args.next().unwrap();
let mut passphrase = String::new();
t!(io::stdin().read_to_string(&mut passphrase));
cargo_release,
rls_release,
rustfmt_release,
+ llvm_tools_release,
input,
output,
cargo_version: None,
rls_version: None,
rustfmt_version: None,
+ llvm_tools_version: None,
rust_git_commit_hash: None,
cargo_git_commit_hash: None,
rls_git_commit_hash: None,
rustfmt_git_commit_hash: None,
+ llvm_tools_git_commit_hash: None,
}.build();
}
self.cargo_version = self.version("cargo", "x86_64-unknown-linux-gnu");
self.rls_version = self.version("rls", "x86_64-unknown-linux-gnu");
self.rustfmt_version = self.version("rustfmt", "x86_64-unknown-linux-gnu");
+ self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu");
self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu");
self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu");
self.rls_git_commit_hash = self.git_commit_hash("rls", "x86_64-unknown-linux-gnu");
self.rustfmt_git_commit_hash = self.git_commit_hash("rustfmt", "x86_64-unknown-linux-gnu");
+ self.llvm_tools_git_commit_hash = self.git_commit_hash("llvm-tools",
+ "x86_64-unknown-linux-gnu");
self.digest_and_sign();
let manifest = self.build_manifest();
self.package("rls-preview", &mut manifest.pkg, HOSTS);
self.package("rustfmt-preview", &mut manifest.pkg, HOSTS);
self.package("rust-analysis", &mut manifest.pkg, TARGETS);
+ self.package("llvm-tools", &mut manifest.pkg, TARGETS);
let rls_present = manifest.pkg.contains_key("rls-preview");
let rustfmt_present = manifest.pkg.contains_key("rustfmt-preview");
+ let llvm_tools_present = manifest.pkg.contains_key("llvm-tools");
if rls_present {
manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
target: host.to_string(),
});
}
+ if llvm_tools_present {
+ extensions.push(Component {
+ pkg: "llvm-tools".to_string(),
+ target: host.to_string(),
+ });
+ }
extensions.push(Component {
pkg: "rust-analysis".to_string(),
target: host.to_string(),
format!("rls-{}-{}.tar.gz", self.rls_release, target)
} else if component == "rustfmt" || component == "rustfmt-preview" {
format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target)
+ } else if component == "llvm_tools" {
+ format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target)
} else {
format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
}
&self.rls_version
} else if component == "rustfmt" || component == "rustfmt-preview" {
&self.rustfmt_version
+ } else if component == "llvm-tools" {
+ &self.llvm_tools_version
} else {
&self.rust_version
}
&self.rls_git_commit_hash
} else if component == "rustfmt" || component == "rustfmt-preview" {
&self.rustfmt_git_commit_hash
+ } else if component == "llvm-tools" {
+ &self.llvm_tools_git_commit_hash
} else {
&self.rust_git_commit_hash
}
-Subproject commit 08da30d72c9abfff4d41f6f081e31fd2929b820d
+Subproject commit 87edd75ecf26c9084969f431bb5e363693a8a4ca