Heather <heather@cynede.net> <Cynede@Gentoo.org>
Heather <heather@cynede.net> <Heather@cynede.net>
Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk>
+Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org>
Ilyong Cho <ilyoan@gmail.com>
+inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com>
Ivan Ivaschenko <defuz.net@gmail.com>
J. J. Weber <jjweber@gmail.com>
+Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com>
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
[[package]]
name = "regex"
-version = "1.4.3"
+version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
+checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
- "thread_local",
]
[[package]]
name = "regex-automata"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
- "byteorder",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.6.22"
+version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remote-test-client"
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RangeEnd {
+ /// `..=` or `...`
Included(RangeSyntax),
+ /// `..`
Excluded,
}
DotDotEq,
}
+/// All the different flavors of pattern that Rust recognizes.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PatKind {
/// Represents a wildcard pattern (`_`).
/// A literal.
Lit(P<Expr>),
- /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
+ /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
/// A slice pattern `[a, b, c]`.
use super::*;
-use rustc_span::with_default_session_globals;
+use rustc_span::create_default_session_globals_then;
#[test]
fn test_block_doc_comment_1() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let comment = "\n * Test \n ** Test\n * Test\n";
let stripped = beautify_doc_string(Symbol::intern(comment));
assert_eq!(stripped.as_str(), " Test \n* Test\n Test");
#[test]
fn test_block_doc_comment_2() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let comment = "\n * Test\n * Test\n";
let stripped = beautify_doc_string(Symbol::intern(comment));
assert_eq!(stripped.as_str(), " Test\n Test");
#[test]
fn test_block_doc_comment_3() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let comment = "\n let a: *i32;\n *a = 5;\n";
let stripped = beautify_doc_string(Symbol::intern(comment));
assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
#[test]
fn test_line_doc_comment() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let stripped = beautify_doc_string(Symbol::intern(" test"));
assert_eq!(stripped.as_str(), " test");
let stripped = beautify_doc_string(Symbol::intern("! test"));
}
);
+ // Some register classes can only be used as clobbers. This
+ // means that we disallow passing a value in/out of the asm and
+ // require that the operand name an explicit register, not a
+ // register class.
+ if reg_class.is_clobber_only(asm_arch.unwrap())
+ && !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
+ {
+ let msg = format!(
+ "register class `{}` can only be used as a clobber, \
+ not as an input or output",
+ reg_class.name()
+ );
+ sess.struct_span_err(op_sp, &msg).emit();
+ continue;
+ }
+
if !is_clobber {
// Validate register classes against currently enabled target
// features. We check that at least one type is available for
/// Desugar `ExprKind::Try` from: `<expr>?` into:
/// ```rust
- /// match Try::into_result(<expr>) {
- /// Ok(val) => #[allow(unreachable_code)] val,
- /// Err(err) => #[allow(unreachable_code)]
- /// // If there is an enclosing `try {...}`:
- /// break 'catch_target Try::from_error(From::from(err)),
- /// // Otherwise:
- /// return Try::from_error(From::from(err)),
+ /// match Try::branch(<expr>) {
+ /// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
+ /// ControlFlow::Break(residual) =>
+ /// #[allow(unreachable_code)]
+ /// // If there is an enclosing `try {...}`:
+ /// break 'catch_target Try::from_residual(residual),
+ /// // Otherwise:
+ /// return Try::from_residual(residual),
/// }
/// ```
fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
fn visit_pat(&mut self, pattern: &'a ast::Pat) {
match &pattern.kind {
+ PatKind::Slice(pats) => {
+ for pat in pats {
+ let inner_pat = match &pat.kind {
+ PatKind::Ident(.., Some(pat)) => pat,
+ _ => pat,
+ };
+ if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
+ gate_feature_post!(
+ &self,
+ half_open_range_patterns,
+ pat.span,
+ "`X..` patterns in slices are experimental"
+ );
+ }
+ }
+ }
PatKind::Box(..) => {
gate_feature_post!(
&self,
"box pattern syntax is experimental"
);
}
- PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
+ PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
gate_feature_post!(
&self,
exclusive_range_pattern,
use super::*;
use rustc_ast as ast;
+use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
-use rustc_span::with_default_session_globals;
fn fun_to_string(
decl: &ast::FnDecl,
#[test]
fn test_fun_to_string() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let abba_ident = Ident::from_str("abba");
let decl =
#[test]
fn test_variant_to_string() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let ident = Ident::from_str("principal_skinner");
let var = ast::Variant {
sym::simd => Some(ReprSimd),
sym::transparent => Some(ReprTransparent),
sym::no_niche => Some(ReprNoNiche),
+ sym::align => {
+ let mut err = struct_span_err!(
+ diagnostic,
+ item.span(),
+ E0589,
+ "invalid `repr(align)` attribute: `align` needs an argument"
+ );
+ err.span_suggestion(
+ item.span(),
+ "supply an argument here",
+ "align(...)".to_string(),
+ Applicability::HasPlaceholders,
+ );
+ err.emit();
+ recognised = true;
+ None
+ }
name => int_type_of_word(name).map(ReprInt),
};
Ok(literal) => acc.push(ReprPacked(literal)),
Err(message) => literal_error = Some(message),
};
+ } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche)
+ || int_type_of_word(name).is_some()
+ {
+ recognised = true;
+ struct_span_err!(
+ diagnostic,
+ item.span(),
+ E0552,
+ "invalid representation hint: `{}` does not take a parenthesized argument list",
+ name.to_ident_string(),
+ ).emit();
}
if let Some(literal_error) = literal_error {
struct_span_err!(
diagnostic,
item.span(),
E0589,
- "invalid `repr(align)` attribute: {}",
+ "invalid `repr({})` attribute: {}",
+ name.to_ident_string(),
literal_error
)
.emit();
}
} else if let Some(meta_item) = item.meta_item() {
- if meta_item.has_name(sym::align) {
- if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+ if let MetaItemKind::NameValue(ref value) = meta_item.kind {
+ if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
+ let name = meta_item.name_or_empty().to_ident_string();
recognised = true;
let mut err = struct_span_err!(
diagnostic,
item.span(),
E0693,
- "incorrect `repr(align)` attribute format"
+ "incorrect `repr({})` attribute format",
+ name,
);
match value.kind {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
err.span_suggestion(
item.span(),
"use parentheses instead",
- format!("align({})", int),
+ format!("{}({})", name, int),
Applicability::MachineApplicable,
);
}
err.span_suggestion(
item.span(),
"use parentheses instead",
- format!("align({})", s),
+ format!("{}({})", name, s),
Applicability::MachineApplicable,
);
}
_ => {}
}
err.emit();
+ } else {
+ if matches!(
+ meta_item.name_or_empty(),
+ sym::C | sym::simd | sym::transparent | sym::no_niche
+ ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+ {
+ recognised = true;
+ struct_span_err!(
+ diagnostic,
+ meta_item.span,
+ E0552,
+ "invalid representation hint: `{}` does not take a value",
+ meta_item.name_or_empty().to_ident_string(),
+ )
+ .emit();
+ }
+ }
+ } else if let MetaItemKind::List(_) = meta_item.kind {
+ if meta_item.has_name(sym::align) {
+ recognised = true;
+ struct_span_err!(
+ diagnostic,
+ meta_item.span,
+ E0693,
+ "incorrect `repr(align)` attribute format: \
+ `align` takes exactly one argument in parentheses"
+ )
+ .emit();
+ } else if meta_item.has_name(sym::packed) {
+ recognised = true;
+ struct_span_err!(
+ diagnostic,
+ meta_item.span,
+ E0552,
+ "incorrect `repr(packed)` attribute format: \
+ `packed` takes exactly one parenthesized argument, \
+ or no parentheses at all"
+ )
+ .emit();
+ } else if matches!(
+ meta_item.name_or_empty(),
+ sym::C | sym::simd | sym::transparent | sym::no_niche
+ ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+ {
+ recognised = true;
+ struct_span_err!(
+ diagnostic,
+ meta_item.span,
+ E0552,
+ "invalid representation hint: `{}` does not take a parenthesized argument list",
+ meta_item.name_or_empty().to_ident_string(),
+ ).emit();
}
}
}
if !recognised {
- // Not a word we recognize
- diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+ // Not a word we recognize. This will be caught and reported by
+ // the `check_mod_attrs` pass, but this pass doesn't always run
+ // (e.g. if we only pretty-print the source), so we have to gate
+ // the `delay_span_bug` call as follows:
+ if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
+ diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
+ }
}
}
}
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
-use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::sym;
mod asm;
}
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
- register(
- sym::quote,
- SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: LOCAL_CRATE })),
- );
+ register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })));
}
- . $HOME/.cargo/env
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- - ./prepare.sh
+ - ./y.rs prepare
test_script:
- . $HOME/.cargo/env
- # Enable backtraces for easier debugging
- os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
+ - os: ubuntu-latest
+ env:
+ TARGET_TRIPLE: aarch64-unknown-linux-gnu
steps:
- uses: actions/checkout@v2
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
rustup target add x86_64-pc-windows-gnu
+ - name: Install AArch64 toolchain and qemu
+ if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu'
+ run: |
+ sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
+
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
- ./prepare.sh
+ ./y.rs prepare
+
+ - name: Build
+ run: ./y.rs build --sysroot none
- name: Test
env:
with:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz
+
+ build_windows:
+ runs-on: windows-latest
+ timeout-minutes: 60
+
+ steps:
+ - uses: actions/checkout@v2
+
+ #- name: Cache cargo installed crates
+ # uses: actions/cache@v2
+ # with:
+ # path: ~/.cargo/bin
+ # key: ${{ runner.os }}-cargo-installed-crates
+
+ #- name: Cache cargo registry and index
+ # uses: actions/cache@v2
+ # with:
+ # path: |
+ # ~/.cargo/registry
+ # ~/.cargo/git
+ # key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
+
+ #- name: Cache cargo target dir
+ # uses: actions/cache@v2
+ # with:
+ # path: target
+ # key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Prepare dependencies
+ run: |
+ git config --global user.email "user@example.com"
+ git config --global user.name "User"
+ git config --global core.autocrlf false
+ rustup set default-host x86_64-pc-windows-gnu
+ rustc y.rs -o y.exe -g
+ ./y.exe prepare
+
+ - name: Build
+ #name: Test
+ run: |
+ # Enable backtraces for easier debugging
+ #export RUST_BACKTRACE=1
+
+ # Reduce amount of benchmark runs as they are slow
+ #export COMPILE_RUNS=2
+ #export RUN_RUNS=2
+
+ # Enable extra checks
+ #export CG_CLIF_ENABLE_VERIFIER=1
+
+ ./y.exe build
+
+ #- name: Package prebuilt cg_clif
+ # run: tar cvfJ cg_clif.tar.xz build
+
+ #- name: Upload prebuilt cg_clif
+ # uses: actions/upload-artifact@v2
+ # with:
+ # name: cg_clif-${{ runner.os }}
+ # path: cg_clif.tar.xz
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
- ./prepare.sh
+ ./y.rs prepare
- name: Test
run: |
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
- ./prepare.sh
+ ./y.rs prepare
- name: Test
run: |
perf.data.old
*.events
*.string*
+/y.bin
/build
/build_sysroot/sysroot_src
/build_sysroot/compiler-builtins
+/build_sysroot/rustc_version
/rust
/rand
/regex
{
// source for rustc_* is not included in the rust-src component; disable the errors about this
"rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
- "rust-analyzer.assist.importMergeBehavior": "last",
+ "rust-analyzer.assist.importGranularity": "module",
+ "rust-analyzer.assist.importEnforceGranularity": true,
+ "rust-analyzer.assist.importPrefix": "crate",
"rust-analyzer.cargo.runBuildScripts": true,
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"cfg": [],
},
]
+ },
+ {
+ "roots": ["./y.rs"],
+ "crates": [
+ {
+ "root_module": "./y.rs",
+ "edition": "2018",
+ "deps": [{ "crate": 1, "name": "std" }],
+ "cfg": [],
+ },
+ {
+ "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
+ "edition": "2018",
+ "deps": [],
+ "cfg": [],
+ },
+ ]
}
]
}
[[package]]
name = "cranelift-bforest"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"cranelift-bforest",
"cranelift-codegen-meta",
[[package]]
name = "cranelift-codegen-meta"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"cranelift-codegen-shared",
"cranelift-entity",
[[package]]
name = "cranelift-codegen-shared"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
[[package]]
name = "cranelift-entity"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
[[package]]
name = "cranelift-frontend"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"cranelift-codegen",
"log",
[[package]]
name = "cranelift-jit"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "cranelift-module"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "cranelift-native"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"cranelift-codegen",
+ "libc",
"target-lexicon",
]
[[package]]
name = "cranelift-object"
-version = "0.74.0"
-source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#76c6b83f6a21a12a11d4f890490f8acb6329a600"
+version = "0.75.0"
+source = "git+https://github.com/bytecodealliance/wasmtime.git?branch=main#c71ad9490e7f3e19bbcae7e28bbe50f8a0b4a5d8"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "libc"
-version = "0.2.86"
+version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
[[package]]
name = "libloading"
"libc",
]
+[[package]]
+name = "memchr"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+
[[package]]
name = "object"
-version = "0.24.0"
+version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
+checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
dependencies = [
"crc32fast",
"indexmap",
+ "memchr",
]
[[package]]
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind"] }
+cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main", features = ["unwind", "all-arch"] }
cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "main" }
target-lexicon = "0.12.0"
gimli = { version = "0.24.0", default-features = false, features = ["write"]}
-object = { version = "0.24.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
+object = { version = "0.25.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2"
```bash
$ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git
$ cd rustc_codegen_cranelift
-$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking
-$ ./build.sh
+$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking
+$ ./y.rs build
```
To run the test suite replace the last command with:
$ ./test.sh
```
-This will implicitly build cg_clif too. Both `build.sh` and `test.sh` accept a `--debug` argument to
+This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to
build in debug mode.
Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section
rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
-Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
+Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
In the directory with your project (where you can do the usual `cargo build`), run:
```bash
-$ $cg_clif_dir/build/cargo.sh build
+$ $cg_clif_dir/build/cargo build
```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
+++ /dev/null
-#!/usr/bin/env bash
-set -e
-
-# Settings
-export CHANNEL="release"
-build_sysroot="clif"
-target_dir='build'
-while [[ $# != 0 ]]; do
- case $1 in
- "--debug")
- export CHANNEL="debug"
- ;;
- "--sysroot")
- build_sysroot=$2
- shift
- ;;
- "--target-dir")
- target_dir=$2
- shift
- ;;
- *)
- echo "Unknown flag '$1'"
- echo "Usage: ./build.sh [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"
- exit 1
- ;;
- esac
- shift
-done
-
-# Build cg_clif
-unset CARGO_TARGET_DIR
-unamestr=$(uname)
-if [[ "$unamestr" == 'Linux' || "$unamestr" == "FreeBSD" ]]; then
- export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS
-elif [[ "$unamestr" == 'Darwin' ]]; then
- export RUSTFLAGS='-Csplit-debuginfo=unpacked -Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS
- dylib_ext='dylib'
-else
- echo "Unsupported os $unamestr"
- exit 1
-fi
-if [[ "$CHANNEL" == "release" ]]; then
- cargo build --release
-else
- cargo build
-fi
-
-source scripts/ext_config.sh
-
-rm -rf "$target_dir"
-mkdir "$target_dir"
-mkdir "$target_dir"/bin "$target_dir"/lib
-ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin
-ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
-ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir"
-
-mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/"
-if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
- cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-fi
-
-case "$build_sysroot" in
- "none")
- ;;
- "llvm")
- cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/"
- if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
- cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/"
- fi
- ;;
- "clif")
- echo "[BUILD] sysroot"
- dir=$(pwd)
- cd "$target_dir"
- time "$dir/build_sysroot/build_sysroot.sh"
- if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
- time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh"
- fi
- cp lib/rustlib/*/lib/libstd-* lib/
- ;;
- *)
- echo "Unknown sysroot kind \`$build_sysroot\`."
- echo "The allowed values are:"
- echo " none A sysroot that doesn't contain the standard library"
- echo " llvm Copy the sysroot from rustc compiled by cg_llvm"
- echo " clif Build a new sysroot using cg_clif"
- exit 1
-esac
[[package]]
name = "compiler_builtins"
-version = "0.1.43"
+version = "0.1.46"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"compiler_builtins",
"libc",
[[package]]
name = "libc"
-version = "0.2.95"
+version = "0.2.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
+checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "rustc-demangle"
-version = "0.1.19"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce"
+checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
+++ /dev/null
-#!/usr/bin/env bash
-
-# Requires the CHANNEL env var to be set to `debug` or `release.`
-
-set -e
-
-source ./config.sh
-
-dir=$(pwd)
-
-# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that
-# build scripts are still compiled using cg_llvm.
-export RUSTC=$dir"/bin/cg_clif_build_sysroot"
-export RUSTFLAGS=$RUSTFLAGS" --clif"
-
-cd "$(dirname "$0")"
-
-# Cleanup for previous run
-# v Clean target dir except for build scripts and incremental cache
-rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true
-
-# We expect the target dir in the default location. Guard against the user changing it.
-export CARGO_TARGET_DIR=target
-
-# Build libs
-export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort"
-export __CARGO_DEFAULT_LIB_METADATA="cg_clif"
-if [[ "$1" != "--debug" ]]; then
- sysroot_channel='release'
- # FIXME Enable incremental again once rust-lang/rust#74946 is fixed
- CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release
-else
- sysroot_channel='debug'
- cargo build --target "$TARGET_TRIPLE"
-fi
-
-# Copy files to sysroot
-ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
-rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d}
+++ /dev/null
-#!/usr/bin/env bash
-set -e
-cd "$(dirname "$0")"
-
-SRC_DIR="$(dirname "$(rustup which rustc)")/../lib/rustlib/src/rust/"
-DST_DIR="sysroot_src"
-
-if [ ! -e "$SRC_DIR" ]; then
- echo "Please install rust-src component"
- exit 1
-fi
-
-rm -rf $DST_DIR
-mkdir -p $DST_DIR/library
-cp -a "$SRC_DIR/library" $DST_DIR/
-
-pushd $DST_DIR
-echo "[GIT] init"
-git init
-echo "[GIT] add"
-git add .
-echo "[GIT] commit"
-git commit -m "Initial commit" -q
-for file in $(ls ../../patches/ | grep -v patcha); do
-echo "[GIT] apply" "$file"
-git apply ../../patches/"$file"
-git add -A
-git commit --no-gpg-sign -m "Patch $file"
-done
-popd
-
-git clone https://github.com/rust-lang/compiler-builtins.git || echo "rust-lang/compiler-builtins has already been cloned"
-pushd compiler-builtins
-git checkout -- .
-git checkout 0.1.43
-git apply ../../crate_patches/000*-compiler-builtins-*.patch
-popd
-
-echo "Successfully prepared sysroot source for building"
--- /dev/null
+use std::env;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf {
+ let mut cmd = Command::new("cargo");
+ cmd.arg("build").arg("--target").arg(host_triple);
+
+ match channel {
+ "debug" => {}
+ "release" => {
+ cmd.arg("--release");
+ }
+ _ => unreachable!(),
+ }
+
+ if cfg!(unix) {
+ if cfg!(target_os = "macos") {
+ cmd.env(
+ "RUSTFLAGS",
+ "-Csplit-debuginfo=unpacked \
+ -Clink-arg=-Wl,-rpath,@loader_path/../lib \
+ -Zosx-rpath-install-name"
+ .to_string()
+ + env::var("RUSTFLAGS").as_deref().unwrap_or(""),
+ );
+ } else {
+ cmd.env(
+ "RUSTFLAGS",
+ "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string()
+ + env::var("RUSTFLAGS").as_deref().unwrap_or(""),
+ );
+ }
+ }
+
+ eprintln!("[BUILD] rustc_codegen_cranelift");
+ crate::utils::spawn_and_wait(cmd);
+
+ Path::new("target").join(host_triple).join(channel)
+}
--- /dev/null
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::process::{self, Command};
+
+use crate::rustc_info::{get_file_name, get_rustc_version};
+use crate::utils::{spawn_and_wait, try_hard_link};
+use crate::SysrootKind;
+
+pub(crate) fn build_sysroot(
+ channel: &str,
+ sysroot_kind: SysrootKind,
+ target_dir: &Path,
+ cg_clif_build_dir: PathBuf,
+ host_triple: &str,
+ target_triple: &str,
+) {
+ if target_dir.exists() {
+ fs::remove_dir_all(target_dir).unwrap();
+ }
+ fs::create_dir_all(target_dir.join("bin")).unwrap();
+ fs::create_dir_all(target_dir.join("lib")).unwrap();
+
+ // Copy the backend
+ for file in ["cg_clif", "cg_clif_build_sysroot"] {
+ try_hard_link(
+ cg_clif_build_dir.join(get_file_name(file, "bin")),
+ target_dir.join("bin").join(get_file_name(file, "bin")),
+ );
+ }
+
+ let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
+ try_hard_link(
+ cg_clif_build_dir.join(&cg_clif_dylib),
+ target_dir
+ .join(if cfg!(windows) {
+ // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+ // binaries.
+ "bin"
+ } else {
+ "lib"
+ })
+ .join(cg_clif_dylib),
+ );
+
+ // Build and copy cargo wrapper
+ let mut build_cargo_wrapper_cmd = Command::new("rustc");
+ build_cargo_wrapper_cmd
+ .arg("scripts/cargo.rs")
+ .arg("-o")
+ .arg(target_dir.join("cargo"))
+ .arg("-g");
+ spawn_and_wait(build_cargo_wrapper_cmd);
+
+ let default_sysroot = crate::rustc_info::get_default_sysroot();
+
+ let rustlib = target_dir.join("lib").join("rustlib");
+ let host_rustlib_lib = rustlib.join(host_triple).join("lib");
+ let target_rustlib_lib = rustlib.join(target_triple).join("lib");
+ fs::create_dir_all(&host_rustlib_lib).unwrap();
+ fs::create_dir_all(&target_rustlib_lib).unwrap();
+
+ if target_triple == "x86_64-pc-windows-gnu" {
+ if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() {
+ eprintln!(
+ "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \
+ to compile a sysroot for it.",
+ );
+ process::exit(1);
+ }
+ for file in fs::read_dir(
+ default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
+ )
+ .unwrap()
+ {
+ let file = file.unwrap().path();
+ if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") {
+ continue; // only copy object files
+ }
+ try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
+ }
+ }
+
+ match sysroot_kind {
+ SysrootKind::None => {} // Nothing to do
+ SysrootKind::Llvm => {
+ for file in fs::read_dir(
+ default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"),
+ )
+ .unwrap()
+ {
+ let file = file.unwrap().path();
+ let file_name_str = file.file_name().unwrap().to_str().unwrap();
+ if file_name_str.contains("rustc_")
+ || file_name_str.contains("chalk")
+ || file_name_str.contains("tracing")
+ || file_name_str.contains("regex")
+ {
+ // These are large crates that are part of the rustc-dev component and are not
+ // necessary to run regular programs.
+ continue;
+ }
+ try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap()));
+ }
+
+ if target_triple != host_triple {
+ for file in fs::read_dir(
+ default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
+ )
+ .unwrap()
+ {
+ let file = file.unwrap().path();
+ try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
+ }
+ }
+ }
+ SysrootKind::Clif => {
+ build_clif_sysroot_for_triple(channel, target_dir, host_triple, None);
+
+ if host_triple != target_triple {
+ // When cross-compiling it is often necessary to manually pick the right linker
+ let linker = if target_triple == "aarch64-unknown-linux-gnu" {
+ Some("aarch64-linux-gnu-gcc")
+ } else {
+ None
+ };
+ build_clif_sysroot_for_triple(channel, target_dir, target_triple, linker);
+ }
+
+ // Copy std for the host to the lib dir. This is necessary for the jit mode to find
+ // libstd.
+ for file in fs::read_dir(host_rustlib_lib).unwrap() {
+ let file = file.unwrap().path();
+ if file.file_name().unwrap().to_str().unwrap().contains("std-") {
+ try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+ }
+ }
+ }
+ }
+}
+
+fn build_clif_sysroot_for_triple(
+ channel: &str,
+ target_dir: &Path,
+ triple: &str,
+ linker: Option<&str>,
+) {
+ match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+ Err(e) => {
+ eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
+ eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
+ process::exit(1);
+ }
+ Ok(source_version) => {
+ let rustc_version = get_rustc_version();
+ if source_version != rustc_version {
+ eprintln!("The patched sysroot source is outdated");
+ eprintln!("Source version: {}", source_version.trim());
+ eprintln!("Rustc version: {}", rustc_version.trim());
+ eprintln!("Hint: Try `./y.rs prepare` to update the patched sysroot source");
+ process::exit(1);
+ }
+ }
+ }
+
+ let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+
+ if !crate::config::get_bool("keep_sysroot") {
+ // Cleanup the target dir with the exception of build scripts and the incremental cache
+ for dir in ["build", "deps", "examples", "native"] {
+ if build_dir.join(dir).exists() {
+ fs::remove_dir_all(build_dir.join(dir)).unwrap();
+ }
+ }
+ }
+
+ // Build sysroot
+ let mut build_cmd = Command::new("cargo");
+ build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
+ let mut rustflags = "--clif -Zforce-unstable-if-unmarked".to_string();
+ if channel == "release" {
+ build_cmd.arg("--release");
+ rustflags.push_str(" -Zmir-opt-level=3");
+ }
+ if let Some(linker) = linker {
+ use std::fmt::Write;
+ write!(rustflags, " -Clinker={}", linker).unwrap();
+ }
+ build_cmd.env("RUSTFLAGS", rustflags);
+ build_cmd.env(
+ "RUSTC",
+ env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"),
+ );
+ // FIXME Enable incremental again once rust-lang/rust#74946 is fixed
+ build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
+ spawn_and_wait(build_cmd);
+
+ // Copy all relevant files to the sysroot
+ for entry in
+ fs::read_dir(Path::new("build_sysroot/target").join(triple).join(channel).join("deps"))
+ .unwrap()
+ {
+ let entry = entry.unwrap();
+ if let Some(ext) = entry.path().extension() {
+ if ext == "rmeta" || ext == "d" || ext == "dSYM" {
+ continue;
+ }
+ } else {
+ continue;
+ };
+ try_hard_link(
+ entry.path(),
+ target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+ );
+ }
+}
--- /dev/null
+use std::{fs, process};
+
+fn load_config_file() -> Vec<(String, Option<String>)> {
+ fs::read_to_string("config.txt")
+ .unwrap()
+ .lines()
+ .map(|line| if let Some((line, _comment)) = line.split_once('#') { line } else { line })
+ .map(|line| line.trim())
+ .filter(|line| !line.is_empty())
+ .map(|line| {
+ if let Some((key, val)) = line.split_once('=') {
+ (key.trim().to_owned(), Some(val.trim().to_owned()))
+ } else {
+ (line.to_owned(), None)
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn get_bool(name: &str) -> bool {
+ let values = load_config_file()
+ .into_iter()
+ .filter(|(key, _)| key == name)
+ .map(|(_, val)| val)
+ .collect::<Vec<_>>();
+ if values.is_empty() {
+ false
+ } else {
+ if values.iter().any(|val| val.is_some()) {
+ eprintln!("Boolean config `{}` has a value", name);
+ process::exit(1);
+ }
+ true
+ }
+}
+
+pub(crate) fn get_value(name: &str) -> Option<String> {
+ let values = load_config_file()
+ .into_iter()
+ .filter(|(key, _)| key == name)
+ .map(|(_, val)| val)
+ .collect::<Vec<_>>();
+ if values.is_empty() {
+ None
+ } else if values.len() == 1 {
+ if values[0].is_none() {
+ eprintln!("Config `{}` missing value", name);
+ process::exit(1);
+ }
+ values.into_iter().next().unwrap()
+ } else {
+ eprintln!("Config `{}` given multiple values: {:?}", name, values);
+ process::exit(1);
+ }
+}
--- /dev/null
+use std::env;
+use std::ffi::OsStr;
+use std::ffi::OsString;
+use std::fs;
+use std::path::Path;
+use std::process::Command;
+
+use crate::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
+use crate::utils::{copy_dir_recursively, spawn_and_wait};
+
+pub(crate) fn prepare() {
+ prepare_sysroot();
+
+ eprintln!("[INSTALL] hyperfine");
+ Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+
+ clone_repo(
+ "rand",
+ "https://github.com/rust-random/rand.git",
+ "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
+ );
+ apply_patches("rand", Path::new("rand"));
+
+ clone_repo(
+ "regex",
+ "https://github.com/rust-lang/regex.git",
+ "341f207c1071f7290e3f228c710817c280c8dca1",
+ );
+
+ clone_repo(
+ "simple-raytracer",
+ "https://github.com/ebobby/simple-raytracer",
+ "804a7a21b9e673a482797aa289a18ed480e4d813",
+ );
+
+ eprintln!("[LLVM BUILD] simple-raytracer");
+ let mut build_cmd = Command::new("cargo");
+ build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
+ spawn_and_wait(build_cmd);
+ fs::copy(
+ Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
+ // FIXME use get_file_name here too once testing is migrated to rust
+ "simple-raytracer/raytracer_cg_llvm",
+ )
+ .unwrap();
+}
+
+fn prepare_sysroot() {
+ let rustc_path = get_rustc_path();
+ let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
+ let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
+
+ assert!(sysroot_src_orig.exists());
+
+ if sysroot_src.exists() {
+ fs::remove_dir_all(&sysroot_src).unwrap();
+ }
+ fs::create_dir_all(sysroot_src.join("library")).unwrap();
+ eprintln!("[COPY] sysroot src");
+ copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+
+ let rustc_version = get_rustc_version();
+ fs::write(
+ Path::new("build_sysroot").join("rustc_version"),
+ &rustc_version,
+ )
+ .unwrap();
+
+ eprintln!("[GIT] init");
+ let mut git_init_cmd = Command::new("git");
+ git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
+ spawn_and_wait(git_init_cmd);
+
+ let mut git_add_cmd = Command::new("git");
+ git_add_cmd.arg("add").arg(".").current_dir(&sysroot_src);
+ spawn_and_wait(git_add_cmd);
+
+ let mut git_commit_cmd = Command::new("git");
+ git_commit_cmd
+ .arg("commit")
+ .arg("-m")
+ .arg("Initial commit")
+ .arg("-q")
+ .current_dir(&sysroot_src);
+ spawn_and_wait(git_commit_cmd);
+
+ apply_patches("sysroot", &sysroot_src);
+
+ clone_repo(
+ "build_sysroot/compiler-builtins",
+ "https://github.com/rust-lang/compiler-builtins.git",
+ "0.1.46",
+ );
+ apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins"));
+}
+
+fn clone_repo(target_dir: &str, repo: &str, rev: &str) {
+ eprintln!("[CLONE] {}", repo);
+ // Ignore exit code as the repo may already have been checked out
+ Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap();
+
+ let mut clean_cmd = Command::new("git");
+ clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir);
+ spawn_and_wait(clean_cmd);
+
+ let mut checkout_cmd = Command::new("git");
+ checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir);
+ spawn_and_wait(checkout_cmd);
+}
+
+fn get_patches(crate_name: &str) -> Vec<OsString> {
+ let mut patches: Vec<_> = fs::read_dir("patches")
+ .unwrap()
+ .map(|entry| entry.unwrap().path())
+ .filter(|path| path.extension() == Some(OsStr::new("patch")))
+ .map(|path| path.file_name().unwrap().to_owned())
+ .filter(|file_name| {
+ file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name)
+ })
+ .collect();
+ patches.sort();
+ patches
+}
+
+fn apply_patches(crate_name: &str, target_dir: &Path) {
+ for patch in get_patches(crate_name) {
+ eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch);
+ let patch_arg = env::current_dir().unwrap().join("patches").join(patch);
+ let mut apply_patch_cmd = Command::new("git");
+ apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir);
+ spawn_and_wait(apply_patch_cmd);
+ }
+}
--- /dev/null
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+
+pub(crate) fn get_rustc_version() -> String {
+ let version_info =
+ Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
+ String::from_utf8(version_info).unwrap()
+}
+
+pub(crate) fn get_host_triple() -> String {
+ let version_info =
+ Command::new("rustc").stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
+ String::from_utf8(version_info)
+ .unwrap()
+ .lines()
+ .to_owned()
+ .find(|line| line.starts_with("host"))
+ .unwrap()
+ .split(":")
+ .nth(1)
+ .unwrap()
+ .trim()
+ .to_owned()
+}
+
+pub(crate) fn get_rustc_path() -> PathBuf {
+ let rustc_path = Command::new("rustup")
+ .stderr(Stdio::inherit())
+ .args(&["which", "rustc"])
+ .output()
+ .unwrap()
+ .stdout;
+ Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
+}
+
+pub(crate) fn get_default_sysroot() -> PathBuf {
+ let default_sysroot = Command::new("rustc")
+ .stderr(Stdio::inherit())
+ .args(&["--print", "sysroot"])
+ .output()
+ .unwrap()
+ .stdout;
+ Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned()
+}
+
+pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
+ let file_name = Command::new("rustc")
+ .stderr(Stdio::inherit())
+ .args(&[
+ "--crate-name",
+ crate_name,
+ "--crate-type",
+ crate_type,
+ "--print",
+ "file-names",
+ "-",
+ ])
+ .output()
+ .unwrap()
+ .stdout;
+ let file_name = String::from_utf8(file_name).unwrap().trim().to_owned();
+ assert!(!file_name.contains('\n'));
+ assert!(file_name.contains(crate_name));
+ file_name
+}
--- /dev/null
+use std::fs;
+use std::path::Path;
+use std::process::{self, Command};
+
+#[track_caller]
+pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
+ let src = src.as_ref();
+ let dst = dst.as_ref();
+ if let Err(_) = fs::hard_link(src, dst) {
+ fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed
+ }
+}
+
+#[track_caller]
+pub(crate) fn spawn_and_wait(mut cmd: Command) {
+ if !cmd.spawn().unwrap().wait().unwrap().success() {
+ process::exit(1);
+ }
+}
+
+pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
+ for entry in fs::read_dir(from).unwrap() {
+ let entry = entry.unwrap();
+ let filename = entry.file_name();
+ if filename == "." || filename == ".." {
+ continue;
+ }
+ if entry.metadata().unwrap().is_dir() {
+ fs::create_dir(to.join(&filename)).unwrap();
+ copy_dir_recursively(&from.join(&filename), &to.join(&filename));
+ } else {
+ fs::copy(from.join(&filename), to.join(&filename)).unwrap();
+ }
+ }
+}
#!/usr/bin/env bash
set -e
-rm -rf target/ build/ build_sysroot/{sysroot_src/,target/,compiler-builtins/} perf.data{,.old}
+rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
+rm -rf target/ build/ perf.data{,.old}
rm -rf rand/ regex/ simple-raytracer/
--- /dev/null
+# This file allows configuring the build system.
+
+# Which triple to produce a compiler toolchain for.
+#
+# Defaults to the default triple of rustc on the host system.
+#host = x86_64-unknown-linux-gnu
+
+# Which triple to build libraries (core/alloc/std/test/proc_macro) for.
+#
+# Defaults to `host`.
+#target = x86_64-unknown-linux-gnu
+
+# Disables cleaning of the sysroot dir. This will cause old compiled artifacts to be re-used when
+# the sysroot source hasn't changed. This is useful when the codegen backend hasn't been modified.
+# This option can be changed while the build system is already running for as long as sysroot
+# building hasn't started yet.
+#keep_sysroot
+++ /dev/null
-From 1d574bf5e32d51641dcacaf8ef777e95b44f6f2a Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Thu, 18 Feb 2021 18:30:55 +0100
-Subject: [PATCH] Disable 128bit atomic operations
-
-Cranelift doesn't support them yet
----
- src/mem/mod.rs | 12 ------------
- 1 file changed, 12 deletions(-)
-
-diff --git a/src/mem/mod.rs b/src/mem/mod.rs
-index 107762c..2d1ae10 100644
---- a/src/mem/mod.rs
-+++ b/src/mem/mod.rs
-@@ -137,10 +137,6 @@ intrinsics! {
- pub extern "C" fn __llvm_memcpy_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
- memcpy_element_unordered_atomic(dest, src, bytes);
- }
-- #[cfg(target_has_atomic_load_store = "128")]
-- pub extern "C" fn __llvm_memcpy_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
-- memcpy_element_unordered_atomic(dest, src, bytes);
-- }
-
- #[cfg(target_has_atomic_load_store = "8")]
- pub extern "C" fn __llvm_memmove_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
-@@ -158,10 +154,6 @@ intrinsics! {
- pub extern "C" fn __llvm_memmove_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
- memmove_element_unordered_atomic(dest, src, bytes);
- }
-- #[cfg(target_has_atomic_load_store = "128")]
-- pub extern "C" fn __llvm_memmove_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
-- memmove_element_unordered_atomic(dest, src, bytes);
-- }
-
- #[cfg(target_has_atomic_load_store = "8")]
- pub extern "C" fn __llvm_memset_element_unordered_atomic_1(s: *mut u8, c: u8, bytes: usize) -> () {
-@@ -179,8 +171,4 @@ intrinsics! {
- pub extern "C" fn __llvm_memset_element_unordered_atomic_8(s: *mut u64, c: u8, bytes: usize) -> () {
- memset_element_unordered_atomic(s, c, bytes);
- }
-- #[cfg(target_has_atomic_load_store = "128")]
-- pub extern "C" fn __llvm_memset_element_unordered_atomic_16(s: *mut u128, c: u8, bytes: usize) -> () {
-- memset_element_unordered_atomic(s, c, bytes);
-- }
- }
---
-2.26.2.7.g19db9cfb68
-
+++ /dev/null
-From 9c5663e36391fa20becf84f3af2e82afa5bb720b Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sat, 15 Aug 2020 19:56:03 +0200
-Subject: [PATCH] [rand] Enable c2-chacha simd feature
-
----
- rand_chacha/Cargo.toml | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/rand_chacha/Cargo.toml b/rand_chacha/Cargo.toml
-index 9190b7f..872cca2 100644
---- a/rand_chacha/Cargo.toml
-+++ b/rand_chacha/Cargo.toml
-@@ -24,5 +24,5 @@ ppv-lite86 = { version = "0.2.8", default-features = false }
-
- [features]
- default = ["std"]
--std = ["ppv-lite86/std"]
-+std = ["ppv-lite86/std", "ppv-lite86/simd"]
- simd = [] # deprecated
---
-2.20.1
-
+++ /dev/null
-From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sat, 15 Aug 2020 20:04:38 +0200
-Subject: [PATCH] [rand] Disable failing test
-
----
- src/distributions/uniform.rs | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
-index 480b859..c80bb6f 100644
---- a/src/distributions/uniform.rs
-+++ b/src/distributions/uniform.rs
-@@ -1085,7 +1085,7 @@ mod tests {
- _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
- }
- }
--
-+
- #[test]
- #[cfg(feature = "serde1")]
- fn test_uniform_serialization() {
-@@ -1314,6 +1314,7 @@ mod tests {
- not(target_arch = "wasm32"),
- not(target_arch = "asmjs")
- ))]
-+ #[ignore] // FIXME
- fn test_float_assertions() {
- use super::SampleUniform;
- use std::panic::catch_unwind;
---
-2.20.1
-
rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
-Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
+Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`y.rs prepare` and `y.rs build` or `test.sh`).
## Cargo
In the directory with your project (where you can do the usual `cargo build`), run:
```bash
-$ $cg_clif_dir/build/cargo.sh build
+$ $cg_clif_dir/build/cargo build
```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
> The jit mode will probably need cargo integration to make this possible.
```bash
-$ $cg_clif_dir/build/cargo.sh jit
+$ $cg_clif_dir/build/cargo jit
```
or
```
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
-first called. It currently does not work with multi-threaded programs. When a not yet compiled
-function is called from another thread than the main thread, you will get an ICE.
+first called.
```bash
-$ $cg_clif_dir/build/cargo.sh lazy-jit
+$ $cg_clif_dir/build/cargo lazy-jit
```
## Shell
#[cfg(not(any(jit, windows)))]
test_tls();
- #[cfg(all(not(jit), target_os = "linux"))]
+ #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
unsafe {
global_asm_test();
}
assert_eq!(*REF1, *REF2);
}
-#[cfg(all(not(jit), target_os = "linux"))]
+#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
extern "C" {
fn global_asm_test();
}
-#[cfg(all(not(jit), target_os = "linux"))]
+#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))]
global_asm! {
"
.global global_asm_test
let stderr = ::std::io::stderr();
let mut stderr = stderr.lock();
- // FIXME support lazy jit when multi threading
- #[cfg(not(lazy_jit))]
std::thread::spawn(move || {
println!("Hello from another thread!");
});
--- /dev/null
+From 1d574bf5e32d51641dcacaf8ef777e95b44f6f2a Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Thu, 18 Feb 2021 18:30:55 +0100
+Subject: [PATCH] Disable 128bit atomic operations
+
+Cranelift doesn't support them yet
+---
+ src/mem/mod.rs | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/src/mem/mod.rs b/src/mem/mod.rs
+index 107762c..2d1ae10 100644
+--- a/src/mem/mod.rs
++++ b/src/mem/mod.rs
+@@ -137,10 +137,6 @@ intrinsics! {
+ pub extern "C" fn __llvm_memcpy_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
+ memcpy_element_unordered_atomic(dest, src, bytes);
+ }
+- #[cfg(target_has_atomic_load_store = "128")]
+- pub extern "C" fn __llvm_memcpy_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
+- memcpy_element_unordered_atomic(dest, src, bytes);
+- }
+
+ #[cfg(target_has_atomic_load_store = "8")]
+ pub extern "C" fn __llvm_memmove_element_unordered_atomic_1(dest: *mut u8, src: *const u8, bytes: usize) -> () {
+@@ -158,10 +154,6 @@ intrinsics! {
+ pub extern "C" fn __llvm_memmove_element_unordered_atomic_8(dest: *mut u64, src: *const u64, bytes: usize) -> () {
+ memmove_element_unordered_atomic(dest, src, bytes);
+ }
+- #[cfg(target_has_atomic_load_store = "128")]
+- pub extern "C" fn __llvm_memmove_element_unordered_atomic_16(dest: *mut u128, src: *const u128, bytes: usize) -> () {
+- memmove_element_unordered_atomic(dest, src, bytes);
+- }
+
+ #[cfg(target_has_atomic_load_store = "8")]
+ pub extern "C" fn __llvm_memset_element_unordered_atomic_1(s: *mut u8, c: u8, bytes: usize) -> () {
+@@ -179,8 +171,4 @@ intrinsics! {
+ pub extern "C" fn __llvm_memset_element_unordered_atomic_8(s: *mut u64, c: u8, bytes: usize) -> () {
+ memset_element_unordered_atomic(s, c, bytes);
+ }
+- #[cfg(target_has_atomic_load_store = "128")]
+- pub extern "C" fn __llvm_memset_element_unordered_atomic_16(s: *mut u128, c: u8, bytes: usize) -> () {
+- memset_element_unordered_atomic(s, c, bytes);
+- }
+ }
+--
+2.26.2.7.g19db9cfb68
+
--- /dev/null
+From 9c5663e36391fa20becf84f3af2e82afa5bb720b Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sat, 15 Aug 2020 19:56:03 +0200
+Subject: [PATCH] [rand] Enable c2-chacha simd feature
+
+---
+ rand_chacha/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rand_chacha/Cargo.toml b/rand_chacha/Cargo.toml
+index 9190b7f..872cca2 100644
+--- a/rand_chacha/Cargo.toml
++++ b/rand_chacha/Cargo.toml
+@@ -24,5 +24,5 @@ ppv-lite86 = { version = "0.2.8", default-features = false }
+
+ [features]
+ default = ["std"]
+-std = ["ppv-lite86/std"]
++std = ["ppv-lite86/std", "ppv-lite86/simd"]
+ simd = [] # deprecated
+--
+2.20.1
+
--- /dev/null
+From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sat, 15 Aug 2020 20:04:38 +0200
+Subject: [PATCH] [rand] Disable failing test
+
+---
+ src/distributions/uniform.rs | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
+index 480b859..c80bb6f 100644
+--- a/src/distributions/uniform.rs
++++ b/src/distributions/uniform.rs
+@@ -1085,7 +1085,7 @@ mod tests {
+ _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
+ }
+ }
+-
++
+ #[test]
+ #[cfg(feature = "serde1")]
+ fn test_uniform_serialization() {
+@@ -1314,6 +1314,7 @@ mod tests {
+ not(target_arch = "wasm32"),
+ not(target_arch = "asmjs")
+ ))]
++ #[ignore] // FIXME
+ fn test_float_assertions() {
+ use super::SampleUniform;
+ use std::panic::catch_unwind;
+--
+2.20.1
+
+++ /dev/null
-From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:10:23 +0100
-Subject: [PATCH] [core] Disable not compiling tests
-
----
- library/core/tests/Cargo.toml | 8 ++++++++
- library/core/tests/num/flt2dec/mod.rs | 1 -
- library/core/tests/num/int_macros.rs | 2 ++
- library/core/tests/num/uint_macros.rs | 2 ++
- library/core/tests/ptr.rs | 2 ++
- library/core/tests/slice.rs | 2 ++
- 6 files changed, 16 insertions(+), 1 deletion(-)
- create mode 100644 library/core/tests/Cargo.toml
-
-diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
-new file mode 100644
-index 0000000..46fd999
---- /dev/null
-+++ b/library/core/tests/Cargo.toml
-@@ -0,0 +1,8 @@
-+[package]
-+name = "core"
-+version = "0.0.0"
-+edition = "2018"
-+
-+[lib]
-+name = "coretests"
-+path = "lib.rs"
-diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
-index a35897e..f0bf645 100644
---- a/library/core/tests/num/flt2dec/mod.rs
-+++ b/library/core/tests/num/flt2dec/mod.rs
-@@ -13,7 +13,6 @@ mod strategy {
- mod dragon;
- mod grisu;
- }
--mod random;
-
- pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
- match decode(v).1 {
-diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
-index 1a6be3a..42dbd59 100644
---- a/library/core/tests/ptr.rs
-+++ b/library/core/tests/ptr.rs
-@@ -250,6 +250,7 @@ fn test_unsized_nonnull() {
- assert!(ys == zs);
- }
-
-+/*
- #[test]
- #[allow(warnings)]
- // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
-@@ -289,6 +290,7 @@ fn write_unaligned_drop() {
- }
- DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
- }
-+*/
-
- #[test]
- fn align_offset_zst() {
-diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 6609bc3..241b497 100644
---- a/library/core/tests/slice.rs
-+++ b/library/core/tests/slice.rs
-@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
- }
- }
-
-+/*
- #[test]
- #[cfg(not(target_arch = "wasm32"))]
- fn sort_unstable() {
-@@ -1394,6 +1395,7 @@ fn partition_at_index() {
- v.select_nth_unstable(0);
- assert!(v == [0xDEADBEEF]);
- }
-+*/
-
- #[test]
- #[should_panic(expected = "index 0 greater than length of slice")]
---
-2.21.0 (Apple Git-122)
--- /dev/null
+From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sun, 24 Nov 2019 15:10:23 +0100
+Subject: [PATCH] [core] Disable not compiling tests
+
+---
+ library/core/tests/Cargo.toml | 8 ++++++++
+ library/core/tests/num/flt2dec/mod.rs | 1 -
+ library/core/tests/num/int_macros.rs | 2 ++
+ library/core/tests/num/uint_macros.rs | 2 ++
+ library/core/tests/ptr.rs | 2 ++
+ library/core/tests/slice.rs | 2 ++
+ 6 files changed, 16 insertions(+), 1 deletion(-)
+ create mode 100644 library/core/tests/Cargo.toml
+
+diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml
+new file mode 100644
+index 0000000..46fd999
+--- /dev/null
++++ b/library/core/tests/Cargo.toml
+@@ -0,0 +1,8 @@
++[package]
++name = "core"
++version = "0.0.0"
++edition = "2018"
++
++[lib]
++name = "coretests"
++path = "lib.rs"
+diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
+index a35897e..f0bf645 100644
+--- a/library/core/tests/num/flt2dec/mod.rs
++++ b/library/core/tests/num/flt2dec/mod.rs
+@@ -13,7 +13,6 @@ mod strategy {
+ mod dragon;
+ mod grisu;
+ }
+-mod random;
+
+ pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
+ match decode(v).1 {
+diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
+index 1a6be3a..42dbd59 100644
+--- a/library/core/tests/ptr.rs
++++ b/library/core/tests/ptr.rs
+@@ -250,6 +250,7 @@ fn test_unsized_nonnull() {
+ assert!(ys == zs);
+ }
+
++/*
+ #[test]
+ #[allow(warnings)]
+ // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
+@@ -289,6 +290,7 @@ fn write_unaligned_drop() {
+ }
+ DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
+ }
++*/
+
+ #[test]
+ fn align_offset_zst() {
+diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
+index 6609bc3..241b497 100644
+--- a/library/core/tests/slice.rs
++++ b/library/core/tests/slice.rs
+@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
+ }
+ }
+
++/*
+ #[test]
+ #[cfg(not(target_arch = "wasm32"))]
+ fn sort_unstable() {
+@@ -1394,6 +1395,7 @@ fn partition_at_index() {
+ v.select_nth_unstable(0);
+ assert!(v == [0xDEADBEEF]);
+ }
++*/
+
+ #[test]
+ #[should_panic(expected = "index 0 greater than length of slice")]
+--
+2.21.0 (Apple Git-122)
+++ /dev/null
-From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:34:06 +0100
-Subject: [PATCH] [core] Ignore failing tests
-
----
- library/core/tests/iter.rs | 4 ++++
- library/core/tests/num/bignum.rs | 10 ++++++++++
- library/core/tests/num/mod.rs | 5 +++--
- library/core/tests/time.rs | 1 +
- 4 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
-index 4bc44e9..8e3c7a4 100644
---- a/library/core/tests/array.rs
-+++ b/library/core/tests/array.rs
-@@ -242,6 +242,7 @@ fn iterator_drops() {
- assert_eq!(i.get(), 5);
- }
-
-+/*
- // This test does not work on targets without panic=unwind support.
- // To work around this problem, test is marked is should_panic, so it will
- // be automagically skipped on unsuitable targets, such as
-@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
- assert_eq!(COUNTER.load(Relaxed), 0);
- panic!("test succeeded")
- }
-+*/
-
- #[test]
- fn empty_array_is_always_default() {
-@@ -304,6 +304,7 @@ fn array_map() {
- assert_eq!(b, [1, 2, 3]);
- }
-
-+/*
- // See note on above test for why `should_panic` is used.
- #[test]
- #[should_panic(expected = "test succeeded")]
-@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
- assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
- panic!("test succeeded")
- }
-+*/
-
- #[test]
- fn cell_allows_array_cycle() {
-diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
-index a17c094..5bb11d2 100644
---- a/library/core/tests/num/mod.rs
-+++ b/library/core/tests/num/mod.rs
-@@ -651,11 +651,12 @@ macro_rules! test_float {
- assert_eq!((9.0 as $fty).min($neginf), $neginf);
- assert_eq!(($neginf as $fty).min(-9.0), $neginf);
- assert_eq!((-9.0 as $fty).min($neginf), $neginf);
-- assert_eq!(($nan as $fty).min(9.0), 9.0);
-- assert_eq!(($nan as $fty).min(-9.0), -9.0);
-- assert_eq!((9.0 as $fty).min($nan), 9.0);
-- assert_eq!((-9.0 as $fty).min($nan), -9.0);
-- assert!(($nan as $fty).min($nan).is_nan());
-+ // Cranelift fmin has NaN propagation
-+ //assert_eq!(($nan as $fty).min(9.0), 9.0);
-+ //assert_eq!(($nan as $fty).min(-9.0), -9.0);
-+ //assert_eq!((9.0 as $fty).min($nan), 9.0);
-+ //assert_eq!((-9.0 as $fty).min($nan), -9.0);
-+ //assert!(($nan as $fty).min($nan).is_nan());
- }
- #[test]
- fn max() {
-@@ -673,11 +674,12 @@ macro_rules! test_float {
- assert_eq!((9.0 as $fty).max($neginf), 9.0);
- assert_eq!(($neginf as $fty).max(-9.0), -9.0);
- assert_eq!((-9.0 as $fty).max($neginf), -9.0);
-- assert_eq!(($nan as $fty).max(9.0), 9.0);
-- assert_eq!(($nan as $fty).max(-9.0), -9.0);
-- assert_eq!((9.0 as $fty).max($nan), 9.0);
-- assert_eq!((-9.0 as $fty).max($nan), -9.0);
-- assert!(($nan as $fty).max($nan).is_nan());
-+ // Cranelift fmax has NaN propagation
-+ //assert_eq!(($nan as $fty).max(9.0), 9.0);
-+ //assert_eq!(($nan as $fty).max(-9.0), -9.0);
-+ //assert_eq!((9.0 as $fty).max($nan), 9.0);
-+ //assert_eq!((-9.0 as $fty).max($nan), -9.0);
-+ //assert!(($nan as $fty).max($nan).is_nan());
- }
- #[test]
- fn rem_euclid() {
---
-2.21.0 (Apple Git-122)
--- /dev/null
+From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Sun, 24 Nov 2019 15:34:06 +0100
+Subject: [PATCH] [core] Ignore failing tests
+
+---
+ library/core/tests/iter.rs | 4 ++++
+ library/core/tests/num/bignum.rs | 10 ++++++++++
+ library/core/tests/num/mod.rs | 5 +++--
+ library/core/tests/time.rs | 1 +
+ 4 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
+index 4bc44e9..8e3c7a4 100644
+--- a/library/core/tests/array.rs
++++ b/library/core/tests/array.rs
+@@ -242,6 +242,7 @@ fn iterator_drops() {
+ assert_eq!(i.get(), 5);
+ }
+
++/*
+ // This test does not work on targets without panic=unwind support.
+ // To work around this problem, test is marked is should_panic, so it will
+ // be automagically skipped on unsuitable targets, such as
+@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
+ assert_eq!(COUNTER.load(Relaxed), 0);
+ panic!("test succeeded")
+ }
++*/
+
+ #[test]
+ fn empty_array_is_always_default() {
+@@ -304,6 +304,7 @@ fn array_map() {
+ assert_eq!(b, [1, 2, 3]);
+ }
+
++/*
+ // See note on above test for why `should_panic` is used.
+ #[test]
+ #[should_panic(expected = "test succeeded")]
+@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
+ assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
+ panic!("test succeeded")
+ }
++*/
+
+ #[test]
+ fn cell_allows_array_cycle() {
+diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
+index a17c094..5bb11d2 100644
+--- a/library/core/tests/num/mod.rs
++++ b/library/core/tests/num/mod.rs
+@@ -651,11 +651,12 @@ macro_rules! test_float {
+ assert_eq!((9.0 as $fty).min($neginf), $neginf);
+ assert_eq!(($neginf as $fty).min(-9.0), $neginf);
+ assert_eq!((-9.0 as $fty).min($neginf), $neginf);
+- assert_eq!(($nan as $fty).min(9.0), 9.0);
+- assert_eq!(($nan as $fty).min(-9.0), -9.0);
+- assert_eq!((9.0 as $fty).min($nan), 9.0);
+- assert_eq!((-9.0 as $fty).min($nan), -9.0);
+- assert!(($nan as $fty).min($nan).is_nan());
++ // Cranelift fmin has NaN propagation
++ //assert_eq!(($nan as $fty).min(9.0), 9.0);
++ //assert_eq!(($nan as $fty).min(-9.0), -9.0);
++ //assert_eq!((9.0 as $fty).min($nan), 9.0);
++ //assert_eq!((-9.0 as $fty).min($nan), -9.0);
++ //assert!(($nan as $fty).min($nan).is_nan());
+ }
+ #[test]
+ fn max() {
+@@ -673,11 +674,12 @@ macro_rules! test_float {
+ assert_eq!((9.0 as $fty).max($neginf), 9.0);
+ assert_eq!(($neginf as $fty).max(-9.0), -9.0);
+ assert_eq!((-9.0 as $fty).max($neginf), -9.0);
+- assert_eq!(($nan as $fty).max(9.0), 9.0);
+- assert_eq!(($nan as $fty).max(-9.0), -9.0);
+- assert_eq!((9.0 as $fty).max($nan), 9.0);
+- assert_eq!((-9.0 as $fty).max($nan), -9.0);
+- assert!(($nan as $fty).max($nan).is_nan());
++ // Cranelift fmax has NaN propagation
++ //assert_eq!(($nan as $fty).max(9.0), 9.0);
++ //assert_eq!(($nan as $fty).max(-9.0), -9.0);
++ //assert_eq!((9.0 as $fty).max($nan), 9.0);
++ //assert_eq!((-9.0 as $fty).max($nan), -9.0);
++ //assert!(($nan as $fty).max($nan).is_nan());
+ }
+ #[test]
+ fn rem_euclid() {
+--
+2.21.0 (Apple Git-122)
+++ /dev/null
-From 894e07dfec2624ba539129b1c1d63e1d7d812bda Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Thu, 18 Feb 2021 18:45:28 +0100
-Subject: [PATCH] Disable 128bit atomic operations
-
-Cranelift doesn't support them yet
----
- library/core/src/sync/atomic.rs | 38 ---------------------------------
- library/core/tests/atomic.rs | 4 ----
- library/std/src/panic.rs | 6 ------
- 3 files changed, 48 deletions(-)
-
-diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
-index 81c9e1d..65c9503 100644
---- a/library/core/src/sync/atomic.rs
-+++ b/library/core/src/sync/atomic.rs
-@@ -2228,44 +2228,6 @@ atomic_int! {
- "AtomicU64::new(0)",
- u64 AtomicU64 ATOMIC_U64_INIT
- }
--#[cfg(target_has_atomic_load_store = "128")]
--atomic_int! {
-- cfg(target_has_atomic = "128"),
-- cfg(target_has_atomic_equal_alignment = "128"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- "i128",
-- "#![feature(integer_atomics)]\n\n",
-- atomic_min, atomic_max,
-- 16,
-- "AtomicI128::new(0)",
-- i128 AtomicI128 ATOMIC_I128_INIT
--}
--#[cfg(target_has_atomic_load_store = "128")]
--atomic_int! {
-- cfg(target_has_atomic = "128"),
-- cfg(target_has_atomic_equal_alignment = "128"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
-- unstable(feature = "integer_atomics", issue = "32976"),
-- "u128",
-- "#![feature(integer_atomics)]\n\n",
-- atomic_umin, atomic_umax,
-- 16,
-- "AtomicU128::new(0)",
-- u128 AtomicU128 ATOMIC_U128_INIT
--}
-
- macro_rules! atomic_int_ptr_sized {
- ( $($target_pointer_width:literal $align:literal)* ) => { $(
-diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
-index 2d1e449..cb6da5d 100644
---- a/library/core/tests/atomic.rs
-+++ b/library/core/tests/atomic.rs
-@@ -145,10 +145,6 @@ fn atomic_alignment() {
- assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
- #[cfg(target_has_atomic = "64")]
- assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
-- #[cfg(target_has_atomic = "128")]
-- assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
-- #[cfg(target_has_atomic = "128")]
-- assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
- #[cfg(target_has_atomic = "ptr")]
- assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
- #[cfg(target_has_atomic = "ptr")]
-diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
-index 89a822a..779fd88 100644
---- a/library/std/src/panic.rs
-+++ b/library/std/src/panic.rs
-@@ -279,9 +279,6 @@ impl RefUnwindSafe for atomic::AtomicI32 {}
- #[cfg(target_has_atomic_load_store = "64")]
- #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
- impl RefUnwindSafe for atomic::AtomicI64 {}
--#[cfg(target_has_atomic_load_store = "128")]
--#[unstable(feature = "integer_atomics", issue = "32976")]
--impl RefUnwindSafe for atomic::AtomicI128 {}
-
- #[cfg(target_has_atomic_load_store = "ptr")]
- #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
-@@ -298,9 +295,6 @@ impl RefUnwindSafe for atomic::AtomicU32 {}
- #[cfg(target_has_atomic_load_store = "64")]
- #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
- impl RefUnwindSafe for atomic::AtomicU64 {}
--#[cfg(target_has_atomic_load_store = "128")]
--#[unstable(feature = "integer_atomics", issue = "32976")]
--impl RefUnwindSafe for atomic::AtomicU128 {}
-
- #[cfg(target_has_atomic_load_store = "8")]
- #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
---
-2.26.2.7.g19db9cfb68
-
--- /dev/null
+From 894e07dfec2624ba539129b1c1d63e1d7d812bda Mon Sep 17 00:00:00 2001
+From: bjorn3 <bjorn3@users.noreply.github.com>
+Date: Thu, 18 Feb 2021 18:45:28 +0100
+Subject: [PATCH] Disable 128bit atomic operations
+
+Cranelift doesn't support them yet
+---
+ library/core/src/sync/atomic.rs | 38 ---------------------------------
+ library/core/tests/atomic.rs | 4 ----
+ library/std/src/panic.rs | 6 ------
+ 3 files changed, 48 deletions(-)
+
+diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
+index 81c9e1d..65c9503 100644
+--- a/library/core/src/sync/atomic.rs
++++ b/library/core/src/sync/atomic.rs
+@@ -2228,44 +2228,6 @@ atomic_int! {
+ "AtomicU64::new(0)",
+ u64 AtomicU64 ATOMIC_U64_INIT
+ }
+-#[cfg(target_has_atomic_load_store = "128")]
+-atomic_int! {
+- cfg(target_has_atomic = "128"),
+- cfg(target_has_atomic_equal_alignment = "128"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- "i128",
+- "#![feature(integer_atomics)]\n\n",
+- atomic_min, atomic_max,
+- 16,
+- "AtomicI128::new(0)",
+- i128 AtomicI128 ATOMIC_I128_INIT
+-}
+-#[cfg(target_has_atomic_load_store = "128")]
+-atomic_int! {
+- cfg(target_has_atomic = "128"),
+- cfg(target_has_atomic_equal_alignment = "128"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+- unstable(feature = "integer_atomics", issue = "32976"),
+- "u128",
+- "#![feature(integer_atomics)]\n\n",
+- atomic_umin, atomic_umax,
+- 16,
+- "AtomicU128::new(0)",
+- u128 AtomicU128 ATOMIC_U128_INIT
+-}
+
+ macro_rules! atomic_int_ptr_sized {
+ ( $($target_pointer_width:literal $align:literal)* ) => { $(
+diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
+index 2d1e449..cb6da5d 100644
+--- a/library/core/tests/atomic.rs
++++ b/library/core/tests/atomic.rs
+@@ -145,10 +145,6 @@ fn atomic_alignment() {
+ assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
+ #[cfg(target_has_atomic = "64")]
+ assert_eq!(align_of::<AtomicI64>(), size_of::<AtomicI64>());
+- #[cfg(target_has_atomic = "128")]
+- assert_eq!(align_of::<AtomicU128>(), size_of::<AtomicU128>());
+- #[cfg(target_has_atomic = "128")]
+- assert_eq!(align_of::<AtomicI128>(), size_of::<AtomicI128>());
+ #[cfg(target_has_atomic = "ptr")]
+ assert_eq!(align_of::<AtomicUsize>(), size_of::<AtomicUsize>());
+ #[cfg(target_has_atomic = "ptr")]
+diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
+index 89a822a..779fd88 100644
+--- a/library/std/src/panic.rs
++++ b/library/std/src/panic.rs
+@@ -279,9 +279,6 @@ impl RefUnwindSafe for atomic::AtomicI32 {}
+ #[cfg(target_has_atomic_load_store = "64")]
+ #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
+ impl RefUnwindSafe for atomic::AtomicI64 {}
+-#[cfg(target_has_atomic_load_store = "128")]
+-#[unstable(feature = "integer_atomics", issue = "32976")]
+-impl RefUnwindSafe for atomic::AtomicI128 {}
+
+ #[cfg(target_has_atomic_load_store = "ptr")]
+ #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+@@ -298,9 +295,6 @@ impl RefUnwindSafe for atomic::AtomicU32 {}
+ #[cfg(target_has_atomic_load_store = "64")]
+ #[stable(feature = "integer_atomics_stable", since = "1.34.0")]
+ impl RefUnwindSafe for atomic::AtomicU64 {}
+-#[cfg(target_has_atomic_load_store = "128")]
+-#[unstable(feature = "integer_atomics", issue = "32976")]
+-impl RefUnwindSafe for atomic::AtomicU128 {}
+
+ #[cfg(target_has_atomic_load_store = "8")]
+ #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
+--
+2.26.2.7.g19db9cfb68
+
+++ /dev/null
-#!/usr/bin/env bash
-set -e
-
-./build_sysroot/prepare_sysroot_src.sh
-cargo install hyperfine || echo "Skipping hyperfine install"
-
-git clone https://github.com/rust-random/rand.git || echo "rust-random/rand has already been cloned"
-pushd rand
-git checkout -- .
-git checkout 0f933f9c7176e53b2a3c7952ded484e1783f0bf1
-git am ../crate_patches/*-rand-*.patch
-popd
-
-git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned"
-pushd regex
-git checkout -- .
-git checkout 341f207c1071f7290e3f228c710817c280c8dca1
-popd
-
-git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned"
-pushd simple-raytracer
-git checkout -- .
-git checkout 804a7a21b9e673a482797aa289a18ed480e4d813
-
-# build with cg_llvm for perf comparison
-unset CARGO_TARGET_DIR
-cargo build
-mv target/debug/main raytracer_cg_llvm
-popd
[toolchain]
-channel = "nightly-2021-05-26"
+channel = "nightly-2021-07-07"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
--- /dev/null
+use std::env;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+ if env::var("RUSTC_WRAPPER").map_or(false, |wrapper| wrapper.contains("sccache")) {
+ eprintln!(
+ "\x1b[1;93m=== Warning: Unsetting RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m"
+ );
+ env::remove_var("RUSTC_WRAPPER");
+ }
+
+ let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+ env::set_var("RUSTC", sysroot.join("bin/cg_clif".to_string() + env::consts::EXE_SUFFIX));
+
+ let mut rustdoc_flags = env::var("RUSTDOCFLAGS").unwrap_or(String::new());
+ rustdoc_flags.push_str(" -Cpanic=abort -Zpanic-abort-tests -Zcodegen-backend=");
+ rustdoc_flags.push_str(
+ sysroot
+ .join(if cfg!(windows) { "bin" } else { "lib" })
+ .join(
+ env::consts::DLL_PREFIX.to_string()
+ + "rustc_codegen_cranelift"
+ + env::consts::DLL_SUFFIX,
+ )
+ .to_str()
+ .unwrap(),
+ );
+ rustdoc_flags.push_str(" --sysroot ");
+ rustdoc_flags.push_str(sysroot.to_str().unwrap());
+ env::set_var("RUSTDOCFLAGS", rustdoc_flags);
+
+ // Ensure that the right toolchain is used
+ env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+ let args: Vec<_> = match env::args().nth(1).as_deref() {
+ Some("jit") => {
+ env::set_var(
+ "RUSTFLAGS",
+ env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
+ );
+ std::array::IntoIter::new(["rustc".to_string()])
+ .chain(env::args().skip(2))
+ .chain(["--".to_string(), "-Cllvm-args=mode=jit".to_string()])
+ .collect()
+ }
+ Some("lazy-jit") => {
+ env::set_var(
+ "RUSTFLAGS",
+ env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic",
+ );
+ std::array::IntoIter::new(["rustc".to_string()])
+ .chain(env::args().skip(2))
+ .chain(["--".to_string(), "-Cllvm-args=mode=jit-lazy".to_string()])
+ .collect()
+ }
+ _ => env::args().skip(1).collect(),
+ };
+
+ #[cfg(unix)]
+ Command::new("cargo").args(args).exec();
+
+ #[cfg(not(unix))]
+ std::process::exit(
+ Command::new("cargo").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+ );
+}
+++ /dev/null
-#!/usr/bin/env bash
-
-dir=$(dirname "$0")
-source "$dir/config.sh"
-
-# read nightly compiler from rust-toolchain file
-TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/")
-
-cmd=$1
-shift || true
-
-if [[ "$cmd" = "jit" ]]; then
-cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit -Cprefer-dynamic
-elif [[ "$cmd" = "lazy-jit" ]]; then
-cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit-lazy -Cprefer-dynamic
-else
-cargo "+${TOOLCHAIN}" "$cmd" "$@"
-fi
set -e
-dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -)
-
-if echo "$RUSTC_WRAPPER" | grep sccache; then
-echo
-echo -e "\x1b[1;93m=== Warning: Unset RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m"
-echo
-export RUSTC_WRAPPER=
-fi
-
-dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
-
-export RUSTC=$dir"/bin/cg_clif"
-
-export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\
-'-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir
-
-# FIXME fix `#[linkage = "extern_weak"]` without this
-if [[ "$(uname)" == 'Darwin' ]]; then
- export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
-fi
-
-export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:"$dir"/lib"
-export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH"
+export DYLD_LIBRARY_PATH="$(rustc --print sysroot)/lib:$DYLD_LIBRARY_PATH"
# Note to people running shellcheck: this file should only be sourced, not executed directly.
-# Various env vars that should only be set for the build system but not for cargo.sh
+# Various env vars that should only be set for the build system
set -e
echo "Unknown non-native platform"
fi
fi
+
+# FIXME fix `#[linkage = "extern_weak"]` without this
+if [[ "$(uname)" == 'Darwin' ]]; then
+ export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
+fi
#![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc
pushd $(dirname "$0")/../
-source build/config.sh
+source scripts/config.sh
+RUSTC="$(pwd)/build/bin/cg_clif"
popd
-PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS -Cllvm-args=mode=jit -Cprefer-dynamic $0
+PROFILE=$1 OUTPUT=$2 exec $RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/
//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
done
./clean_all.sh
- ./prepare.sh
+ ./y.rs prepare
(cd build_sysroot && cargo update)
#!/bin/bash
set -e
-./build.sh
-source build/config.sh
+./y.rs build
+source scripts/config.sh
echo "[SETUP] Rust fork"
git clone https://github.com/rust-lang/rust.git || true
[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] }
-+compiler_builtins = { version = "0.1.43", features = ['rustc-dep-of-std', 'no-asm'] }
++compiler_builtins = { version = "0.1.45", features = ['rustc-dep-of-std', 'no-asm'] }
[dev-dependencies]
rand = "0.7"
rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs
rm src/test/ui/drop/drop-trait-enum.rs
rm src/test/ui/numbers-arithmetic/issue-8460.rs
-rm src/test/incremental/change_crate_dep_kind.rs # requires -Cpanic=unwind
+rm src/test/ui/rt-explody-panic-payloads.rs
+rm src/test/incremental/change_crate_dep_kind.rs
rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations
rm src/test/ui/init-large-type.rs # same
rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
rm -r src/test/run-make/unstable-flag-required # same
+rm -r src/test/run-make/emit-named-files # requires full --emit support
rm src/test/pretty/asm.rs # inline asm
rm src/test/pretty/raw-str-nonexpr.rs # same
set -e
-source build/config.sh
+source scripts/config.sh
source scripts/ext_config.sh
-MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
+export RUSTC=false # ensure that cg_llvm isn't accidentally used
+MY_RUSTC="$(pwd)/build/bin/cg_clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
function no_sysroot_tests() {
echo "[BUILD] mini_core"
$MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
echo "[JIT-lazy] std_example"
- $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --cfg lazy_jit --target "$HOST_TRIPLE"
+ $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
else
echo "[JIT] std_example (skipped)"
fi
function extended_sysroot_tests() {
pushd rand
- cargo clean
+ ../build/cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-random/rand"
- ../build/cargo.sh test --workspace
+ ../build/cargo test --workspace
else
echo "[AOT] rust-random/rand"
- ../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests
+ ../build/cargo build --workspace --target $TARGET_TRIPLE --tests
fi
popd
pushd simple-raytracer
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[BENCH COMPILE] ebobby/simple-raytracer"
- hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \
+ hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \
"RUSTC=rustc RUSTFLAGS='' cargo build" \
- "../build/cargo.sh build"
+ "../build/cargo build"
echo "[BENCH RUN] ebobby/simple-raytracer"
cp ./target/debug/main ./raytracer_cg_clif
hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
else
+ ../build/cargo clean
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
echo "[COMPILE] ebobby/simple-raytracer"
- ../build/cargo.sh build --target $TARGET_TRIPLE
+ ../build/cargo build --target $TARGET_TRIPLE
echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
fi
popd
pushd build_sysroot/sysroot_src/library/core/tests
echo "[TEST] libcore"
- cargo clean
+ ../../../../../build/cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
- ../../../../../build/cargo.sh test
+ ../../../../../build/cargo test
else
- ../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests
+ ../../../../../build/cargo build --target $TARGET_TRIPLE --tests
fi
popd
pushd regex
echo "[TEST] rust-lang/regex example shootout-regex-dna"
- cargo clean
+ ../build/cargo clean
export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning
# Make sure `[codegen mono items] start` doesn't poison the diff
- ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE
+ ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
cat examples/regexdna-input.txt \
- | ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \
+ | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \
| grep -v "Spawned thread" > res.txt
diff -u res.txt examples/regexdna-output.txt
fi
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-lang/regex tests"
- ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
+ ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
else
echo "[AOT] rust-lang/regex tests"
- ../build/cargo.sh build --tests --target $TARGET_TRIPLE
+ ../build/cargo build --tests --target $TARGET_TRIPLE
fi
popd
}
debug_assert!(!instance.substs.needs_infer());
let mir = tcx.instance_mir(instance.def);
+ let _mir_guard = crate::PrintOnPanic(|| {
+ let mut buf = Vec::new();
+ rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap();
+ String::from_utf8_lossy(&buf).into_owned()
+ });
// Declare function
let symbol_name = tcx.symbol_name(instance);
module,
tcx,
pointer_type,
- vtables: FxHashMap::default(),
constants_cx: ConstantCx::new(),
instance,
let context = &mut cx.cached_context;
context.func = func;
- crate::pretty_clif::write_clif_file(tcx, "unopt", None, instance, &context, &clif_comments);
+ crate::pretty_clif::write_clif_file(
+ tcx,
+ "unopt",
+ module.isa(),
+ instance,
+ &context,
+ &clif_comments,
+ );
// Verify function
verify_func(tcx, &clif_comments, &context.func);
// Perform rust specific optimizations
tcx.sess.time("optimize clif ir", || {
- crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments);
+ crate::optimize::optimize_function(
+ tcx,
+ module.isa(),
+ instance,
+ context,
+ &mut clif_comments,
+ );
});
// Define function
crate::pretty_clif::write_clif_file(
tcx,
"opt",
- Some(module.isa()),
+ module.isa(),
instance,
&context,
&clif_comments,
extern crate rustc_session;
extern crate rustc_target;
-use std::panic;
use std::lazy::SyncLazy;
+use std::panic;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_interface::interface;
pub(crate) module: &'m mut dyn Module,
pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) pointer_type: Type, // Cached from module
- pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer>,
pub(crate) constants_cx: ConstantCx,
pub(crate) instance: Instance<'tcx>,
//! Handling of `static`s, `const`s and promoted allocations
-use rustc_span::DUMMY_SP;
-
-use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::ErrorReported;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{
- alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc,
- Scalar,
+ read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use rustc_middle::ty::ConstKind;
+use rustc_span::DUMMY_SP;
use cranelift_codegen::ir::GlobalValueData;
use cranelift_module::*;
}
match const_val {
- ConstValue::Scalar(x) => {
- if fx.clif_type(layout.ty).is_none() {
- let (size, align) = (layout.size, layout.align.pref);
- let mut alloc = Allocation::from_bytes(
- std::iter::repeat(0).take(size.bytes_usize()).collect::<Vec<u8>>(),
- align,
- Mutability::Not,
- );
- alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap();
- let alloc = fx.tcx.intern_const_alloc(alloc);
- return CValue::by_ref(pointer_for_allocation(fx, alloc), layout);
- }
-
- match x {
- Scalar::Int(int) => CValue::const_val(fx, layout, int),
- Scalar::Ptr(ptr) => {
- let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
- let base_addr = match alloc_kind {
- Some(GlobalAlloc::Memory(alloc)) => {
- fx.constants_cx.todo.push(TodoItem::Alloc(ptr.alloc_id));
- let data_id = data_id_for_alloc_id(
- &mut fx.constants_cx,
- fx.module,
- ptr.alloc_id,
- alloc.mutability,
- );
- let local_data_id =
- fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
- if fx.clif_comments.enabled() {
- fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
- }
- fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
- }
- Some(GlobalAlloc::Function(instance)) => {
- let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
- let local_func_id =
- fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
- fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
- }
- Some(GlobalAlloc::Static(def_id)) => {
- assert!(fx.tcx.is_static(def_id));
- let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
- let local_data_id =
- fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
- if fx.clif_comments.enabled() {
- fx.add_comment(local_data_id, format!("{:?}", def_id));
- }
- fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+ ConstValue::Scalar(x) => match x {
+ Scalar::Int(int) => {
+ if fx.clif_type(layout.ty).is_some() {
+ return CValue::const_val(fx, layout, int);
+ } else {
+ let raw_val = int.to_bits(int.size()).unwrap();
+ let val = match int.size().bytes() {
+ 1 => fx.bcx.ins().iconst(types::I8, raw_val as i64),
+ 2 => fx.bcx.ins().iconst(types::I16, raw_val as i64),
+ 4 => fx.bcx.ins().iconst(types::I32, raw_val as i64),
+ 8 => fx.bcx.ins().iconst(types::I64, raw_val as i64),
+ 16 => {
+ let lsb = fx.bcx.ins().iconst(types::I64, raw_val as u64 as i64);
+ let msb =
+ fx.bcx.ins().iconst(types::I64, (raw_val >> 64) as u64 as i64);
+ fx.bcx.ins().iconcat(lsb, msb)
}
- None => bug!("missing allocation {:?}", ptr.alloc_id),
- };
- let val = if ptr.offset.bytes() != 0 {
- fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap())
- } else {
- base_addr
+ _ => unreachable!(),
};
- CValue::by_val(val, layout)
+
+ let place = CPlace::new_stack_slot(fx, layout);
+ place.to_ptr().store(fx, val, MemFlags::trusted());
+ place.to_cvalue(fx)
}
}
- }
+ Scalar::Ptr(ptr) => {
+ let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
+ let base_addr = match alloc_kind {
+ Some(GlobalAlloc::Memory(alloc)) => {
+ let data_id = data_id_for_alloc_id(
+ &mut fx.constants_cx,
+ fx.module,
+ ptr.alloc_id,
+ alloc.mutability,
+ );
+ let local_data_id =
+ fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+ if fx.clif_comments.enabled() {
+ fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
+ }
+ fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+ }
+ Some(GlobalAlloc::Function(instance)) => {
+ let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
+ let local_func_id =
+ fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
+ fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
+ }
+ Some(GlobalAlloc::Static(def_id)) => {
+ assert!(fx.tcx.is_static(def_id));
+ let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
+ let local_data_id =
+ fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+ if fx.clif_comments.enabled() {
+ fx.add_comment(local_data_id, format!("{:?}", def_id));
+ }
+ fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
+ }
+ None => bug!("missing allocation {:?}", ptr.alloc_id),
+ };
+ let val = if ptr.offset.bytes() != 0 {
+ fx.bcx.ins().iadd_imm(base_addr, i64::try_from(ptr.offset.bytes()).unwrap())
+ } else {
+ base_addr
+ };
+ CValue::by_val(val, layout)
+ }
+ },
ConstValue::ByRef { alloc, offset } => CValue::by_ref(
pointer_for_allocation(fx, alloc)
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
alloc: &'tcx Allocation,
) -> crate::pointer::Pointer {
let alloc_id = fx.tcx.create_memory_alloc(alloc);
- fx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
let data_id =
data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, alloc.mutability);
crate::pointer::Pointer::new(global_ptr)
}
-fn data_id_for_alloc_id(
+pub(crate) fn data_id_for_alloc_id(
cx: &mut ConstantCx,
module: &mut dyn Module,
alloc_id: AllocId,
mutability: rustc_hir::Mutability,
) -> DataId {
+ cx.todo.push(TodoItem::Alloc(alloc_id));
*cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
module.declare_anonymous_data(mutability == rustc_hir::Mutability::Mut, false).unwrap()
})
GlobalAlloc::Memory(alloc) => alloc,
GlobalAlloc::Function(_) | GlobalAlloc::Static(_) => unreachable!(),
};
- let data_id = data_id_for_alloc_id(cx, module, alloc_id, alloc.mutability);
+ let data_id = *cx.anon_allocs.entry(alloc_id).or_insert_with(|| {
+ module
+ .declare_anonymous_data(
+ alloc.mutability == rustc_hir::Mutability::Mut,
+ false,
+ )
+ .unwrap()
+ });
(data_id, alloc, None)
}
TodoItem::Static(def_id) => {
continue;
}
GlobalAlloc::Memory(target_alloc) => {
- cx.todo.push(TodoItem::Alloc(reloc));
data_id_for_alloc_id(cx, module, reloc, target_alloc.mutability)
}
GlobalAlloc::Static(def_id) => {
};
use cranelift_codegen::binemit::CodeOffset;
-use cranelift_codegen::machinst::MachSrcLoc;
+use cranelift_codegen::MachSrcLoc;
use gimli::write::{
Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
let mut dwarf = DwarfUnit::new(encoding);
- // FIXME: how to get version when building out of tree?
- // Normally this would use option_env!("CFG_VERSION").
- let producer = format!("cg_clif (rustc {})", "unknown version");
+ let producer = format!(
+ "cg_clif (rustc {}, cranelift {})",
+ rustc_interface::util::version_str().unwrap_or("unknown version"),
+ cranelift_codegen::VERSION,
+ );
let comp_dir = tcx.sess.working_dir.to_string_lossy(false).into_owned();
let (name, file_info) = match tcx.sess.local_crate_source_file.clone() {
Some(path) => {
use std::path::PathBuf;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_codegen_ssa::back::linker::LinkerInfo;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
None
};
+ // FIXME handle `-Ctarget-cpu=native`
+ let target_cpu =
+ tcx.sess.opts.cg.target_cpu.as_ref().unwrap_or(&tcx.sess.target.cpu).to_owned();
Box::new((
CodegenResults {
modules,
allocator_module,
metadata_module,
metadata,
- linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
- crate_info: CrateInfo::new(tcx),
+ crate_info: CrateInfo::new(tcx, target_cpu),
},
work_products,
))
use std::cell::RefCell;
use std::ffi::CString;
+use std::lazy::{Lazy, SyncOnceCell};
use std::os::raw::{c_char, c_int};
+use std::sync::{mpsc, Mutex};
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem;
+use rustc_session::Session;
use cranelift_jit::{JITBuilder, JITModule};
static LAZY_JIT_STATE: RefCell<Option<JitState>> = RefCell::new(None);
}
+/// The Sender owned by the rustc thread
+static GLOBAL_MESSAGE_SENDER: SyncOnceCell<Mutex<mpsc::Sender<UnsafeMessage>>> =
+ SyncOnceCell::new();
+
+/// A message that is sent from the jitted runtime to the rustc thread.
+/// Senders are responsible for upholding `Send` semantics.
+enum UnsafeMessage {
+ /// Request that the specified `Instance` be lazily jitted.
+ ///
+ /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
+ /// this message is sent.
+ JitFn {
+ instance_ptr: *const Instance<'static>,
+ trampoline_ptr: *const u8,
+ tx: mpsc::Sender<*const u8>,
+ },
+}
+unsafe impl Send for UnsafeMessage {}
+
+impl UnsafeMessage {
+ /// Send the message.
+ fn send(self) -> Result<(), mpsc::SendError<UnsafeMessage>> {
+ thread_local! {
+ /// The Sender owned by the local thread
+ static LOCAL_MESSAGE_SENDER: Lazy<mpsc::Sender<UnsafeMessage>> = Lazy::new(||
+ GLOBAL_MESSAGE_SENDER
+ .get().unwrap()
+ .lock().unwrap()
+ .clone()
+ );
+ }
+ LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self))
+ }
+}
+
fn create_jit_module<'tcx>(
tcx: TyCtxt<'tcx>,
backend_config: &BackendConfig,
hotswap: bool,
) -> (JITModule, CodegenCx<'tcx>) {
- let imported_symbols = load_imported_symbols_for_jit(tcx);
+ let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
+ let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
let isa = crate::build_isa(tcx.sess, backend_config);
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
.chain(backend_config.jit_args.iter().map(|arg| &**arg))
.map(|arg| CString::new(arg).unwrap())
.collect::<Vec<_>>();
- let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
-
- // Push a null pointer as a terminating argument. This is required by POSIX and
- // useful as some dynamic linkers use it as a marker to jump over.
- argv.push(std::ptr::null());
let start_sig = Signature {
params: vec![
AbiParam::new(jit_module.target_config().pointer_type()),
],
returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)],
- call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
+ call_conv: jit_module.target_config().default_call_conv,
};
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_start) };
- let ret = f(args.len() as c_int, argv.as_ptr());
- std::process::exit(ret);
+
+ let (tx, rx) = mpsc::channel();
+ GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
+
+ // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
+ // (eg to lazily JIT further functions as required)
+ std::thread::spawn(move || {
+ let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
+
+ // Push a null pointer as a terminating argument. This is required by POSIX and
+ // useful as some dynamic linkers use it as a marker to jump over.
+ argv.push(std::ptr::null());
+
+ let ret = f(args.len() as c_int, argv.as_ptr());
+ std::process::exit(ret);
+ });
+
+ // Handle messages
+ loop {
+ match rx.recv().unwrap() {
+ // lazy JIT compilation request - compile requested instance and return pointer to result
+ UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
+ tx.send(jit_fn(instance_ptr, trampoline_ptr))
+ .expect("jitted runtime hung up before response to lazy JIT request was sent");
+ }
+ }
+ }
}
#[no_mangle]
-extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8 {
+extern "C" fn __clif_jit_fn(
+ instance_ptr: *const Instance<'static>,
+ trampoline_ptr: *const u8,
+) -> *const u8 {
+ // send the JIT request to the rustc thread, with a channel for the response
+ let (tx, rx) = mpsc::channel();
+ UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }
+ .send()
+ .expect("rustc thread hung up before lazy JIT request was sent");
+
+ // block on JIT compilation result
+ rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
+}
+
+fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
rustc_middle::ty::tls::with(|tcx| {
// lift is used to ensure the correct lifetime for instance.
let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
let name = tcx.symbol_name(instance).name;
let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
+
+ let current_ptr = jit_module.read_got_entry(func_id);
+
+ // If the function's GOT entry has already been updated to point at something other
+ // than the shim trampoline, don't re-jit but just return the new pointer instead.
+ // This does not need synchronization as this code is executed only by a sole rustc
+ // thread.
+ if current_ptr != trampoline_ptr {
+ return current_ptr;
+ }
+
jit_module.prepare_for_function_redefine(func_id).unwrap();
let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false);
})
}
-fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
+fn load_imported_symbols_for_jit(
+ sess: &Session,
+ crate_info: CrateInfo,
+) -> Vec<(String, *const u8)> {
use rustc_middle::middle::dependency_format::Linkage;
let mut dylib_paths = Vec::new();
- let crate_info = CrateInfo::new(tcx);
- let formats = tcx.dependency_formats(());
- let data = &formats
+ let data = &crate_info
+ .dependency_formats
.iter()
.find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable)
.unwrap()
.1;
- for &(cnum, _) in &crate_info.used_crates_dynamic {
+ for &cnum in &crate_info.used_crates {
let src = &crate_info.used_crate_source[&cnum];
match data[cnum.as_usize() - 1] {
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
Linkage::Static => {
- let name = tcx.crate_name(cnum);
- let mut err =
- tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
+ let name = &crate_info.crate_name[&cnum];
+ let mut err = sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
err.emit();
}
std::mem::forget(lib)
}
- tcx.sess.abort_if_errors();
+ sess.abort_if_errors();
imported_symbols
}
Linkage::Import,
&Signature {
call_conv: module.target_config().default_call_conv,
- params: vec![AbiParam::new(pointer_type)],
+ params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
returns: vec![AbiParam::new(pointer_type)],
},
)
let mut builder_ctx = FunctionBuilderContext::new();
let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
+ let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
let sig_ref = trampoline_builder.func.import_signature(sig);
trampoline_builder.switch_to_block(entry_block);
let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
- let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr]);
+ let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
+ let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
dest.write_cvalue(fx, a);
};
+ "llvm.x86.addcarry.64", (v c_in, c a, c b) {
+ llvm_add_sub(
+ fx,
+ BinOp::Add,
+ ret,
+ c_in,
+ a,
+ b
+ );
+ };
+ "llvm.x86.subborrow.64", (v b_in, c a, c b) {
+ llvm_add_sub(
+ fx,
+ BinOp::Sub,
+ ret,
+ b_in,
+ a,
+ b
+ );
+ };
}
if let Some((_, dest)) = destination {
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w
+
+fn llvm_add_sub<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ bin_op: BinOp,
+ ret: CPlace<'tcx>,
+ cb_in: Value,
+ a: CValue<'tcx>,
+ b: CValue<'tcx>,
+) {
+ assert_eq!(
+ a.layout().ty,
+ fx.tcx.types.u64,
+ "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64"
+ );
+ assert_eq!(
+ b.layout().ty,
+ fx.tcx.types.u64,
+ "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64"
+ );
+
+ // c + carry -> c + first intermediate carry or borrow respectively
+ let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b);
+ let c = int0.value_field(fx, mir::Field::new(0));
+ let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
+
+ // c + carry -> c + second intermediate carry or borrow respectively
+ let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
+ let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
+ let int1 = crate::num::codegen_checked_int_binop(fx, bin_op, c, cb_in_as_u64);
+ let (c, cb1) = int1.load_scalar_pair(fx);
+
+ // carry0 | carry1 -> carry or borrow respectively
+ let cb_out = fx.bcx.ins().bor(cb0, cb1);
+
+ let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+ let val = CValue::by_val_pair(cb_out, c, layout);
+ ret.write_cvalue(fx, val);
+}
);
ret.write_cvalue(fx, CValue::by_val(res, ret.layout()));
};
+
+ raw_eq, <T>(v lhs_ref, v rhs_ref) {
+ fn type_by_size(size: Size) -> Option<Type> {
+ Type::int(size.bits().try_into().ok()?)
+ }
+
+ let size = fx.layout_of(T).layout.size;
+ let is_eq_value =
+ if size == Size::ZERO {
+ // No bytes means they're trivially equal
+ fx.bcx.ins().iconst(types::I8, 1)
+ } else if let Some(clty) = type_by_size(size) {
+ // Can't use `trusted` for these loads; they could be unaligned.
+ let mut flags = MemFlags::new();
+ flags.set_notrap();
+ let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0);
+ let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0);
+ let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val);
+ fx.bcx.ins().bint(types::I8, eq)
+ } else {
+ // Just call `memcmp` (like slices do in core) when the
+ // size is too large or it's not a power-of-two.
+ let ptr_ty = pointer_ty(fx.tcx);
+ let signed_bytes = i64::try_from(size.bytes()).unwrap();
+ let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes);
+ let params = vec![AbiParam::new(ptr_ty); 3];
+ let returns = vec![AbiParam::new(types::I32)];
+ let args = &[lhs_ref, rhs_ref, bytes_val];
+ let cmp = fx.lib_call("memcmp", params, returns, args)[0];
+ let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0);
+ fx.bcx.ins().bint(types::I8, eq)
+ };
+ ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
+ };
}
if let Some((_, dest)) = destination {
-#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
+#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
+extern crate rustc_interface;
extern crate rustc_metadata;
+extern crate rustc_mir;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
sess,
&codegen_results,
outputs,
- &codegen_results.crate_info.local_crate_name.as_str(),
);
Ok(())
}
None => {
let mut builder =
- cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
- // Don't use "haswell" as the default, as it implies `has_lzcnt`.
- // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
- builder.enable("nehalem").unwrap();
+ cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant).unwrap();
+ if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+ // Don't use "haswell" as the default, as it implies `has_lzcnt`.
+ // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
+ builder.enable("nehalem").unwrap();
+ }
builder
}
};
//! Various optimizations specific to cg_clif
+use cranelift_codegen::isa::TargetIsa;
+
use crate::prelude::*;
pub(crate) mod peephole;
pub(crate) fn optimize_function<'tcx>(
tcx: TyCtxt<'tcx>,
+ isa: &dyn TargetIsa,
instance: Instance<'tcx>,
ctx: &mut Context,
clif_comments: &mut crate::pretty_clif::CommentWriter,
) {
// FIXME classify optimizations over opt levels once we have more
- crate::pretty_clif::write_clif_file(tcx, "preopt", None, instance, &ctx, &*clif_comments);
+ crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx, &*clif_comments);
crate::base::verify_func(tcx, &*clif_comments, &ctx.func);
}
pub(crate) fn write_clif_file<'tcx>(
tcx: TyCtxt<'tcx>,
postfix: &str,
- isa: Option<&dyn cranelift_codegen::isa::TargetIsa>,
+ isa: &dyn cranelift_codegen::isa::TargetIsa,
instance: Instance<'tcx>,
context: &cranelift_codegen::Context,
mut clif_comments: &CommentWriter,
tcx,
|| format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix),
|file| {
- let value_ranges = isa
- .map(|isa| context.build_value_labels_ranges(isa).expect("value location ranges"));
-
let mut clif = String::new();
cranelift_codegen::write::decorate_function(
&mut clif_comments,
&mut clif,
&context.func,
- &DisplayFunctionAnnotations { isa, value_ranges: value_ranges.as_ref() },
+ &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None },
)
.unwrap();
- writeln!(file, "test compile")?;
- writeln!(file, "set is_pic")?;
- writeln!(file, "set enable_simd")?;
- writeln!(file, "target {} haswell", crate::target_triple(tcx.sess))?;
+ for flag in isa.flags().iter() {
+ writeln!(file, "set {}", flag)?;
+ }
+ write!(file, "target {}", isa.triple().architecture.to_string())?;
+ for isa_flag in isa.isa_flags().iter() {
+ write!(file, " {}", isa_flag)?;
+ }
+ writeln!(file, "\n")?;
writeln!(file)?;
file.write_all(clif.as_bytes())?;
Ok(())
ptr.store(fx, data, MemFlags::trusted());
ptr.load(fx, dst_ty, MemFlags::trusted())
}
+
+ // `CValue`s should never contain SSA-only types, so if you ended
+ // up here having seen an error like `B1 -> I8`, then before
+ // calling `write_cvalue` you need to add a `bint` instruction.
_ => unreachable!("write_cvalue_transmute: {:?} -> {:?}", src_ty, dst_ty),
};
//fx.bcx.set_val_label(data, cranelift_codegen::ir::ValueLabel::new(var.index()));
//! Codegen vtables and vtable accesses.
//!
//! See `rustc_codegen_ssa/src/meth.rs` for reference.
-// FIXME dedup this logic between miri, cg_llvm and cg_clif
+use crate::constant::data_id_for_alloc_id;
use crate::prelude::*;
-use super::constant::pointer_for_allocation;
fn vtable_memflags() -> MemFlags {
let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
pointer_ty(fx.tcx),
vtable_memflags(),
vtable,
- (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
+ (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32,
)
}
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
- let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) {
- *vtable_ptr
- } else {
- let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
- let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory();
- let vtable_ptr = pointer_for_allocation(fx, vtable_allocation);
-
- fx.vtables.insert((ty, trait_ref), vtable_ptr);
- vtable_ptr
- };
-
- vtable_ptr.get_addr(fx)
+ let alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
+ let data_id =
+ data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
+ let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+ if fx.clif_comments.enabled() {
+ fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
+ }
+ fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}
#!/usr/bin/env bash
set -e
-./build.sh --sysroot none "$@"
+./y.rs build --sysroot none "$@"
rm -r target/out || true
scripts/tests.sh no_sysroot
-./build.sh "$@"
+./y.rs build "$@"
scripts/tests.sh base_sysroot
scripts/tests.sh extended_sysroot
--- /dev/null
+#!/usr/bin/env bash
+#![allow()] /*This line is ignored by bash
+# This block is ignored by rustc
+set -e
+echo "[BUILD] y.rs" 1>&2
+rustc $0 -o ${0/.rs/.bin} -g
+exec ${0/.rs/.bin} $@
+*/
+
+//! The build system for cg_clif
+//!
+//! # Manual compilation
+//!
+//! If your system doesn't support shell scripts you can manually compile and run this file using
+//! for example:
+//!
+//! ```shell
+//! $ rustc y.rs -o build/y.bin
+//! $ build/y.bin
+//! ```
+//!
+//! # Naming
+//!
+//! The name `y.rs` was chosen to not conflict with rustc's `x.py`.
+
+use std::env;
+use std::path::PathBuf;
+use std::process;
+
+#[path = "build_system/build_backend.rs"]
+mod build_backend;
+#[path = "build_system/build_sysroot.rs"]
+mod build_sysroot;
+#[path = "build_system/config.rs"]
+mod config;
+#[path = "build_system/prepare.rs"]
+mod prepare;
+#[path = "build_system/rustc_info.rs"]
+mod rustc_info;
+#[path = "build_system/utils.rs"]
+mod utils;
+
+fn usage() {
+ eprintln!("Usage:");
+ eprintln!(" ./y.rs prepare");
+ eprintln!(" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]");
+}
+
+macro_rules! arg_error {
+ ($($err:tt)*) => {{
+ eprintln!($($err)*);
+ usage();
+ std::process::exit(1);
+ }};
+}
+
+enum Command {
+ Build,
+}
+
+#[derive(Copy, Clone)]
+enum SysrootKind {
+ None,
+ Clif,
+ Llvm,
+}
+
+fn main() {
+ env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
+ env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
+ // The target dir is expected in the default location. Guard against the user changing it.
+ env::set_var("CARGO_TARGET_DIR", "target");
+
+ let mut args = env::args().skip(1);
+ let command = match args.next().as_deref() {
+ Some("prepare") => {
+ if args.next().is_some() {
+ arg_error!("./x.rs prepare doesn't expect arguments");
+ }
+ prepare::prepare();
+ process::exit(0);
+ }
+ Some("build") => Command::Build,
+ Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
+ Some(command) => arg_error!("Unknown command {}", command),
+ None => {
+ usage();
+ process::exit(0);
+ }
+ };
+
+ let mut target_dir = PathBuf::from("build");
+ let mut channel = "release";
+ let mut sysroot_kind = SysrootKind::Clif;
+ while let Some(arg) = args.next().as_deref() {
+ match arg {
+ "--target-dir" => {
+ target_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+ arg_error!("--target-dir requires argument");
+ }))
+ }
+ "--debug" => channel = "debug",
+ "--sysroot" => {
+ sysroot_kind = match args.next().as_deref() {
+ Some("none") => SysrootKind::None,
+ Some("clif") => SysrootKind::Clif,
+ Some("llvm") => SysrootKind::Llvm,
+ Some(arg) => arg_error!("Unknown sysroot kind {}", arg),
+ None => arg_error!("--sysroot requires argument"),
+ }
+ }
+ flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag),
+ arg => arg_error!("Unexpected argument {}", arg),
+ }
+ }
+
+ let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
+ host_triple
+ } else if let Some(host_triple) = crate::config::get_value("host") {
+ host_triple
+ } else {
+ rustc_info::get_host_triple()
+ };
+ let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") {
+ if target_triple != "" {
+ target_triple
+ } else {
+ host_triple.clone() // Empty target triple can happen on GHA
+ }
+ } else if let Some(target_triple) = crate::config::get_value("target") {
+ target_triple
+ } else {
+ host_triple.clone()
+ };
+
+ if target_triple.ends_with("-msvc") {
+ eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
+ eprintln!("Switch to the MinGW toolchain for Windows support.");
+ eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
+ eprintln!("set the global default target to MinGW");
+ process::exit(1);
+ }
+
+ let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple);
+ build_sysroot::build_sysroot(
+ channel,
+ sysroot_kind,
+ &target_dir,
+ cg_clif_build_dir,
+ &host_triple,
+ &target_triple,
+ );
+}
let mut clobbers = vec![];
let mut output_types = vec![];
let mut op_idx = FxHashMap::default();
+ let mut clobbered_x87 = false;
for (idx, op) in operands.iter().enumerate() {
match *op {
InlineAsmOperandRef::Out { reg, late, place } => {
let ty = if let Some(ref place) = place {
layout = Some(&place.layout);
llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout)
- } else if !is_target_supported(reg.reg_class()) {
+ } else if matches!(
+ reg.reg_class(),
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::x87_reg
+ )
+ ) {
+ // Special handling for x87/mmx registers: we always
+ // clobber the whole set if one register is marked as
+ // clobbered. This is due to the way LLVM handles the
+ // FP stack in inline assembly.
+ if !clobbered_x87 {
+ clobbered_x87 = true;
+ clobbers.push("~{st}".to_string());
+ for i in 1..=7 {
+ clobbers.push(format!("~{{st({})}}", i));
+ }
+ }
+ continue;
+ } else if !is_target_supported(reg.reg_class())
+ || reg.reg_class().is_clobber_only(asm_arch)
+ {
// We turn discarded outputs into clobber constraints
// if the target feature needed by the register class is
// disabled. This is necessary otherwise LLVM will try
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
+ ) => unreachable!("clobber-only"),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
if modifier == Some('v') { None } else { modifier }
}
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
InlineAsmRegClass::PowerPC(_) => None,
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
None if arch == InlineAsmArch::X86_64 => Some('q'),
_ => unreachable!(),
},
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
InlineAsmRegClass::Bpf(_) => None,
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
cx.type_vector(cx.type_i64(), 2)
}
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
use rustc_data_structures::temp_dir::MaybeTempDir;
-use rustc_middle::middle::cstore::DllImport;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
use rustc_session::Session;
use rustc_span::symbol::Symbol;
// have any \0 characters
let import_name_vector: Vec<CString> = dll_imports
.iter()
- .map(if self.config.sess.target.arch == "x86" {
- |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap()
- } else {
- |import: &DllImport| CString::new(import.name.to_string()).unwrap()
+ .map(|import: &DllImport| {
+ if self.config.sess.target.arch == "x86" {
+ LlvmArchiveBuilder::i686_decorated_name(import)
+ } else {
+ CString::new(import.name.to_string()).unwrap()
+ }
})
.collect();
ret
}
}
+
+ fn i686_decorated_name(import: &DllImport) -> CString {
+ let name = import.name;
+ // We verified during construction that `name` does not contain any NULL characters, so the
+ // conversion to CString is guaranteed to succeed.
+ CString::new(match import.calling_convention {
+ DllCallingConvention::C => format!("_{}", name),
+ DllCallingConvention::Stdcall(arg_list_size) => format!("_{}@{}", name, arg_list_size),
+ DllCallingConvention::Fastcall(arg_list_size) => format!("@{}@{}", name, arg_list_size),
+ DllCallingConvention::Vectorcall(arg_list_size) => {
+ format!("{}@@{}", name, arg_list_size)
+ }
+ })
+ .unwrap()
+ }
}
fn string_to_io_error(s: String) -> io::Error {
}
}
- fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
+ fn load(&mut self, ty: &'ll Type, ptr: &'ll Value, align: Align) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
+ let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
load
}
}
- fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
+ fn volatile_load(&mut self, ty: &'ll Type, ptr: &'ll Value) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
+ let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
llvm::LLVMSetVolatile(load, llvm::True);
load
}
fn atomic_load(
&mut self,
+ ty: &'ll Type,
ptr: &'ll Value,
order: rustc_codegen_ssa::common::AtomicOrdering,
size: Size,
unsafe {
let load = llvm::LLVMRustBuildAtomicLoad(
self.llbuilder,
+ ty,
ptr,
UNNAMED,
AtomicOrdering::from_generic(order),
}
}
let llval = const_llval.unwrap_or_else(|| {
- let load = self.load(place.llval, place.align);
+ let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
scalar_load_metadata(self, load, scalar);
}
let mut load = |i, scalar: &abi::Scalar, align| {
let llptr = self.struct_gep(place.llval, i as u64);
- let load = self.load(llptr, align);
+ let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
+ let load = self.load(llty, llptr, align);
scalar_load_metadata(self, load, scalar);
self.to_immediate_scalar(load, scalar)
};
size: &'ll Value,
flags: MemFlags,
) {
- if flags.contains(MemFlags::NONTEMPORAL) {
- // HACK(nox): This is inefficient but there is no nontemporal memcpy.
- let val = self.load(src, src_align);
- let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
- self.store_with_flags(val, ptr, dst_align, flags);
- return;
- }
+ assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
let size = self.intcast(size, self.type_isize(), false);
let is_volatile = flags.contains(MemFlags::VOLATILE);
let dst = self.pointercast(dst, self.type_i8p());
size: &'ll Value,
flags: MemFlags,
) {
- if flags.contains(MemFlags::NONTEMPORAL) {
- // HACK(nox): This is inefficient but there is no nontemporal memmove.
- let val = self.load(src, src_align);
- let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
- self.store_with_flags(val, ptr, dst_align, flags);
- return;
- }
+ assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
let size = self.intcast(size, self.type_isize(), false);
let is_volatile = flags.contains(MemFlags::VOLATILE);
let dst = self.pointercast(dst, self.type_i8p());
let t_i32 = self.type_i32();
let t_i64 = self.type_i64();
let t_i128 = self.type_i128();
+ let t_isize = self.type_isize();
let t_f32 = self.type_f32();
let t_f64 = self.type_f64();
ifn!("llvm.assume", fn(i1) -> void);
ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
+ // This isn't an "LLVM intrinsic", but LLVM's optimization passes
+ // recognize it like one and we assume it exists in `core::slice::cmp`
+ ifn!("memcmp", fn(i8p, i8p, t_isize) -> t_i32);
+
// variadic intrinsics
ifn!("llvm.va_start", fn(i8p) -> void);
ifn!("llvm.va_end", fn(i8p) -> void);
// LLVM to keep around the reference to the global.
let indices = [bx.const_i32(0), bx.const_i32(0)];
let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
- let volative_load_instruction = bx.volatile_load(element);
+ let volative_load_instruction = bx.volatile_load(bx.type_i8(), element);
unsafe {
llvm::LLVMSetAlignment(volative_load_instruction, 1);
}
-use self::EnumTagInfo::*;
use self::MemberDescriptionFactory::*;
use self::RecursiveTypeDescription::*;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ich::NodeIdHashingMode;
-use rustc_middle::mir::{self, Field, GeneratorLayout};
+use rustc_middle::mir::{self, GeneratorLayout};
use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::Instance;
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
- VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>),
+ VariantMDF(VariantMemberDescriptionFactory<'tcx>),
}
impl MemberDescriptionFactory<'ll, 'tcx> {
}
let variant_info = variant_info_for(index);
- let (variant_type_metadata, member_description_factory) = describe_enum_variant(
- cx,
- self.layout,
- variant_info,
- None,
- self_metadata,
- self.span,
- );
+ let (variant_type_metadata, member_description_factory) =
+ describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span);
let member_descriptions = member_description_factory.create_member_descriptions(cx);
Some(&self.common_members),
);
vec![MemberDescription {
- name: if fallback { String::new() } else { variant_info.variant_name() },
+ name: variant_info.variant_name(),
type_metadata: variant_type_metadata,
offset: Size::ZERO,
size: self.layout.size,
ref variants,
..
} => {
- let tag_info = if fallback {
- // For MSVC, we generate a union of structs for each variant with an explicit
- // discriminant field roughly equivalent to the following C:
+ let fallback_discr_variant = if fallback {
+ // For MSVC, we generate a union of structs for each variant and an
+ // explicit discriminant field roughly equivalent to the following C:
// ```c
// union enum$<{name}> {
// struct {variant 0 name} {
- // tag$ variant$;
// <variant 0 fields>
// } variant0;
// <other variant structs>
+ // {name} discriminant;
// }
// ```
- // The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to
+ // The natvis in `intrinsic.natvis` then matches on `this.discriminant` to
// determine which variant is active and then displays it.
- Some(DirectTag {
- tag_field: Field::from(tag_field),
- tag_type_metadata: self.tag_type_metadata.unwrap(),
+ let enum_layout = self.layout;
+ let offset = enum_layout.fields.offset(tag_field);
+ let discr_ty = enum_layout.field(cx, tag_field).ty;
+ let (size, align) = cx.size_and_align_of(discr_ty);
+ Some(MemberDescription {
+ name: "discriminant".into(),
+ type_metadata: self.tag_type_metadata.unwrap(),
+ offset,
+ size,
+ align,
+ flags: DIFlags::FlagZero,
+ discriminant: None,
+ source_info: None,
})
} else {
- // This doesn't matter in this case.
None
};
+
variants
.iter_enumerated()
.map(|(i, _)| {
cx,
variant,
variant_info,
- tag_info,
self_metadata,
self.span,
);
source_info: variant_info.source_info(cx),
}
})
+ .chain(fallback_discr_variant.into_iter())
.collect()
}
Variants::Multiple {
cx,
dataful_variant_layout,
variant_info,
- Some(NicheTag),
self_metadata,
self.span,
);
cx,
variant,
variant_info,
- Some(NicheTag),
self_metadata,
self.span,
);
}
// Creates `MemberDescription`s for the fields of a single enum variant.
-struct VariantMemberDescriptionFactory<'ll, 'tcx> {
+struct VariantMemberDescriptionFactory<'tcx> {
/// Cloned from the `layout::Struct` describing the variant.
offsets: Vec<Size>,
args: Vec<(String, Ty<'tcx>)>,
- tag_type_metadata: Option<&'ll DIType>,
span: Span,
}
-impl VariantMemberDescriptionFactory<'ll, 'tcx> {
+impl VariantMemberDescriptionFactory<'tcx> {
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
self.args
.iter()
.enumerate()
.map(|(i, &(ref name, ty))| {
- // Discriminant is always the first field of our variant
- // when using the enum fallback.
- let is_artificial_discr = use_enum_fallback(cx) && i == 0;
let (size, align) = cx.size_and_align_of(ty);
MemberDescription {
name: name.to_string(),
- type_metadata: if is_artificial_discr {
- self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span))
- } else {
- type_metadata(cx, ty, self.span)
- },
+ type_metadata: type_metadata(cx, ty, self.span),
offset: self.offsets[i],
size,
align,
- flags: if is_artificial_discr {
- DIFlags::FlagArtificial
- } else {
- DIFlags::FlagZero
- },
+ flags: DIFlags::FlagZero,
discriminant: None,
source_info: None,
}
}
}
-#[derive(Copy, Clone)]
-enum EnumTagInfo<'ll> {
- DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType },
- NicheTag,
-}
-
#[derive(Copy, Clone)]
enum VariantInfo<'a, 'tcx> {
Adt(&'tcx ty::VariantDef),
cx: &CodegenCx<'ll, 'tcx>,
layout: layout::TyAndLayout<'tcx>,
variant: VariantInfo<'_, 'tcx>,
- discriminant_info: Option<EnumTagInfo<'ll>>,
containing_scope: &'ll DIScope,
span: Span,
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
)
});
- // Build an array of (field name, field type) pairs to be captured in the factory closure.
- let (offsets, args) = if use_enum_fallback(cx) {
- // If this is not a univariant enum, there is also the discriminant field.
- let (discr_offset, discr_arg) = match discriminant_info {
- Some(DirectTag { tag_field, .. }) => {
- // We have the layout of an enum variant, we need the layout of the outer enum
- let enum_layout = cx.layout_of(layout.ty);
- let offset = enum_layout.fields.offset(tag_field.as_usize());
- let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
- (Some(offset), Some(args))
- }
- _ => (None, None),
- };
- (
- discr_offset
- .into_iter()
- .chain((0..layout.fields.count()).map(|i| layout.fields.offset(i)))
- .collect(),
- discr_arg
- .into_iter()
- .chain(
- (0..layout.fields.count())
- .map(|i| (variant.field_name(i), layout.field(cx, i).ty)),
- )
- .collect(),
- )
- } else {
- (
- (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(),
- (0..layout.fields.count())
- .map(|i| (variant.field_name(i), layout.field(cx, i).ty))
- .collect(),
- )
- };
+ let offsets = (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect();
+ let args = (0..layout.fields.count())
+ .map(|i| (variant.field_name(i), layout.field(cx, i).ty))
+ .collect();
- let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
- offsets,
- args,
- tag_type_metadata: match discriminant_info {
- Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata),
- _ => None,
- },
- span,
- });
+ let member_description_factory =
+ VariantMDF(VariantMemberDescriptionFactory { offsets, args, span });
(metadata_stub, member_description_factory)
}
sym::volatile_load | sym::unaligned_volatile_load => {
let tp_ty = substs.type_at(0);
- let mut ptr = args[0].immediate();
- if let PassMode::Cast(ty) = fn_abi.ret.mode {
- ptr = self.pointercast(ptr, self.type_ptr_to(ty.llvm_type(self)));
- }
- let load = self.volatile_load(ptr);
+ let ptr = args[0].immediate();
+ let load = if let PassMode::Cast(ty) = fn_abi.ret.mode {
+ let llty = ty.llvm_type(self);
+ let ptr = self.pointercast(ptr, self.type_ptr_to(llty));
+ self.volatile_load(llty, ptr)
+ } else {
+ self.volatile_load(self.layout_of(tp_ty).llvm_type(self), ptr)
+ };
let align = if name == sym::unaligned_volatile_load {
1
} else {
}
}
+ sym::raw_eq => {
+ use abi::Abi::*;
+ let tp_ty = substs.type_at(0);
+ let layout = self.layout_of(tp_ty).layout;
+ let use_integer_compare = match layout.abi {
+ Scalar(_) | ScalarPair(_, _) => true,
+ Uninhabited | Vector { .. } => false,
+ Aggregate { .. } => {
+ // For rusty ABIs, small aggregates are actually passed
+ // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
+ // so we re-use that same threshold here.
+ layout.size <= self.data_layout().pointer_size * 2
+ }
+ };
+
+ let a = args[0].immediate();
+ let b = args[1].immediate();
+ if layout.size.bytes() == 0 {
+ self.const_bool(true)
+ } else if use_integer_compare {
+ let integer_ty = self.type_ix(layout.size.bits());
+ let ptr_ty = self.type_ptr_to(integer_ty);
+ let a_ptr = self.bitcast(a, ptr_ty);
+ let a_val = self.load(integer_ty, a_ptr, layout.align.abi);
+ let b_ptr = self.bitcast(b, ptr_ty);
+ let b_val = self.load(integer_ty, b_ptr, layout.align.abi);
+ self.icmp(IntPredicate::IntEQ, a_val, b_val)
+ } else {
+ let i8p_ty = self.type_i8p();
+ let a_ptr = self.bitcast(a, i8p_ty);
+ let b_ptr = self.bitcast(b, i8p_ty);
+ let n = self.const_usize(layout.size.bytes());
+ let llfn = self.get_intrinsic("memcmp");
+ let cmp = self.call(llfn, &[a_ptr, b_ptr, n], None);
+ self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
+ }
+ }
+
_ if name_str.starts_with("simd_") => {
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
Ok(llval) => llval,
// Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang
let flags = bx.const_i32(8);
let funclet = catchpad_rust.catch_pad(cs, &[tydesc, flags, slot]);
- let ptr = catchpad_rust.load(slot, ptr_align);
+ let ptr = catchpad_rust.load(bx.type_i8p(), slot, ptr_align);
catchpad_rust.call(catch_func, &[data, ptr], Some(&funclet));
catchpad_rust.catch_ret(&funclet, caught.llbb());
// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
- link_binary::<LlvmArchiveBuilder<'_>>(
- sess,
- &codegen_results,
- outputs,
- &codegen_results.crate_info.local_crate_name.as_str(),
- );
+ link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);
Ok(())
}
Val: &'a Value,
Name: *const c_char,
) -> &'a Value;
- pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value;
+ pub fn LLVMBuildLoad2(
+ B: &Builder<'a>,
+ Ty: &'a Type,
+ PointerVal: &'a Value,
+ Name: *const c_char,
+ ) -> &'a Value;
pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value;
// Atomic Operations
pub fn LLVMRustBuildAtomicLoad(
B: &Builder<'a>,
+ ElementType: &'a Type,
PointerVal: &'a Value,
Name: *const c_char,
Order: AtomicOrdering,
slot_size: Align,
allow_higher_align: bool,
) -> (&'ll Value, Align) {
- let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p());
+ let va_list_ty = bx.type_i8p();
+ let va_list_ptr_ty = bx.type_ptr_to(va_list_ty);
let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty {
bx.bitcast(list.immediate(), va_list_ptr_ty)
} else {
list.immediate()
};
- let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi);
+ let ptr = bx.load(va_list_ty, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
let (addr, addr_align) = if allow_higher_align && align > slot_size {
(round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align)
let (addr, addr_align) =
emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align);
if indirect {
- let tmp_ret = bx.load(addr, addr_align);
- bx.load(tmp_ret, align.abi)
+ let tmp_ret = bx.load(llty, addr, addr_align);
+ bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi)
} else {
- bx.load(addr, addr_align)
+ bx.load(llty, addr, addr_align)
}
}
};
// if the offset >= 0 then the value will be on the stack
- let mut reg_off_v = bx.load(reg_off, offset_align);
+ let mut reg_off_v = bx.load(bx.type_i32(), reg_off, offset_align);
let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());
let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());
+ let top_type = bx.type_i8p();
let top = in_reg.struct_gep(va_list_addr, reg_top_index);
- let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);
+ let top = in_reg.load(top_type, top, bx.tcx().data_layout.pointer_align.abi);
// reg_value = *(@top + reg_off_v);
let mut reg_addr = in_reg.gep(top, &[reg_off_v]);
let offset = bx.const_i32((slot_size - layout.size.bytes()) as i32);
reg_addr = in_reg.gep(reg_addr, &[offset]);
}
- let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(layout.llvm_type(bx)));
- let reg_value = in_reg.load(reg_addr, layout.align.abi);
+ let reg_type = layout.llvm_type(bx);
+ let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type));
+ let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi);
in_reg.br(&end.llbb());
// On Stack block
use rustc_errors::Handler;
use rustc_fs_util::fix_windows_verbatim_for_gcc;
use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{DllImport, LibSource};
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
use tempfile::Builder as TempFileBuilder;
-use std::cmp::Ordering;
use std::ffi::OsString;
+use std::iter::FromIterator;
use std::path::{Path, PathBuf};
use std::process::{ExitStatus, Output, Stdio};
use std::{ascii, char, env, fmt, fs, io, mem, str};
sess: &'a Session,
codegen_results: &CodegenResults,
outputs: &OutputFilenames,
- crate_name: &str,
) {
let _timer = sess.timer("link_binary");
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
.tempdir()
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
- let out_filename = out_filename(sess, crate_type, outputs, crate_name);
+ let out_filename = out_filename(
+ sess,
+ crate_type,
+ outputs,
+ &codegen_results.crate_info.local_crate_name.as_str(),
+ );
match crate_type {
CrateType::Rlib => {
let _timer = sess.timer("link_rlib");
});
}
-// The third parameter is for env vars, used on windows to set up the
-// path for MSVC to find its DLLs, and gcc to find its bundled
-// toolchain
-fn get_linker(
- sess: &Session,
- linker: &Path,
- flavor: LinkerFlavor,
- self_contained: bool,
-) -> Command {
- let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
-
- // If our linker looks like a batch script on Windows then to execute this
- // we'll need to spawn `cmd` explicitly. This is primarily done to handle
- // emscripten where the linker is `emcc.bat` and needs to be spawned as
- // `cmd /c emcc.bat ...`.
- //
- // This worked historically but is needed manually since #42436 (regression
- // was tagged as #42791) and some more info can be found on #44443 for
- // emscripten itself.
- let mut cmd = match linker.to_str() {
- Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
- _ => match flavor {
- LinkerFlavor::Lld(f) => Command::lld(linker, f),
- LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
- Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
- }
- _ => Command::new(linker),
- },
- };
-
- // UWP apps have API restrictions enforced during Store submissions.
- // To comply with the Windows App Certification Kit,
- // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
- let t = &sess.target;
- if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
- && t.vendor == "uwp"
- {
- if let Some(ref tool) = msvc_tool {
- let original_path = tool.path();
- if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
- let arch = match t.arch.as_str() {
- "x86_64" => Some("x64"),
- "x86" => Some("x86"),
- "aarch64" => Some("arm64"),
- "arm" => Some("arm"),
- _ => None,
- };
- if let Some(ref a) = arch {
- // FIXME: Move this to `fn linker_with_args`.
- let mut arg = OsString::from("/LIBPATH:");
- arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
- cmd.arg(&arg);
- } else {
- warn!("arch is not supported");
- }
- } else {
- warn!("MSVC root path lib location not found");
- }
- } else {
- warn!("link.exe not found");
- }
- }
-
- // The compiler's sysroot often has some bundled tools, so add it to the
- // PATH for the child.
- let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
- let mut msvc_changed_path = false;
- if sess.target.is_like_msvc {
- if let Some(ref tool) = msvc_tool {
- cmd.args(tool.args());
- for &(ref k, ref v) in tool.env() {
- if k == "PATH" {
- new_path.extend(env::split_paths(v));
- msvc_changed_path = true;
- } else {
- cmd.env(k, v);
- }
- }
- }
- }
-
- if !msvc_changed_path {
- if let Some(path) = env::var_os("PATH") {
- new_path.extend(env::split_paths(&path));
- }
- }
- cmd.env("PATH", env::join_paths(new_path).unwrap());
-
- cmd
-}
-
pub fn each_linked_rlib(
info: &CrateInfo,
f: &mut dyn FnMut(CrateNum, &Path),
) -> Result<(), String> {
- let crates = info.used_crates_static.iter();
+ let crates = info.used_crates.iter();
let mut fmts = None;
for (ty, list) in info.dependency_formats.iter() {
match ty {
Some(f) => f,
None => return Err("could not find formats for rlibs".to_string()),
};
- for &(cnum, ref path) in crates {
+ for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {
Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue,
Some(_) => {}
None => return Err("could not find formats for rlibs".to_string()),
}
let name = &info.crate_name[&cnum];
- let path = match *path {
- LibSource::Some(ref p) => p,
- LibSource::MetadataOnly => {
- return Err(format!(
- "could not find rlib for: `{}`, found rmeta (metadata) file",
- name
- ));
- }
- LibSource::None => return Err(format!("could not find rlib for: `{}`", name)),
+ let used_crate_source = &info.used_crate_source[&cnum];
+ let path = if let Some((path, _)) = &used_crate_source.rlib {
+ path
+ } else if used_crate_source.rmeta.is_some() {
+ return Err(format!(
+ "could not find rlib for: `{}`, found rmeta (metadata) file",
+ name
+ ));
+ } else {
+ return Err(format!("could not find rlib for: `{}`", name));
};
f(cnum, &path);
}
}
for (raw_dylib_name, raw_dylib_imports) in
- collate_raw_dylibs(&codegen_results.crate_info.used_libraries)
+ collate_raw_dylibs(sess, &codegen_results.crate_info.used_libraries)
{
ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
}
/// then the CodegenResults value contains one NativeLib instance for each block. However, the
/// linker appears to expect only a single import library for each library used, so we need to
/// collate the symbols together by library name before generating the import libraries.
-fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> {
- let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default();
+fn collate_raw_dylibs(
+ sess: &Session,
+ used_libraries: &[NativeLib],
+) -> Vec<(String, Vec<DllImport>)> {
+ let mut dylib_table: FxHashMap<String, FxHashSet<DllImport>> = FxHashMap::default();
for lib in used_libraries {
if lib.kind == NativeLibKind::RawDylib {
} else {
format!("{}.dll", name)
};
- dylib_table
- .entry(name)
- .or_default()
- .extend(lib.dll_imports.iter().map(|import| import.name));
+ dylib_table.entry(name).or_default().extend(lib.dll_imports.iter().cloned());
}
}
- // FIXME: when we add support for ordinals, fix this to propagate ordinals. Also figure out
- // what we should do if we have two DllImport values with the same name but different
- // ordinals.
- let mut result = dylib_table
+ // Rustc already signals an error if we have two imports with the same name but different
+ // calling conventions (or function signatures), so we don't have pay attention to those
+ // when ordering.
+ // FIXME: when we add support for ordinals, figure out if we need to do anything if we
+ // have two DllImport values with the same name but different ordinals.
+ let mut result: Vec<(String, Vec<DllImport>)> = dylib_table
.into_iter()
- .map(|(lib_name, imported_names)| {
- let mut names = imported_names
- .iter()
- .map(|name| DllImport { name: *name, ordinal: None })
- .collect::<Vec<_>>();
- names.sort_unstable_by(|a: &DllImport, b: &DllImport| {
- match a.name.as_str().cmp(&b.name.as_str()) {
- Ordering::Equal => a.ordinal.cmp(&b.ordinal),
- x => x,
- }
- });
- (lib_name, names)
+ .map(|(lib_name, import_table)| {
+ let mut imports = Vec::from_iter(import_table.into_iter());
+ imports.sort_unstable_by_key(|x: &DllImport| x.name.as_str());
+ (lib_name, imports)
})
.collect::<Vec<_>>();
result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
a.0.cmp(&b.0)
});
+ let result = result;
+
+ // Check for multiple imports with the same name but different calling conventions or
+ // (when relevant) argument list sizes. Rustc only signals an error for this if the
+ // declarations are at the same scope level; if one shadows the other, we only get a lint
+ // warning.
+ for (library, imports) in &result {
+ let mut import_table: FxHashMap<Symbol, DllCallingConvention> = FxHashMap::default();
+ for import in imports {
+ if let Some(old_convention) =
+ import_table.insert(import.name, import.calling_convention)
+ {
+ if import.calling_convention != old_convention {
+ sess.span_fatal(
+ import.span,
+ &format!(
+ "multiple definitions of external function `{}` from library `{}` have different calling conventions",
+ import.name,
+ library,
+ ));
+ }
+ }
+ }
+ }
+
result
}
// where extern libraries might live, based on the
// add_lib_search_paths
if sess.opts.cg.rpath {
+ let libs = codegen_results
+ .crate_info
+ .used_crates
+ .iter()
+ .filter_map(|cnum| {
+ codegen_results.crate_info.used_crate_source[cnum]
+ .dylib
+ .as_ref()
+ .map(|(path, _)| &**path)
+ })
+ .collect::<Vec<_>>();
let mut rpath_config = RPathConfig {
- used_crates: &codegen_results.crate_info.used_crates_dynamic,
+ libs: &*libs,
out_filename: out_filename.to_path_buf(),
has_rpath: sess.target.has_rpath,
is_like_osx: sess.target.is_like_osx,
codegen_results: &CodegenResults,
) -> Command {
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
- let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
- // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
- // to the linker args construction.
- assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
- let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
+ let cmd = &mut *super::linker::get_linker(
+ sess,
+ path,
+ flavor,
+ crt_objects_fallback,
+ &codegen_results.crate_info.target_cpu,
+ );
let link_output_kind = link_output_kind(sess, crate_type);
// ------------ Early order-dependent options ------------
// dynamic library.
// Must be passed before any libraries to prevent the symbols to export from being thrown away,
// at least on some platforms (e.g. windows-gnu).
- cmd.export_symbols(tmpdir, crate_type);
+ cmd.export_symbols(
+ tmpdir,
+ crate_type,
+ &codegen_results.crate_info.exported_symbols[&crate_type],
+ );
// Can be used for adding custom CRT objects or overriding order-dependent options above.
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
if flavor == LinkerFlavor::PtxLinker {
// Provide the linker with fallback to internal `target-cpu`.
cmd.arg("--fallback-arch");
- cmd.arg(&codegen_results.linker_info.target_cpu);
+ cmd.arg(&codegen_results.crate_info.target_cpu);
} else if flavor == LinkerFlavor::BpfLinker {
cmd.arg("--cpu");
- cmd.arg(&codegen_results.linker_info.target_cpu);
+ cmd.arg(&codegen_results.crate_info.target_cpu);
cmd.arg("--cpu-features");
cmd.arg(match &sess.opts.cg.target_feature {
feat if !feat.is_empty() => feat,
// Invoke get_used_crates to ensure that we get a topological sorting of
// crates.
- let deps = &codegen_results.crate_info.used_crates_dynamic;
+ let deps = &codegen_results.crate_info.used_crates;
// There's a few internal crates in the standard library (aka libcore and
// libstd) which actually have a circular dependence upon one another. This
let mut required = FxHashSet::default();
let info = &codegen_results.crate_info;
- for &(cnum, _) in deps.iter().rev() {
+ for &cnum in deps.iter().rev() {
if let Some(missing) = info.missing_lang_items.get(&cnum) {
let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied());
required.extend(missing_crates);
let mut compiler_builtins = None;
- for &(cnum, _) in deps.iter() {
+ for &cnum in deps.iter() {
if group_start == Some(cnum) {
cmd.group_start();
}
.find(|(ty, _)| *ty == crate_type)
.expect("failed to find crate type in dependency format list");
- let crates = &codegen_results.crate_info.used_crates_static;
+ let crates = &codegen_results.crate_info.used_crates;
let mut last = (NativeLibKind::Unspecified, None);
- for &(cnum, _) in crates {
+ for &cnum in crates {
for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
let name = match lib.name {
Some(l) => l,
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
-use std::mem;
use std::path::{Path, PathBuf};
+use std::{env, mem, str};
-use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{json, Encoder};
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
+use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_span::symbol::Symbol;
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
+use cc::windows_registry;
+
/// Disables non-English messages from localized linkers.
/// Such messages may cause issues with text encoding on Windows (#35785)
/// and prevent inspection of linker output in case of errors, which we occasionally do.
linker.env("VSLANG", "1033");
}
-/// For all the linkers we support, and information they might
-/// need out of the shared crate context before we get rid of it.
-#[derive(Encodable, Decodable)]
-pub struct LinkerInfo {
- pub(super) target_cpu: String,
- exports: FxHashMap<CrateType, Vec<String>>,
-}
-
-impl LinkerInfo {
- pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> LinkerInfo {
- LinkerInfo {
- target_cpu,
- exports: tcx
- .sess
- .crate_types()
- .iter()
- .map(|&c| (c, exported_symbols(tcx, c)))
- .collect(),
+// The third parameter is for env vars, used on windows to set up the
+// path for MSVC to find its DLLs, and gcc to find its bundled
+// toolchain
+pub fn get_linker<'a>(
+ sess: &'a Session,
+ linker: &Path,
+ flavor: LinkerFlavor,
+ self_contained: bool,
+ target_cpu: &'a str,
+) -> Box<dyn Linker + 'a> {
+ let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
+
+ // If our linker looks like a batch script on Windows then to execute this
+ // we'll need to spawn `cmd` explicitly. This is primarily done to handle
+ // emscripten where the linker is `emcc.bat` and needs to be spawned as
+ // `cmd /c emcc.bat ...`.
+ //
+ // This worked historically but is needed manually since #42436 (regression
+ // was tagged as #42791) and some more info can be found on #44443 for
+ // emscripten itself.
+ let mut cmd = match linker.to_str() {
+ Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
+ _ => match flavor {
+ LinkerFlavor::Lld(f) => Command::lld(linker, f),
+ LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
+ Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
+ }
+ _ => Command::new(linker),
+ },
+ };
+
+ // UWP apps have API restrictions enforced during Store submissions.
+ // To comply with the Windows App Certification Kit,
+ // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
+ let t = &sess.target;
+ if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
+ && t.vendor == "uwp"
+ {
+ if let Some(ref tool) = msvc_tool {
+ let original_path = tool.path();
+ if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
+ let arch = match t.arch.as_str() {
+ "x86_64" => Some("x64"),
+ "x86" => Some("x86"),
+ "aarch64" => Some("arm64"),
+ "arm" => Some("arm"),
+ _ => None,
+ };
+ if let Some(ref a) = arch {
+ // FIXME: Move this to `fn linker_with_args`.
+ let mut arg = OsString::from("/LIBPATH:");
+ arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
+ cmd.arg(&arg);
+ } else {
+ warn!("arch is not supported");
+ }
+ } else {
+ warn!("MSVC root path lib location not found");
+ }
+ } else {
+ warn!("link.exe not found");
}
}
- pub fn to_linker<'a>(
- &'a self,
- cmd: Command,
- sess: &'a Session,
- flavor: LinkerFlavor,
- ) -> Box<dyn Linker + 'a> {
- match flavor {
- LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
- Box::new(MsvcLinker { cmd, sess, info: self }) as Box<dyn Linker>
- }
- LinkerFlavor::Em => Box::new(EmLinker { cmd, sess, info: self }) as Box<dyn Linker>,
- LinkerFlavor::Gcc => {
- Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: false })
- as Box<dyn Linker>
+ // The compiler's sysroot often has some bundled tools, so add it to the
+ // PATH for the child.
+ let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
+ let mut msvc_changed_path = false;
+ if sess.target.is_like_msvc {
+ if let Some(ref tool) = msvc_tool {
+ cmd.args(tool.args());
+ for &(ref k, ref v) in tool.env() {
+ if k == "PATH" {
+ new_path.extend(env::split_paths(v));
+ msvc_changed_path = true;
+ } else {
+ cmd.env(k, v);
+ }
}
+ }
+ }
- LinkerFlavor::Lld(LldFlavor::Ld)
- | LinkerFlavor::Lld(LldFlavor::Ld64)
- | LinkerFlavor::Ld => {
- Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: true })
- as Box<dyn Linker>
- }
+ if !msvc_changed_path {
+ if let Some(path) = env::var_os("PATH") {
+ new_path.extend(env::split_paths(&path));
+ }
+ }
+ cmd.env("PATH", env::join_paths(new_path).unwrap());
- LinkerFlavor::Lld(LldFlavor::Wasm) => {
- Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
- }
+ // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
+ // to the linker args construction.
+ assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
- LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+ match flavor {
+ LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
+ Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
+ }
+ LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
+ LinkerFlavor::Gcc => {
+ Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
+ as Box<dyn Linker>
+ }
- LinkerFlavor::BpfLinker => {
- Box::new(BpfLinker { cmd, sess, info: self }) as Box<dyn Linker>
- }
+ LinkerFlavor::Lld(LldFlavor::Ld)
+ | LinkerFlavor::Lld(LldFlavor::Ld64)
+ | LinkerFlavor::Ld => {
+ Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
+ as Box<dyn Linker>
}
+
+ LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
+
+ LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+
+ LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
}
}
fn debuginfo(&mut self, strip: Strip);
fn no_crt_objects(&mut self);
fn no_default_libraries(&mut self);
- fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
+ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
fn subsystem(&mut self, subsystem: &str);
fn group_start(&mut self);
fn group_end(&mut self);
pub struct GccLinker<'a> {
cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo,
+ target_cpu: &'a str,
hinted_static: bool, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
};
self.linker_arg(&format!("-plugin-opt={}", opt_level));
- self.linker_arg(&format!("-plugin-opt=mcpu={}", self.info.target_cpu));
+ self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu));
}
fn build_dylib(&mut self, out_filename: &Path) {
}
}
- fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
// Symbol visibility in object files typically takes care of this.
if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none()
{
// Write a plain, newline-separated list of symbols
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
- for sym in self.info.exports[&crate_type].iter() {
+ for sym in symbols {
debug!(" _{}", sym);
writeln!(f, "_{}", sym)?;
}
// .def file similar to MSVC one but without LIBRARY section
// because LD doesn't like when it's empty
writeln!(f, "EXPORTS")?;
- for symbol in self.info.exports[&crate_type].iter() {
+ for symbol in symbols {
debug!(" _{}", symbol);
writeln!(f, " {}", symbol)?;
}
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
writeln!(f, "{{")?;
- if !self.info.exports[&crate_type].is_empty() {
+ if !symbols.is_empty() {
writeln!(f, " global:")?;
- for sym in self.info.exports[&crate_type].iter() {
+ for sym in symbols {
debug!(" {};", sym);
writeln!(f, " {};", sym)?;
}
pub struct MsvcLinker<'a> {
cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo,
}
impl<'a> Linker for MsvcLinker<'a> {
// crates. Upstream rlibs may be linked statically to this dynamic library,
// in which case they may continue to transitively be used and hence need
// their symbols exported.
- fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
// Symbol visibility takes care of this typically
if crate_type == CrateType::Executable {
return;
// straight to exports.
writeln!(f, "LIBRARY")?;
writeln!(f, "EXPORTS")?;
- for symbol in self.info.exports[&crate_type].iter() {
+ for symbol in symbols {
debug!(" _{}", symbol);
writeln!(f, " {}", symbol)?;
}
pub struct EmLinker<'a> {
cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo,
}
impl<'a> Linker for EmLinker<'a> {
self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
}
- fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
- let symbols = &self.info.exports[&crate_type];
-
+ fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
debug!("EXPORTED SYMBOLS:");
self.cmd.arg("-s");
pub struct WasmLd<'a> {
cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo,
}
impl<'a> WasmLd<'a> {
- fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
+ fn new(mut cmd: Command, sess: &'a Session) -> WasmLd<'a> {
// If the atomics feature is enabled for wasm then we need a whole bunch
// of flags:
//
cmd.arg("--export=__tls_align");
cmd.arg("--export=__tls_base");
}
- WasmLd { cmd, sess, info }
+ WasmLd { cmd, sess }
}
}
fn no_default_libraries(&mut self) {}
- fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
- for sym in self.info.exports[&crate_type].iter() {
+ fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
+ for sym in symbols {
self.cmd.arg("--export").arg(&sym);
}
}
}
-fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
+pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
return exports.clone();
}
fn control_flow_guard(&mut self) {}
- fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+ fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
fn subsystem(&mut self, _subsystem: &str) {}
pub struct BpfLinker<'a> {
cmd: Command,
sess: &'a Session,
- info: &'a LinkerInfo,
}
impl<'a> Linker for BpfLinker<'a> {
fn control_flow_guard(&mut self) {}
- fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+ fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
let path = tmpdir.join("symbols");
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
- for sym in self.info.exports[&crate_type].iter() {
+ for sym in symbols {
writeln!(f, "{}", sym)?;
}
};
use std::fs;
use std::path::{Path, PathBuf};
-use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::LibSource;
-
pub struct RPathConfig<'a> {
- pub used_crates: &'a [(CrateNum, LibSource)],
+ pub libs: &'a [&'a Path],
pub out_filename: PathBuf,
pub is_like_osx: bool,
pub has_rpath: bool,
debug!("preparing the RPATH!");
- let libs = config.used_crates;
- let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::<Vec<_>>();
- let rpaths = get_rpaths(config, &libs);
+ let rpaths = get_rpaths(config);
let mut flags = rpaths_to_flags(&rpaths);
// Use DT_RUNPATH instead of DT_RPATH if available
ret
}
-fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
+fn get_rpaths(config: &mut RPathConfig<'_>) -> Vec<String> {
debug!("output: {:?}", config.out_filename.display());
debug!("libs:");
- for libpath in libs {
+ for libpath in config.libs {
debug!(" {:?}", libpath.display());
}
// Use relative paths to the libraries. Binaries can be moved
// as long as they maintain the relative relationship to the
// crates they depend on.
- let rpaths = get_rpaths_relative_to_output(config, libs);
+ let rpaths = get_rpaths_relative_to_output(config);
debug!("rpaths:");
for rpath in &rpaths {
minimize_rpaths(&rpaths)
}
-fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
- libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
+fn get_rpaths_relative_to_output(config: &mut RPathConfig<'_>) -> Vec<String> {
+ config.libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect()
}
fn get_rpath_relative_to_output(config: &mut RPathConfig<'_>, lib: &Path) -> String {
fn test_rpath_relative() {
if cfg!(target_os = "macos") {
let config = &mut RPathConfig {
- used_crates: &[],
+ libs: &[],
has_rpath: true,
is_like_osx: true,
linker_is_gnu: false,
assert_eq!(res, "@loader_path/../lib");
} else {
let config = &mut RPathConfig {
- used_crates: &[],
+ libs: &[],
out_filename: PathBuf::from("bin/rustc"),
has_rpath: true,
is_like_osx: false,
use super::link::{self, ensure_removed};
-use super::linker::LinkerInfo;
use super::lto::{self, SerializedModule};
use super::symbol_export::symbol_name_for_instance_in_crate;
let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
- let linker_info = LinkerInfo::new(tcx, target_cpu);
- let crate_info = CrateInfo::new(tcx);
+ let crate_info = CrateInfo::new(tcx, target_cpu);
let regular_config =
ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
OngoingCodegen {
backend,
metadata,
- linker_info,
crate_info,
coordinator_send,
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub metadata: EncodedMetadata,
- pub linker_info: LinkerInfo,
pub crate_info: CrateInfo,
pub coordinator_send: Sender<Box<dyn Any + Send>>,
pub codegen_worker_receive: Receiver<Message<B>>,
(
CodegenResults {
metadata: self.metadata,
- linker_info: self.linker_info,
crate_info: self.crate_info,
modules: compiled_modules.modules,
use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::cstore::EncodedMetadata;
-use rustc_middle::middle::cstore::{self, LinkagePreference};
use rustc_middle::middle::lang_items;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
}
impl CrateInfo {
- pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
+ pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
+ let exported_symbols = tcx
+ .sess
+ .crate_types()
+ .iter()
+ .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
+ .collect();
let local_crate_name = tcx.crate_name(LOCAL_CRATE);
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
subsystem.to_string()
});
+ // This list is used when generating the command line to pass through to
+ // system linker. The linker expects undefined symbols on the left of the
+ // command line to be defined in libraries on the right, not the other way
+ // around. For more info, see some comments in the add_used_library function
+ // below.
+ //
+ // In order to get this left-to-right dependency ordering, we use the reverse
+ // postorder of all crates putting the leaves at the right-most positions.
+ let used_crates = tcx
+ .postorder_cnums(())
+ .iter()
+ .rev()
+ .copied()
+ .filter(|&cnum| !tcx.dep_kind(cnum).macros_only())
+ .collect();
+
let mut info = CrateInfo {
+ target_cpu,
+ exported_symbols,
local_crate_name,
- panic_runtime: None,
compiler_builtins: None,
profiler_runtime: None,
is_no_builtins: Default::default(),
native_libraries: Default::default(),
used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
crate_name: Default::default(),
- used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
- used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
+ used_crates,
used_crate_source: Default::default(),
lang_item_to_crate: Default::default(),
missing_lang_items: Default::default(),
.insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
- if tcx.is_panic_runtime(cnum) {
- info.panic_runtime = Some(cnum);
- }
if tcx.is_compiler_builtins(cnum) {
info.compiler_builtins = Some(cnum);
}
) {
let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
+ output.push_str("enum$<");
+ push_item_name(tcx, def.did, true, output);
+ push_generic_params_internal(tcx, substs, output, visited);
+
if let Variants::Multiple {
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
tag,
let max = dataful_discriminant_range.end();
let max = tag.value.size(&tcx).truncate(*max);
- output.push_str("enum$<");
- push_item_name(tcx, def.did, true, output);
- push_generic_params_internal(tcx, substs, output, visited);
-
let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
- output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
- } else {
- output.push_str("enum$<");
- push_item_name(tcx, def.did, true, output);
- push_generic_params_internal(tcx, substs, output, visited);
- push_close_angle_bracket(tcx, output);
+ output.push_str(&format!(", {}, {}, {}", min, max, dataful_variant_name));
+ } else if let Variants::Single { index: variant_idx } = &layout.variants {
+ // Uninhabited enums can't be constructed and should never need to be visualized so
+ // skip this step for them.
+ if def.variants.len() != 0 {
+ let variant = def.variants[*variant_idx].ident.as_str();
+
+ output.push_str(&format!(", {}", variant));
+ }
}
+ push_close_angle_bracket(tcx, output);
}
}
use rustc_hir::def_id::CrateNum;
use rustc_hir::LangItem;
use rustc_middle::dep_graph::WorkProduct;
-use rustc_middle::middle::cstore::{self, CrateSource, LibSource};
+use rustc_middle::middle::cstore::{self, CrateSource};
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::ty::query::Providers;
-use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
+use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
use rustc_session::utils::NativeLibKind;
use rustc_span::symbol::Symbol;
use std::path::{Path, PathBuf};
/// and the corresponding properties without referencing information outside of a `CrateInfo`.
#[derive(Debug, Encodable, Decodable)]
pub struct CrateInfo {
+ pub target_cpu: String,
+ pub exported_symbols: FxHashMap<CrateType, Vec<String>>,
pub local_crate_name: Symbol,
- pub panic_runtime: Option<CrateNum>,
pub compiler_builtins: Option<CrateNum>,
pub profiler_runtime: Option<CrateNum>,
pub is_no_builtins: FxHashSet<CrateNum>,
pub crate_name: FxHashMap<CrateNum, String>,
pub used_libraries: Vec<NativeLib>,
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
- pub used_crates_static: Vec<(CrateNum, LibSource)>,
- pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
+ pub used_crates: Vec<CrateNum>,
pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
pub dependency_formats: Lrc<Dependencies>,
pub allocator_module: Option<CompiledModule>,
pub metadata_module: Option<CompiledModule>,
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
- pub linker_info: back::linker::LinkerInfo,
pub crate_info: CrateInfo,
}
// Load the data pointer from the object.
debug!("get_fn({:?}, {:?})", llvtable, self);
- let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.fn_ptr_backend_type(fn_abi)));
+ let llty = bx.fn_ptr_backend_type(fn_abi);
+ let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
- let ptr = bx.load(gep, ptr_align);
+ let ptr = bx.load(llty, gep, ptr_align);
bx.nonnull_metadata(ptr);
// Vtable loads are invariant.
bx.set_invariant_load(ptr);
// Load the data pointer from the object.
debug!("get_int({:?}, {:?})", llvtable, self);
- let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(bx.type_isize()));
+ let llty = bx.type_isize();
+ let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
let usize_align = bx.tcx().data_layout.pointer_align.abi;
let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
- let ptr = bx.load(gep, usize_align);
+ let ptr = bx.load(llty, gep, usize_align);
// Vtable loads are invariant.
bx.set_invariant_load(ptr);
ptr
PassMode::Direct(_) | PassMode::Pair(..) => {
let op = self.codegen_consume(&mut bx, mir::Place::return_place().as_ref());
if let Ref(llval, _, align) = op.val {
- bx.load(llval, align)
+ bx.load(bx.backend_type(op.layout), llval, align)
} else {
op.immediate_or_packed_pair(&mut bx)
}
llval
}
};
- let addr = bx.pointercast(llslot, bx.type_ptr_to(bx.cast_backend_type(&cast_ty)));
- bx.load(addr, self.fn_abi.ret.layout.align.abi)
+ let ty = bx.cast_backend_type(&cast_ty);
+ let addr = bx.pointercast(llslot, bx.type_ptr_to(ty));
+ bx.load(ty, addr, self.fn_abi.ret.layout.align.abi)
}
};
bx.ret(llval);
if by_ref && !arg.is_indirect() {
// Have to load the argument, maybe while casting it.
if let PassMode::Cast(ty) = arg.mode {
- let addr = bx.pointercast(llval, bx.type_ptr_to(bx.cast_backend_type(&ty)));
- llval = bx.load(addr, align.min(arg.layout.align.abi));
+ let llty = bx.cast_backend_type(&ty);
+ let addr = bx.pointercast(llval, bx.type_ptr_to(llty));
+ llval = bx.load(llty, addr, align.min(arg.layout.align.abi));
} else {
// We can't use `PlaceRef::load` here because the argument
// may have a type we don't treat as immediate, but the ABI
// used for this call is passing it by-value. In that case,
// the load would just produce `OperandValue::Ref` instead
// of the `OperandValue::Immediate` we need for the call.
- llval = bx.load(llval, align);
+ llval = bx.load(bx.backend_type(arg.layout), llval, align);
if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
if scalar.is_bool() {
bx.range_metadata(llval, 0..2);
match *elem {
mir::ProjectionElem::Deref => {
indirect_offsets.push(Size::ZERO);
- place = place.project_deref(bx);
+ place = bx.load_operand(place).deref(bx.cx());
}
mir::ProjectionElem::Field(field, _) => {
let i = field.index();
if ty.is_unsafe_ptr() {
// Some platforms do not support atomic operations on pointers,
// so we cast to integer first...
- let ptr_llty = bx.type_ptr_to(bx.type_isize());
+ let llty = bx.type_isize();
+ let ptr_llty = bx.type_ptr_to(llty);
source = bx.pointercast(source, ptr_llty);
- }
- let result = bx.atomic_load(source, order, size);
- if ty.is_unsafe_ptr() {
+ let result = bx.atomic_load(llty, source, order, size);
// ... and then cast the result back to a pointer
bx.inttoptr(result, bx.backend_type(layout))
} else {
- result
+ bx.atomic_load(bx.backend_type(layout), source, order, size)
}
} else {
return invalid_monomorphization(ty);
}
match self {
OperandValue::Ref(r, None, source_align) => {
+ if flags.contains(MemFlags::NONTEMPORAL) {
+ // HACK(nox): This is inefficient but there is no nontemporal memcpy.
+ let ty = bx.backend_type(dest.layout);
+ let ptr = bx.pointercast(r, bx.type_ptr_to(ty));
+ let val = bx.load(ty, ptr, source_align);
+ bx.store_with_flags(val, dest.llval, dest.align, flags);
+ return;
+ }
base::memcpy_ty(bx, dest.llval, dest.align, r, source_align, dest.layout, flags)
}
OperandValue::Ref(_, Some(_), _) => {
downcast
}
- pub fn project_deref<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) -> Self {
- let target_ty = self.layout.ty.builtin_deref(true).expect("failed to deref");
- let layout = bx.layout_of(target_ty.ty);
-
- PlaceRef {
- llval: bx.load(self.llval, self.align),
- llextra: None,
- layout,
- align: layout.align.abi,
- }
- }
-
pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
bx.lifetime_start(self.llval, self.layout.size);
}
fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value;
- fn load(&mut self, ptr: Self::Value, align: Align) -> Self::Value;
- fn volatile_load(&mut self, ptr: Self::Value) -> Self::Value;
- fn atomic_load(&mut self, ptr: Self::Value, order: AtomicOrdering, size: Size) -> Self::Value;
+ fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
+ fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
+ fn atomic_load(
+ &mut self,
+ ty: Self::Type,
+ ptr: Self::Value,
+ order: AtomicOrdering,
+ size: Size,
+ ) -> Self::Value;
fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
-> OperandRef<'tcx, Self::Value>;
fn _stable_fn() {}
#[rustc_const_stable(feature = "_stable_const_fn")] // invalid
-fn _stable_const_fn() {}
+const fn _stable_const_fn() {}
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
#[rustc_deprecated(
fn _stable_fn() {}
#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok!
-fn _stable_const_fn() {}
+const fn _stable_const_fn() {}
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
#[rustc_deprecated(
fn _unstable_fn() {}
#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
```
To fix this issue, you need to provide a correct value in the `issue` field.
fn _unstable_fn() {}
#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "1")] // ok!
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
```
See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
fn _unstable_fn() {}
#[rustc_const_unstable(feature = "_unstable_const_fn")] // invalid
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
```
To fix this issue, you need to provide the `issue` field. Example:
feature = "_unstable_const_fn",
issue = "none"
)] // ok!
-fn _unstable_const_fn() {}
+const fn _unstable_const_fn() {}
```
See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
title: Some(Annotation {
label: Some(&message),
id: code.as_ref().map(|c| match c {
- DiagnosticId::Error(val)
- | DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(),
+ DiagnosticId::Error(val) | DiagnosticId::Lint { name: val, .. } => {
+ val.as_str()
+ }
}),
annotation_type: annotation_type_for_level(*level),
}),
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum DiagnosticId {
Error(String),
- Lint { name: String, has_future_breakage: bool },
+ Lint { name: String, has_future_breakage: bool, is_force_warn: bool },
}
/// A "sub"-diagnostic attached to a parent diagnostic.
}
}
+ pub fn is_force_warn(&self) -> bool {
+ match self.code {
+ Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn,
+ _ => false,
+ }
+ }
+
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
/// canceled or it will panic when dropped).
pub fn cancel(&mut self) {
// are some which do actually involve macros.
ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
- ExpnKind::Macro { kind: macro_kind, name, proc_macro: _ } => {
- Some((macro_kind, name))
- }
+ ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)),
}
});
new_labels
.push((trace.call_site, "in the inlined copy of this code".to_string()));
} else if always_backtrace {
- let proc_macro = if let ExpnKind::Macro { kind: _, name: _, proc_macro: true } =
- trace.kind
- {
- "procedural macro "
- } else {
- ""
- };
-
new_labels.push((
trace.def_site,
format!(
- "in this expansion of {}`{}`{}",
- proc_macro,
+ "in this expansion of `{}`{}",
trace.kind.descr(),
if macro_backtrace.len() > 1 {
// if macro_backtrace.len() == 1 it'll be
// and it needs an "in this macro invocation" label to match that.
let redundant_span = trace.call_site.contains(sp);
- if !redundant_span
- && matches!(
- trace.kind,
- ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ }
- )
+ if !redundant_span && matches!(trace.kind, ExpnKind::Macro(MacroKind::Bang, _))
|| always_backtrace
{
new_labels.push((
s.map(|s| {
let s = match s {
DiagnosticId::Error(s) => s,
- DiagnosticId::Lint { name, has_future_breakage: _ } => name,
+ DiagnosticId::Lint { name, .. } => name,
};
let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
}
}
-fn with_default_session_globals(f: impl FnOnce()) {
- let session_globals = rustc_span::SessionGlobals::new(rustc_span::edition::DEFAULT_EDITION);
- rustc_span::SESSION_GLOBALS.set(&session_globals, f);
-}
-
/// Test the span yields correct positions in JSON.
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
let expected_output = TestData { spans: vec![expected_output] };
- with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
}
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
+ ///
+ /// The builder will be canceled if warnings cannot be emitted.
pub fn struct_span_warn(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> {
let mut result = self.struct_warn(msg);
result.set_span(span);
result
}
+ /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
+ ///
+ /// This will "force" the warning meaning it will not be canceled even
+ /// if warnings cannot be emitted.
+ pub fn struct_span_force_warn(
+ &self,
+ span: impl Into<MultiSpan>,
+ msg: &str,
+ ) -> DiagnosticBuilder<'_> {
+ let mut result = self.struct_force_warn(msg);
+ result.set_span(span);
+ result
+ }
+
/// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
pub fn struct_span_allow(
&self,
}
/// Construct a builder at the `Warning` level with the `msg`.
+ ///
+ /// The builder will be canceled if warnings cannot be emitted.
pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
if !self.flags.can_emit_warnings {
result
}
+ /// Construct a builder at the `Warning` level with the `msg`.
+ ///
+ /// This will "force" a warning meaning it will not be canceled even
+ /// if warnings cannot be emitted.
+ pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
+ DiagnosticBuilder::new(self, Level::Warning, msg)
+ }
+
/// Construct a builder at the `Allow` level with the `msg`.
pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Allow, msg)
self.future_breakage_diagnostics.push(diagnostic.clone());
}
- if diagnostic.level == Warning && !self.flags.can_emit_warnings {
+ if diagnostic.level == Warning
+ && !self.flags.can_emit_warnings
+ && !diagnostic.is_force_warn()
+ {
if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTICS)(diagnostic);
}
match (errors.len(), warnings.len()) {
(0, 0) => return,
- (0, _) => self.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)),
+ (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)),
(_, 0) => {
let _ = self.fatal(&errors);
}
call_site: Span,
descr: Symbol,
macro_def_id: Option<DefId>,
+ parent_module: Option<DefId>,
) -> ExpnData {
- use SyntaxExtensionKind::*;
- let proc_macro = match self.kind {
- // User-defined proc macro
- Bang(..) | Attr(..) | Derive(..) => true,
- // Consider everthing else to be not a proc
- // macro for diagnostic purposes
- LegacyBang(..) | LegacyAttr(..) | NonMacroAttr { .. } | LegacyDerive(..) => false,
- };
ExpnData::new(
- ExpnKind::Macro { kind: self.macro_kind(), name: descr, proc_macro },
+ ExpnKind::Macro(self.macro_kind(), descr),
parent,
call_site,
self.span,
self.local_inner_macros,
self.edition,
macro_def_id,
+ parent_module,
)
}
}
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_feature::Features;
-use rustc_lint_defs::builtin::{OR_PATTERNS_BACK_COMPAT, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS};
+use rustc_lint_defs::builtin::{
+ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
+};
use rustc_lint_defs::BuiltinLintDiagnostics;
use rustc_parse::parser::Parser;
use rustc_session::parse::ParseSess;
Some(NonterminalKind::PatParam { inferred: false }),
));
sess.buffer_lint_with_diagnostic(
- &OR_PATTERNS_BACK_COMPAT,
+ &RUST_2021_INCOMPATIBLE_OR_PATTERNS,
span,
ast::CRATE_NODE_ID,
"the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",
use rustc_ast as ast;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast_pretty::pprust;
+use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
-use rustc_span::with_default_session_globals;
// This version doesn't care about getting comments or doc-strings in.
fn print_crate_items(krate: &ast::Crate) -> String {
// Make sure idents get transformed everywhere.
#[test]
fn ident_transformation() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut zz_visitor = ToZzIdentMutVisitor;
let mut krate =
string_to_crate("#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
// Make sure idents get transformed even inside macro defs.
#[test]
fn ident_transformation_in_defs() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut zz_visitor = ToZzIdentMutVisitor;
let mut krate = string_to_crate(
"macro_rules! a {(b $c:expr $(d $e:token)f+ => \
use rustc_parse::new_parser_from_source_str;
use rustc_parse::parser::ForceCollect;
use rustc_session::parse::ParseSess;
+use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::FilePathMapping;
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::with_default_session_globals;
use rustc_span::{BytePos, FileName, Pos, Span};
use std::path::PathBuf;
#[should_panic]
#[test]
fn bad_path_expr_1() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
string_to_expr("::abc::def::return".to_string());
})
}
// Checks the token-tree-ization of macros.
#[test]
fn string_to_tts_macro() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let tts: Vec<_> =
string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).trees().collect();
let tts: &[TokenTree] = &tts[..];
#[test]
fn string_to_tts_1() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
let expected = TokenStream::new(vec![
#[test]
fn parse_use() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let use_s = "use foo::bar::baz;";
let vitem = string_to_item(use_s.to_string()).unwrap();
let vitem_s = item_to_string(&vitem);
#[test]
fn parse_extern_crate() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let ex_s = "extern crate foo;";
let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = item_to_string(&vitem);
#[test]
fn span_of_self_arg_pat_idents_are_correct() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let srcs = [
"impl z { fn a (&self, &myarg: i32) {} }",
"impl z { fn a (&mut self, &myarg: i32) {} }",
#[test]
fn parse_exprs() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
// just make sure that they parse....
string_to_expr("3 + 4".to_string());
string_to_expr("a::z.froob(b,&(987+3))".to_string());
#[test]
fn attrs_fix_bug() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
string_to_item(
"pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
-> Result<Box<Writer>, String> {
#[test]
fn crlf_doc_comments() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let sess = sess();
let name_1 = FileName::Custom("crlf_source_1".to_string());
new_parser_from_source_str(sess, name, source).parse_expr()
}
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let sess = sess();
let expr = parse_expr_from_source_str(
PathBuf::from("foo").into(),
// See `recurse_into_file_modules` in the parser.
#[test]
fn out_of_line_mod() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let item = parse_item_from_source_str(
PathBuf::from("foo").into(),
"mod foo { struct S; mod this_does_not_exist; }".to_owned(),
use rustc_errors::ErrorReported;
use rustc_parse::nt_to_tokenstream;
use rustc_parse::parser::ForceCollect;
-use rustc_span::def_id::CrateNum;
use rustc_span::{Span, DUMMY_SP};
const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
pub struct BangProcMacro {
pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
- pub krate: CrateNum,
}
impl base::ProcMacro for BangProcMacro {
span: Span,
input: TokenStream,
) -> Result<TokenStream, ErrorReported> {
- let server = proc_macro_server::Rustc::new(ecx, self.krate);
+ let server = proc_macro_server::Rustc::new(ecx);
self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace).map_err(|e| {
let mut err = ecx.struct_span_err(span, "proc macro panicked");
if let Some(s) = e.as_str() {
pub struct AttrProcMacro {
pub client: pm::bridge::client::Client<fn(pm::TokenStream, pm::TokenStream) -> pm::TokenStream>,
- pub krate: CrateNum,
}
impl base::AttrProcMacro for AttrProcMacro {
annotation: TokenStream,
annotated: TokenStream,
) -> Result<TokenStream, ErrorReported> {
- let server = proc_macro_server::Rustc::new(ecx, self.krate);
+ let server = proc_macro_server::Rustc::new(ecx);
self.client
.run(&EXEC_STRATEGY, server, annotation, annotated, ecx.ecfg.proc_macro_backtrace)
.map_err(|e| {
pub struct ProcMacroDerive {
pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
- pub krate: CrateNum,
}
impl MultiItemModifier for ProcMacroDerive {
nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::No)
};
- let server = proc_macro_server::Rustc::new(ecx, self.krate);
+ let server = proc_macro_server::Rustc::new(ecx);
let stream =
match self.client.run(&EXEC_STRATEGY, server, input, ecx.ecfg.proc_macro_backtrace) {
Ok(stream) => stream,
use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
use rustc_session::parse::ParseSess;
use rustc_span::def_id::CrateNum;
-use rustc_span::hygiene::ExpnId;
use rustc_span::hygiene::ExpnKind;
use rustc_span::symbol::{self, kw, sym, Symbol};
use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span};
mixed_site: Span,
span_debug: bool,
krate: CrateNum,
- expn_id: ExpnId,
rebased_spans: FxHashMap<usize, Span>,
}
impl<'a> Rustc<'a> {
- pub fn new(cx: &'a ExtCtxt<'_>, krate: CrateNum) -> Self {
+ pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
let expn_data = cx.current_expansion.id.expn_data();
- let def_site = cx.with_def_site_ctxt(expn_data.def_site);
- let call_site = cx.with_call_site_ctxt(expn_data.call_site);
- let mixed_site = cx.with_mixed_site_ctxt(expn_data.call_site);
- let sess = cx.parse_sess();
Rustc {
resolver: cx.resolver,
- sess,
- def_site,
- call_site,
- mixed_site,
+ sess: cx.parse_sess(),
+ def_site: cx.with_def_site_ctxt(expn_data.def_site),
+ call_site: cx.with_call_site_ctxt(expn_data.call_site),
+ mixed_site: cx.with_mixed_site_ctxt(expn_data.call_site),
span_debug: cx.ecfg.span_debug,
- krate,
- expn_id: cx.current_expansion.id,
+ krate: expn_data.macro_def_id.unwrap().krate,
rebased_spans: FxHashMap::default(),
}
}
/// span from the metadata of `my_proc_macro` (which we have access to,
/// since we've loaded `my_proc_macro` from disk in order to execute it).
/// In this way, we have obtained a span pointing into `my_proc_macro`
- fn save_span(&mut self, mut span: Self::Span) -> usize {
- // Throw away the `SyntaxContext`, since we currently
- // skip serializing `SyntaxContext`s for proc-macro crates
- span = span.with_ctxt(rustc_span::SyntaxContext::root());
+ fn save_span(&mut self, span: Self::Span) -> usize {
self.sess.save_proc_macro_span(span)
}
fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
- let resolver = self.resolver;
- let krate = self.krate;
- let expn_id = self.expn_id;
+ let (resolver, krate, def_site) = (self.resolver, self.krate, self.def_site);
*self.rebased_spans.entry(id).or_insert_with(|| {
- let raw_span = resolver.get_proc_macro_quoted_span(krate, id);
- // Ignore the deserialized `SyntaxContext` entirely.
- // FIXME: Preserve the macro backtrace from the serialized span
- // For example, if a proc-macro crate has code like
- // `macro_one!() -> macro_two!() -> quote!()`, we might
- // want to 'concatenate' this backtrace with the backtrace from
- // our current call site.
- raw_span.with_def_site_ctxt(expn_id)
+ // FIXME: `SyntaxContext` for spans from proc macro crates is lost during encoding,
+ // replace it with a def-site context until we are encoding it properly.
+ resolver.get_proc_macro_quoted_span(krate, id).with_ctxt(def_site.ctxt())
})
}
}
rustc: &mut Rustc<'_>,
) -> Option<(rustc_span::symbol::Ident, bool)> {
if let NtIdent(ident, is_raw) = nt {
- if let ExpnKind::Macro { name: macro_name, .. } = orig_span.ctxt().outer_expn_data().kind {
+ if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
let source_map = rustc.sess.source_map();
let filename = source_map.span_to_filename(orig_span);
if let FileName::Real(RealFileName::LocalPath(path)) = filename {
use rustc_ast::tokenstream::TokenStream;
use rustc_parse::{new_parser_from_source_str, parser::Parser, source_file_to_stream};
use rustc_session::parse::ParseSess;
+use rustc_span::create_default_session_if_not_set_then;
use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::with_default_session_globals;
use rustc_span::{BytePos, MultiSpan, Span};
use rustc_data_structures::sync::Lrc;
}
fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
- with_default_session_globals(|| {
+ create_default_session_if_not_set_then(|_| {
let output = Arc::new(Mutex::new(Vec::new()));
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
use rustc_ast::token;
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenStreamBuilder, TokenTree};
-use rustc_span::with_default_session_globals;
+use rustc_span::create_default_session_globals_then;
use rustc_span::{BytePos, Span, Symbol};
use smallvec::smallvec;
#[test]
fn test_concat() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("foo::bar::baz");
let test_fst = string_to_ts("foo::bar");
let test_snd = string_to_ts("::baz");
#[test]
fn test_to_from_bijection() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_start = string_to_ts("foo::bar(baz)");
let test_end = test_start.trees().collect();
assert_eq!(test_start, test_end)
#[test]
fn test_eq_0() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("foo");
let test_eqs = string_to_ts("foo");
assert_eq!(test_res, test_eqs)
#[test]
fn test_eq_1() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("::bar::baz");
let test_eqs = string_to_ts("::bar::baz");
assert_eq!(test_res, test_eqs)
#[test]
fn test_eq_3() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("");
let test_eqs = string_to_ts("");
assert_eq!(test_res, test_eqs)
#[test]
fn test_diseq_0() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("::bar::baz");
let test_eqs = string_to_ts("bar::baz");
assert_eq!(test_res == test_eqs, false)
#[test]
fn test_diseq_1() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test_res = string_to_ts("(bar,baz)");
let test_eqs = string_to_ts("bar,baz");
assert_eq!(test_res == test_eqs, false)
#[test]
fn test_is_empty() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let test0: TokenStream = Vec::<TokenTree>::new().into_iter().collect();
let test1: TokenStream =
TokenTree::token(token::Ident(Symbol::intern("a"), false), sp(0, 1)).into();
#[test]
fn test_dotdotdot() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut builder = TokenStreamBuilder::new();
builder.push(joint(TokenTree::token(token::Dot, sp(0, 1))));
builder.push(joint(TokenTree::token(token::Dot, sp(1, 2))));
/// Allows accessing fields of unions inside `const` functions.
(active, const_fn_union, "1.27.0", Some(51909), None),
- /// Allows casting raw pointers to `usize` during const eval.
- (active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),
-
/// Allows dereferencing raw pointers during const eval.
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
(incomplete, unnamed_fields, "1.53.0", Some(49804), None),
/// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
- (active, more_qualified_paths, "1.54.0", Some(80080), None),
+ (active, more_qualified_paths, "1.54.0", Some(86935), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
(removed, external_doc, "1.54.0", Some(44732), None,
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
+ /// Allows casting raw pointers to `usize` during const eval.
+ (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
+ Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
+
// -------------------------------------------------------------------------
// feature-group-end: removed features
// -------------------------------------------------------------------------
//! expressions) that are mostly just leftovers.
pub use crate::def_id::DefPathHash;
-use crate::def_id::{
- CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE,
-};
+use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
use crate::hir;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::unhash::UnhashMap;
use rustc_index::vec::IndexVec;
-use rustc_span::crate_disambiguator::CrateDisambiguator;
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
/// stores the `DefIndex` of its parent.
/// There is one `DefPathTable` for each crate.
-#[derive(Clone, Default)]
+#[derive(Clone, Default, Debug)]
pub struct DefPathTable {
index_to_key: IndexVec<DefIndex, DefKey>,
def_path_hashes: IndexVec<DefIndex, DefPathHash>,
/// The definition table containing node definitions.
/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct Definitions {
table: DefPathTable,
/// The reverse mapping of `def_id_to_hir_id`.
pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>,
- /// If `ExpnId` 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<ExpnId, DefId>,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
}
}
/// Adds a root definition (no parent) and a few other reserved definitions.
- pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions {
+ pub fn new(stable_crate_id: StableCrateId) -> Definitions {
let key = DefKey {
parent: None,
disambiguated_data: DisambiguatedDefPathData {
},
};
- let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
let parent_hash = DefPathHash::new(stable_crate_id, 0);
let def_path_hash = key.compute_stable_hash(parent_hash);
def_id_to_hir_id: Default::default(),
hir_id_to_def_id: Default::default(),
expansions_that_defined: Default::default(),
- parent_modules_of_macro_defs: Default::default(),
}
}
self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
}
- pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId {
- self.parent_modules_of_macro_defs[&expn_id]
- }
-
- pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId) {
- self.parent_modules_of_macro_defs.insert(expn_id, module);
- }
-
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
}
Range, sym::Range, range_struct, Target::Struct;
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct;
RangeTo, sym::RangeTo, range_to_struct, Target::Struct;
- Send, sym::send, send_trait, Target::Trait;
- UnwindSafe, sym::unwind_safe, unwind_safe_trait, Target::Trait;
- RefUnwindSafe, sym::ref_unwind_safe, ref_unwind_safe_trait, Target::Trait;
}
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_span::crate_disambiguator::CrateDisambiguator;
use rustc_span::def_id::{DefPathHash, StableCrateId};
#[test]
// the crate by changing the crate disambiguator (e.g. via bumping the
// crate's version number).
- let d0 = CrateDisambiguator::from(Fingerprint::new(12, 34));
- let d1 = CrateDisambiguator::from(Fingerprint::new(56, 78));
+ let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
+ let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
- let h0 = mk_test_hash("foo", d0);
- let h1 = mk_test_hash("foo", d1);
+ let h0 = mk_test_hash(id0);
+ let h1 = mk_test_hash(id1);
assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
assert_ne!(h0.local_hash(), h1.local_hash());
- fn mk_test_hash(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> DefPathHash {
- let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
+ fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
let parent_hash = DefPathHash::new(stable_crate_id, 0);
let key = DefKey {
use rustc_data_structures::{base_n, flock};
use rustc_errors::ErrorReported;
use rustc_fs_util::{link_or_copy, LinkOrCopy};
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
use std::fs as std_fs;
use std::io;
pub fn prepare_session_directory(
sess: &Session,
crate_name: &str,
- crate_disambiguator: CrateDisambiguator,
+ stable_crate_id: StableCrateId,
) -> Result<(), ErrorReported> {
if sess.opts.incremental.is_none() {
return Ok(());
debug!("prepare_session_directory");
// {incr-comp-dir}/{crate-name-and-disambiguator}
- let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
+ let crate_dir = crate_path(sess, crate_name, stable_crate_id);
debug!("crate-dir: {}", crate_dir.display());
create_dir(sess, &crate_dir, "crate")?;
Ok(UNIX_EPOCH + duration)
}
-fn crate_path(
- sess: &Session,
- crate_name: &str,
- crate_disambiguator: CrateDisambiguator,
-) -> PathBuf {
+fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
- // The full crate disambiguator is really long. 64 bits of it should be
- // sufficient.
- let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
- let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE);
+ let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
- let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
+ let crate_name = format!("{}-{}", crate_name, stable_crate_id);
incr_dir.join(crate_name)
}
/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
- rustc_span::with_default_session_globals(move || {
+ rustc_span::create_default_session_if_not_set_then(move |_| {
let cfg = cfgspecs
.into_iter()
.map(|s| {
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
use rustc_hir::Crate;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore;
let crate_types = util::collect_crate_types(sess, &krate.attrs);
sess.init_crate_types(crate_types);
- let disambiguator = util::compute_crate_disambiguator(sess);
- sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
- rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
+ let stable_crate_id = StableCrateId::new(
+ crate_name,
+ sess.crate_types().contains(&CrateType::Executable),
+ sess.opts.cg.metadata.clone(),
+ );
+ sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
+ rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?;
if sess.opts.incremental.is_some() {
sess.time("incr_comp_garbage_collect_session_directories", || {
});
}
- sess.time("recursion_limit", || {
- middle::limits::update_limits(sess, &krate);
- });
-
let mut lint_store = rustc_lint::new_lint_store(
sess.opts.debugging_opts.no_interleave_lints,
sess.unstable_options(),
// Create the config for macro expansion
let features = sess.features_untracked();
+ let recursion_limit =
+ rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
let cfg = rustc_expand::expand::ExpansionConfig {
features: Some(&features),
- recursion_limit: sess.recursion_limit(),
+ recursion_limit,
trace_mac: sess.opts.debugging_opts.trace_macros,
should_test: sess.opts.test,
span_debug: sess.opts.debugging_opts.span_debug,
tcx.ensure().check_mod_unstable_api_usage(module);
tcx.ensure().check_mod_const_bodies(module);
});
+ },
+ {
+ // We force these querie to run,
+ // since they might not otherwise get called.
+ // This marks the corresponding crate-level attributes
+ // as used, and ensures that their values are valid.
+ tcx.ensure().limits(());
}
);
});
// When the user supplies --test we should implicitly supply --cfg test
#[test]
fn test_switch_implies_cfg_test() {
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["--test".to_string()]).unwrap();
let (sess, cfg) = mk_session(matches);
let cfg = build_configuration(&sess, to_crate_config(cfg));
// When the user supplies --test and --cfg test, don't implicitly add another --cfg test
#[test]
fn test_switch_implies_cfg_test_unless_cfg_test() {
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]).unwrap();
let (sess, cfg) = mk_session(matches);
let cfg = build_configuration(&sess, to_crate_config(cfg));
#[test]
fn test_can_print_warnings() {
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
assert!(!sess.diagnostic().can_emit_warnings());
});
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let matches =
optgroups().parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
assert!(sess.diagnostic().can_emit_warnings());
});
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
let (sess, _) = mk_session(matches);
assert!(sess.diagnostic().can_emit_warnings());
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
#[cfg(parallel_compiler)]
use rustc_data_structures::jobserver;
-use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
use rustc_metadata::dynamic_lib::DynamicLibrary;
use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::CrateConfig;
-use rustc_session::CrateDisambiguator;
use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
crate::callbacks::setup_callbacks();
let main_handler = move || {
- rustc_span::with_session_globals(edition, || {
+ rustc_span::create_session_globals_then(edition, || {
io::set_output_capture(stderr.clone());
f()
})
rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>();
let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>);
- let session_globals = rustc_span::SESSION_GLOBALS.with(|sg| sg as *const _);
+ let session_globals = rustc_span::with_session_globals(|sg| sg as *const _);
let session_globals = &*session_globals;
thread::spawn(move || {
tls::enter_context(icx, |_| {
- rustc_span::SESSION_GLOBALS
- .set(session_globals, || tls::with(|tcx| tcx.queries.deadlock(tcx, ®istry)))
+ rustc_span::set_session_globals_then(session_globals, || {
+ tls::with(|tcx| tcx.queries.deadlock(tcx, ®istry))
+ })
});
});
}
let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);
- rustc_span::with_session_globals(edition, || {
- rustc_span::SESSION_GLOBALS.with(|session_globals| {
+ rustc_span::create_session_globals_then(edition, || {
+ rustc_span::with_session_globals(|session_globals| {
// The main handler runs for each Rayon worker thread and sets up
// the thread local rustc uses. `session_globals` is captured and set
// on the new threads.
let main_handler = move |thread: rayon::ThreadBuilder| {
- rustc_span::SESSION_GLOBALS.set(session_globals, || {
+ rustc_span::set_session_globals_then(session_globals, || {
io::set_output_capture(stderr.clone());
thread.run()
})
}
}
-pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
- use std::hash::Hasher;
-
- // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
- // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
- // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
- // should still be safe enough to avoid collisions in practice.
- let mut hasher = StableHasher::new();
-
- let mut metadata = session.opts.cg.metadata.clone();
- // We don't want the crate_disambiguator to dependent on the order
- // -C metadata arguments, so sort them:
- metadata.sort();
- // Every distinct -C metadata value is only incorporated once:
- metadata.dedup();
-
- hasher.write(b"metadata");
- for s in &metadata {
- // Also incorporate the length of a metadata string, so that we generate
- // different values for `-Cmetadata=ab -Cmetadata=c` and
- // `-Cmetadata=a -Cmetadata=bc`
- hasher.write_usize(s.len());
- hasher.write(s.as_bytes());
- }
-
- // Also incorporate crate type, so that we don't get symbol conflicts when
- // linking against a library of the same name, if this is an executable.
- let is_exe = session.crate_types().contains(&CrateType::Executable);
- hasher.write(if is_exe { b"exe" } else { b"lib" });
-
- CrateDisambiguator::from(hasher.finish::<Fingerprint>())
-}
-
pub(crate) fn check_attr_crate_type(
sess: &Session,
attrs: &[ast::Attribute],
self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.inner, "the", "crate");
for macro_def in krate.exported_macros {
+ // Non exported macros should be skipped, since `missing_docs` only
+ // applies to externally visible items.
+ if !cx.access_levels.is_exported(macro_def.hir_id()) {
+ continue;
+ }
+
let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
if !has_doc {
use self::TargetLint::*;
-use crate::levels::LintLevelsBuilder;
+use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
Ok(&'a [LintId]),
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
NoLint(Option<Symbol>),
+ /// The lint refers to a tool that has not been registered.
+ NoTool,
/// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed).
Warning(String, Option<String>),
}
}
- /// Checks the validity of lint names derived from the command line
- pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Level) {
- let db = match self.check_lint_name(lint_name, None) {
+ /// Checks the validity of lint names derived from the command line.
+ pub fn check_lint_name_cmdline(
+ &self,
+ sess: &Session,
+ lint_name: &str,
+ level: Level,
+ crate_attrs: &[ast::Attribute],
+ ) {
+ let (tool_name, lint_name_only) = parse_lint_and_tool_name(lint_name);
+
+ let db = match self.check_lint_name(sess, lint_name_only, tool_name, crate_attrs) {
CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
CheckLintNameResult::NoLint(suggestion) => {
))),
_ => None,
},
+ CheckLintNameResult::NoTool => Some(struct_span_err!(
+ sess,
+ DUMMY_SP,
+ E0602,
+ "unknown lint tool: `{}`",
+ tool_name.unwrap()
+ )),
};
if let Some(mut db) = db {
/// printing duplicate warnings.
pub fn check_lint_name(
&self,
+ sess: &Session,
lint_name: &str,
tool_name: Option<Symbol>,
+ crate_attrs: &[ast::Attribute],
) -> CheckLintNameResult<'_> {
+ if let Some(tool_name) = tool_name {
+ if !is_known_lint_tool(tool_name, sess, crate_attrs) {
+ return CheckLintNameResult::NoTool;
+ }
+ }
+
let complete_name = if let Some(tool_name) = tool_name {
format!("{}::{}", tool_name, lint_name)
} else {
self.tcx.layout_of(self.param_env.and(ty))
}
}
+
+pub fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
+ match lint_name.split_once("::") {
+ Some((tool_name, lint_name)) => {
+ let tool_name = Symbol::intern(tool_name);
+
+ (Some(tool_name), lint_name)
+ }
+ None => (None, lint_name),
+ }
+}
if last.ident.name == sym::LintPass {
let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
let call_site = expn_data.call_site;
- if !matches!(
- expn_data.kind,
- ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: sym::impl_lint_pass,
- proc_macro: _
- }
- ) && !matches!(
- call_site.ctxt().outer_expn_data().kind,
- ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: sym::declare_lint_pass,
- proc_macro: _
- }
- ) {
+ if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
+ && call_site.ctxt().outer_expn_data().kind
+ != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
+ {
cx.struct_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span,
use rustc_middle::lint::LevelAndSource;
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::lint::{
- struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
+ struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, LintStackIndex,
+ COMMAND_LINE,
};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
pub struct LintLevelsBuilder<'s> {
sess: &'s Session,
sets: LintLevelSets,
- id_to_set: FxHashMap<HirId, u32>,
- cur: u32,
+ id_to_set: FxHashMap<HirId, LintStackIndex>,
+ cur: LintStackIndex,
warn_about_weird_lints: bool,
store: &'s LintStore,
crate_attrs: &'s [ast::Attribute],
}
pub struct BuilderPush {
- prev: u32,
+ prev: LintStackIndex,
pub changed: bool,
}
let mut builder = LintLevelsBuilder {
sess,
sets: LintLevelSets::new(),
- cur: 0,
+ cur: COMMAND_LINE,
id_to_set: Default::default(),
warn_about_weird_lints,
store,
self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
for &(ref lint_name, level) in &sess.opts.lint_opts {
- store.check_lint_name_cmdline(sess, &lint_name, level);
+ store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs);
let orig_level = level;
// If the cap is less than this specified level, e.g., if we've got
}
for lint_name in &sess.opts.force_warns {
- store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn);
+ store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn, self.crate_attrs);
let lints = store
.find_lints(lint_name)
.unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
}
}
- self.sets.list.push(LintSet::CommandLine { specs });
+ self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE });
}
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
continue;
}
};
- let tool_name = if meta_item.path.segments.len() > 1 {
- let tool_ident = meta_item.path.segments[0].ident;
- if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) {
- let mut err = struct_span_err!(
- sess,
- tool_ident.span,
- E0710,
- "unknown tool name `{}` found in scoped lint: `{}`",
- tool_ident.name,
- pprust::path_to_string(&meta_item.path),
- );
- if sess.is_nightly_build() {
- err.help(&format!(
- "add `#![register_tool({})]` to the crate root",
- tool_ident.name
- ));
- }
- err.emit();
- continue;
- }
-
- Some(meta_item.path.segments.remove(0).ident.name)
+ let tool_ident = if meta_item.path.segments.len() > 1 {
+ Some(meta_item.path.segments.remove(0).ident)
} else {
None
};
+ let tool_name = tool_ident.map(|ident| ident.name);
let name = pprust::path_to_string(&meta_item.path);
- let lint_result = store.check_lint_name(&name, tool_name);
+ let lint_result = store.check_lint_name(sess, &name, tool_name, self.crate_attrs);
match &lint_result {
CheckLintNameResult::Ok(ids) => {
let src = LintLevelSource::Node(
CheckLintNameResult::Tool(result) => {
match *result {
Ok(ids) => {
- let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
+ let complete_name =
+ &format!("{}::{}", tool_ident.unwrap().name, name);
let src = LintLevelSource::Node(
Symbol::intern(complete_name),
sp,
}
}
+ &CheckLintNameResult::NoTool => {
+ let mut err = struct_span_err!(
+ sess,
+ tool_ident.map_or(DUMMY_SP, |ident| ident.span),
+ E0710,
+ "unknown tool name `{}` found in scoped lint: `{}::{}`",
+ tool_name.unwrap(),
+ tool_name.unwrap(),
+ pprust::path_to_string(&meta_item.path),
+ );
+ if sess.is_nightly_build() {
+ err.help(&format!(
+ "add `#![register_tool({})]` to the crate root",
+ tool_name.unwrap()
+ ));
+ }
+ err.emit();
+ continue;
+ }
+
_ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Warning(msg, renamed) => {
let (level, src) =
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
- let name = if let Some(tool_name) = tool_name {
- format!("{}::{}", tool_name, name)
+ let name = if let Some(tool_ident) = tool_ident {
+ format!("{}::{}", tool_ident.name, name)
} else {
name.to_string()
};
if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result {
// Ignore any errors or warnings that happen because the new name is inaccurate
// NOTE: `new_name` already includes the tool name, so we don't have to add it again.
- if let CheckLintNameResult::Ok(ids) = store.check_lint_name(&new_name, None) {
+ if let CheckLintNameResult::Ok(ids) =
+ store.check_lint_name(sess, &new_name, None, self.crate_attrs)
+ {
let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
for &id in ids {
self.check_gated_lint(id, attr.span);
let prev = self.cur;
if !specs.is_empty() {
- self.cur = self.sets.list.len() as u32;
- self.sets.list.push(LintSet::Node { specs, parent: prev });
+ self.cur = self.sets.list.push(LintSet { specs, parent: prev });
}
BuilderPush { prev, changed: prev != self.cur }
}
}
-fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
+pub fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool {
if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) {
return true;
}
store.register_renamed("redundant_semicolon", "redundant_semicolons");
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
store.register_renamed("safe_packed_borrows", "unaligned_references");
+ store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
+ store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
+ store.register_renamed("non_fmt_panic", "non_fmt_panics");
// These were moved to tool lints, but rustc still sees them when compiling normally, before
// tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use
],
);
}
+
+#[cfg(test)]
+mod tests;
use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol};
declare_lint! {
- /// The `non_fmt_panic` lint detects `panic!(..)` invocations where the first
+ /// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first
/// argument is not a formatting string.
///
/// ### Example
/// an `i32` as message.
///
/// Rust 2021 always interprets the first argument as format string.
- NON_FMT_PANIC,
+ NON_FMT_PANICS,
Warn,
"detect single-argument panic!() invocations in which the argument is not a format string",
@future_incompatible = FutureIncompatibleInfo {
report_in_external_macro
}
-declare_lint_pass!(NonPanicFmt => [NON_FMT_PANIC]);
+declare_lint_pass!(NonPanicFmt => [NON_FMT_PANICS]);
impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
arg_span = expn.call_site;
}
- cx.struct_span_lint(NON_FMT_PANIC, arg_span, |lint| {
+ cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
let mut l = lint.build("panic message is not a string literal");
l.note("this usage of panic!() is deprecated; it will be a hard error in Rust 2021");
l.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>");
[] => vec![fmt_span],
v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
};
- cx.struct_span_lint(NON_FMT_PANIC, arg_spans, |lint| {
+ cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
let mut l = lint.build(match n_arguments {
1 => "panic message contains an unused formatting placeholder",
_ => "panic message contains unused formatting placeholders",
Some(v) if v.len() == 1 => "panic message contains a brace",
_ => "panic message contains braces",
};
- cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
+ cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
let mut l = lint.build(msg);
l.note("this message is not used as a format string, but will be in Rust 2021");
if span.contains(arg.span) {
}
let macro_symbol =
- if let hygiene::ExpnKind::Macro { kind: _, name: symbol, proc_macro: _ } = expn.kind {
- symbol
- } else {
- Symbol::intern("panic")
- };
+ if let hygiene::ExpnKind::Macro(_, symbol) = expn.kind { symbol } else { sym::panic };
(expn.call_site, panic_macro, macro_symbol.as_str())
}
--- /dev/null
+use crate::context::parse_lint_and_tool_name;
+use rustc_span::{create_default_session_globals_then, Symbol};
+
+#[test]
+fn parse_lint_no_tool() {
+ create_default_session_globals_then(|| {
+ assert_eq!(parse_lint_and_tool_name("foo"), (None, "foo"))
+ });
+}
+
+#[test]
+fn parse_lint_with_tool() {
+ create_default_session_globals_then(|| {
+ assert_eq!(parse_lint_and_tool_name("clippy::foo"), (Some(Symbol::intern("clippy")), "foo"))
+ });
+}
+
+#[test]
+fn parse_lint_multiple_path() {
+ create_default_session_globals_then(|| {
+ assert_eq!(
+ parse_lint_and_tool_name("clippy::foo::bar"),
+ (Some(Symbol::intern("clippy")), "foo::bar")
+ )
+ });
+}
MISSING_ABI,
INVALID_DOC_ATTRIBUTES,
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
- DISJOINT_CAPTURE_MIGRATION,
+ RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
LEGACY_DERIVE_HELPERS,
PROC_MACRO_BACK_COMPAT,
- OR_PATTERNS_BACK_COMPAT,
+ RUST_2021_INCOMPATIBLE_OR_PATTERNS,
LARGE_ASSIGNMENTS,
- FUTURE_PRELUDE_COLLISION,
- RESERVED_PREFIX,
+ RUST_2021_PRELUDE_COLLISIONS,
+ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+ UNSUPPORTED_CALLING_CONVENTIONS,
]
}
}
declare_lint! {
- /// The `disjoint_capture_migration` lint detects variables that aren't completely
+ /// The `rust_2021_incompatible_closure_captures` lint detects variables that aren't completely
/// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable.
/// It can also detect when a variable implements a trait, but one of its field does not and
/// the field is captured by a closure and used with the assumption that said field implements
/// ### Example of drop reorder
///
/// ```rust,compile_fail
- /// # #![deny(disjoint_capture_migration)]
+ /// # #![deny(rust_2021_incompatible_closure_captures)]
/// # #![allow(unused)]
/// struct FancyInteger(i32);
///
/// ### Example of auto-trait
///
/// ```rust,compile_fail
- /// #![deny(disjoint_capture_migration)]
+ /// #![deny(rust_2021_incompatible_closure_captures)]
/// use std::thread;
///
/// struct Pointer(*mut i32);
/// In the above example, only `fptr.0` is captured in Rust 2021.
/// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the
/// field cannot be sent between thread safely.
- pub DISJOINT_CAPTURE_MIGRATION,
+ pub RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
Allow,
"detects closures affected by Rust 2021 changes",
@future_incompatible = FutureIncompatibleInfo {
}
declare_lint! {
- /// The `or_patterns_back_compat` lint detects usage of old versions of or-patterns.
+ /// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns.
///
/// ### Example
///
/// ```rust,compile_fail
- /// #![deny(or_patterns_back_compat)]
+ /// #![deny(rust_2021_incompatible_or_patterns)]
/// macro_rules! match_any {
/// ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
/// match $expr {
/// ### Explanation
///
/// In Rust 2021, the pat matcher will match new patterns, which include the | character.
- pub OR_PATTERNS_BACK_COMPAT,
+ pub RUST_2021_INCOMPATIBLE_OR_PATTERNS,
Allow,
"detects usage of old versions of or-patterns",
@future_incompatible = FutureIncompatibleInfo {
}
declare_lint! {
- /// The `future_prelude_collision` lint detects the usage of trait methods which are ambiguous
+ /// The `rust_2021_prelude_collisions` lint detects the usage of trait methods which are ambiguous
/// with traits added to the prelude in future editions.
///
/// ### Example
///
/// ```rust,compile_fail
- /// #![deny(future_prelude_collision)]
+ /// #![deny(rust_2021_prelude_collisions)]
///
/// trait Foo {
/// fn try_into(self) -> Result<String, !>;
/// is called directly on a type.
///
/// [prelude changes]: https://blog.rust-lang.org/inside-rust/2021/03/04/planning-rust-2021.html#prelude-changes
- pub FUTURE_PRELUDE_COLLISION,
+ pub RUST_2021_PRELUDE_COLLISIONS,
Allow,
"detects the usage of trait methods which are ambiguous with traits added to the \
prelude in future editions",
}
declare_lint! {
- /// The `reserved_prefix` lint detects identifiers that will be parsed as a
+ /// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a
/// prefix instead in Rust 2021.
///
/// ### Example
///
/// ```rust,compile_fail
- /// #![deny(reserved_prefix)]
+ /// #![deny(rust_2021_prefixes_incompatible_syntax)]
///
/// macro_rules! m {
/// (z $x:expr) => ();
///
/// This lint suggests to add whitespace between the `z` and `"hey"` tokens
/// to keep them separated in Rust 2021.
- pub RESERVED_PREFIX,
+ pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
Allow,
"identifiers that will be parsed as a prefix in Rust 2021",
@future_incompatible = FutureIncompatibleInfo {
};
crate_level_only
}
+
+declare_lint! {
+ /// The `unsupported_calling_conventions` lint is output whenever there is an use of the
+ /// `stdcall`, `fastcall`, `thiscall`, `vectorcall` calling conventions (or their unwind
+ /// variants) on targets that cannot meaningfully be supported for the requested target.
+ ///
+ /// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc
+ /// code, because this calling convention was never specified for those targets.
+ ///
+ /// Historically MSVC toolchains have fallen back to the regular C calling convention for
+ /// targets other than x86, but Rust doesn't really see a similar need to introduce a similar
+ /// hack across many more targets.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,ignore (needs specific targets)
+ /// extern "stdcall" fn stdcall() {}
+ /// ```
+ ///
+ /// This will produce:
+ ///
+ /// ```text
+ /// warning: use of calling convention not supported on this target
+ /// --> $DIR/unsupported.rs:39:1
+ /// |
+ /// LL | extern "stdcall" fn stdcall() {}
+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// |
+ /// = note: `#[warn(unsupported_calling_conventions)]` on by default
+ /// = warning: this was previously accepted by the compiler but is being phased out;
+ /// it will become a hard error in a future release!
+ /// = note: for more information, see issue ...
+ /// ```
+ ///
+ /// ### Explanation
+ ///
+ /// On most of the targets the behaviour of `stdcall` and similar calling conventions is not
+ /// defined at all, but was previously accepted due to a bug in the implementation of the
+ /// compiler.
+ pub UNSUPPORTED_CALLING_CONVENTIONS,
+ Warn,
+ "use of unsupported calling convention",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #00000 <https://github.com/rust-lang/rust/issues/00000>",
+ };
+}
}
extern "C" LLVMValueRef
-LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
- LLVMAtomicOrdering Order) {
+LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
+ const char *Name, LLVMAtomicOrdering Order) {
Value *Ptr = unwrap(Source);
- Type *Ty = Ptr->getType()->getPointerElementType();
- LoadInst *LI = unwrap(B)->CreateLoad(Ty, Ptr, Name);
+ LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
LI->setAtomic(fromRust(Order));
return wrap(LI);
}
use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
use rustc_session::output::validate_crate_name;
use rustc_session::search_paths::PathKind;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
unused_externs: Vec<Symbol>,
}
+impl std::fmt::Debug for CStore {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("CStore").finish_non_exhaustive()
+ }
+}
+
pub struct CrateLoader<'a> {
// Immutable configuration.
sess: &'a Session,
metadata_loader: Box<MetadataLoaderDyn>,
local_crate_name: &str,
) -> Self {
- let local_crate_stable_id =
- StableCrateId::new(local_crate_name, sess.local_crate_disambiguator());
let mut stable_crate_ids = FxHashMap::default();
- stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE);
+ stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
CrateLoader {
sess,
fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
// Check for (potential) conflicts with the local crate
- if self.local_crate_name == root.name()
- && self.sess.local_crate_disambiguator() == root.disambiguator()
- {
+ if self.sess.local_stable_crate_id() == root.stable_crate_id() {
return Err(CrateError::SymbolConflictsCurrent(root.name()));
}
// Check for conflicts with any crate loaded so far
let mut res = Ok(());
self.cstore.iter_crate_data(|_, other| {
- if other.name() == root.name() && // same crate-name
- other.disambiguator() == root.disambiguator() && // same crate-disambiguator
+ if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id
other.hash() != root.hash()
{
// but different SVH
None => (&source, &crate_root),
};
let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
- Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?)
+ Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
} else {
None
};
fn dlsym_proc_macros(
&self,
path: &Path,
- disambiguator: CrateDisambiguator,
+ stable_crate_id: StableCrateId,
) -> Result<&'static [ProcMacro], CrateError> {
// Make sure the path contains a / or the linker will search for it.
let path = env::current_dir().unwrap().join(path);
Err(s) => return Err(CrateError::DlOpen(s)),
};
- let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
+ let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
let decls = unsafe {
let sym = match lib.symbol(&sym) {
Ok(f) => f,
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::CrateNum;
+use rustc_middle::middle::cstore::CrateDepKind;
use rustc_middle::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
-use rustc_middle::middle::cstore::{self, CrateDepKind};
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
}
fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
- let crates = cstore::used_crates(tcx, RequireStatic);
- if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
+ let all_crates_available_as_rlib = tcx
+ .crates(())
+ .iter()
+ .cloned()
+ .filter_map(|cnum| {
+ if tcx.dep_kind(cnum).macros_only() {
+ return None;
+ }
+ Some(tcx.used_crate_source(cnum).rlib.is_some())
+ })
+ .all(|is_rlib| is_rlib);
+ if !all_crates_available_as_rlib {
return None;
}
use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
use rustc_session::search_paths::PathKind;
use rustc_session::utils::CanonicalizedPath;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use rustc_target::spec::{Target, TargetTriple};
metadata_loader: &dyn MetadataLoader,
span: Span,
name: Symbol,
-) -> (PathBuf, CrateDisambiguator) {
+) -> (PathBuf, StableCrateId) {
match find_plugin_registrar_impl(sess, metadata_loader, name) {
Ok(res) => res,
// `core` is always available if we got as far as loading plugins.
sess: &'a Session,
metadata_loader: &dyn MetadataLoader,
name: Symbol,
-) -> Result<(PathBuf, CrateDisambiguator), CrateError> {
+) -> Result<(PathBuf, StableCrateId), CrateError> {
info!("find plugin registrar `{}`", name);
let mut locator = CrateLocator::new(
sess,
match locator.maybe_load_library_crate()? {
Some(library) => match library.source.dylib {
- Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())),
+ Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())),
None => Err(CrateError::NonDylibPlugin(name)),
},
None => Err(locator.into_error()),
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::{DllImport, NativeLib};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::middle::cstore::{DllCallingConvention, DllImport, NativeLib};
+use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
}
if lib.kind == NativeLibKind::RawDylib {
- match abi {
- Abi::C { .. } => (),
- Abi::Cdecl => (),
- _ => {
- if sess.target.arch == "x86" {
- sess.span_fatal(
- it.span,
- r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
- );
- }
- }
- };
lib.dll_imports.extend(
foreign_mod_items
.iter()
- .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+ .map(|child_item| self.build_dll_import(abi, child_item)),
);
}
}
}
}
+
+ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+ let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
+ self.tcx
+ .type_of(item.id.def_id)
+ .fn_sig(self.tcx)
+ .inputs()
+ .map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
+ );
+
+ argument_types
+ .iter()
+ .map(|ty| {
+ let layout = self
+ .tcx
+ .layout_of(ParamEnvAnd { param_env: ParamEnv::empty(), value: ty })
+ .expect("layout")
+ .layout;
+ // In both stdcall and fastcall, we always round up the argument size to the
+ // nearest multiple of 4 bytes.
+ (layout.size.bytes_usize() + 3) & !3
+ })
+ .sum()
+ }
+
+ fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+ let calling_convention = if self.tcx.sess.target.arch == "x86" {
+ match abi {
+ Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
+ Abi::Stdcall { .. } | Abi::System { .. } => {
+ DllCallingConvention::Stdcall(self.i686_arg_list_size(item))
+ }
+ Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)),
+ // Vectorcall is intentionally not supported at this time.
+ _ => {
+ self.tcx.sess.span_fatal(
+ item.span,
+ r#"ABI not supported by `#[link(kind = "raw-dylib")]` on i686"#,
+ );
+ }
+ }
+ } else {
+ match abi {
+ Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C,
+ _ => {
+ self.tcx.sess.span_fatal(
+ item.span,
+ r#"ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture"#,
+ );
+ }
+ }
+ };
+ DllImport { name: item.ident.name, ordinal: None, calling_convention, span: item.span }
+ }
}
self.name
}
- crate fn disambiguator(&self) -> CrateDisambiguator {
- self.disambiguator
- }
-
crate fn hash(&self) -> Svh {
self.hash
}
.decode((self, sess))
}
- fn load_proc_macro(&self, def_id: DefId, sess: &Session) -> SyntaxExtension {
- let (name, kind, helper_attrs) = match *self.raw_proc_macro(def_id.index) {
+ fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
+ let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
ProcMacro::CustomDerive { trait_name, attributes, client } => {
let helper_attrs =
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(
trait_name,
- SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
- client,
- krate: def_id.krate,
- })),
+ SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })),
helper_attrs,
)
}
- ProcMacro::Attr { name, client } => (
- name,
- SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client, krate: def_id.krate })),
- Vec::new(),
- ),
- ProcMacro::Bang { name, client } => (
- name,
- SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client, krate: def_id.krate })),
- Vec::new(),
- ),
+ ProcMacro::Attr { name, client } => {
+ (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new())
+ }
+ ProcMacro::Bang { name, client } => {
+ (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new())
+ }
};
- let attrs: Vec<_> = self.get_item_attrs(def_id.index, sess).collect();
+ let attrs: Vec<_> = self.get_item_attrs(id, sess).collect();
SyntaxExtension::new(
sess,
kind,
- self.get_span(def_id.index, sess),
+ self.get_span(id, sess),
helper_attrs,
self.root.edition,
Symbol::intern(name),
self.root.name
}
- crate fn disambiguator(&self) -> CrateDisambiguator {
- self.root.disambiguator
+ crate fn stable_crate_id(&self) -> StableCrateId {
+ self.root.stable_crate_id
}
crate fn hash(&self) -> Svh {
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_session::utils::NativeLibKind;
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::{Session, StableCrateId};
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::Symbol;
}
native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
foreign_modules => { cdata.get_foreign_modules(tcx) }
- crate_disambiguator => { cdata.root.disambiguator }
crate_hash => { cdata.root.hash }
crate_host_hash => { cdata.host_hash }
crate_name => { cdata.root.name }
let data = self.get_crate_data(id.krate);
if data.root.is_proc_macro_crate() {
- return LoadedMacro::ProcMacro(data.load_proc_macro(id, sess));
+ return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess));
}
let span = data.get_span(id.index, sess);
self.get_crate_data(cnum).root.name
}
- fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
- self.get_crate_data(cnum).root.disambiguator
+ fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId {
+ self.get_crate_data(cnum).root.stable_crate_id
}
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh {
}
fn encode_def_path_table(&mut self) {
- let table = self.tcx.hir().definitions().def_path_table();
+ let table = self.tcx.resolutions(()).definitions.def_path_table();
if self.is_proc_macro {
for def_index in std::iter::once(CRATE_DEF_INDEX)
.chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
- disambiguator: tcx.sess.local_crate_disambiguator(),
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
panic_strategy: tcx.sess.panic_strategy(),
edition: tcx.sess.edition(),
let data = ModData {
reexports,
- expansion: tcx.hir().definitions().expansion_that_defined(local_def_id),
+ expansion: tcx.resolutions(()).definitions.expansion_that_defined(local_def_id),
};
record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
.map(|(trait_def_id, mut impls)| {
// Bring everything into deterministic order for hashing
impls.sort_by_cached_key(|&(index, _)| {
- tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
+ tcx.hir().def_path_hash(LocalDefId { local_def_index: index })
});
TraitImpls {
use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion;
-use rustc_session::CrateDisambiguator;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{Ident, Symbol};
triple: TargetTriple,
extra_filename: String,
hash: Svh,
- disambiguator: CrateDisambiguator,
stable_crate_id: StableCrateId,
panic_strategy: PanicStrategy,
edition: Edition,
use rustc_data_structures::svh::Svh;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, Definitions};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::*;
use rustc_index::vec::Idx;
+use rustc_span::def_id::StableCrateId;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, Ident, Symbol};
self.tcx.hir_crate(())
}
- #[inline]
- pub fn definitions(&self) -> &'hir Definitions {
- &self.tcx.definitions
- }
-
pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
- self.tcx.definitions.def_key(def_id)
+ // Accessing the DefKey is ok, since it is part of DefPathHash.
+ self.tcx.untracked_resolutions.definitions.def_key(def_id)
}
pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> {
}
pub fn def_path(&self, def_id: LocalDefId) -> DefPath {
- self.tcx.definitions.def_path(def_id)
+ // Accessing the DefPath is ok, since it is part of DefPathHash.
+ self.tcx.untracked_resolutions.definitions.def_path(def_id)
+ }
+
+ #[inline]
+ pub fn def_path_hash(self, def_id: LocalDefId) -> DefPathHash {
+ // Accessing the DefPathHash is ok, it is incr. comp. stable.
+ self.tcx.untracked_resolutions.definitions.def_path_hash(def_id)
}
#[inline]
#[inline]
pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<LocalDefId> {
- self.tcx.definitions.opt_hir_id_to_local_def_id(hir_id)
+ // FIXME(#85914) is this access safe for incr. comp.?
+ self.tcx.untracked_resolutions.definitions.opt_hir_id_to_local_def_id(hir_id)
}
#[inline]
pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
- self.tcx.definitions.local_def_id_to_hir_id(def_id)
+ // FIXME(#85914) is this access safe for incr. comp.?
+ self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id)
}
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
- self.tcx.definitions.iter_local_def_id()
+ // Create a dependency to the crate to be sure we reexcute this when the amount of
+ // definitions change.
+ self.tcx.ensure().hir_crate(());
+ self.tcx.untracked_resolutions.definitions.iter_local_def_id()
}
pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> {
let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
+ // We can access untracked state since we are an eval_always query.
let hcx = tcx.create_stable_hashing_context();
- let mut collector =
- NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx);
+ let mut collector = NodeCollector::root(
+ tcx.sess,
+ &**tcx.arena,
+ tcx.untracked_crate,
+ &tcx.untracked_resolutions.definitions,
+ hcx,
+ );
intravisit::walk_crate(&mut collector, tcx.untracked_crate);
let map = collector.finalize_and_compute_crate_hash();
pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
assert_eq!(crate_num, LOCAL_CRATE);
+ // We can access untracked state since we are an eval_always query.
let mut hcx = tcx.create_stable_hashing_context();
let mut hir_body_nodes: Vec<_> = tcx
.map
.iter_enumerated()
.filter_map(|(def_id, hod)| {
- let def_path_hash = tcx.definitions.def_path_hash(def_id);
+ let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
let mut hasher = StableHasher::new();
hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
},
);
- let upstream_crates = upstream_crates(&*tcx.cstore);
+ let upstream_crates = upstream_crates(&*tcx.untracked_resolutions.cstore);
// We hash the final, remapped names of all local source files so we
// don't have to include the path prefix remapping commandline args.
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
- tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher);
+ tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
let crate_hash: Fingerprint = stable_hasher.finish();
Svh::new(crate_hash.to_smaller_hash())
}
-fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> {
let mut upstream_crates: Vec<_> = cstore
.crates_untracked()
.iter()
.map(|&cnum| {
- let name = cstore.crate_name_untracked(cnum);
- let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
+ let stable_crate_id = cstore.stable_crate_id_untracked(cnum);
let hash = cstore.crate_hash_untracked(cnum);
- (name, disambiguator, hash)
+ (stable_crate_id, hash)
})
.collect();
- upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
+ upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
upstream_crates
}
providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
providers.expn_that_defined = |tcx, id| {
let id = id.expect_local();
- tcx.definitions.expansion_that_defined(id)
+ tcx.resolutions(()).definitions.expansion_that_defined(id)
};
}
}
}
+impl rustc_session::HashStableContext for StableHashingContext<'a> {}
+
pub fn hash_stable_trait_impls<'a>(
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher,
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
use rustc_hir::HirId;
+use rustc_index::vec::IndexVec;
use rustc_session::lint::{
builtin::{self, FORBIDDEN_LINT_GROUPS},
FutureIncompatibilityReason, Level, Lint, LintId,
/// A tuple of a lint level and its source.
pub type LevelAndSource = (Level, LintLevelSource);
-#[derive(Debug)]
+#[derive(Debug, HashStable)]
pub struct LintLevelSets {
- pub list: Vec<LintSet>,
+ pub list: IndexVec<LintStackIndex, LintSet>,
pub lint_cap: Level,
}
-#[derive(Debug)]
-pub enum LintSet {
- CommandLine {
- // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
- // flag.
- specs: FxHashMap<LintId, LevelAndSource>,
- },
-
- Node {
- specs: FxHashMap<LintId, LevelAndSource>,
- parent: u32,
- },
+rustc_index::newtype_index! {
+ #[derive(HashStable)]
+ pub struct LintStackIndex {
+ const COMMAND_LINE = 0,
+ }
+}
+
+#[derive(Debug, HashStable)]
+pub struct LintSet {
+ // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+ // flag.
+ pub specs: FxHashMap<LintId, LevelAndSource>,
+
+ pub parent: LintStackIndex,
}
impl LintLevelSets {
pub fn new() -> Self {
- LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+ LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid }
}
pub fn get_lint_level(
&self,
lint: &'static Lint,
- idx: u32,
+ idx: LintStackIndex,
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
sess: &Session,
) -> LevelAndSource {
}
}
- // Ensure that we never exceed the `--cap-lints` argument.
- level = cmp::min(level, self.lint_cap);
+ // Ensure that we never exceed the `--cap-lints` argument
+ // unless the source is a --force-warn
+ level = if let LintLevelSource::CommandLine(_, Level::ForceWarn) = src {
+ level
+ } else {
+ cmp::min(level, self.lint_cap)
+ };
if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
// Ensure that we never exceed driver level.
pub fn get_lint_id_level(
&self,
id: LintId,
- mut idx: u32,
+ mut idx: LintStackIndex,
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
) -> (Option<Level>, LintLevelSource) {
if let Some(specs) = aux {
}
}
loop {
- match self.list[idx as usize] {
- LintSet::CommandLine { ref specs } => {
- if let Some(&(level, src)) = specs.get(&id) {
- return (Some(level), src);
- }
- return (None, LintLevelSource::Default);
- }
- LintSet::Node { ref specs, parent } => {
- if let Some(&(level, src)) = specs.get(&id) {
- return (Some(level), src);
- }
- idx = parent;
- }
+ let LintSet { ref specs, parent } = self.list[idx];
+ if let Some(&(level, src)) = specs.get(&id) {
+ return (Some(level), src);
+ }
+ if idx == COMMAND_LINE {
+ return (None, LintLevelSource::Default);
}
+ idx = parent;
}
}
}
#[derive(Debug)]
pub struct LintLevelMap {
pub sets: LintLevelSets,
- pub id_to_set: FxHashMap<HirId, u32>,
+ pub id_to_set: FxHashMap<HirId, LintStackIndex>,
}
impl LintLevelMap {
id_to_set.hash_stable(hcx, hasher);
- let LintLevelSets { ref list, lint_cap } = *sets;
-
- lint_cap.hash_stable(hcx, hasher);
-
- hcx.while_hashing_spans(true, |hcx| {
- list.len().hash_stable(hcx, hasher);
-
- // We are working under the assumption here that the list of
- // lint-sets is built in a deterministic order.
- for lint_set in list {
- ::std::mem::discriminant(lint_set).hash_stable(hcx, hasher);
-
- match *lint_set {
- LintSet::CommandLine { ref specs } => {
- specs.hash_stable(hcx, hasher);
- }
- LintSet::Node { ref specs, parent } => {
- specs.hash_stable(hcx, hasher);
- parent.hash_stable(hcx, hasher);
- }
- }
- }
- })
+ hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher))
}
}
return;
}
}
- (Level::Warn | Level::ForceWarn, Some(span)) => sess.struct_span_warn(span, ""),
- (Level::Warn | Level::ForceWarn, None) => sess.struct_warn(""),
+ (Level::Warn, Some(span)) => sess.struct_span_warn(span, ""),
+ (Level::Warn, None) => sess.struct_warn(""),
+ (Level::ForceWarn, Some(span)) => sess.struct_span_force_warn(span, ""),
+ (Level::ForceWarn, None) => sess.struct_force_warn(""),
(Level::Deny | Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
(Level::Deny | Level::Forbid, None) => sess.struct_err(""),
};
}
}
- err.code(DiagnosticId::Lint { name, has_future_breakage });
+ let is_force_warn = matches!(level, Level::ForceWarn);
+ err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
if let Some(future_incompatible) = future_incompatible {
let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
false
}
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
- ExpnKind::Macro { kind: MacroKind::Bang, name: _, proc_macro: _ } => {
+ ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.
expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site)
}
use rustc_macros::HashStable;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
+use rustc_session::StableCrateId;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::Target;
}
}
-#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
-pub enum LibSource {
- Some(PathBuf),
- MetadataOnly,
- None,
-}
-
-impl LibSource {
- pub fn is_some(&self) -> bool {
- matches!(self, LibSource::Some(_))
- }
-
- pub fn option(&self) -> Option<PathBuf> {
- match *self {
- LibSource::Some(ref p) => Some(p.clone()),
- LibSource::MetadataOnly | LibSource::None => None,
- }
- }
-}
-
#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)]
pub enum LinkagePreference {
RequireDynamic,
pub dll_imports: Vec<DllImport>,
}
-#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
pub struct DllImport {
pub name: Symbol,
pub ordinal: Option<u16>,
+ /// Calling convention for the function.
+ ///
+ /// On x86_64, this is always `DllCallingConvention::C`; on i686, it can be any
+ /// of the values, and we use `DllCallingConvention::C` to represent `"cdecl"`.
+ pub calling_convention: DllCallingConvention,
+ /// Span of import's "extern" declaration; used for diagnostics.
+ pub span: Span,
+}
+
+/// Calling convention for a function defined in an external library.
+///
+/// The usize value, where present, indicates the size of the function's argument list
+/// in bytes.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable)]
+pub enum DllCallingConvention {
+ C,
+ Stdcall(usize),
+ Fastcall(usize),
+ Vectorcall(usize),
}
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
/// that it's *not* tracked for dependency information throughout compilation
/// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
/// during resolve)
-pub trait CrateStore {
+pub trait CrateStore: std::fmt::Debug {
fn as_any(&self) -> &dyn Any;
// resolve
// "queries" used in resolve that aren't tracked for incremental compilation
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
- fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
+ fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId;
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
// This is basically a 1-based range of ints, which is a little
}
pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
-
-// This method is used when generating the command line to pass through to
-// system linker. The linker expects undefined symbols on the left of the
-// command line to be defined in libraries on the right, not the other way
-// around. For more info, see some comments in the add_used_library function
-// below.
-//
-// In order to get this left-to-right dependency ordering, we perform a
-// topological sort of all crates putting the leaves at the right-most
-// positions.
-pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> {
- let mut libs = tcx
- .crates(())
- .iter()
- .cloned()
- .filter_map(|cnum| {
- if tcx.dep_kind(cnum).macros_only() {
- return None;
- }
- let source = tcx.used_crate_source(cnum);
- let path = match prefer {
- LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
- LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
- };
- let path = match path {
- Some(p) => LibSource::Some(p),
- None => {
- if source.rmeta.is_some() {
- LibSource::MetadataOnly
- } else {
- LibSource::None
- }
- }
- };
- Some((cnum, path))
- })
- .collect::<Vec<_>>();
- let mut ordering = tcx.postorder_cnums(()).to_owned();
- ordering.reverse();
- libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a));
- libs
-}
pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
format!(
- "rust_metadata_{}_{}",
+ "rust_metadata_{}_{:08x}",
tcx.crate_name(LOCAL_CRATE),
- tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
+ tcx.sess.local_stable_crate_id().to_u64(),
)
}
//! just peeks and looks for that attribute.
use crate::bug;
-use rustc_ast as ast;
-use rustc_data_structures::sync::OnceCell;
+use crate::ty;
+use rustc_ast::Attribute;
use rustc_session::Session;
+use rustc_session::{Limit, Limits};
use rustc_span::symbol::{sym, Symbol};
use std::num::IntErrorKind;
-pub fn update_limits(sess: &Session, krate: &ast::Crate) {
- update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
- update_limit(sess, krate, &sess.move_size_limit, sym::move_size_limit, 0);
- update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
- update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000);
+pub fn provide(providers: &mut ty::query::Providers) {
+ providers.limits = |tcx, ()| Limits {
+ recursion_limit: get_recursion_limit(tcx.hir().krate_attrs(), tcx.sess),
+ move_size_limit: get_limit(tcx.hir().krate_attrs(), tcx.sess, sym::move_size_limit, 0),
+ type_length_limit: get_limit(
+ tcx.hir().krate_attrs(),
+ tcx.sess,
+ sym::type_length_limit,
+ 1048576,
+ ),
+ const_eval_limit: get_limit(
+ tcx.hir().krate_attrs(),
+ tcx.sess,
+ sym::const_eval_limit,
+ 1_000_000,
+ ),
+ }
+}
+
+pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
+ get_limit(krate_attrs, sess, sym::recursion_limit, 128)
}
-fn update_limit(
- sess: &Session,
- krate: &ast::Crate,
- limit: &OnceCell<impl From<usize> + std::fmt::Debug>,
- name: Symbol,
- default: usize,
-) {
- for attr in &krate.attrs {
+fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
+ for attr in krate_attrs {
if !sess.check_name(attr, name) {
continue;
}
if let Some(s) = attr.value_str() {
match s.as_str().parse() {
- Ok(n) => {
- limit.set(From::from(n)).unwrap();
- return;
- }
+ Ok(n) => return Limit::new(n),
Err(e) => {
let mut err =
sess.struct_span_err(attr.span, "`limit` must be a non-negative integer");
}
}
}
- limit.set(From::from(default)).unwrap();
+ return Limit::new(default);
}
pub mod region;
pub mod resolve_lifetime;
pub mod stability;
+
+pub fn provide(providers: &mut crate::ty::query::Providers) {
+ limits::provide(providers);
+}
suggestion: Option<Symbol>,
lint: &'static Lint,
span: Span,
+ method_span: Option<Span>,
hir_id: HirId,
def_id: DefId,
) {
if span.in_derive_expansion() {
return;
}
-
- tcx.struct_span_lint_hir(lint, hir_id, span, |lint| {
+ let method_span = method_span.unwrap_or(span);
+ tcx.struct_span_lint_hir(lint, hir_id, method_span, |lint| {
let mut diag = lint.build(message);
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
let kind = tcx.def_kind(def_id).descr(def_id);
- deprecation_suggestion(&mut diag, kind, suggestion, span);
+ deprecation_suggestion(&mut diag, kind, suggestion, method_span);
}
diag.emit()
});
let path = &with_no_trimmed_paths(|| self.def_path_str(def_id));
let kind = self.def_kind(def_id).descr(def_id);
let (message, lint) = deprecation_message(&depr_entry.attr, kind, path);
- let span = method_span.unwrap_or(span);
late_report_deprecation(
self,
&message,
depr_entry.attr.suggestion,
lint,
span,
+ method_span,
id,
def_id,
);
range: AllocRange,
val: ScalarMaybeUninit<Tag>,
) -> AllocResult {
+ assert!(self.mutability == Mutability::Mut);
+
let val = match val {
ScalarMaybeUninit::Scalar(scalar) => scalar,
ScalarMaybeUninit::Uninit => {
if range.size.bytes() == 0 {
return;
}
+ assert!(self.mutability == Mutability::Mut);
self.init_mask.set_range(range.start, range.end(), is_init);
}
}
/// in an aliasable location. To solve, you'd have to translate with
/// an `&mut` borrow:
///
- /// struct Env { x: & &mut isize }
+ /// struct Env { x: &mut &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
// local crate's ID. Otherwise there can be collisions between CGUs
// instantiating stuff for upstream crates.
let local_crate_id = if cnum != LOCAL_CRATE {
- let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE));
- format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8])
+ let local_stable_crate_id = tcx.sess.local_stable_crate_id();
+ format!(
+ "-in-{}.{:08x}",
+ tcx.crate_name(LOCAL_CRATE),
+ local_stable_crate_id.to_u64() as u32,
+ )
} else {
String::new()
};
- let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
- // Using a shortened disambiguator of about 40 bits
- format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id)
+ let stable_crate_id = tcx.sess.local_stable_crate_id();
+ format!(
+ "{}.{:08x}{}",
+ tcx.crate_name(cnum),
+ stable_crate_id.to_u64() as u32,
+ local_crate_id,
+ )
});
write!(cgu_name, "{}", crate_prefix).unwrap();
desc { "trigger a delay span bug" }
}
+ query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
+ eval_always
+ no_hash
+ desc { "get the resolver outputs" }
+ }
+
/// Represents crate as a whole (as distinct from the top-level crate module).
/// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
/// we will have to assume that any change means that you need to be recompiled.
}
query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
- eval_always
desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
}
desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
}
+ query should_inherit_track_caller(def_id: DefId) -> bool {
+ desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
+ }
+
query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
}
query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export<LocalDefId>]> {
desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
- eval_always
}
query impl_defaultness(def_id: DefId) -> hir::Defaultness {
query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
desc { "looking up the derive registrar for a crate" }
}
- query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
- eval_always
- desc { "looking up the disambiguator a crate" }
- }
// The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
// Changing the name should cause a compiler error, but in case that changes, be aware.
query crate_hash(_: CrateNum) -> Svh {
}
query visibility(def_id: DefId) -> ty::Visibility {
- eval_always
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
}
desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
}
query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
- // This depends on untracked global state (`tcx.extern_crate_map`)
- eval_always
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
eval_always
}
query maybe_unused_trait_import(def_id: LocalDefId) -> bool {
- eval_always
desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
- eval_always
desc { "looking up all possibly unused extern crates" }
}
- query names_imported_by_glob_use(def_id: LocalDefId)
- -> &'tcx FxHashSet<Symbol> {
- eval_always
+ query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
desc { "calculating the stability index for the local crate" }
}
query crates(_: ()) -> &'tcx [CrateNum] {
- eval_always
desc { "fetching all foreign CrateNum instances" }
}
desc { "evaluating trait selection obligation `{}`", goal.value }
}
- /// Evaluates whether the given type implements the given trait
- /// in the given environment.
- ///
- /// The inputs are:
- ///
- /// - the def-id of the trait
- /// - the self type
- /// - the *other* type parameters of the trait, excluding the self-type
- /// - the parameter environment
- ///
- /// FIXME. If the type, trait, or environment has inference variables,
- /// this yields `EvaluatedToUnknown`. It should be refactored
- /// to use canonicalization, really.
- query type_implements_trait(
- key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
- ) -> traits::EvaluationResult {
- desc { "evaluating `type_implements_trait` `{:?}`", key }
- }
-
/// Do not call this query directly: part of the `Eq` type-op
query type_op_ascribe_user_type(
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
desc { "conservatively checking if {:?} is privately uninhabited", key }
}
+
+ query limits(key: ()) -> Limits {
+ desc { "looking up limits" }
+ }
}
/// impl Clone for i32 { ... } // Impl_3
///
/// fn foo<T: Clone>(concrete: Option<Box<i32>>, param: T, mixed: Option<T>) {
-/// // Case A: Vtable points at a specific impl. Only possible when
+/// // Case A: ImplSource points at a specific impl. Only possible when
/// // type is concretely known. If the impl itself has bounded
-/// // type parameters, Vtable will carry resolutions for those as well:
-/// concrete.clone(); // Vtable(Impl_1, [Vtable(Impl_2, [Vtable(Impl_3)])])
+/// // type parameters, ImplSource will carry resolutions for those as well:
+/// concrete.clone(); // ImpleSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
///
/// // Case A: ImplSource points at a specific impl. Only possible when
/// // type is concretely known. If the impl itself has bounded
/// an `&mut` borrow:
///
/// ```
- /// struct Env { x: & &mut isize }
+ /// struct Env { x: &mut &mut isize }
/// let x: &mut isize = ...;
/// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
/// fn fn_ptr(env: &mut Env) { **env.x += 5; }
use crate::arena::Arena;
use crate::dep_graph::DepGraph;
-use crate::hir::exports::ExportMap;
use crate::hir::place::Place as HirPlace;
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
use crate::middle;
-use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata};
+use crate::middle::cstore::EncodedMetadata;
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
use crate::ty::{
self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar,
- FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List,
- MainDefinition, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
- ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
- TyVid, TypeAndMut, UintTy, Visibility,
+ FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+ ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind,
+ ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::definitions::Definitions;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint};
+use rustc_session::Limit;
use rustc_session::Session;
use rustc_span::def_id::StableCrateId;
use rustc_span::source_map::MultiSpan;
interners: CtxtInterners<'tcx>,
- pub(crate) cstore: Box<CrateStoreDyn>,
-
pub sess: &'tcx Session,
/// This only ever stores a `LintStore` but we don't want a dependency on that type here.
/// Common consts, pre-interned for your convenience.
pub consts: CommonConsts<'tcx>,
- /// Visibilities produced by resolver.
- pub visibilities: FxHashMap<LocalDefId, Visibility>,
-
- /// Resolutions of `extern crate` items produced by resolver.
- extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-
- /// Export map produced by name resolution.
- export_map: ExportMap<LocalDefId>,
+ /// Output of the resolver.
+ pub(crate) untracked_resolutions: ty::ResolverOutputs,
pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
- pub(crate) definitions: Definitions,
/// This provides access to the incremental compilation on-disk cache for query results.
/// Do not access this directly. It is only meant to be used by
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
pub query_caches: query::QueryCaches<'tcx>,
- maybe_unused_trait_imports: FxHashSet<LocalDefId>,
- maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
- /// A map of glob use to a set of names it actually imports. Currently only
- /// used in save-analysis.
- pub(crate) glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
- /// Extern prelude entries. The value is `true` if the entry was introduced
- /// via `extern crate` item and not `--extern` option or compiler built-in.
- pub extern_prelude: FxHashMap<Symbol, bool>,
-
// Internal caches for metadata decoding. No need to track deps on this.
pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
output_filenames: Arc<OutputFilenames>,
- pub main_def: Option<MainDefinition>,
-
pub(super) vtables_cache:
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
}
let common_types = CommonTypes::new(&interners);
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
- let cstore = resolutions.cstore;
GlobalCtxt {
sess: s,
lint_store,
- cstore,
arena,
interners,
dep_graph,
+ untracked_resolutions: resolutions,
prof: s.prof.clone(),
types: common_types,
lifetimes: common_lifetimes,
consts: common_consts,
- visibilities: resolutions.visibilities,
- extern_crate_map: resolutions.extern_crate_map,
- export_map: resolutions.export_map,
- maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
- maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
- glob_map: resolutions.glob_map,
- extern_prelude: resolutions.extern_prelude,
untracked_crate: krate,
- definitions: resolutions.definitions,
on_disk_cache,
queries,
query_caches: query::QueryCaches::default(),
const_stability_interner: Default::default(),
alloc_map: Lock::new(interpret::AllocMap::new()),
output_filenames: Arc::new(output_filenames),
- main_def: resolutions.main_def,
vtables_cache: Default::default(),
}
}
}
pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
- if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) }
+ // Accessing the DefKey is ok, since it is part of DefPathHash.
+ if let Some(id) = id.as_local() {
+ self.untracked_resolutions.definitions.def_key(id)
+ } else {
+ self.untracked_resolutions.cstore.def_key(id)
+ }
}
/// Converts a `DefId` into its fully expanded `DefPath` (every
/// Note that if `id` is not local to this crate, the result will
/// be a non-local `DefPath`.
pub fn def_path(self, id: DefId) -> rustc_hir::definitions::DefPath {
+ // Accessing the DefPath is ok, since it is part of DefPathHash.
if let Some(id) = id.as_local() {
- self.hir().def_path(id)
+ self.untracked_resolutions.definitions.def_path(id)
} else {
- self.cstore.def_path(id)
+ self.untracked_resolutions.cstore.def_path(id)
}
}
#[inline]
pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
+ // Accessing the DefPathHash is ok, it is incr. comp. stable.
if let Some(def_id) = def_id.as_local() {
- self.definitions.def_path_hash(def_id)
+ self.untracked_resolutions.definitions.def_path_hash(def_id)
} else {
- self.cstore.def_path_hash(def_id)
+ self.untracked_resolutions.cstore.def_path_hash(def_id)
}
}
#[inline]
- pub fn stable_crate_id(self, cnum: CrateNum) -> StableCrateId {
- self.def_path_hash(cnum.as_def_id()).stable_crate_id()
+ pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
+ if crate_num == LOCAL_CRATE {
+ self.sess.local_stable_crate_id()
+ } else {
+ self.untracked_resolutions.cstore.stable_crate_id_untracked(crate_num)
+ }
}
pub fn def_path_debug_str(self, def_id: DefId) -> String {
// We are explicitly not going through queries here in order to get
- // crate name and disambiguator since this code is called from debug!()
+ // crate name and stable crate id since this code is called from debug!()
// statements within the query system and we'd run into endless
// recursion otherwise.
- let (crate_name, crate_disambiguator) = if def_id.is_local() {
- (self.crate_name, self.sess.local_crate_disambiguator())
+ let (crate_name, stable_crate_id) = if def_id.is_local() {
+ (self.crate_name, self.sess.local_stable_crate_id())
} else {
+ let cstore = &self.untracked_resolutions.cstore;
(
- self.cstore.crate_name_untracked(def_id.krate),
- self.cstore.crate_disambiguator_untracked(def_id.krate),
+ cstore.crate_name_untracked(def_id.krate),
+ cstore.stable_crate_id_untracked(def_id.krate),
)
};
format!(
"{}[{}]{}",
crate_name,
- // Don't print the whole crate disambiguator. That's just
+ // Don't print the whole stable crate id. That's just
// annoying in debug output.
- &(crate_disambiguator.to_fingerprint().to_hex())[..4],
+ &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
self.def_path(def_id).to_string_no_crate_verbose()
)
}
pub fn encode_metadata(self) -> EncodedMetadata {
let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata");
- self.cstore.encode_metadata(self)
+ self.untracked_resolutions.cstore.encode_metadata(self)
}
// Note that this is *untracked* and should only be used within the query
// system if the result is otherwise tracked through queries
pub fn cstore_as_any(self) -> &'tcx dyn Any {
- self.cstore.as_any()
+ self.untracked_resolutions.cstore.as_any()
}
#[inline(always)]
pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
let krate = self.gcx.untracked_crate;
+ let resolutions = &self.gcx.untracked_resolutions;
- StableHashingContext::new(self.sess, krate, &self.definitions, &*self.cstore)
+ StableHashingContext::new(self.sess, krate, &resolutions.definitions, &*resolutions.cstore)
}
#[inline(always)]
pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> {
let krate = self.gcx.untracked_crate;
+ let resolutions = &self.gcx.untracked_resolutions;
- StableHashingContext::ignore_spans(self.sess, krate, &self.definitions, &*self.cstore)
+ StableHashingContext::ignore_spans(
+ self.sess,
+ krate,
+ &resolutions.definitions,
+ &*resolutions.cstore,
+ )
}
pub fn serialize_query_result_cache(self, encoder: &mut FileEncoder) -> FileEncodeResult {
def_kind => (def_kind.article(), def_kind.descr(def_id)),
}
}
+
+ pub fn type_length_limit(self) -> Limit {
+ self.limits(()).type_length_limit
+ }
+
+ pub fn recursion_limit(self) -> Limit {
+ self.limits(()).recursion_limit
+ }
+
+ pub fn move_size_limit(self) -> Limit {
+ self.limits(()).move_size_limit
+ }
+
+ pub fn const_eval_limit(self) -> Limit {
+ self.limits(()).const_eval_limit
+ }
}
/// A trait implemented for all `X<'a>` types that can be safely and
pub fn provide(providers: &mut ty::query::Providers) {
providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id);
- providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|v| &v[..]);
+ providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
+ providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]);
providers.crate_name = |tcx, id| {
assert_eq!(id, LOCAL_CRATE);
tcx.crate_name
};
- providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id);
- providers.maybe_unused_extern_crates = |tcx, ()| &tcx.maybe_unused_extern_crates[..];
- providers.names_imported_by_glob_use =
- |tcx, id| tcx.arena.alloc(tcx.glob_map.get(&id).cloned().unwrap_or_default());
+ providers.maybe_unused_trait_import =
+ |tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id);
+ providers.maybe_unused_extern_crates =
+ |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
+ providers.names_imported_by_glob_use = |tcx, id| {
+ tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
+ };
providers.lookup_stability = |tcx, id| {
let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
let id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
tcx.stability().local_deprecation_entry(id)
};
- providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned();
- providers.crates = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked());
+ providers.extern_mod_stmt_cnum =
+ |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
+ providers.crates =
+ |tcx, ()| tcx.arena.alloc_slice(&tcx.resolutions(()).cstore.crates_untracked());
providers.output_filenames = |tcx, ()| tcx.output_filenames.clone();
providers.features_query = |tcx, ()| tcx.sess.features_untracked();
providers.is_panic_runtime = |tcx, cnum| {
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
- InstanceDef::Item(def) => {
- tcx.codegen_fn_attrs(def.did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
+ InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
+ | InstanceDef::Virtual(def_id, _) => {
+ tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
_ => false,
}
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
- debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+ debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
let fn_sig = tcx.fn_sig(def_id);
let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
&& fn_sig.input(0).skip_binder().is_param(0)
debug!(" => associated item with unsizeable self: Self");
Some(Instance { def: InstanceDef::VtableShim(def_id), substs })
} else {
- Instance::resolve_for_fn_ptr(tcx, param_env, def_id, substs)
+ Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
+ match resolved.def {
+ InstanceDef::Item(def) => {
+ // We need to generate a shim when we cannot guarantee that
+ // the caller of a trait object method will be aware of
+ // `#[track_caller]` - this ensures that the caller
+ // and callee ABI will always match.
+ //
+ // The shim is generated when all of these conditions are met:
+ //
+ // 1) The underlying method expects a caller location parameter
+ // in the ABI
+ if resolved.def.requires_caller_location(tcx)
+ // 2) The caller location parameter comes from having `#[track_caller]`
+ // on the implementation, and *not* on the trait method.
+ && !tcx.should_inherit_track_caller(def.did)
+ // If the method implementation comes from the trait definition itself
+ // (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
+ // then we don't need to generate a shim. This check is needed because
+ // `should_inherit_track_caller` returns `false` if our method
+ // implementation comes from the trait block, and not an impl block
+ && !matches!(
+ tcx.opt_associated_item(def.did),
+ Some(ty::AssocItem {
+ container: ty::AssocItemContainer::TraitContainer(_),
+ ..
+ })
+ )
+ {
+ debug!(
+ " => vtable fn pointer created for function with #[track_caller]"
+ );
+ resolved.def = InstanceDef::ReifyShim(def.did);
+ }
+ }
+ InstanceDef::Virtual(def_id, _) => {
+ debug!(" => vtable fn pointer created for virtual call");
+ resolved.def = InstanceDef::ReifyShim(def_id);
+ }
+ _ => {}
+ }
+
+ resolved
+ })
}
}
ty::tls::with_related_context(tcx, move |icx| {
let (param_env, ty) = query.into_parts();
- if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
+ if !tcx.recursion_limit().value_within_limit(icx.layout_depth) {
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
}
// Data types
+#[derive(Debug)]
pub struct ResolverOutputs {
pub definitions: rustc_hir::definitions::Definitions,
pub cstore: Box<CrateStoreDyn>,
scope: DefId,
block: hir::HirId,
) -> (Ident, DefId) {
- let scope =
- match ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) {
- Some(actual_expansion) => {
- self.hir().definitions().parent_module_of_macro_def(actual_expansion)
- }
- None => self.parent_module(block).to_def_id(),
- };
+ let scope = ident
+ .span
+ .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope))
+ .and_then(|actual_expansion| actual_expansion.expn_data().parent_module)
+ .unwrap_or_else(|| self.parent_module(block).to_def_id());
(ident, scope)
}
util::provide(providers);
print::provide(providers);
super::util::bug::provide(providers);
+ super::middle::provide(providers);
*providers = ty::query::Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
type_uninhabited_from: inhabitedness::type_uninhabited_from,
}
fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
- let type_length_limit = self.tcx.sess.type_length_limit();
+ let type_length_limit = self.tcx.type_length_limit();
if type_length_limit.value_within_limit(self.printed_type_count) {
self.printed_type_count += 1;
self.pretty_print_type(ty)
let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
&mut FxHashMap::default();
- for symbol_set in tcx.glob_map.values() {
+ for symbol_set in tcx.resolutions(()).glob_map.values() {
for symbol in symbol_set {
unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
use rustc_serialize::opaque;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
-use rustc_session::CrateDisambiguator;
+use rustc_session::Limits;
use rustc_target::spec::PanicStrategy;
use rustc_ast as ast;
debug!("def_path_hash_to_def_id({:?})", hash);
// Check if the `DefPathHash` corresponds to a definition in the current
// crate
- if let Some(def_id) = tcx.definitions.local_def_path_hash_to_def_id(hash) {
+ if let Some(def_id) =
+ tcx.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash)
+ {
let def_id = def_id.to_def_id();
e.insert(Some(def_id));
return Some(def_id);
debug_assert_ne!(krate, LOCAL_CRATE);
// Try to find a definition in the current session, using the previous `DefIndex`
// as an initial guess.
- let opt_def_id = tcx.cstore.def_path_hash_to_def_id(krate, raw_def_id.index, hash);
+ let opt_def_id = tcx.untracked_resolutions.cstore.def_path_hash_to_def_id(
+ krate,
+ raw_def_id.index,
+ hash,
+ );
debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
e.insert(opt_def_id);
opt_def_id
mut ty: Ty<'tcx>,
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>,
) -> Ty<'tcx> {
+ let recursion_limit = self.recursion_limit();
for iteration in 0.. {
- if !self.sess.recursion_limit().value_within_limit(iteration) {
+ if !recursion_limit.value_within_limit(iteration) {
return self.ty_error_with_message(
DUMMY_SP,
&format!("reached the recursion limit finding the struct tail for {}", ty),
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt;
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
// to avoid panics
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
- if tcx
- .type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
+ if self
+ .infcx
+ .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env)
.must_apply_modulo_regions()
{
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
if let Some(desc) = access_place_desc {
item_msg = format!("`{}`", desc);
reason = match error_access {
- AccessKind::Mutate => format!(" which is behind {}", pointer_type),
+ AccessKind::Mutate => format!(", which is behind {}", pointer_type),
AccessKind::MutableBorrow => {
format!(", as it is behind {}", pointer_type)
}
) -> (Span, String) {
if let Some(assignment_rhs_span) = opt_assignment_rhs_span {
if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) {
+ let is_mutbl = |ty: &str| -> bool {
+ if ty.starts_with("mut") {
+ let rest = &ty[3..];
+ match rest.chars().next() {
+ // e.g. `&mut x`
+ Some(c) if c.is_whitespace() => true,
+ // e.g. `&mut(x)`
+ Some('(') => true,
+ // e.g. `&mutablevar`
+ _ => false,
+ }
+ } else {
+ false
+ }
+ };
if let (true, Some(ws_pos)) =
(src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() }))
{
let lt_name = &src[1..ws_pos];
- let ty = &src[ws_pos..];
- if !ty.trim_start().starts_with("mut") {
+ let ty = src[ws_pos..].trim_start();
+ if !is_mutbl(ty) {
return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
}
} else if let Some(stripped) = src.strip_prefix('&') {
- if !stripped.trim_start().starts_with("mut") {
+ let stripped = stripped.trim_start();
+ if !is_mutbl(stripped) {
return (assignment_rhs_span, format!("&mut {}", stripped));
}
}
tcx,
root_span,
param_env,
- CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
+ CompileTimeInterpreter::new(tcx.const_eval_limit()),
MemoryExtra { can_access_statics },
)
}
tcx,
tcx.def_span(def.did),
key.param_env,
- CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
+ CompileTimeInterpreter::new(tcx.const_eval_limit()),
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
MemoryExtra { can_access_statics: is_static },
frame: Frame<'mir, 'tcx>,
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
// Enforce stack size limit. Add 1 because this is run before the new frame is pushed.
- if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len() + 1) {
+ if !ecx.recursion_limit.value_within_limit(ecx.stack().len() + 1) {
throw_exhaust!(StackFrameLimitReached)
} else {
Ok(frame)
use rustc_middle::ty::{
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
};
+use rustc_session::Limit;
use rustc_span::{Pos, Span};
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
/// The virtual memory system.
pub memory: Memory<'mir, 'tcx, M>,
+
+ /// The recursion limit (cached from `tcx.recursion_limit(())`)
+ pub recursion_limit: Limit,
}
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
tcx: tcx.at(root_span),
param_env,
memory: Memory::new(tcx, memory_extra),
+ recursion_limit: tcx.recursion_limit(),
}
}
#[inline(always)]
pub fn cur_span(&self) -> Span {
- self.stack().last().map_or(self.tcx.span, |f| f.current_span())
+ self.stack()
+ .iter()
+ .rev()
+ .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
+ .map_or(self.tcx.span, |f| f.current_span())
}
#[inline(always)]
#[must_use]
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
let mut frames = Vec::new();
- for frame in self.stack().iter().rev() {
+ for frame in self
+ .stack()
+ .iter()
+ .rev()
+ .skip_while(|frame| frame.instance.def.requires_caller_location(*self.tcx))
+ {
let lint_root = frame.current_source_info().and_then(|source_info| {
match &frame.body.source_scopes[source_info.scope].local_data {
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
throw_ub_format!("`assume` intrinsic called with `false`");
}
}
+ sym::raw_eq => {
+ let result = self.raw_eq_intrinsic(&args[0], &args[1])?;
+ self.write_scalar(result, dest)?;
+ }
_ => return Ok(false),
}
self.memory.copy(src, align, dst, align, size, nonoverlapping)
}
+
+ pub(crate) fn raw_eq_intrinsic(
+ &mut self,
+ lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+ rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
+ ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+ let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?;
+ assert!(!layout.is_unsized());
+
+ let lhs = self.read_scalar(lhs)?.check_init()?;
+ let rhs = self.read_scalar(rhs)?.check_init()?;
+ let lhs_bytes = self.memory.read_bytes(lhs, layout.size)?;
+ let rhs_bytes = self.memory.read_bytes(rhs, layout.size)?;
+ Ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
+ }
}
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;
+use rustc_session::Limit;
use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP};
use rustc_target::abi::Size;
use smallvec::SmallVec;
let mut visited = MTLock::new(FxHashSet::default());
let mut inlining_map = MTLock::new(InliningMap::new());
+ let recursion_limit = tcx.recursion_limit();
{
let visited: MTRef<'_, _> = &mut visited;
dummy_spanned(root),
visited,
&mut recursion_depths,
+ recursion_limit,
inlining_map,
);
});
starting_point: Spanned<MonoItem<'tcx>>,
visited: MTRef<'_, MTLock<FxHashSet<MonoItem<'tcx>>>>,
recursion_depths: &mut DefIdMap<usize>,
+ recursion_limit: Limit,
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
) {
if !visited.lock_mut().insert(starting_point.node) {
debug_assert!(should_codegen_locally(tcx, &instance));
// Keep track of the monomorphization recursion depth
- recursion_depth_reset =
- Some(check_recursion_limit(tcx, instance, starting_point.span, recursion_depths));
+ recursion_depth_reset = Some(check_recursion_limit(
+ tcx,
+ instance,
+ starting_point.span,
+ recursion_depths,
+ recursion_limit,
+ ));
check_type_length_limit(tcx, instance);
rustc_data_structures::stack::ensure_sufficient_stack(|| {
record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
for neighbour in neighbors {
- collect_items_rec(tcx, neighbour, visited, recursion_depths, inlining_map);
+ collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
}
if let Some((def_id, depth)) = recursion_depth_reset {
instance: Instance<'tcx>,
span: Span,
recursion_depths: &mut DefIdMap<usize>,
+ recursion_limit: Limit,
) -> (DefId, usize) {
let def_id = instance.def_id();
let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
// Code that needs to instantiate the same function recursively
// more than the recursion limit is assumed to be causing an
// infinite expansion.
- if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
+ if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
let error = format!("reached the recursion limit while instantiating `{}`", shrunk);
let mut err = tcx.sess.struct_span_fatal(span, &error);
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
- if !tcx.sess.type_length_limit().value_within_limit(type_length) {
+ if !tcx.type_length_limit().value_within_limit(type_length) {
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32);
let msg = format!("reached the type-length limit while instantiating `{}`", shrunk);
let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg);
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
self.super_operand(operand, location);
- let limit = self.tcx.sess.move_size_limit();
+ let limit = self.tcx.move_size_limit().0;
if limit == 0 {
return;
}
}
}
+/// Comparing raw pointers for equality.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
#[derive(Debug)]
pub struct RawPtrComparison;
impl NonConstOp for RawPtrComparison {
}
}
+/// Casting raw pointer or function pointer to an integer.
+/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
+/// allocation base addresses that are not known at compile-time.
#[derive(Debug)]
pub struct RawPtrToIntCast;
impl NonConstOp for RawPtrToIntCast {
- fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
- Status::Unstable(sym::const_raw_ptr_to_usize_cast)
- }
-
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
- feature_err(
- &ccx.tcx.sess.parse_sess,
- sym::const_raw_ptr_to_usize_cast,
- span,
- &format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),),
- )
+ let mut err = ccx
+ .tcx
+ .sess
+ .struct_span_err(span, "pointers cannot be cast to integers during const eval.");
+ err.note("at compile-time, pointers do not have an integer value");
+ err.note(
+ "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior",
+ );
+ err
}
}
use rustc_hir::Node;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
pub struct UnsafetyChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
body_did: LocalDefId,
- const_context: bool,
violations: Vec<UnsafetyViolation>,
source_info: SourceInfo,
tcx: TyCtxt<'tcx>,
impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
fn new(
- const_context: bool,
body: &'a Body<'tcx>,
body_did: LocalDefId,
tcx: TyCtxt<'tcx>,
Self {
body,
body_did,
- const_context,
violations: vec![],
source_info: SourceInfo::outermost(body.span),
tcx,
self.register_violations(&violations, &unsafe_blocks);
}
},
- // casting pointers to ints is unsafe in const fn because the const evaluator cannot
- // possibly know what the result of various operations like `address / 2` would be
- // pointers during const evaluation have no integral address, only an abstract one
- Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
- if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast =>
- {
- let operand_ty = operand.ty(self.body, self.tcx);
- let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
- let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
- match (cast_in, cast_out) {
- (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
- self.require_unsafe(
- UnsafetyViolationKind::General,
- UnsafetyViolationDetails::CastOfPointerToInt,
- );
- }
- _ => {}
- }
- }
_ => {}
}
self.super_rvalue(rvalue, location);
let param_env = tcx.param_env(def.did);
- let id = tcx.hir().local_def_id_to_hir_id(def.did);
- let const_context = match tcx.hir().body_owner_kind(id) {
- hir::BodyOwnerKind::Closure => false,
- hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
- hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
- };
- let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env);
+ let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
checker.visit_body(&body);
check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
self.current_macro_or_none
.borrow_mut()
.get_or_insert_with(|| {
- if let ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: current_macro,
- proc_macro: _,
- } = self.expn_span.ctxt().outer_expn_data().kind
+ if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
+ self.expn_span.ctxt().outer_expn_data().kind
{
return Some(current_macro);
}
//! are unrelated to the `TyCtxt` global. Without initializing the `Span` session globals, some
//! basic, coverage-specific features would be impossible to test, but thankfully initializing these
//! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument
-//! to: `rustc_span::with_default_session_globals(|| { test_here(); })`.
+//! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
use super::counters;
use super::debug;
#[test]
fn test_make_bcb_counters() {
- rustc_span::with_default_session_globals(|| {
+ rustc_span::create_default_session_globals_then(|| {
let mir_body = goto_switchint();
let body_span = synthesize_body_span_from_terminators(&mir_body);
let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
&self,
callsite: &CallSite<'tcx>,
callee_attrs: &CodegenFnAttrs,
- ) -> Result<(), &'satic str> {
+ ) -> Result<(), &'static str> {
if let InlineAttr::Never = callee_attrs.inline {
return Err("never inline hint");
}
fn visit_span(&mut self, span: &mut Span) {
let mut expn_data =
- ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None);
+ ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None, None);
expn_data.def_site = self.body_span;
// Make sure that all spans track the fact that they were inlined.
*span = self.callsite_span.fresh_expansion(expn_data);
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
+use rustc_session::Limit;
// FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
// this query riddiculously often.
);
#[instrument(
level = "debug",
- skip(tcx, param_env, target, stack, seen, recursion_limiter, caller)
+ skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
)]
fn process(
tcx: TyCtxt<'tcx>,
stack: &mut Vec<ty::Instance<'tcx>>,
seen: &mut FxHashSet<ty::Instance<'tcx>>,
recursion_limiter: &mut FxHashMap<DefId, usize>,
+ recursion_limit: Limit,
) -> bool {
trace!(%caller);
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
if seen.insert(callee) {
let recursion = recursion_limiter.entry(callee.def_id()).or_default();
trace!(?callee, recursion = *recursion);
- if tcx.sess.recursion_limit().value_within_limit(*recursion) {
+ if recursion_limit.value_within_limit(*recursion) {
*recursion += 1;
stack.push(callee);
let found_recursion = ensure_sufficient_stack(|| {
- process(tcx, param_env, callee, target, stack, seen, recursion_limiter)
+ process(
+ tcx,
+ param_env,
+ callee,
+ target,
+ stack,
+ seen,
+ recursion_limiter,
+ recursion_limit,
+ )
});
if found_recursion {
return true;
&mut Vec::new(),
&mut FxHashSet::default(),
&mut FxHashMap::default(),
+ tcx.recursion_limit(),
)
}
/// The `#[target_feature]` attributes of the body. Used for checking
/// calls to functions with `#[target_feature]` (RFC 2396).
body_target_features: &'tcx Vec<Symbol>,
- is_const: bool,
+ in_possible_lhs_union_assign: bool,
+ in_union_destructure: bool,
}
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
}
}
+ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+ use PatKind::*;
+
+ if self.in_union_destructure {
+ match *pat.kind {
+ // binding to a variable allows getting stuff out of variable
+ Binding { .. }
+ // match is conditional on having this value
+ | Constant { .. }
+ | Variant { .. }
+ | Leaf { .. }
+ | Deref { .. }
+ | Range { .. }
+ | Slice { .. }
+ | Array { .. } => {
+ self.requires_unsafe(pat.span, AccessToUnionField);
+ return; // don't walk pattern
+ }
+ // wildcard doesn't take anything
+ Wild |
+ // these just wrap other patterns
+ Or { .. } |
+ AscribeUserType { .. } => {}
+ }
+ };
+
+ if let ty::Adt(adt_def, _) = pat.ty.kind() {
+ // check for extracting values from union via destructuring
+ if adt_def.is_union() {
+ match *pat.kind {
+ // assigning the whole union is okay
+ // let x = Union { ... };
+ // let y = x; // safe
+ Binding { .. } |
+ // binding to wildcard is okay since that never reads anything and stops double errors
+ // with implict wildcard branches from `if let`s
+ Wild |
+ // doesn't have any effect on semantics
+ AscribeUserType { .. } |
+ // creating a union literal
+ Constant { .. } => {},
+ Leaf { .. } | Or { .. } => {
+ // pattern matching with a union and not doing something like v = Union { bar: 5 }
+ self.in_union_destructure = true;
+ visit::walk_pat(self, pat);
+ self.in_union_destructure = false;
+ return; // don't walk pattern
+ }
+ Variant { .. } | Deref { .. } | Range { .. } | Slice { .. } | Array { .. } =>
+ unreachable!("impossible union destructuring type"),
+ }
+ }
+ }
+
+ visit::walk_pat(self, pat);
+ }
+
fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+ // could we be in a the LHS of an assignment of a union?
+ match expr.kind {
+ ExprKind::Field { .. }
+ | ExprKind::VarRef { .. }
+ | ExprKind::UpvarRef { .. }
+ | ExprKind::Scope { .. }
+ | ExprKind::Cast { .. } => {}
+
+ ExprKind::AddressOf { .. }
+ | ExprKind::Adt { .. }
+ | ExprKind::Array { .. }
+ | ExprKind::Binary { .. }
+ | ExprKind::Block { .. }
+ | ExprKind::Borrow { .. }
+ | ExprKind::Literal { .. }
+ | ExprKind::ConstBlock { .. }
+ | ExprKind::Deref { .. }
+ | ExprKind::Index { .. }
+ | ExprKind::NeverToAny { .. }
+ | ExprKind::PlaceTypeAscription { .. }
+ | ExprKind::ValueTypeAscription { .. }
+ | ExprKind::Pointer { .. }
+ | ExprKind::Repeat { .. }
+ | ExprKind::StaticRef { .. }
+ | ExprKind::ThreadLocalRef { .. }
+ | ExprKind::Tuple { .. }
+ | ExprKind::Unary { .. }
+ | ExprKind::Call { .. }
+ | ExprKind::Assign { .. }
+ | ExprKind::AssignOp { .. }
+ | ExprKind::Break { .. }
+ | ExprKind::Closure { .. }
+ | ExprKind::Continue { .. }
+ | ExprKind::Return { .. }
+ | ExprKind::Yield { .. }
+ | ExprKind::Loop { .. }
+ | ExprKind::Match { .. }
+ | ExprKind::Box { .. }
+ | ExprKind::If { .. }
+ | ExprKind::InlineAsm { .. }
+ | ExprKind::LlvmInlineAsm { .. }
+ | ExprKind::LogicalOp { .. }
+ | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false,
+ };
match expr.kind {
ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
let prev_id = self.hir_context;
self.hir_context = hir_id;
self.visit_expr(&self.thir[value]);
self.hir_context = prev_id;
- return;
+ return; // don't visit the whole expression
}
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
},
- ExprKind::Cast { source } => {
- let source = &self.thir[source];
- if self.tcx.features().const_raw_ptr_to_usize_cast
- && self.is_const
- && (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
- && expr.ty.is_integral()
- {
- self.requires_unsafe(expr.span, CastOfPointerToInt);
- }
- }
ExprKind::Closure {
closure_id,
substs: _,
// Unsafe blocks can be used in closures, make sure to take it into account
self.safety_context = closure_visitor.safety_context;
}
+ ExprKind::Field { lhs, .. } => {
+ // assigning to union field is okay for AccessToUnionField
+ if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() {
+ if adt_def.is_union() {
+ if self.in_possible_lhs_union_assign {
+ // FIXME: trigger AssignToDroppingUnionField unsafety if needed
+ } else {
+ self.requires_unsafe(expr.span, AccessToUnionField);
+ }
+ }
+ }
+ }
+ // don't have any special handling for AssignOp since it causes a read *and* write to lhs
+ ExprKind::Assign { lhs, rhs } => {
+ // assigning to a union is safe, check here so it doesn't get treated as a read later
+ self.in_possible_lhs_union_assign = true;
+ visit::walk_expr(self, &self.thir()[lhs]);
+ self.in_possible_lhs_union_assign = false;
+ visit::walk_expr(self, &self.thir()[rhs]);
+ return; // don't visit the whole expression
+ }
_ => {}
}
-
visit::walk_expr(self, expr);
}
}
CallToUnsafeFunction,
UseOfInlineAssembly,
InitializingTypeWith,
- CastOfPointerToInt,
UseOfMutableStatic,
UseOfExternStatic,
DerefOfRawPointer,
#[allow(dead_code)] // FIXME
AssignToDroppingUnionField,
- #[allow(dead_code)] // FIXME
AccessToUnionField,
#[allow(dead_code)] // FIXME
MutationOfLayoutConstrainedField,
"initializing a layout restricted type's field with a value outside the valid \
range is undefined behavior",
),
- CastOfPointerToInt => {
- ("cast of pointer to int", "casting pointers to integers in constants")
- }
UseOfMutableStatic => (
"use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations or data \
let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
let safety_context =
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
- let is_const = match tcx.hir().body_owner_kind(hir_id) {
- hir::BodyOwnerKind::Closure => false,
- hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
- hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
- };
let mut visitor = UnsafetyVisitor {
tcx,
thir,
hir_context: hir_id,
body_unsafety,
body_target_features,
- is_const,
+ in_possible_lhs_union_assign: false,
+ in_union_destructure: false,
};
visitor.visit_expr(&thir[expr]);
}
let kind = match cv.ty.kind() {
ty::Float(_) => {
- tcx.struct_span_lint_hir(
- lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
- id,
- span,
- |lint| lint.build("floating-point types cannot be used in patterns").emit(),
- );
+ if self.include_lint_checks {
+ tcx.struct_span_lint_hir(
+ lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+ id,
+ span,
+ |lint| lint.build("floating-point types cannot be used in patterns").emit(),
+ );
+ }
PatKind::Constant { value: cv }
}
ty::Adt(adt_def, _) if adt_def.is_union() => {
}
pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
- match stmt.kind {
- StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
+ match &stmt.kind {
+ StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
StmtKind::Let {
initializer,
remainder_scope: _,
lint_level: _,
} => {
if let Some(init) = initializer {
- visitor.visit_expr(&visitor.thir()[init]);
+ visitor.visit_expr(&visitor.thir()[*init]);
}
visitor.visit_pat(pattern);
}
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
use rustc_lexer::unescape::{self, Mode};
use rustc_lexer::{Base, DocStyle, RawStrError};
-use rustc_session::lint::builtin::RESERVED_PREFIX;
+use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::{sym, Symbol};
} else {
// Before Rust 2021, only emit a lint for migration.
self.sess.buffer_lint_with_diagnostic(
- &RESERVED_PREFIX,
+ &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
prefix_span,
ast::CRATE_NODE_ID,
&msg,
if self.check_keyword(kw::Pub) {
let sp = sp_start.to(self.prev_token.span);
if let Ok(snippet) = self.span_to_snippet(sp) {
- let vis = self.parse_visibility(FollowedByType::No)?;
+ let vis = match self.parse_visibility(FollowedByType::No) {
+ Ok(v) => v,
+ Err(mut d) => {
+ d.cancel();
+ return Err(err);
+ }
+ };
let vs = pprust::vis_to_string(&vis);
let vs = vs.trim_end();
err.span_suggestion(
} else if self.eat(&token::DotDotEq) {
RangeEnd::Included(RangeSyntax::DotDotEq)
} else if self.eat(&token::DotDot) {
- self.sess.gated_spans.gate(sym::exclusive_range_pattern, self.prev_token.span);
RangeEnd::Excluded
} else {
return None;
Some(self.parse_pat_range_end()?)
} else {
// Parsing e.g. `X..`.
- self.sess.gated_spans.gate(sym::half_open_range_patterns, begin.span.to(re.span));
if let RangeEnd::Included(_) = re.node {
// FIXME(Centril): Consider semantic errors instead in `ast_validation`.
// Possibly also do this for `X..=` in *expression* contexts.
let and_span = self.prev_token.span;
let mut opt_lifetime =
if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
- let mutbl = self.parse_mutability();
+ let mut mutbl = self.parse_mutability();
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
// it to be followed by a plus, but we disallow plus in the pointee type.
opt_lifetime = Some(self.expect_lifetime());
}
+ } else if self.token.is_keyword(kw::Dyn)
+ && mutbl == Mutability::Not
+ && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
+ {
+ // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
+ let span = and_span.to(self.look_ahead(1, |t| t.span));
+ let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
+ err.span_suggestion(
+ span,
+ "place `mut` before `dyn`",
+ "&mut dyn".to_string(),
+ Applicability::MachineApplicable,
+ );
+ err.emit();
+
+ // Recovery
+ mutbl = Mutability::Mut;
+ let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
+ self.bump();
+ self.bump_with((dyn_tok, dyn_tok_sp));
}
let ty = self.parse_ty_no_plus()?;
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
}
#[test]
fn format_counts() {
- use rustc_span::{edition, SessionGlobals, SESSION_GLOBALS};
- SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || {
+ rustc_span::create_default_session_globals_then(|| {
same(
"{:10x}",
&[NextArgument(Argument {
Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Start))
} else if let Some((hir_id, _)) = visitor.attr_main_fn {
Some((tcx.hir().local_def_id(hir_id).to_def_id(), EntryFnType::Main))
- } else if let Some(def_id) = tcx.main_def.and_then(|main_def| main_def.opt_fn_def_id()) {
- // non-local main imports are handled below
- if def_id.is_local() {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) {
- tcx.sess
- .struct_span_err(
- tcx.hir().span(hir_id),
- "the `main` function cannot be declared in an `extern` block",
+ } else {
+ if let Some(main_def) = tcx.resolutions(()).main_def {
+ if let Some(def_id) = main_def.opt_fn_def_id() {
+ // non-local main imports are handled below
+ if def_id.is_local() {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ if matches!(tcx.hir().find(hir_id), Some(Node::ForeignItem(_))) {
+ tcx.sess
+ .struct_span_err(
+ tcx.hir().span(hir_id),
+ "the `main` function cannot be declared in an `extern` block",
+ )
+ .emit();
+ return None;
+ }
+ }
+
+ if main_def.is_import && !tcx.features().imported_main {
+ let span = main_def.span;
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::imported_main,
+ span,
+ "using an imported function as entry point `main` is experimental",
)
.emit();
- return None;
+ }
+ return Some((def_id, EntryFnType::Main));
}
}
-
- if tcx.main_def.unwrap().is_import && !tcx.features().imported_main {
- let span = tcx.main_def.unwrap().span;
- feature_err(
- &tcx.sess.parse_sess,
- sym::imported_main,
- span,
- "using an imported function as entry point `main` is experimental",
- )
- .emit();
- }
- Some((def_id, EntryFnType::Main))
- } else {
no_main_err(tcx, visitor);
None
}
err.note(¬e);
}
- if let Some(main_def) = tcx.main_def {
+ if let Some(main_def) = tcx.resolutions(()).main_def {
if main_def.opt_fn_def_id().is_none() {
// There is something at `crate::main`, but it is not a function definition.
err.span_label(main_def.span, &format!("non-function item at `crate::main` is found"));
| LangItem::Unpin
| LangItem::Termination
| LangItem::Try
- | LangItem::Send
- | LangItem::UnwindSafe
- | LangItem::RefUnwindSafe
=> Some(0),
// Not a trait
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use rustc_target::spec::abi::Abi;
use std::cmp::Ordering;
use std::iter;
impl<'a, 'tcx> Annotator<'a, 'tcx> {
// Determine the stability for a node based on its attributes and inherited
// stability. The stability is recorded in the index and used as the parent.
+ // If the node is a function, `fn_sig` is its signature
fn annotate<F>(
&mut self,
hir_id: HirId,
item_sp: Span,
+ fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
kind: AnnotationKind,
inherit_deprecation: InheritDeprecation,
inherit_const_stability: InheritConstStability,
}
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
+ let mut const_span = None;
- let const_stab = const_stab.map(|(const_stab, _)| {
+ let const_stab = const_stab.map(|(const_stab, const_span_node)| {
let const_stab = self.tcx.intern_const_stability(const_stab);
self.index.const_stab_map.insert(hir_id, const_stab);
+ const_span = Some(const_span_node);
const_stab
});
+ // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
+ // check if the function/method is const or the parent impl block is const
+ if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) {
+ if fn_sig.header.abi != Abi::RustIntrinsic
+ && fn_sig.header.abi != Abi::PlatformIntrinsic
+ && !fn_sig.header.is_const()
+ {
+ if !self.in_trait_impl
+ || (self.in_trait_impl && !self.tcx.is_const_fn_raw(hir_id.owner.to_def_id()))
+ {
+ missing_const_err(&self.tcx.sess, fn_sig.span, const_span);
+ }
+ }
+ }
+
// `impl const Trait for Type` items forward their const stability to their
// immediate children.
if const_stab.is_none() {
let orig_in_trait_impl = self.in_trait_impl;
let mut kind = AnnotationKind::Required;
let mut const_stab_inherit = InheritConstStability::No;
+ let mut fn_sig = None;
+
match i.kind {
// Inherent impls and foreign modules serve only as containers for other items,
// they don't have their own stability. They still can be annotated as unstable
self.annotate(
ctor_hir_id,
i.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
)
}
}
+ hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
+ fn_sig = Some(item_fn_sig);
+ }
_ => {}
}
self.annotate(
i.hir_id(),
i.span,
+ fn_sig,
kind,
InheritDeprecation::Yes,
const_stab_inherit,
}
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
+ let fn_sig = match ti.kind {
+ hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
+ _ => None,
+ };
+
self.annotate(
ti.hir_id(),
ti.span,
+ fn_sig,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
let kind =
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
+
+ let fn_sig = match ii.kind {
+ hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
+ _ => None,
+ };
+
self.annotate(
ii.hir_id(),
ii.span,
+ fn_sig,
kind,
InheritDeprecation::Yes,
InheritConstStability::No,
self.annotate(
var.id,
var.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
v.annotate(
ctor_hir_id,
var.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
self.annotate(
s.hir_id,
s.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
self.annotate(
i.hir_id(),
i.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
self.annotate(
md.hir_id(),
md.span,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
self.annotate(
p.hir_id,
p.span,
+ None,
kind,
InheritDeprecation::No,
InheritConstStability::No,
annotator.annotate(
hir::CRATE_HIR_ID,
krate.item.inner,
+ None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
if let Some(def_id) = path.res.opt_def_id() {
- self.tcx.check_stability(def_id, Some(id), path.span, None)
+ let method_span = path.segments.last().map(|s| s.ident.span);
+ self.tcx.check_stability(def_id, Some(id), path.span, method_span)
}
intravisit::walk_path(self, path)
}
struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature)
.emit();
}
+
+fn missing_const_err(session: &Session, fn_sig_span: Span, const_span: Span) {
+ const ERROR_MSG: &'static str = "attributes `#[rustc_const_unstable]` \
+ and `#[rustc_const_stable]` require \
+ the function or method to be `const`";
+
+ session
+ .struct_span_err(fn_sig_span, ERROR_MSG)
+ .span_help(fn_sig_span, "make the function or method const")
+ .span_label(const_span, "attribute specified here")
+ .emit();
+}
fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
let def_id = def_id.expect_local();
- match tcx.visibilities.get(&def_id) {
+ match tcx.resolutions(()).visibilities.get(&def_id) {
Some(vis) => *vis,
None => {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect();
def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap());
eprintln!("\nLocal DefId density:");
- let total = tcx.hir().definitions().def_index_count() as f64;
+ let total = tcx.resolutions(()).definitions.def_index_count() as f64;
for q in def_id_density.iter().rev() {
let local = q.local_def_id_keys.unwrap();
eprintln!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total);
Some(def_id) => def_id,
None => return self.ast_transform_scopes.get(&expn_id).unwrap_or(&self.graph_root),
};
+ self.macro_def_scope_from_def_id(def_id)
+ }
+
+ crate fn macro_def_scope_from_def_id(&mut self, def_id: DefId) -> Module<'a> {
if let Some(id) = def_id.as_local() {
self.local_macro_def_scopes[&id]
} else {
let mut module_map = FxHashMap::default();
module_map.insert(root_local_def_id, graph_root);
- let definitions = Definitions::new(crate_name, session.local_crate_disambiguator());
+ let definitions = Definitions::new(session.local_stable_crate_id());
let root = definitions.get_root_def();
let mut visibilities = FxHashMap::default();
let expn_data = expn_id.expn_data();
match expn_data.kind {
ExpnKind::Root
- | ExpnKind::Macro {
- kind: MacroKind::Bang | MacroKind::Derive,
- name: _,
- proc_macro: _,
- } => Scope::DeriveHelpersCompat,
+ | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
+ Scope::DeriveHelpersCompat
+ }
_ => Scope::DeriveHelpers(expn_data.parent),
}
}
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion};
use rustc_feature::is_builtin_attr_name;
use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc_hir::def_id::{self, CrateNum};
+use rustc_hir::def_id::{CrateNum, LocalDefId};
use rustc_hir::PrimTy;
use rustc_middle::middle::stability;
use rustc_middle::ty;
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> ExpnId {
+ let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
call_site,
self.session.edition(),
features.into(),
None,
+ parent_module.map(LocalDefId::to_def_id),
)));
- let parent_scope = if let Some(module_id) = parent_module_id {
- let parent_def_id = self.local_def_id(module_id);
- self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id.to_def_id());
- self.module_map[&parent_def_id]
- } else {
- self.definitions.add_parent_module_of_macro_def(
- expn_id,
- def_id::DefId::local(def_id::CRATE_DEF_INDEX),
- );
- self.empty_module
- };
+ let parent_scope = parent_module
+ .map_or(self.empty_module, |parent_def_id| self.module_map[&parent_def_id]);
self.ast_transform_scopes.insert(expn_id, parent_scope);
+
expn_id
}
span,
fast_print_path(path),
res.opt_def_id(),
+ res.opt_def_id().map(|macro_def_id| {
+ self.macro_def_scope_from_def_id(macro_def_id).nearest_parent_mod
+ }),
));
if let Res::Def(_, _) = res {
- let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod;
- self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
-
// Gate macro attributes in `#[derive]` output.
if !self.session.features_untracked().macro_attributes_in_derive_output
&& kind == MacroKind::Attr
let expn_data = expn_id.expn_data();
match expn_data.kind {
ExpnKind::Root
- | ExpnKind::Macro {
- name: _,
- kind: MacroKind::Bang | MacroKind::Derive,
- proc_macro: _,
- } => {
+ | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
break;
}
_ => expn_id = expn_data.parent,
let data = CratePreludeData {
crate_id: GlobalCrateId {
name: name.into(),
- disambiguator: self
- .tcx
- .sess
- .local_crate_disambiguator()
- .to_fingerprint()
- .as_value(),
+ disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
},
crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
external_crates: self.save_ctxt.get_external_crates(),
num: n.as_u32(),
id: GlobalCrateId {
name: self.tcx.crate_name(n).to_string(),
- disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
+ disambiguator: (
+ self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
+ 0,
+ ),
},
});
}
let callee = span.source_callee()?;
let mac_name = match callee.kind {
- ExpnKind::Macro { kind, name, proc_macro: _ } => match kind {
+ ExpnKind::Macro(kind, name) => match kind {
MacroKind::Bang => name,
// Ignore attribute macros, their spans are usually mangled
pub mod output;
pub use getopts;
+
+/// Requirements for a `StableHashingContext` to be used in this crate.
+/// This is a hack to allow using the `HashStable_Generic` derive macro
+/// instead of implementing everything in `rustc_middle`.
+pub trait HashStableContext {}
use rustc_errors::registry::Registry;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_lint_defs::FutureBreakage;
-pub use rustc_span::crate_disambiguator::CrateDisambiguator;
+use rustc_macros::HashStable_Generic;
+pub use rustc_span::def_id::StableCrateId;
use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
use rustc_span::{edition::Edition, RealFileName};
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
/// limits are consistent throughout the compiler.
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct Limit(pub usize);
impl Limit {
}
}
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
+pub struct Limits {
+ /// The maximum recursion limit for potentially infinitely recursive
+ /// operations such as auto-dereference and monomorphization.
+ pub recursion_limit: Limit,
+ /// The size at which the `large_assignments` lint starts
+ /// being emitted.
+ pub move_size_limit: Limit,
+ /// The maximum length of types during monomorphization.
+ pub type_length_limit: Limit,
+ /// The maximum blocks a const expression can evaluate.
+ pub const_eval_limit: Limit,
+}
+
/// Represents the data associated with a compilation
/// session for a single crate.
pub struct Session {
/// in order to avoid redundantly verbose output (Issue #24690, #44953).
pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
crate_types: OnceCell<Vec<CrateType>>,
- /// The `crate_disambiguator` is constructed out of all the `-C metadata`
- /// arguments passed to the compiler. Its value together with the crate-name
- /// forms a unique global identifier for the crate. It is used to allow
- /// multiple crates with the same name to coexist. See the
+ /// The `stable_crate_id` is constructed out of the crate name and all the
+ /// `-C metadata` arguments passed to the compiler. Its value forms a unique
+ /// global identifier for the crate. It is used to allow multiple crates
+ /// with the same name to coexist. See the
/// `rustc_codegen_llvm::back::symbol_names` module for more information.
- pub crate_disambiguator: OnceCell<CrateDisambiguator>,
+ pub stable_crate_id: OnceCell<StableCrateId>,
features: OnceCell<rustc_feature::Features>,
lint_store: OnceCell<Lrc<dyn SessionLintStore>>,
- /// The maximum recursion limit for potentially infinitely recursive
- /// operations such as auto-dereference and monomorphization.
- pub recursion_limit: OnceCell<Limit>,
-
- /// The size at which the `large_assignments` lint starts
- /// being emitted.
- pub move_size_limit: OnceCell<usize>,
-
- /// The maximum length of types during monomorphization.
- pub type_length_limit: OnceCell<Limit>,
-
- /// The maximum blocks a const expression can evaluate.
- pub const_eval_limit: OnceCell<Limit>,
-
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
/// Used for incremental compilation tests. Will only be populated if
/// `-Zquery-dep-graph` is specified.
.into_iter()
.map(|diag| {
let lint_name = match &diag.code {
- Some(DiagnosticId::Lint { name, has_future_breakage: true }) => name,
+ Some(DiagnosticId::Lint { name, has_future_breakage: true, .. }) => name,
_ => panic!("Unexpected code in diagnostic {:?}", diag),
};
let lint = lint_store.name_to_lint(&lint_name);
self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
}
- pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
- self.crate_disambiguator.get().copied().unwrap()
+ pub fn local_stable_crate_id(&self) -> StableCrateId {
+ self.stable_crate_id.get().copied().unwrap()
}
pub fn crate_types(&self) -> &[CrateType] {
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
}
- #[inline]
- pub fn recursion_limit(&self) -> Limit {
- self.recursion_limit.get().copied().unwrap()
- }
-
- #[inline]
- pub fn move_size_limit(&self) -> usize {
- self.move_size_limit.get().copied().unwrap()
- }
-
- #[inline]
- pub fn type_length_limit(&self) -> Limit {
- self.type_length_limit.get().copied().unwrap()
- }
-
- pub fn const_eval_limit(&self) -> Limit {
- self.const_eval_limit.get().copied().unwrap()
- }
-
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_warn(sp, msg)
}
+ pub fn struct_span_force_warn<S: Into<MultiSpan>>(
+ &self,
+ sp: S,
+ msg: &str,
+ ) -> DiagnosticBuilder<'_> {
+ self.diagnostic().struct_span_force_warn(sp, msg)
+ }
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_warn(msg)
}
+ pub fn struct_force_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
+ self.diagnostic().struct_force_warn(msg)
+ }
pub fn struct_span_allow<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> {
self.diagnostic().struct_span_allow(sp, msg)
}
/// Returns the symbol name for the registrar function,
/// given the crate `Svh` and the function `DefIndex`.
- pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
- format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
+ pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String {
+ format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64())
}
- pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String {
- format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex())
+ pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
+ format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
}
pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
working_dir,
one_time_diagnostics: Default::default(),
crate_types: OnceCell::new(),
- crate_disambiguator: OnceCell::new(),
+ stable_crate_id: OnceCell::new(),
features: OnceCell::new(),
lint_store: OnceCell::new(),
- recursion_limit: OnceCell::new(),
- move_size_limit: OnceCell::new(),
- type_length_limit: OnceCell::new(),
- const_eval_limit: OnceCell::new(),
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
cgu_reuse_tracker,
prof,
+++ /dev/null
-// This is here because `rustc_session` wants to refer to it,
-// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`.
-
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::{base_n, impl_stable_hash_via_hash};
-
-use std::fmt;
-
-/// Hash value constructed out of all the `-C metadata` arguments passed to the
-/// compiler. Together with the crate-name forms a unique global identifier for
-/// the crate.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
-pub struct CrateDisambiguator(Fingerprint);
-
-impl CrateDisambiguator {
- pub fn to_fingerprint(self) -> Fingerprint {
- self.0
- }
-}
-
-impl fmt::Display for CrateDisambiguator {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
- let (a, b) = self.0.as_value();
- let as_u128 = a as u128 | ((b as u128) << 64);
- f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
- }
-}
-
-impl From<Fingerprint> for CrateDisambiguator {
- fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
- CrateDisambiguator(fingerprint)
- }
-}
-
-impl_stable_hash_via_hash!(CrateDisambiguator);
-use crate::crate_disambiguator::CrateDisambiguator;
use crate::HashStableContext;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
}
}
-/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It
-/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across
-/// compilation sessions.
+/// A [StableCrateId] is a 64 bit hash of the crate name combined with all
+/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to
+/// [DefId]. It is stable across compilation sessions.
///
/// Since the ID is a hash value there is a (very small) chance that two crates
/// end up with the same [StableCrateId]. The compiler will check for such
/// collisions when loading crates and abort compilation in order to avoid
/// further trouble.
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub struct StableCrateId(u64);
impl StableCrateId {
+ pub fn to_u64(self) -> u64 {
+ self.0
+ }
+
/// Computes the stable ID for a crate with the given name and
- /// disambiguator.
- pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId {
+ /// `-Cmetadata` arguments.
+ pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
use std::hash::Hash;
+ use std::hash::Hasher;
let mut hasher = StableHasher::new();
crate_name.hash(&mut hasher);
- crate_disambiguator.hash(&mut hasher);
+
+ // We don't want the stable crate id to dependent on the order
+ // -C metadata arguments, so sort them:
+ metadata.sort();
+ // Every distinct -C metadata value is only incorporated once:
+ metadata.dedup();
+
+ hasher.write(b"metadata");
+ for s in &metadata {
+ // Also incorporate the length of a metadata string, so that we generate
+ // different values for `-Cmetadata=ab -Cmetadata=c` and
+ // `-Cmetadata=a -Cmetadata=bc`
+ hasher.write_usize(s.len());
+ hasher.write(s.as_bytes());
+ }
+
+ // Also incorporate crate type, so that we don't get symbol conflicts when
+ // linking against a library of the same name, if this is an executable.
+ hasher.write(if is_exe { b"exe" } else { b"lib" });
+
StableCrateId(hasher.finish())
}
}
use crate::edition::Edition;
use crate::symbol::{kw, sym, Symbol};
-use crate::SESSION_GLOBALS;
+use crate::with_session_globals;
use crate::{BytePos, CachingSourceMapView, ExpnIdCache, SourceFile, Span, DUMMY_SP};
use crate::def_id::{CrateNum, DefId, DefPathHash, CRATE_DEF_INDEX, LOCAL_CRATE};
let expn_data = self.expn_data();
// Stop going up the backtrace once include! is encountered
if expn_data.is_root()
- || matches!(
- expn_data.kind,
- ExpnKind::Macro { kind: MacroKind::Bang, name: sym::include, proc_macro: _ }
- )
+ || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
{
break;
}
DUMMY_SP,
edition,
Some(DefId::local(CRATE_DEF_INDEX)),
+ None,
);
root_data.orig_id = Some(0);
}
pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
- SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
+ with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
}
fn fresh_expn(&mut self, mut expn_data: Option<ExpnData>) -> ExpnId {
) -> Span {
self.fresh_expansion(ExpnData {
allow_internal_unstable,
- ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None)
+ ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None)
})
}
}
/// call_site span would have its own ExpnData, with the call_site
/// pointing to the `foo!` invocation.
pub call_site: Span,
-
- // --- The part specific to the macro/desugaring definition.
- // --- It may be reasonable to share this part between expansions with the same definition,
- // --- but such sharing is known to bring some minor inconveniences without also bringing
- // --- noticeable perf improvements (PR #62898).
- /// The span of the macro definition (possibly dummy).
- /// This span serves only informational purpose and is not used for resolution.
- pub def_site: Span,
- /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
- /// internally without forcing the whole crate to opt-in
- /// to them.
- pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
- /// Whether the macro is allowed to use `unsafe` internally
- /// even if the user crate has `#![forbid(unsafe_code)]`.
- pub allow_internal_unsafe: bool,
- /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
- /// for a given macro.
- pub local_inner_macros: bool,
- /// Edition of the crate in which the macro is defined.
- pub edition: Edition,
- /// The `DefId` of the macro being invoked,
- /// if this `ExpnData` corresponds to a macro invocation
- pub macro_def_id: Option<DefId>,
/// The crate that originally created this `ExpnData`. During
/// metadata serialization, we only encode `ExpnData`s that were
/// created locally - when our serialized metadata is decoded,
// be considered equivalent.
#[stable_hasher(ignore)]
orig_id: Option<u32>,
-
/// Used to force two `ExpnData`s to have different `Fingerprint`s.
/// Due to macro expansion, it's possible to end up with two `ExpnId`s
/// that have identical `ExpnData`s. This violates the contract of `HashStable`
/// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes
/// a `krate` field, this value only needs to be unique within a single crate.
disambiguator: u32,
+
+ // --- The part specific to the macro/desugaring definition.
+ // --- It may be reasonable to share this part between expansions with the same definition,
+ // --- but such sharing is known to bring some minor inconveniences without also bringing
+ // --- noticeable perf improvements (PR #62898).
+ /// The span of the macro definition (possibly dummy).
+ /// This span serves only informational purpose and is not used for resolution.
+ pub def_site: Span,
+ /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
+ /// internally without forcing the whole crate to opt-in
+ /// to them.
+ pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
+ /// Whether the macro is allowed to use `unsafe` internally
+ /// even if the user crate has `#![forbid(unsafe_code)]`.
+ pub allow_internal_unsafe: bool,
+ /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+ /// for a given macro.
+ pub local_inner_macros: bool,
+ /// Edition of the crate in which the macro is defined.
+ pub edition: Edition,
+ /// The `DefId` of the macro being invoked,
+ /// if this `ExpnData` corresponds to a macro invocation
+ pub macro_def_id: Option<DefId>,
+ /// The normal module (`mod`) in which the expanded macro was defined.
+ pub parent_module: Option<DefId>,
}
// These would require special handling of `orig_id`.
local_inner_macros: bool,
edition: Edition,
macro_def_id: Option<DefId>,
+ parent_module: Option<DefId>,
) -> ExpnData {
ExpnData {
kind,
local_inner_macros,
edition,
macro_def_id,
+ parent_module,
krate: LOCAL_CRATE,
orig_id: None,
disambiguator: 0,
call_site: Span,
edition: Edition,
macro_def_id: Option<DefId>,
+ parent_module: Option<DefId>,
) -> ExpnData {
ExpnData {
kind,
local_inner_macros: false,
edition,
macro_def_id,
+ parent_module,
krate: LOCAL_CRATE,
orig_id: None,
disambiguator: 0,
edition: Edition,
allow_internal_unstable: Lrc<[Symbol]>,
macro_def_id: Option<DefId>,
+ parent_module: Option<DefId>,
) -> ExpnData {
ExpnData {
allow_internal_unstable: Some(allow_internal_unstable),
- ..ExpnData::default(kind, call_site, edition, macro_def_id)
+ ..ExpnData::default(kind, call_site, edition, macro_def_id, parent_module)
}
}
/// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
Root,
/// Expansion produced by a macro.
- Macro {
- kind: MacroKind,
- name: Symbol,
- /// If `true`, this macro is a procedural macro. This
- /// flag is only used for diagnostic purposes
- proc_macro: bool,
- },
+ Macro(MacroKind, Symbol),
/// Transform done by the compiler on the AST.
AstPass(AstPass),
/// Desugaring done by the compiler during HIR lowering.
pub fn descr(&self) -> String {
match *self {
ExpnKind::Root => kw::PathRoot.to_string(),
- ExpnKind::Macro { kind, name, proc_macro: _ } => match kind {
+ ExpnKind::Macro(macro_kind, name) => match macro_kind {
MacroKind::Bang => format!("{}!", name),
MacroKind::Attr => format!("#[{}]", name),
MacroKind::Derive => format!("#[derive({})]", name),
}
}
- let source_map = SESSION_GLOBALS
- .with(|session_globals| session_globals.source_map.borrow().as_ref().unwrap().clone());
+ let source_map = with_session_globals(|session_globals| {
+ session_globals.source_map.borrow().as_ref().unwrap().clone()
+ });
let mut ctx =
DummyHashStableContext { caching_source_map: CachingSourceMapView::new(&source_map) };
#[test]
fn test_find_best_match_for_name() {
- use crate::with_default_session_globals;
- with_default_session_globals(|| {
+ use crate::create_default_session_globals_then;
+ create_default_session_globals_then(|| {
let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
assert_eq!(
find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
-pub mod crate_disambiguator;
-
pub mod symbol;
pub use symbol::{sym, Symbol};
}
}
-pub fn with_session_globals<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+#[inline]
+pub fn create_session_globals_then<R>(edition: Edition, f: impl FnOnce() -> R) -> R {
+ assert!(
+ !SESSION_GLOBALS.is_set(),
+ "SESSION_GLOBALS should never be overwritten! \
+ Use another thread if you need another SessionGlobals"
+ );
let session_globals = SessionGlobals::new(edition);
SESSION_GLOBALS.set(&session_globals, f)
}
-pub fn with_default_session_globals<R>(f: impl FnOnce() -> R) -> R {
- with_session_globals(edition::DEFAULT_EDITION, f)
+#[inline]
+pub fn set_session_globals_then<R>(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R {
+ assert!(
+ !SESSION_GLOBALS.is_set(),
+ "SESSION_GLOBALS should never be overwritten! \
+ Use another thread if you need another SessionGlobals"
+ );
+ SESSION_GLOBALS.set(session_globals, f)
+}
+
+#[inline]
+pub fn create_default_session_if_not_set_then<R, F>(f: F) -> R
+where
+ F: FnOnce(&SessionGlobals) -> R,
+{
+ create_session_if_not_set_then(edition::DEFAULT_EDITION, f)
+}
+
+#[inline]
+pub fn create_session_if_not_set_then<R, F>(edition: Edition, f: F) -> R
+where
+ F: FnOnce(&SessionGlobals) -> R,
+{
+ if !SESSION_GLOBALS.is_set() {
+ let session_globals = SessionGlobals::new(edition);
+ SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f))
+ } else {
+ SESSION_GLOBALS.with(f)
+ }
+}
+
+#[inline]
+pub fn with_session_globals<R, F>(f: F) -> R
+where
+ F: FnOnce(&SessionGlobals) -> R,
+{
+ SESSION_GLOBALS.with(f)
+}
+
+#[inline]
+pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R {
+ create_session_globals_then(edition::DEFAULT_EDITION, f)
}
// If this ever becomes non thread-local, `decode_syntax_context`
// and `decode_expn_id` will need to be updated to handle concurrent
// deserialization.
-scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
+scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
// FIXME: We should use this enum or something like it to get rid of the
// use of magic `/rust/1.x/...` paths across the board.
/// Returns `true` if `span` originates in a derive-macro's expansion.
pub fn in_derive_expansion(self) -> bool {
- matches!(
- self.ctxt().outer_expn_data().kind,
- ExpnKind::Macro { kind: MacroKind::Derive, name: _, proc_macro: _ }
- )
+ matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
}
#[inline]
/// the `SourceMap` provided to this function. If that is not available,
/// we fall back to printing the raw `Span` field values.
pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) -> T {
- SESSION_GLOBALS.with(|session_globals| {
+ with_session_globals(|session_globals| {
*session_globals.source_map.borrow_mut() = Some(source_map);
});
struct ClearSourceMap;
impl Drop for ClearSourceMap {
fn drop(&mut self) {
- SESSION_GLOBALS.with(|session_globals| {
+ with_session_globals(|session_globals| {
session_globals.source_map.borrow_mut().take();
});
}
}
pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- SESSION_GLOBALS.with(|session_globals| {
+ with_session_globals(|session_globals| {
if let Some(source_map) = &*session_globals.source_map.borrow() {
debug_with_source_map(span, f, source_map)
} else {
/// number. If the source_file is empty or the position is located before the
/// first line, `None` is returned.
pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
- if self.lines.is_empty() {
- return None;
+ match self.lines.binary_search(&pos) {
+ Ok(idx) => Some(idx),
+ Err(0) => None,
+ Err(idx) => Some(idx - 1),
}
-
- let line_index = lookup_line(&self.lines[..], pos);
- assert!(line_index < self.lines.len() as isize);
- if line_index >= 0 { Some(line_index as usize) } else { None }
}
pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
}
}
-// Given a slice of line start positions and a position, returns the index of
-// the line the position is on. Returns -1 if the position is located before
-// the first line.
-fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize {
- match lines.binary_search(&pos) {
- Ok(line) => line as isize,
- Err(line) => line as isize - 1,
- }
-}
-
/// Requirements for a `StableHashingContext` to be used in this crate.
///
/// This is a hack to allow using the [`HashStable_Generic`] derive macro
// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
use crate::hygiene::SyntaxContext;
-use crate::SESSION_GLOBALS;
use crate::{BytePos, SpanData};
use rustc_data_structures::fx::FxIndexSet;
// If an interner exists, return it. Otherwise, prepare a fresh one.
#[inline]
fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T {
- SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.span_interner.lock()))
+ crate::with_session_globals(|session_globals| f(&mut *session_globals.span_interner.lock()))
}
use std::hash::{Hash, Hasher};
use std::str;
-use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS};
+use crate::{with_session_globals, Edition, Span, DUMMY_SP};
#[cfg(test)]
mod tests;
FormatSpec,
Formatter,
From,
+ FromIterator,
Future,
FxHashMap,
FxHashSet,
minnumf64,
mips_target_feature,
misc,
+ mmx_reg,
modifiers,
module,
module_path,
prefetch_read_instruction,
prefetch_write_data,
prefetch_write_instruction,
+ preg,
prelude,
prelude_import,
preserves_flags,
quote,
range_inclusive_new,
raw_dylib,
+ raw_eq,
raw_identifiers,
raw_ref_op,
re_rebalance_coherence,
receiver,
recursion_limit,
reexport_test_harness_main,
- ref_unwind_safe,
+ ref_unwind_safe_trait,
reference,
reflect,
reg,
self_in_typedefs,
self_struct_ctor,
semitransparent,
- send,
send_trait,
shl,
shl_assign,
unused_qualifications,
unwind,
unwind_attributes,
- unwind_safe,
+ unwind_safe_trait,
unwrap,
unwrap_or,
use_extern_macros,
wrapping_sub,
wreg,
write_bytes,
+ x87_reg,
xmm_reg,
ymm_reg,
zmm_reg,
#[inline]
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
- SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
+ with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
}
/// An alternative to [`Symbol`], useful when the chars within the symbol need to
use super::*;
-use crate::{edition, SessionGlobals};
+use crate::create_default_session_globals_then;
#[test]
fn interner_tests() {
#[test]
fn without_first_quote_test() {
- SESSION_GLOBALS.set(&SessionGlobals::new(edition::DEFAULT_EDITION), || {
+ create_default_session_globals_then(|| {
let i = Ident::from_str("'break");
assert_eq!(i.without_first_quote().name, kw::Break);
});
#[test]
fn test_lookup_line() {
- let lines = &[BytePos(3), BytePos(17), BytePos(28)];
+ let source = "abcdefghijklm\nabcdefghij\n...".to_owned();
+ let sf =
+ SourceFile::new(FileName::Anon(0), source, BytePos(3), SourceFileHashAlgorithm::Sha256);
+ assert_eq!(sf.lines.as_slice(), &[BytePos(3), BytePos(17), BytePos(28)]);
- assert_eq!(lookup_line(lines, BytePos(0)), -1);
- assert_eq!(lookup_line(lines, BytePos(3)), 0);
- assert_eq!(lookup_line(lines, BytePos(4)), 0);
+ assert_eq!(sf.lookup_line(BytePos(0)), None);
+ assert_eq!(sf.lookup_line(BytePos(3)), Some(0));
+ assert_eq!(sf.lookup_line(BytePos(4)), Some(0));
- assert_eq!(lookup_line(lines, BytePos(16)), 0);
- assert_eq!(lookup_line(lines, BytePos(17)), 1);
- assert_eq!(lookup_line(lines, BytePos(18)), 1);
+ assert_eq!(sf.lookup_line(BytePos(16)), Some(0));
+ assert_eq!(sf.lookup_line(BytePos(17)), Some(1));
+ assert_eq!(sf.lookup_line(BytePos(18)), Some(1));
- assert_eq!(lookup_line(lines, BytePos(28)), 2);
- assert_eq!(lookup_line(lines, BytePos(29)), 2);
+ assert_eq!(sf.lookup_line(BytePos(28)), Some(2));
+ assert_eq!(sf.lookup_line(BytePos(29)), Some(2));
}
#[test]
substs.hash_stable(&mut hcx, &mut hasher);
if let Some(instantiating_crate) = instantiating_crate {
- tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher);
- tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher);
+ tcx.def_path_hash(instantiating_crate.as_def_id())
+ .stable_crate_id()
+ .hash_stable(&mut hcx, &mut hasher);
}
// We want to avoid accidental collision between different types of instances.
// FIXME(eddyb) Precompute a custom symbol name based on attributes.
let is_foreign = if let Some(def_id) = def_id.as_local() {
if tcx.plugin_registrar_fn(()) == Some(def_id) {
- let disambiguator = tcx.sess.local_crate_disambiguator();
- return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
+ let stable_crate_id = tcx.sess.local_stable_crate_id();
+ return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id);
}
if tcx.proc_macro_decls_static(()) == Some(def_id) {
- let disambiguator = tcx.sess.local_crate_disambiguator();
- return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
+ let stable_crate_id = tcx.sess.local_stable_crate_id();
+ return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
matches!(tcx.hir().get(hir_id), Node::ForeignItem(_))
fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
self.push("C");
- let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
- self.push_disambiguator(fingerprint.to_smaller_hash());
+ let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
+ self.push_disambiguator(stable_crate_id.to_u64());
let name = self.tcx.crate_name(cnum).as_str();
self.push_ident(&name);
Ok(self)
reg,
vreg,
vreg_low16,
+ preg,
}
}
match self {
Self::reg => &['w', 'x'],
Self::vreg | Self::vreg_low16 => &['b', 'h', 's', 'd', 'q', 'v'],
+ Self::preg => &[],
}
}
128 => Some(('q', "q0")),
_ => None,
},
+ Self::preg => None,
}
}
match self {
Self::reg => Some(('x', "x0")),
Self::vreg | Self::vreg_low16 => Some(('v', "v0")),
+ Self::preg => None,
}
}
VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
},
+ Self::preg => &[],
}
}
}
x27: reg = ["x27", "w27"],
x28: reg = ["x28", "w28"],
x30: reg = ["x30", "w30", "lr", "wlr"],
- v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0"],
- v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1"],
- v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2"],
- v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3"],
- v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4"],
- v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5"],
- v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6"],
- v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7"],
- v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8"],
- v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9"],
- v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10"],
- v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11"],
- v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12"],
- v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13"],
- v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14"],
- v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15"],
- v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16"],
- v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17"],
- v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18"],
- v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19"],
- v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20"],
- v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21"],
- v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22"],
- v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23"],
- v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24"],
- v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25"],
- v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26"],
- v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27"],
- v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28"],
- v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29"],
- v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30"],
- v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31"],
+ v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"],
+ v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"],
+ v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2", "z2"],
+ v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3", "z3"],
+ v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4", "z4"],
+ v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5", "z5"],
+ v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6", "z6"],
+ v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7", "z7"],
+ v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8", "z8"],
+ v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9", "z9"],
+ v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10", "z10"],
+ v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11", "z11"],
+ v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12", "z12"],
+ v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"],
+ v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"],
+ v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"],
+ v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"],
+ v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"],
+ v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"],
+ v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"],
+ v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"],
+ v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"],
+ v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"],
+ v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"],
+ v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"],
+ v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"],
+ v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"],
+ v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"],
+ v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"],
+ v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"],
+ v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"],
+ v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"],
+ p0: preg = ["p0"],
+ p1: preg = ["p1"],
+ p2: preg = ["p2"],
+ p3: preg = ["p3"],
+ p4: preg = ["p4"],
+ p5: preg = ["p5"],
+ p6: preg = ["p6"],
+ p7: preg = ["p7"],
+ p8: preg = ["p8"],
+ p9: preg = ["p9"],
+ p10: preg = ["p10"],
+ p11: preg = ["p11"],
+ p12: preg = ["p12"],
+ p13: preg = ["p13"],
+ p14: preg = ["p14"],
+ p15: preg = ["p15"],
+ ffr: preg = ["ffr"],
#error = ["x18", "w18"] =>
"x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm",
#error = ["x19", "w19"] =>
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
}
}
+
+ /// Returns whether registers in this class can only be used as clobbers
+ /// and not as inputs/outputs.
+ pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool {
+ self.supported_types(arch).is_empty()
+ }
}
#[derive(
RiscV RiscVInlineAsmRegClass {
reg,
freg,
+ vreg,
}
}
}
}
Self::freg => types! { "f": F32; "d": F64; },
+ Self::vreg => &[],
}
}
}
f29: freg = ["f29", "ft9"],
f30: freg = ["f30", "ft10"],
f31: freg = ["f31", "ft11"],
+ v0: vreg = ["v0"],
+ v1: vreg = ["v1"],
+ v2: vreg = ["v2"],
+ v3: vreg = ["v3"],
+ v4: vreg = ["v4"],
+ v5: vreg = ["v5"],
+ v6: vreg = ["v6"],
+ v7: vreg = ["v7"],
+ v8: vreg = ["v8"],
+ v9: vreg = ["v9"],
+ v10: vreg = ["v10"],
+ v11: vreg = ["v11"],
+ v12: vreg = ["v12"],
+ v13: vreg = ["v13"],
+ v14: vreg = ["v14"],
+ v15: vreg = ["v15"],
+ v16: vreg = ["v16"],
+ v17: vreg = ["v17"],
+ v18: vreg = ["v18"],
+ v19: vreg = ["v19"],
+ v20: vreg = ["v20"],
+ v21: vreg = ["v21"],
+ v22: vreg = ["v22"],
+ v23: vreg = ["v23"],
+ v24: vreg = ["v24"],
+ v25: vreg = ["v25"],
+ v26: vreg = ["v26"],
+ v27: vreg = ["v27"],
+ v28: vreg = ["v28"],
+ v29: vreg = ["v29"],
+ v30: vreg = ["v30"],
+ v31: vreg = ["v31"],
#error = ["x9", "s1"] =>
"s1 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["x8", "s0", "fp"] =>
ymm_reg,
zmm_reg,
kreg,
+ mmx_reg,
+ x87_reg,
}
}
Self::reg_byte => &[],
Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'],
Self::kreg => &[],
+ Self::mmx_reg | Self::x87_reg => &[],
}
}
_ => Some(('x', "xmm0")),
},
Self::kreg => None,
+ Self::mmx_reg | Self::x87_reg => None,
}
}
Self::ymm_reg => Some(('y', "ymm0")),
Self::zmm_reg => Some(('z', "zmm0")),
Self::kreg => None,
+ Self::mmx_reg | Self::x87_reg => None,
}
}
"avx512f": I8, I16;
"avx512bw": I32, I64;
},
+ Self::mmx_reg | Self::x87_reg => &[],
}
}
}
k5: kreg = ["k5"],
k6: kreg = ["k6"],
k7: kreg = ["k7"],
+ mm0: mmx_reg = ["mm0"],
+ mm1: mmx_reg = ["mm1"],
+ mm2: mmx_reg = ["mm2"],
+ mm3: mmx_reg = ["mm3"],
+ mm4: mmx_reg = ["mm4"],
+ mm5: mmx_reg = ["mm5"],
+ mm6: mmx_reg = ["mm6"],
+ mm7: mmx_reg = ["mm7"],
+ st0: x87_reg = ["st(0)", "st"],
+ st1: x87_reg = ["st(1)"],
+ st2: x87_reg = ["st(2)"],
+ st3: x87_reg = ["st(3)"],
+ st4: x87_reg = ["st(4)"],
+ st5: x87_reg = ["st(5)"],
+ st6: x87_reg = ["st(6)"],
+ st7: x87_reg = ["st(7)"],
#error = ["bp", "bpl", "ebp", "rbp"] =>
"the frame pointer cannot be used as an operand for inline asm",
#error = ["sp", "spl", "esp", "rsp"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["ip", "eip", "rip"] =>
"the instruction pointer cannot be used as an operand for inline asm",
- #error = ["st", "st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"] =>
- "x87 registers are not currently supported as operands for inline asm",
- #error = ["mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"] =>
- "MMX registers are not currently supported as operands for inline asm",
#error = ["k0"] =>
"the k0 AVX mask register cannot be used as an operand for inline asm",
}
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
- let base = opts("ios", Arch::Arm64);
Target {
llvm_target: "arm64-apple-ios".to_string(),
pointer_width: 64,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".to_string(),
max_atomic_width: Some(128),
- unsupported_abis: super::arm_base::unsupported_abis(),
forces_embed_bitcode: true,
frame_pointer: FramePointer::NonLeaf,
// Taken from a clang build on Xcode 11.4.1.
darwinpcs\0\
-Os\0"
.to_string(),
- ..base
+ ..opts("ios", Arch::Arm64)
},
}
}
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
- let base = opts("ios", Arch::Arm64_macabi);
Target {
llvm_target: "arm64-apple-ios14.0-macabi".to_string(),
pointer_width: 64,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12".to_string(),
max_atomic_width: Some(128),
- unsupported_abis: super::arm_base::unsupported_abis(),
forces_embed_bitcode: true,
frame_pointer: FramePointer::NonLeaf,
// Taken from a clang build on Xcode 11.4.1.
-disable-llvm-passes\0\
-Os\0"
.to_string(),
- ..base
+ ..opts("ios", Arch::Arm64_macabi)
},
}
}
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".to_string(),
max_atomic_width: Some(128),
- unsupported_abis: super::arm_base::unsupported_abis(),
forces_embed_bitcode: true,
frame_pointer: FramePointer::NonLeaf,
// Taken from a clang build on Xcode 11.4.1.
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
- let base = opts("tvos", Arch::Arm64);
Target {
llvm_target: "arm64-apple-tvos".to_string(),
pointer_width: 64,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".to_string(),
max_atomic_width: Some(128),
- unsupported_abis: super::arm_base::unsupported_abis(),
forces_embed_bitcode: true,
frame_pointer: FramePointer::NonLeaf,
- ..base
+ ..opts("tvos", Arch::Arm64)
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_gnu_base::opts();
- base.max_atomic_width = Some(128);
-
Target {
llvm_target: "aarch64_be-unknown-linux-gnu".to_string(),
pointer_width: 64,
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
+ max_atomic_width: Some(128),
mcount: "\u{1}_mcount".to_string(),
endian: Endian::Big,
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
pointer_width: 32,
data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
- mcount: "\u{1}_mcount".to_string(),
- endian: Endian::Big,
- ..base
- },
+ options: TargetOptions { mcount: "\u{1}_mcount".to_string(), endian: Endian::Big, ..base },
}
}
use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::fuchsia_base::opts();
- base.max_atomic_width = Some(128);
- base.supported_sanitizers = SanitizerSet::ADDRESS;
-
Target {
llvm_target: "aarch64-fuchsia".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS,
+ ..super::fuchsia_base::opts()
+ },
}
}
// for target ABI requirements.
pub fn target() -> Target {
- let mut base = super::android_base::opts();
- base.max_atomic_width = Some(128);
- // As documented in https://developer.android.com/ndk/guides/cpu-features.html
- // the neon (ASIMD) and FP must exist on all android aarch64 targets.
- base.features = "+neon,+fp-armv8".to_string();
- base.supported_sanitizers = SanitizerSet::HWADDRESS;
Target {
llvm_target: "aarch64-linux-android".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ // As documented in https://developer.android.com/ndk/guides/cpu-features.html
+ // the neon (ASIMD) and FP must exist on all android aarch64 targets.
+ features: "+neon,+fp-armv8".to_string(),
+ supported_sanitizers: SanitizerSet::HWADDRESS,
+ ..super::android_base::opts()
+ },
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::freebsd_base::opts();
- base.max_atomic_width = Some(128);
-
Target {
llvm_target: "aarch64-unknown-freebsd".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions { max_atomic_width: Some(128), ..super::freebsd_base::opts() },
}
}
use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_gnu_base::opts();
- base.max_atomic_width = Some(128);
- base.supported_sanitizers = SanitizerSet::ADDRESS
- | SanitizerSet::LEAK
- | SanitizerSet::MEMORY
- | SanitizerSet::THREAD
- | SanitizerSet::HWADDRESS;
-
Target {
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}_mcount".to_string(),
- ..base
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS
+ | SanitizerSet::LEAK
+ | SanitizerSet::MEMORY
+ | SanitizerSet::THREAD
+ | SanitizerSet::HWADDRESS,
+ ..super::linux_gnu_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_gnu_base::opts();
- base.max_atomic_width = Some(128);
-
Target {
llvm_target: "aarch64-unknown-linux-gnu_ilp32".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
+ max_atomic_width: Some(128),
mcount: "\u{1}_mcount".to_string(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
- mcount: "\u{1}_mcount".to_string(),
- ..base
- },
+ options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::netbsd_base::opts();
- base.max_atomic_width = Some(128);
- base.unsupported_abis = super::arm_base::unsupported_abis();
-
Target {
llvm_target: "aarch64-unknown-netbsd".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { mcount: "__mcount".to_string(), ..base },
+ options: TargetOptions {
+ mcount: "__mcount".to_string(),
+ max_atomic_width: Some(128),
+ ..super::netbsd_base::opts()
+ },
}
}
disable_redzone: true,
max_atomic_width: Some(128),
panic_strategy: PanicStrategy::Abort,
- unsupported_abis: super::arm_base::unsupported_abis(),
..Default::default()
};
Target {
disable_redzone: true,
max_atomic_width: Some(128),
panic_strategy: PanicStrategy::Abort,
- unsupported_abis: super::arm_base::unsupported_abis(),
..Default::default()
};
Target {
-use crate::spec::Target;
+use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::openbsd_base::opts();
- base.max_atomic_width = Some(128);
- base.unsupported_abis = super::arm_base::unsupported_abis();
-
Target {
llvm_target: "aarch64-unknown-openbsd".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: base,
+ options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() },
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::vxworks_base::opts();
- base.max_atomic_width = Some(128);
-
Target {
llvm_target: "aarch64-unknown-linux-gnu".to_string(),
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() },
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum Abi {
- // Multiplatform / generic ABIs
- //
- // These ABIs come first because every time we add a new ABI, we
- // have to re-bless all the hashing tests. These are used in many
- // places, so giving them stable values reduces test churn. The
- // specific values are meaningless.
+ // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the
+ // hashing tests. These are used in many places, so giving them stable values reduces test
+ // churn. The specific values are meaningless.
Rust,
C { unwind: bool },
-
- // Single platform ABIs
Cdecl,
Stdcall { unwind: bool },
Fastcall,
AvrNonBlockingInterrupt,
CCmseNonSecureCall,
Wasm,
-
- // Multiplatform / generic ABIs
System { unwind: bool },
RustIntrinsic,
RustCall,
/// Name of this ABI as we like it called.
name: &'static str,
-
- /// A generic ABI is supported on all platforms.
- generic: bool,
}
#[allow(non_upper_case_globals)]
const AbiDatas: &[AbiData] = &[
- // Cross-platform ABIs
- AbiData { abi: Abi::Rust, name: "Rust", generic: true },
- AbiData { abi: Abi::C { unwind: false }, name: "C", generic: true },
- AbiData { abi: Abi::C { unwind: true }, name: "C-unwind", generic: true },
- // Platform-specific ABIs
- AbiData { abi: Abi::Cdecl, name: "cdecl", generic: false },
- AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall", generic: false },
- AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind", generic: false },
- AbiData { abi: Abi::Fastcall, name: "fastcall", generic: false },
- AbiData { abi: Abi::Vectorcall, name: "vectorcall", generic: false },
- AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall", generic: false },
- AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind", generic: false },
- AbiData { abi: Abi::Aapcs, name: "aapcs", generic: false },
- AbiData { abi: Abi::Win64, name: "win64", generic: false },
- AbiData { abi: Abi::SysV64, name: "sysv64", generic: false },
- AbiData { abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
- AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt", generic: false },
- AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
- AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
- AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false },
- AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false },
- AbiData {
- abi: Abi::AvrNonBlockingInterrupt,
- name: "avr-non-blocking-interrupt",
- generic: false,
- },
- AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false },
- AbiData { abi: Abi::Wasm, name: "wasm", generic: false },
- // Cross-platform ABIs
- AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true },
- AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true },
- AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
- AbiData { abi: Abi::RustCall, name: "rust-call", generic: true },
- AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
- AbiData { abi: Abi::Unadjusted, name: "unadjusted", generic: true },
+ AbiData { abi: Abi::Rust, name: "Rust" },
+ AbiData { abi: Abi::C { unwind: false }, name: "C" },
+ AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
+ AbiData { abi: Abi::Cdecl, name: "cdecl" },
+ AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" },
+ AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" },
+ AbiData { abi: Abi::Fastcall, name: "fastcall" },
+ AbiData { abi: Abi::Vectorcall, name: "vectorcall" },
+ AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" },
+ AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" },
+ AbiData { abi: Abi::Aapcs, name: "aapcs" },
+ AbiData { abi: Abi::Win64, name: "win64" },
+ AbiData { abi: Abi::SysV64, name: "sysv64" },
+ AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" },
+ AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" },
+ AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" },
+ AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" },
+ AbiData { abi: Abi::EfiApi, name: "efiapi" },
+ AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
+ AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
+ AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
+ AbiData { abi: Abi::Wasm, name: "wasm" },
+ AbiData { abi: Abi::System { unwind: false }, name: "system" },
+ AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
+ AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
+ AbiData { abi: Abi::RustCall, name: "rust-call" },
+ AbiData { abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" },
+ AbiData { abi: Abi::Unadjusted, name: "unadjusted" },
];
/// Returns the ABI with the given name (if any).
pub fn name(self) -> &'static str {
self.data().name
}
-
- pub fn generic(self) -> bool {
- self.data().generic
- }
}
impl fmt::Display for Abi {
+++ /dev/null
-use crate::spec::abi::Abi;
-
-// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
-pub fn unsupported_abis() -> Vec<Abi> {
- vec![
- Abi::Stdcall { unwind: false },
- Abi::Stdcall { unwind: true },
- Abi::Fastcall,
- Abi::Vectorcall,
- Abi::Thiscall { unwind: false },
- Abi::Thiscall { unwind: true },
- Abi::Win64,
- Abi::SysV64,
- ]
-}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::android_base::opts();
- // https://developer.android.com/ndk/guides/abis.html#armeabi
- base.features = "+strict-align,+v5te".to_string();
- base.max_atomic_width = Some(32);
-
Target {
llvm_target: "arm-linux-androideabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions {
+ // https://developer.android.com/ndk/guides/abis.html#armeabi
+ features: "+strict-align,+v5te".to_string(),
+ max_atomic_width: Some(32),
+ ..super::android_base::opts()
+ },
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_gnu_base::opts();
- base.max_atomic_width = Some(64);
Target {
llvm_target: "arm-unknown-linux-gnueabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+strict-align,+v6".to_string(),
- unsupported_abis: super::arm_base::unsupported_abis(),
+ max_atomic_width: Some(64),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_gnu_base::opts();
- base.max_atomic_width = Some(64);
Target {
llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+strict-align,+v6,+vfp2,-d32".to_string(),
- unsupported_abis: super::arm_base::unsupported_abis(),
+ max_atomic_width: Some(64),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_musl_base::opts();
-
- // Most of these settings are copied from the arm_unknown_linux_gnueabi
- // target.
- base.features = "+strict-align,+v6".to_string();
- base.max_atomic_width = Some(64);
Target {
// It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
// to determine the calling convention and float ABI, and it doesn't
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
+ // Most of these settings are copied from the arm_unknown_linux_gnueabi
+ // target.
+ features: "+strict-align,+v6".to_string(),
+ max_atomic_width: Some(64),
mcount: "\u{1}mcount".to_string(),
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::linux_musl_base::opts();
-
- // Most of these settings are copied from the arm_unknown_linux_gnueabihf
- // target.
- base.features = "+strict-align,+v6,+vfp2,-d32".to_string();
- base.max_atomic_width = Some(64);
Target {
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
// uses it to determine the calling convention and float ABI, and it
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
options: TargetOptions {
- unsupported_abis: super::arm_base::unsupported_abis(),
+ // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+ // target.
+ features: "+strict-align,+v6,+vfp2,-d32".to_string(),
+ max_atomic_width: Some(64),
mcount: "\u{1}mcount".to_string(),
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
pointer_width: 32,
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
endian: Endian::Big,
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
},
pointer_width: 32,
data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
endian: Endian::Big,
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
panic_strategy: PanicStrategy::Abort,
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
},
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::linux_gnu_base::opts();
Target {
llvm_target: "armv4t-unknown-linux-gnueabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+soft-float,+strict-align".to_string(),
// Atomic operations provided by compiler-builtins
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
has_thumb_interworking: true,
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::linux_gnu_base::opts();
Target {
llvm_target: "armv5te-unknown-linux-gnueabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+soft-float,+strict-align".to_string(),
// Atomic operations provided by compiler-builtins
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
has_thumb_interworking: true,
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::linux_musl_base::opts();
Target {
+ // FIXME: this comment below does not seem applicable?
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
// uses it to determine the calling convention and float ABI, and LLVM
// doesn't support the "musleabihf" value.
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+soft-float,+strict-align".to_string(),
// Atomic operations provided by compiler-builtins
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}mcount".to_string(),
has_thumb_interworking: true,
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
features: "+soft-float,+strict-align".to_string(),
// Atomic operations provided by compiler-builtins
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
has_thumb_interworking: true,
-
..super::linux_uclibc_base::opts()
},
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::freebsd_base::opts();
Target {
llvm_target: "armv6-unknown-freebsd-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
env: "gnueabihf".to_string(),
features: "+v6,+vfp2,-d32".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::freebsd_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::netbsd_base::opts();
- base.max_atomic_width = Some(64);
Target {
llvm_target: "armv6-unknown-netbsdelf-eabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
env: "eabihf".to_string(),
features: "+v6,+vfp2,-d32".to_string(),
- unsupported_abis: super::arm_base::unsupported_abis(),
+ max_atomic_width: Some(64),
mcount: "__mcount".to_string(),
- ..base
+ ..super::netbsd_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = opts("ios", Arch::Armv7);
Target {
llvm_target: "armv7-apple-ios".to_string(),
pointer_width: 32,
options: TargetOptions {
features: "+v7,+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
- ..base
+ ..opts("ios", Arch::Armv7)
},
}
}
pub fn target() -> Target {
let mut base = super::android_base::opts();
- base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string();
- base.max_atomic_width = Some(64);
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
-
Target {
llvm_target: "armv7-none-linux-android".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions {
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string(),
+ max_atomic_width: Some(64),
+ ..base
+ },
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::freebsd_base::opts();
Target {
llvm_target: "armv7-unknown-freebsd-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
env: "gnueabihf".to_string(),
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::freebsd_base::opts()
},
}
}
// hardfloat.
pub fn target() -> Target {
- let base = super::linux_gnu_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabi".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+v7,+thumb2,+soft-float,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
// thumb-mode. See the thumbv7neon variant for enabling both.
pub fn target() -> Target {
- let base = super::linux_gnu_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
// Info about features at https://wiki.debian.org/ArmHardFloatPort
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}__gnu_mcount_nc".to_string(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
// hardfloat.
pub fn target() -> Target {
- let base = super::linux_musl_base::opts();
// Most of these settings are copied from the armv7_unknown_linux_gnueabi
// target.
Target {
options: TargetOptions {
features: "+v7,+thumb2,+soft-float,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}mcount".to_string(),
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
// This target is for musl Linux on ARMv7 without thumb-mode or NEON.
pub fn target() -> Target {
- let base = super::linux_musl_base::opts();
Target {
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
// uses it to determine the calling convention and float ABI, and LLVM
options: TargetOptions {
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}mcount".to_string(),
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::netbsd_base::opts();
Target {
llvm_target: "armv7-unknown-netbsdelf-eabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
env: "eabihf".to_string(),
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "__mcount".to_string(),
- ..base
+ ..super::netbsd_base::opts()
},
}
}
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = super::vxworks_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
pointer_width: 32,
// Info about features at https://wiki.debian.org/ArmHardFloatPort
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
- ..base
+ ..super::vxworks_base::opts()
},
}
}
disable_redzone: true,
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
};
disable_redzone: true,
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
};
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
},
panic_strategy: PanicStrategy::Abort,
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
- unsupported_abis: super::arm_base::unsupported_abis(),
emit_debug_gdb_scripts: false,
..Default::default()
},
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
- let base = opts("ios", Arch::Armv7s);
Target {
llvm_target: "armv7s-apple-ios".to_string(),
pointer_width: 32,
options: TargetOptions {
features: "+v7,+vfp4,+neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
- ..base
+ ..opts("ios", Arch::Armv7s)
},
}
}
+use crate::abi::Endian;
use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
-use crate::{abi::Endian, spec::abi::Abi};
pub fn opts(endian: Endian) -> TargetOptions {
TargetOptions {
requires_lto: false,
singlethread: true,
max_atomic_width: Some(64),
- unsupported_abis: vec![
- Abi::Cdecl,
- Abi::Stdcall { unwind: false },
- Abi::Stdcall { unwind: true },
- Abi::Fastcall,
- Abi::Vectorcall,
- Abi::Thiscall { unwind: false },
- Abi::Thiscall { unwind: true },
- Abi::Aapcs,
- Abi::Win64,
- Abi::SysV64,
- Abi::PtxKernel,
- Abi::Msp430Interrupt,
- Abi::X86Interrupt,
- Abi::AmdGpuKernel,
- ],
..Default::default()
}
}
//!
//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
-use crate::spec::abi::Abi;
use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
use crate::spec::{PanicStrategy, Target, TargetOptions};
linker: Some("rust-lld".to_owned()),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
- unsupported_abis: vec![
- Abi::Stdcall { unwind: false },
- Abi::Stdcall { unwind: true },
- Abi::Fastcall,
- Abi::Vectorcall,
- Abi::Thiscall { unwind: false },
- Abi::Thiscall { unwind: true },
- Abi::Win64,
- Abi::SysV64,
- ],
emit_debug_gdb_scripts: false,
..Default::default()
},
mod android_base;
mod apple_base;
mod apple_sdk_base;
-mod arm_base;
mod avr_gnu_base;
mod bpf_base;
mod dragonfly_base;
mod netbsd_base;
mod openbsd_base;
mod redox_base;
-mod riscv_base;
mod solaris_base;
mod thumb_base;
mod uefi_msvc_base;
/// Panic strategy: "unwind" or "abort"
pub panic_strategy: PanicStrategy,
- /// A list of ABIs unsupported by the current target. Note that generic ABIs
- /// are considered to be supported on all platforms and cannot be marked
- /// unsupported.
- pub unsupported_abis: Vec<Abi>,
-
/// Whether or not linking dylibs to a static CRT is allowed.
pub crt_static_allows_dylibs: bool,
/// Whether or not the CRT is statically linked by default.
max_atomic_width: None,
atomic_cas: true,
panic_strategy: PanicStrategy::Unwind,
- unsupported_abis: vec![],
crt_static_allows_dylibs: false,
crt_static_default: false,
crt_static_respected: false,
/// Given a function ABI, turn it into the correct ABI for this target.
pub fn adjust_abi(&self, abi: Abi) -> Abi {
match abi {
- Abi::System { unwind } => {
- if self.is_like_windows && self.arch == "x86" {
- Abi::Stdcall { unwind }
- } else {
- Abi::C { unwind }
- }
- }
- // These ABI kinds are ignored on non-x86 Windows targets.
- // See https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
- // and the individual pages for __stdcall et al.
- Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => {
- if self.is_like_windows && self.arch != "x86" { Abi::C { unwind } } else { abi }
- }
- Abi::Fastcall | Abi::Vectorcall => {
- if self.is_like_windows && self.arch != "x86" {
- Abi::C { unwind: false }
- } else {
- abi
- }
- }
- Abi::EfiApi => {
- if self.arch == "x86_64" {
- Abi::Win64
- } else {
- Abi::C { unwind: false }
- }
+ Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi),
+ Abi::System { unwind } if self.is_like_windows && self.arch == "x86" => {
+ Abi::Stdcall { unwind }
}
+ Abi::System { unwind } => Abi::C { unwind },
+ Abi::EfiApi if self.arch == "x86_64" => Abi::Win64,
+ Abi::EfiApi => Abi::C { unwind: false },
- Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }),
+ // See commentary in `is_abi_supported`.
+ Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi,
+ Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind },
+ Abi::Fastcall if self.arch == "x86" => abi,
+ Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
+ Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false },
abi => abi,
}
}
+ /// Returns a None if the UNSUPPORTED_CALLING_CONVENTIONS lint should be emitted
+ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
+ use Abi::*;
+ Some(match abi {
+ Rust
+ | C { .. }
+ | System { .. }
+ | RustIntrinsic
+ | RustCall
+ | PlatformIntrinsic
+ | Unadjusted
+ | Cdecl
+ | EfiApi => true,
+ X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
+ Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+ Win64 | SysV64 => self.arch == "x86_64",
+ PtxKernel => self.arch == "nvptx64",
+ Msp430Interrupt => self.arch == "msp430",
+ AmdGpuKernel => self.arch == "amdgcn",
+ AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
+ Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]),
+ // On windows these fall-back to platform native calling convention (C) when the
+ // architecture is not supported.
+ //
+ // This is I believe a historical accident that has occurred as part of Microsoft
+ // striving to allow most of the code to "just" compile when support for 64-bit x86
+ // was added and then later again, when support for ARM architectures was added.
+ //
+ // This is well documented across MSDN. Support for this in Rust has been added in
+ // #54576. This makes much more sense in context of Microsoft's C++ than it does in
+ // Rust, but there isn't much leeway remaining here to change it back at the time this
+ // comment has been written.
+ //
+ // Following are the relevant excerpts from the MSDN documentation.
+ //
+ // > The __vectorcall calling convention is only supported in native code on x86 and
+ // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
+ // > ...
+ // > On ARM machines, __vectorcall is accepted and ignored by the compiler.
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
+ //
+ // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
+ //
+ // > In most cases, keywords or compiler switches that specify an unsupported
+ // > convention on a particular platform are ignored, and the platform default
+ // > convention is used.
+ //
+ // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
+ Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall if self.is_like_windows => {
+ true
+ }
+ // Outside of Windows we want to only support these calling conventions for the
+ // architectures for which these calling conventions are actually well defined.
+ Stdcall { .. } | Fastcall | Thiscall { .. } if self.arch == "x86" => true,
+ Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
+ // Return a `None` for other cases so that we know to emit a future compat lint.
+ Stdcall { .. } | Fastcall | Thiscall { .. } | Vectorcall => return None,
+ })
+ }
+
/// Minimum integer size in bits that this target can perform atomic
/// operations on.
pub fn min_atomic_width(&self) -> u64 {
self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into())
}
- pub fn is_abi_supported(&self, abi: Abi) -> bool {
- abi.generic() || !self.unsupported_abis.contains(&abi)
- }
-
/// Loads a target descriptor from a JSON object.
pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> {
// While ugly, this code must remain this way to retain
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
- // NB: The old name is deprecated, but support for it is retained for
- // compatibility.
- for name in ["abi-blacklist", "unsupported-abis"].iter() {
- if let Some(j) = obj.remove_key(name) {
- if let Some(array) = Json::as_array(&j) {
- for name in array.iter().filter_map(|abi| abi.as_string()) {
- match lookup_abi(name) {
- Some(abi) => {
- if abi.generic() {
- return Err(format!(
- "The ABI \"{}\" is considered to be supported on all \
- targets and cannot be marked unsupported",
- abi
- ));
- }
-
- base.unsupported_abis.push(abi)
- }
- None => {
- return Err(format!(
- "Unknown ABI \"{}\" in target specification",
- name
- ));
- }
- }
- }
- }
- }
- }
-
// Each field should have been read using `Json::remove_key` so any keys remaining are unused.
let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys();
Ok((
d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
}
- if default.unsupported_abis != self.unsupported_abis {
- d.insert(
- "unsupported-abis".to_string(),
- self.unsupported_abis
- .iter()
- .map(|&name| Abi::name(name).to_json())
- .collect::<Vec<_>>()
- .to_json(),
- );
- }
-
Json::Object(d)
}
}
-use crate::spec::abi::Abi;
use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions};
pub fn target() -> Target {
// produce kernel functions that call other kernel functions.
// This behavior is not supported by PTX ISA.
merge_functions: MergeFunctions::Disabled,
-
- // FIXME: enable compilation tests for the target and
- // create the tests for this.
- unsupported_abis: vec![
- Abi::Cdecl,
- Abi::Stdcall { unwind: false },
- Abi::Stdcall { unwind: true },
- Abi::Fastcall,
- Abi::Vectorcall,
- Abi::Thiscall { unwind: false },
- Abi::Thiscall { unwind: true },
- Abi::Aapcs,
- Abi::Win64,
- Abi::SysV64,
- Abi::Msp430Interrupt,
- Abi::X86Interrupt,
- Abi::AmdGpuKernel,
- ],
-
..Default::default()
},
}
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
arch: "riscv32".to_string(),
options: TargetOptions {
- unsupported_abis: super::riscv_base::unsupported_abis(),
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".to_string(),
features: "+m,+a,+f,+d,+c".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
arch: "riscv32".to_string(),
options: TargetOptions {
- unsupported_abis: super::riscv_base::unsupported_abis(),
code_model: Some(CodeModel::Medium),
cpu: "generic-rv32".to_string(),
features: "+m,+a,+f,+d,+c".to_string(),
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
- unsupported_abis: super::riscv_base::unsupported_abis(),
eh_frame_header: false,
..Default::default()
},
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
- unsupported_abis: super::riscv_base::unsupported_abis(),
eh_frame_header: false,
..Default::default()
},
panic_strategy: PanicStrategy::Abort,
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
- unsupported_abis: super::riscv_base::unsupported_abis(),
eh_frame_header: false,
..Default::default()
},
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
arch: "riscv64".to_string(),
options: TargetOptions {
- unsupported_abis: super::riscv_base::unsupported_abis(),
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".to_string(),
features: "+m,+a,+f,+d,+c".to_string(),
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
arch: "riscv64".to_string(),
options: TargetOptions {
- unsupported_abis: super::riscv_base::unsupported_abis(),
code_model: Some(CodeModel::Medium),
cpu: "generic-rv64".to_string(),
features: "+m,+a,+f,+d,+c".to_string(),
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
- unsupported_abis: super::riscv_base::unsupported_abis(),
eh_frame_header: false,
..Default::default()
},
relocation_model: RelocModel::Static,
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
- unsupported_abis: super::riscv_base::unsupported_abis(),
eh_frame_header: false,
..Default::default()
},
+++ /dev/null
-use crate::spec::abi::Abi;
-
-// All the calling conventions trigger an assertion(Unsupported calling
-// convention) in llvm on RISCV
-pub fn unsupported_abis() -> Vec<Abi> {
- vec![
- Abi::Cdecl,
- Abi::Stdcall { unwind: false },
- Abi::Stdcall { unwind: true },
- Abi::Fastcall,
- Abi::Vectorcall,
- Abi::Thiscall { unwind: false },
- Abi::Thiscall { unwind: true },
- Abi::Aapcs,
- Abi::Win64,
- Abi::SysV64,
- Abi::PtxKernel,
- Abi::Msp430Interrupt,
- Abi::X86Interrupt,
- Abi::AmdGpuKernel,
- ]
-}
// Similarly, one almost always never wants to use relocatable code because of the extra
// costs it involves.
relocation_model: RelocModel::Static,
- unsupported_abis: super::arm_base::unsupported_abis(),
// When this section is added a volatile load to its start address is also generated. This
// volatile load is a footgun as it can end up loading an invalid memory address, depending
// on how the user set up their linker scripts. This section adds pretty printer for stuff
pub fn target() -> Target {
let mut base = super::windows_msvc_base::opts();
-
// Prevent error LNK2013: BRANCH24(T) fixup overflow
// The LBR optimization tries to eliminate branch islands,
// but if the displacement is larger than can fit
.or_default()
.push(pre_link_args_msvc);
- // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
- // implemented for windows/arm in LLVM
- base.panic_strategy = PanicStrategy::Abort;
-
Target {
llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
pointer_width: 32,
data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
features: "+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
+ // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+ // implemented for windows/arm in LLVM
+ panic_strategy: PanicStrategy::Abort,
..base
},
}
use crate::spec::{PanicStrategy, Target, TargetOptions};
pub fn target() -> Target {
- let mut base = super::windows_uwp_msvc_base::opts();
- base.max_atomic_width = Some(64);
- base.has_elf_tls = true;
-
- // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
- // implemented for windows/arm in LLVM
- base.panic_strategy = PanicStrategy::Abort;
-
Target {
llvm_target: "thumbv7a-pc-windows-msvc".to_string(),
pointer_width: 32,
arch: "arm".to_string(),
options: TargetOptions {
features: "+vfp3,+neon".to_string(),
- unsupported_abis: super::arm_base::unsupported_abis(),
- ..base
+ max_atomic_width: Some(64),
+ has_elf_tls: true,
+ // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is
+ // implemented for windows/arm in LLVM
+ panic_strategy: PanicStrategy::Abort,
+ ..super::windows_uwp_msvc_base::opts()
},
}
}
pub fn target() -> Target {
let mut base = super::android_base::opts();
- base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string();
- base.max_atomic_width = Some(64);
base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-march=armv7-a".to_string());
-
Target {
llvm_target: "armv7-none-linux-android".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
- options: TargetOptions { unsupported_abis: super::arm_base::unsupported_abis(), ..base },
+ options: TargetOptions {
+ features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
+ max_atomic_width: Some(64),
+ ..base
+ },
}
}
// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
pub fn target() -> Target {
- let base = super::linux_gnu_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
-
options: TargetOptions {
// Info about features at https://wiki.debian.org/ArmHardFloatPort
features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
- ..base
+ ..super::linux_gnu_base::opts()
},
}
}
// https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf
pub fn target() -> Target {
- let base = super::linux_musl_base::opts();
Target {
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
// uses it to determine the calling convention and float ABI, and LLVM
options: TargetOptions {
features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
- unsupported_abis: super::arm_base::unsupported_abis(),
mcount: "\u{1}mcount".to_string(),
- ..base
+ ..super::linux_musl_base::opts()
},
}
}
}
// If we have reached the recursion limit, error gracefully.
- if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) {
+ if !tcx.recursion_limit().value_within_limit(self.state.steps.len()) {
if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty);
}
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
// We've reached the recursion limit, error gracefully.
- let suggested_limit = tcx.sess.recursion_limit() * 2;
+ let suggested_limit = tcx.recursion_limit() * 2;
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt};
use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
use rustc_middle::traits::query::Fallible;
+use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::ToPredicate;
+use rustc_middle::ty::WithConstness;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::{Span, DUMMY_SP};
) -> InferOk<'tcx, T>
where
T: TypeFoldable<'tcx>;
-}
+ /// Check whether a `ty` implements given trait(trait_def_id).
+ /// The inputs are:
+ ///
+ /// - the def-id of the trait
+ /// - the self type
+ /// - the *other* type parameters of the trait, excluding the self-type
+ /// - the parameter environment
+ fn type_implements_trait(
+ &self,
+ trait_def_id: DefId,
+ ty: Ty<'tcx>,
+ params: SubstsRef<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> traits::EvaluationResult;
+}
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
fn type_is_copy_modulo_regions(
&self,
);
InferOk { value, obligations }
}
+
+ fn type_implements_trait(
+ &self,
+ trait_def_id: DefId,
+ ty: Ty<'tcx>,
+ params: SubstsRef<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> traits::EvaluationResult {
+ debug!(
+ "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
+ trait_def_id, ty, params, param_env
+ );
+
+ let trait_ref =
+ ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };
+
+ let obligation = traits::Obligation {
+ cause: traits::ObligationCause::dummy(),
+ param_env,
+ recursion_depth: 0,
+ predicate: trait_ref.without_const().to_predicate(self.tcx),
+ };
+ self.evaluate_obligation_no_overflow(&obligation)
+ }
}
pub trait InferCtxtBuilderExt<'tcx> {
use std::fmt;
use super::InferCtxtPrivExt;
+use crate::infer::InferCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_middle::ty::print::with_no_trimmed_paths;
return false;
}
- // Blacklist traits for which it would be nonsensical to suggest borrowing.
+ // List of traits for which it would be nonsensical to suggest borrowing.
// For instance, immutable references are always Copy, so suggesting to
// borrow would always succeed, but it's probably not what the user wanted.
- let blacklist: Vec<_> =
- [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized, LangItem::Send]
+ let mut never_suggest_borrow: Vec<_> =
+ [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
.iter()
.filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
.collect();
+ never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
+
let span = obligation.cause.span;
let param_env = obligation.param_env;
let trait_ref = trait_ref.skip_binder();
ty::TraitRef::new(trait_ref.def_id, imm_substs),
trait_ref,
false,
- &blacklist[..],
+ &never_suggest_borrow[..],
) {
return true;
} else {
ty::TraitRef::new(trait_ref.def_id, mut_substs),
trait_ref,
true,
- &blacklist[..],
+ &never_suggest_borrow[..],
);
}
} else {
}
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
- let current_limit = self.tcx.sess.recursion_limit();
+ let current_limit = self.tcx.recursion_limit();
let suggested_limit = current_limit * 2;
err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
}
let self_ty = self.tcx.erase_regions(self_ty);
- let impls_future = self.tcx.type_implements_trait((
+ let impls_future = self.type_implements_trait(
future_trait,
self_ty.skip_binder(),
ty::List::empty(),
obligation.param_env,
- ));
+ );
let item_def_id = self
.tcx
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{
- self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
+ self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
COMMON_VTABLE_ENTRIES,
};
use rustc_span::Span;
vtable_base
}
-/// Check whether a `ty` implements given trait(trait_def_id).
-/// See query definition for details.
-fn type_implements_trait<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: (
- DefId, // trait_def_id,
- Ty<'tcx>, // type
- SubstsRef<'tcx>,
- ParamEnv<'tcx>,
- ),
-) -> EvaluationResult {
- let (trait_def_id, ty, params, param_env) = key;
-
- debug!(
- "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
- trait_def_id, ty, params, param_env
- );
-
- let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };
-
- // FIXME(#86868): If there are inference variables anywhere, just give up and assume
- // we don't know the answer. This works around the ICEs that would result from
- // using those inference variables within the `infer_ctxt` we create below.
- // Really we should be using canonicalized variables, or perhaps removing
- // this query altogether.
- if (trait_ref, param_env).needs_infer() {
- return EvaluationResult::EvaluatedToUnknown;
- }
-
- let obligation = Obligation {
- cause: ObligationCause::dummy(),
- param_env,
- recursion_depth: 0,
- predicate: trait_ref.without_const().to_predicate(tcx),
- };
- tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation))
-}
-
pub fn provide(providers: &mut ty::query::Providers) {
object_safety::provide(providers);
structural_match::provide(providers);
specializes: specialize::specializes,
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
vtable_entries,
- type_implements_trait,
subst_and_check_impossible_predicates,
mir_abstract_const: |tcx, def_id| {
let def_id = def_id.expect_local();
Reveal::UserFacing => ty,
Reveal::All => {
- let recursion_limit = self.tcx().sess.recursion_limit();
+ let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
let obligation = Obligation::with_depth(
self.cause.clone(),
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
debug!(?obligation, "project_type");
- if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
+ if !selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth) {
debug!("project: overflow!");
// This should really be an immediate error, but some existing code
// relies on being able to recover from this.
Reveal::UserFacing => ty,
Reveal::All => {
- let recursion_limit = self.tcx().sess.recursion_limit();
+ let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth(
self.cause.clone(),
obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError> {
- if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
+ if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
match self.query_mode {
TraitQueryMode::Standard => {
self.infcx().report_overflow_error(error_obligation, true);
) -> Result<(), NoSolution> {
debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
- if !tcx.sess.recursion_limit().value_within_limit(depth) {
+ if !tcx.recursion_limit().value_within_limit(depth) {
constraints.overflows.push(ty);
return Ok(());
}
seen_tys,
query_ty: ty,
unchecked_tys: vec![(ty, 0)],
- recursion_limit: tcx.sess.recursion_limit(),
+ recursion_limit: tcx.recursion_limit(),
adt_components,
}
}
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{
self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
};
-use rustc_session::CrateDisambiguator;
use rustc_span::Span;
use rustc_trait_selection::traits;
tcx.param_env(def_id).with_reveal_all_normalized(tcx)
}
-fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
- assert_eq!(crate_num, LOCAL_CRATE);
- tcx.sess.local_crate_disambiguator()
-}
-
fn instance_def_size_estimate<'tcx>(
tcx: TyCtxt<'tcx>,
instance_def: ty::InstanceDef<'tcx>,
param_env,
param_env_reveal_all_normalized,
trait_of_item,
- crate_disambiguator,
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
fcx.write_method_call(self.call_expr.hir_id, method_callee);
}
None => {
- span_bug!(
+ // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`
+ // lang items are not defined (issue #86238).
+ let mut err = fcx.inh.tcx.sess.struct_span_err(
self.call_expr.span,
- "failed to find an overloaded call trait for closure call"
+ "failed to find an overloaded call trait for closure call",
);
+ err.help(
+ "make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \
+ and have associated `call`/`call_mut`/`call_once` functions",
+ );
+ err.emit();
}
}
}
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
let expr_ty = fcx.tcx.erase_regions(expr_ty);
let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
if fcx
- .tcx
- .type_implements_trait((from_trait, ty, ty_params, fcx.param_env))
+ .infcx
+ .type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt};
-use rustc_session::lint::builtin::UNINHABITED_STATIC;
+use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, MultiSpan, Span};
use rustc_target::spec::abi::Abi;
tcx.hir().krate().par_visit_all_item_likes(&visit);
}
-pub(super) fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
- if !tcx.sess.target.is_abi_supported(abi) {
- struct_span_err!(
+pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
+ match tcx.sess.target.is_abi_supported(abi) {
+ Some(true) => (),
+ Some(false) => struct_span_err!(
tcx.sess,
span,
E0570,
- "The ABI `{}` is not supported for the current target",
+ "`{}` is not a supported ABI for the current target",
abi
)
- .emit()
+ .emit(),
+ None => {
+ tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
+ lint.build("use of calling convention not supported on this target").emit()
+ });
+ }
}
// This ABI is only allowed on function pointers
check_type_params_are_used(tcx, &generics, pty_ty);
}
hir::ItemKind::ForeignMod { abi, items } => {
- check_abi(tcx, it.span, abi);
+ check_abi(tcx, it.hir_id(), it.span, abi);
if abi == Abi::RustIntrinsic {
for item in items {
expected.is_unit(),
pointing_at_return_type,
) {
- // If the block is from an external macro, then do not suggest
- // adding a semicolon, because there's nowhere to put it.
- // See issue #81943.
+ // If the block is from an external macro or try (`?`) desugaring, then
+ // do not suggest adding a semicolon, because there's nowhere to put it.
+ // See issues #81943 and #87051.
if cond_expr.span.desugaring_kind().is_none()
&& !in_external_macro(fcx.tcx.sess, cond_expr.span)
+ && !matches!(
+ cond_expr.kind,
+ hir::ExprKind::Match(.., hir::MatchSource::TryDesugar)
+ )
{
err.span_label(cond_expr.span, "expected this to be `()`");
if expr.can_have_side_effects() {
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+ sym::raw_eq => {
+ let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) };
+ let param_ty =
+ tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
+ (1, vec![param_ty; 2], tcx.types.bool)
+ }
+
other => {
tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
return;
use rustc_ast::Mutability;
use rustc_errors::Applicability;
use rustc_hir as hir;
+use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{Ref, Ty};
-use rustc_session::lint::builtin::FUTURE_PRELUDE_COLLISION;
+use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_span::symbol::kw::Underscore;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
use crate::check::{
method::probe::{self, Pick},
// Inherent impls only require not relying on autoref and autoderef in order to
// ensure that the trait implementation won't be used
self.tcx.struct_span_lint_hir(
- FUTURE_PRELUDE_COLLISION,
+ RUST_2021_PRELUDE_COLLISIONS,
self_expr.hir_id,
self_expr.span,
|lint| {
// trait implementations require full disambiguation to not clash with the new prelude
// additions (i.e. convert from dot-call to fully-qualified call)
self.tcx.struct_span_lint_hir(
- FUTURE_PRELUDE_COLLISION,
+ RUST_2021_PRELUDE_COLLISIONS,
call_expr.hir_id,
call_expr.span,
|lint| {
return;
}
+ // For from_iter, check if the type actually implements FromIterator.
+ // If we know it does not, we don't need to warn.
+ if method_name.name == sym::from_iter {
+ if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
+ if !self
+ .infcx
+ .type_implements_trait(
+ trait_def_id,
+ self_ty,
+ InternalSubsts::empty(),
+ self.param_env,
+ )
+ .may_apply()
+ {
+ return;
+ }
+ }
+ }
+
// No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
// since such methods take precedence over trait methods.
if matches!(pick.kind, probe::PickKind::InherentImplPick) {
return;
}
- self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
+ self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
// "type" refers to either a type or, more likely, a trait from which
// the associated function or method is from.
let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
tcx.fn_sig(def_id)
};
- check_abi(tcx, span, fn_sig.abi());
+ check_abi(tcx, id, span, fn_sig.abi());
// Compute the fty from point of view of inside the fn.
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{
- self, ClosureSizeProfileData, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts,
+ self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarCapture, UpvarSubsts,
};
use rustc_session::lint;
use rustc_span::sym;
use rustc_span::{MultiSpan, Span, Symbol};
-use rustc_trait_selection::traits::{Obligation, ObligationCause};
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_data_structures::stable_map::FxHashMap;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_index::vec::Idx;
use rustc_target::abi::VariantIdx;
}
}
+/// Intermediate format to store the hir_id pointing to the use that resulted in the
+/// corresponding place being captured and a String which contains the captured value's
+/// name (i.e: a.b.c)
+type CapturesInfo = (Option<hir::HirId>, String);
+
+/// Intermediate format to store information needed to generate migration lint. The tuple
+/// contains the hir_id pointing to the use that resulted in the
+/// corresponding place being captured, a String which contains the captured value's
+/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that
+/// capture
+type MigrationNeededForCapture = (Option<hir::HirId>, String, String);
+
+/// Intermediate format to store the hir id of the root variable and a HashSet containing
+/// information on why the root variable should be fully captured
+type MigrationDiagnosticInfo = (hir::HirId, Vec<MigrationNeededForCapture>);
+
struct InferBorrowKindVisitor<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
}
fcx: self,
closure_def_id,
closure_span: span,
- capture_clause,
- current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
- current_origin: None,
capture_information: Default::default(),
fake_reads: Default::default(),
};
"For closure={:?}, capture_information={:#?}",
closure_def_id, delegate.capture_information
);
+
self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span);
- self.compute_min_captures(closure_def_id, capture_clause, delegate.capture_information);
+ let (capture_information, closure_kind, origin) = self
+ .process_collected_capture_information(capture_clause, delegate.capture_information);
+
+ self.compute_min_captures(closure_def_id, capture_information);
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
- if should_do_disjoint_capture_migration_analysis(self.tcx, closure_hir_id) {
+ if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
self.perform_2229_migration_anaysis(closure_def_id, body_id, capture_clause, span);
}
}
// This will update the min captures based on this new fake information.
- self.compute_min_captures(closure_def_id, capture_clause, capture_information);
+ self.compute_min_captures(closure_def_id, capture_information);
}
let before_feature_tys = self.final_upvar_tys(closure_def_id);
if let Some(closure_substs) = infer_kind {
// Unify the (as yet unbound) type variable in the closure
// substs with the kind we inferred.
- let inferred_kind = delegate.current_closure_kind;
let closure_kind_ty = closure_substs.as_closure().kind_ty();
- self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
+ self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
// If we have an origin, store it.
- if let Some(origin) = delegate.current_origin.clone() {
+ if let Some(origin) = origin {
let origin = if enable_precise_capture(self.tcx, span) {
- (origin.0, restrict_capture_precision(capture_clause, origin.1))
+ (origin.0, origin.1)
} else {
(origin.0, Place { projections: vec![], ..origin.1 })
};
captured_place.place, upvar_ty, capture, captured_place.mutability,
);
- match capture {
- ty::UpvarCapture::ByValue(_) => upvar_ty,
- ty::UpvarCapture::ByRef(borrow) => self.tcx.mk_ref(
- borrow.region,
- ty::TypeAndMut { ty: upvar_ty, mutbl: borrow.kind.to_mutbl_lossy() },
- ),
- }
+ apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture)
})
.collect()
}
+ /// Adjusts the closure capture information to ensure that the operations aren't unsafe,
+ /// and that the path can be captured with required capture kind (depending on use in closure,
+ /// move closure etc.)
+ ///
+ /// Returns the set of of adjusted information along with the inferred closure kind and span
+ /// associated with the closure kind inference.
+ ///
+ /// Note that we *always* infer a minimal kind, even if
+ /// we don't always *use* that in the final result (i.e., sometimes
+ /// we've taken the closure kind from the expectations instead, and
+ /// for generators we don't even implement the closure traits
+ /// really).
+ ///
+ /// If we inferred that the closure needs to be FnMut/FnOnce, last element of the returned tuple
+ /// contains a `Some()` with the `Place` that caused us to do so.
+ fn process_collected_capture_information(
+ &self,
+ capture_clause: hir::CaptureBy,
+ capture_information: InferredCaptureInformation<'tcx>,
+ ) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) {
+ let mut processed: InferredCaptureInformation<'tcx> = Default::default();
+
+ let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM;
+ let mut origin: Option<(Span, Place<'tcx>)> = None;
+
+ for (place, mut capture_info) in capture_information {
+ // Apply rules for safety before inferring closure kind
+ let place = restrict_capture_precision(place);
+
+ let place = truncate_capture_for_optimization(&place);
+
+ let usage_span = if let Some(usage_expr) = capture_info.path_expr_id {
+ self.tcx.hir().span(usage_expr)
+ } else {
+ unreachable!()
+ };
+
+ let updated = match capture_info.capture_kind {
+ ty::UpvarCapture::ByValue(..) => match closure_kind {
+ ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
+ (ty::ClosureKind::FnOnce, Some((usage_span, place.clone())))
+ }
+ // If closure is already FnOnce, don't update
+ ty::ClosureKind::FnOnce => (closure_kind, origin),
+ },
+
+ ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+ kind: ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
+ ..
+ }) => {
+ match closure_kind {
+ ty::ClosureKind::Fn => {
+ (ty::ClosureKind::FnMut, Some((usage_span, place.clone())))
+ }
+ // Don't update the origin
+ ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce => (closure_kind, origin),
+ }
+ }
+
+ _ => (closure_kind, origin),
+ };
+
+ closure_kind = updated.0;
+ origin = updated.1;
+
+ let (place, capture_kind) = match capture_clause {
+ hir::CaptureBy::Value => adjust_for_move_closure(place, capture_info.capture_kind),
+ hir::CaptureBy::Ref => {
+ adjust_for_non_move_closure(place, capture_info.capture_kind)
+ }
+ };
+
+ capture_info.capture_kind = capture_kind;
+ processed.insert(place, capture_info);
+ }
+
+ (processed, closure_kind, origin)
+ }
+
/// Analyzes the information collected by `InferBorrowKind` to compute the min number of
/// Places (and corresponding capture kind) that we need to keep track of to support all
/// the required captured paths.
fn compute_min_captures(
&self,
closure_def_id: DefId,
- capture_clause: hir::CaptureBy,
capture_information: InferredCaptureInformation<'tcx>,
) {
if capture_information.is_empty() {
base => bug!("Expected upvar, found={:?}", base),
};
- let place = restrict_capture_precision(capture_clause, place);
-
let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
None => {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
let local_def_id = closure_def_id.expect_local();
let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
+ let closure_span = self.tcx.hir().span(closure_hir_id);
+ let closure_head_span = self.tcx.sess.source_map().guess_head_span(closure_span);
self.tcx.struct_span_lint_hir(
- lint::builtin::DISJOINT_CAPTURE_MIGRATION,
+ lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
closure_hir_id,
- span,
+ closure_head_span,
|lint| {
let mut diagnostics_builder = lint.build(
format!(
- "{} will change in Rust 2021",
+ "changes to closure capture in Rust 2021 will affect {}",
reasons
)
.as_str(),
);
+ for (var_hir_id, diagnostics_info) in need_migrations.iter() {
+ // Labels all the usage of the captured variable and why they are responsible
+ // for migration being needed
+ for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
+ if let Some(captured_hir_id) = captured_hir_id {
+ let cause_span = self.tcx.hir().span(*captured_hir_id);
+ diagnostics_builder.span_label(cause_span, format!("in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`",
+ self.tcx.hir().name(*var_hir_id),
+ captured_name,
+ ));
+ }
+
+ // Add a label pointing to where a captured variable affected by drop order
+ // is dropped
+ if reasons.contains("drop order") {
+ let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
+
+ diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only `{}` would be dropped here alongside the closure",
+ self.tcx.hir().name(*var_hir_id),
+ captured_name,
+ ));
+ }
+
+ // Add a label explaining why a closure no longer implements a trait
+ if reasons.contains("trait implementation") {
+ let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
+
+ diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure would no longer implement {} as `{}` does not implement {}",
+ missing_trait,
+ self.tcx.hir().name(*var_hir_id),
+ missing_trait,
+ missing_trait,
+ captured_name,
+ missing_trait,
+ ));
+ }
+ }
+ }
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
let closure_body_span = self.tcx.hir().span(body_id.hir_id);
let (sugg, app) =
if auto_trait_reasons.len() > 0 {
reasons = format!(
- "{} trait implementation",
+ "{} trait implementation for closure",
auto_trait_reasons.clone().into_iter().collect::<Vec<&str>>().join(", ")
);
}
if auto_trait_reasons.len() > 0 && drop_reason {
- reasons = format!("{}, and ", reasons);
+ reasons = format!("{} and ", reasons);
}
if drop_reason {
reasons
}
- /// Returns true if `ty` may implement `trait_def_id`
- fn ty_impls_trait(
- &self,
- ty: Ty<'tcx>,
- cause: &ObligationCause<'tcx>,
- trait_def_id: DefId,
- ) -> bool {
- use crate::rustc_middle::ty::ToPredicate;
- use crate::rustc_middle::ty::WithConstness;
- use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
- let tcx = self.infcx.tcx;
-
- let trait_ref = TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };
-
- let obligation = Obligation::new(
- cause.clone(),
- self.param_env,
- trait_ref.without_const().to_predicate(tcx),
- );
-
- self.infcx.predicate_may_hold(&obligation)
- }
-
- /// Returns true if migration is needed for trait for the provided var_hir_id
- fn need_2229_migrations_for_trait(
+ /// Figures out the list of root variables (and their types) that aren't completely
+ /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits
+ /// differ between the root variable and the captured paths.
+ ///
+ /// Returns a tuple containing a HashMap of CapturesInfo that maps to a HashSet of trait names
+ /// if migration is needed for traits for the provided var_hir_id, otherwise returns None
+ fn compute_2229_migrations_for_trait(
&self,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
var_hir_id: hir::HirId,
- check_trait: Option<DefId>,
- ) -> bool {
+ closure_clause: hir::CaptureBy,
+ ) -> Option<FxHashMap<CapturesInfo, FxHashSet<&str>>> {
+ let auto_traits_def_id = vec![
+ self.tcx.lang_items().clone_trait(),
+ self.tcx.lang_items().sync_trait(),
+ self.tcx.get_diagnostic_item(sym::send_trait),
+ self.tcx.lang_items().unpin_trait(),
+ self.tcx.get_diagnostic_item(sym::unwind_safe_trait),
+ self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait),
+ ];
+ let auto_traits =
+ vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"];
+
let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
min_captures.and_then(|m| m.get(&var_hir_id))
{
root_var_min_capture_list
} else {
- return false;
+ return None;
};
let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
- let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id);
-
- let obligation_should_hold = check_trait
- .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
- .unwrap_or(false);
-
- // Check whether catpured fields also implement the trait
-
- for capture in root_var_min_capture_list.iter() {
- let ty = capture.place.ty();
-
- let obligation_holds_for_capture = check_trait
- .map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
- .unwrap_or(false);
+ let ty = match closure_clause {
+ hir::CaptureBy::Value => ty, // For move closure the capture kind should be by value
+ hir::CaptureBy::Ref => {
+ // For non move closure the capture kind is the max capture kind of all captures
+ // according to the ordering ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue
+ let mut max_capture_info = root_var_min_capture_list.first().unwrap().info;
+ for capture in root_var_min_capture_list.iter() {
+ max_capture_info = determine_capture_info(max_capture_info, capture.info);
+ }
- if !obligation_holds_for_capture && obligation_should_hold {
- return true;
+ apply_capture_kind_on_capture_ty(self.tcx, ty, max_capture_info.capture_kind)
}
- }
- false
- }
+ };
- /// Figures out the list of root variables (and their types) that aren't completely
- /// captured by the closure when `capture_disjoint_fields` is enabled and auto-traits
- /// differ between the root variable and the captured paths.
- ///
- /// The output list would include a root variable if:
- /// - It would have been captured into the closure when `capture_disjoint_fields` wasn't
- /// enabled, **and**
- /// - It wasn't completely captured by the closure, **and**
- /// - One of the paths captured does not implement all the auto-traits its root variable
- /// implements.
- fn compute_2229_migrations_for_trait(
- &self,
- min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
- var_hir_id: hir::HirId,
- ) -> Option<FxHashSet<&str>> {
- let tcx = self.infcx.tcx;
-
- // Check whether catpured fields also implement the trait
- let mut auto_trait_reasons = FxHashSet::default();
-
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().clone_trait(),
- ) {
- auto_trait_reasons.insert("`Clone`");
+ let mut obligations_should_hold = Vec::new();
+ // Checks if a root variable implements any of the auto traits
+ for check_trait in auto_traits_def_id.iter() {
+ obligations_should_hold.push(
+ check_trait
+ .map(|check_trait| {
+ self.infcx
+ .type_implements_trait(
+ check_trait,
+ ty,
+ self.tcx.mk_substs_trait(ty, &[]),
+ self.param_env,
+ )
+ .must_apply_modulo_regions()
+ })
+ .unwrap_or(false),
+ );
}
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().sync_trait(),
- ) {
- auto_trait_reasons.insert("`Sync`");
- }
+ let mut problematic_captures = FxHashMap::default();
+ // Check whether captured fields also implement the trait
+ for capture in root_var_min_capture_list.iter() {
+ let ty = apply_capture_kind_on_capture_ty(
+ self.tcx,
+ capture.place.ty(),
+ capture.info.capture_kind,
+ );
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().send_trait(),
- ) {
- auto_trait_reasons.insert("`Send`");
- }
+ // Checks if a capture implements any of the auto traits
+ let mut obligations_holds_for_capture = Vec::new();
+ for check_trait in auto_traits_def_id.iter() {
+ obligations_holds_for_capture.push(
+ check_trait
+ .map(|check_trait| {
+ self.infcx
+ .type_implements_trait(
+ check_trait,
+ ty,
+ self.tcx.mk_substs_trait(ty, &[]),
+ self.param_env,
+ )
+ .must_apply_modulo_regions()
+ })
+ .unwrap_or(false),
+ );
+ }
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().unpin_trait(),
- ) {
- auto_trait_reasons.insert("`Unpin`");
- }
+ let mut capture_problems = FxHashSet::default();
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().unwind_safe_trait(),
- ) {
- auto_trait_reasons.insert("`UnwindSafe`");
- }
+ // Checks if for any of the auto traits, one or more trait is implemented
+ // by the root variable but not by the capture
+ for (idx, _) in obligations_should_hold.iter().enumerate() {
+ if !obligations_holds_for_capture[idx] && obligations_should_hold[idx] {
+ capture_problems.insert(auto_traits[idx]);
+ }
+ }
- if self.need_2229_migrations_for_trait(
- min_captures,
- var_hir_id,
- tcx.lang_items().ref_unwind_safe_trait(),
- ) {
- auto_trait_reasons.insert("`RefUnwindSafe`");
+ if capture_problems.len() > 0 {
+ problematic_captures.insert(
+ (capture.info.path_expr_id, capture.to_string(self.tcx)),
+ capture_problems,
+ );
+ }
}
-
- if auto_trait_reasons.len() > 0 {
- return Some(auto_trait_reasons);
+ if problematic_captures.len() > 0 {
+ return Some(problematic_captures);
}
-
- return None;
+ None
}
/// Figures out the list of root variables (and their types) that aren't completely
/// - It wasn't completely captured by the closure, **and**
/// - One of the paths starting at this root variable, that is not captured needs Drop.
///
- /// This function only returns true for significant drops. A type is considerent to have a
- /// significant drop if it's Drop implementation is not annotated by `rustc_insignificant_dtor`.
+ /// This function only returns a HashSet of CapturesInfo for significant drops. If there
+ /// are no significant drops than None is returned
fn compute_2229_migrations_for_drop(
&self,
closure_def_id: DefId,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
closure_clause: hir::CaptureBy,
var_hir_id: hir::HirId,
- ) -> bool {
+ ) -> Option<FxHashSet<CapturesInfo>> {
let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
- return false;
+ return None;
}
let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
match closure_clause {
// Only migrate if closure is a move closure
- hir::CaptureBy::Value => return true,
+ hir::CaptureBy::Value => return Some(FxHashSet::default()),
hir::CaptureBy::Ref => {}
}
- return false;
+ return None;
};
- let projections_list = root_var_min_capture_list
- .iter()
- .filter_map(|captured_place| match captured_place.info.capture_kind {
+ let mut projections_list = Vec::new();
+ let mut diagnostics_info = FxHashSet::default();
+
+ for captured_place in root_var_min_capture_list.iter() {
+ match captured_place.info.capture_kind {
// Only care about captures that are moved into the closure
- ty::UpvarCapture::ByValue(..) => Some(captured_place.place.projections.as_slice()),
- ty::UpvarCapture::ByRef(..) => None,
- })
- .collect::<Vec<_>>();
+ ty::UpvarCapture::ByValue(..) => {
+ projections_list.push(captured_place.place.projections.as_slice());
+ diagnostics_info.insert((
+ captured_place.info.path_expr_id,
+ captured_place.to_string(self.tcx),
+ ));
+ }
+ ty::UpvarCapture::ByRef(..) => {}
+ }
+ }
let is_moved = !projections_list.is_empty();
projections_list,
)
{
- return true;
+ return Some(diagnostics_info);
}
- return false;
+ return None;
}
/// Figures out the list of root variables (and their types) that aren't completely
/// - One of the paths captured does not implement all the auto-traits its root variable
/// implements.
///
- /// Returns a tuple containing a vector of HirIds as well as a String containing the reason
- /// why root variables whose HirId is contained in the vector should be fully captured.
+ /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String
+ /// containing the reason why root variables whose HirId is contained in the vector should
+ /// be captured
fn compute_2229_migrations(
&self,
closure_def_id: DefId,
closure_span: Span,
closure_clause: hir::CaptureBy,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
- ) -> (Vec<hir::HirId>, String) {
+ ) -> (Vec<MigrationDiagnosticInfo>, String) {
let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
upvars
} else {
};
let mut need_migrations = Vec::new();
- let mut auto_trait_reasons = FxHashSet::default();
- let mut drop_reorder_reason = false;
+ let mut auto_trait_migration_reasons = FxHashSet::default();
+ let mut drop_migration_needed = false;
// Perform auto-trait analysis
for (&var_hir_id, _) in upvars.iter() {
- let mut need_migration = false;
- if let Some(trait_migration_cause) =
- self.compute_2229_migrations_for_trait(min_captures, var_hir_id)
+ let mut responsible_captured_hir_ids = Vec::new();
+
+ let auto_trait_diagnostic = if let Some(diagnostics_info) =
+ self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
{
- need_migration = true;
- auto_trait_reasons.extend(trait_migration_cause);
+ diagnostics_info
+ } else {
+ FxHashMap::default()
+ };
+
+ let drop_reorder_diagnostic = if let Some(diagnostics_info) = self
+ .compute_2229_migrations_for_drop(
+ closure_def_id,
+ closure_span,
+ min_captures,
+ closure_clause,
+ var_hir_id,
+ ) {
+ drop_migration_needed = true;
+ diagnostics_info
+ } else {
+ FxHashSet::default()
+ };
+
+ // Combine all the captures responsible for needing migrations into one HashSet
+ let mut capture_diagnostic = drop_reorder_diagnostic.clone();
+ for key in auto_trait_diagnostic.keys() {
+ capture_diagnostic.insert(key.clone());
}
- if self.compute_2229_migrations_for_drop(
- closure_def_id,
- closure_span,
- min_captures,
- closure_clause,
- var_hir_id,
- ) {
- need_migration = true;
- drop_reorder_reason = true;
+ let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>();
+ capture_diagnostic.sort();
+ for captured_info in capture_diagnostic.iter() {
+ // Get the auto trait reasons of why migration is needed because of that capture, if there are any
+ let capture_trait_reasons =
+ if let Some(reasons) = auto_trait_diagnostic.get(captured_info) {
+ reasons.clone()
+ } else {
+ FxHashSet::default()
+ };
+
+ // Check if migration is needed because of drop reorder as a result of that capture
+ let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info);
+
+ // Combine all the reasons of why the root variable should be captured as a result of
+ // auto trait implementation issues
+ auto_trait_migration_reasons.extend(capture_trait_reasons.clone());
+
+ responsible_captured_hir_ids.push((
+ captured_info.0,
+ captured_info.1.clone(),
+ self.compute_2229_migrations_reasons(
+ capture_trait_reasons,
+ capture_drop_reorder_reason,
+ ),
+ ));
}
- if need_migration {
- need_migrations.push(var_hir_id);
+ if capture_diagnostic.len() > 0 {
+ need_migrations.push((var_hir_id, responsible_captured_hir_ids));
}
}
-
(
need_migrations,
- self.compute_2229_migrations_reasons(auto_trait_reasons, drop_reorder_reason),
+ self.compute_2229_migrations_reasons(
+ auto_trait_migration_reasons,
+ drop_migration_needed,
+ ),
)
}
let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]);
- self.tcx
- .type_implements_trait((
+ self.infcx
+ .type_implements_trait(
drop_trait,
ty,
ty_params,
self.tcx.param_env(closure_def_id.expect_local()),
- ))
+ )
.must_apply_modulo_regions()
};
place
}
+/// Returns a Ty that applies the specified capture kind on the provided capture Ty
+fn apply_capture_kind_on_capture_ty(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ capture_kind: UpvarCapture<'tcx>,
+) -> Ty<'tcx> {
+ match capture_kind {
+ ty::UpvarCapture::ByValue(_) => ty,
+ ty::UpvarCapture::ByRef(borrow) => tcx
+ .mk_ref(borrow.region, ty::TypeAndMut { ty: ty, mutbl: borrow.kind.to_mutbl_lossy() }),
+ }
+}
+
+/// Returns the Span of where the value with the provided HirId would be dropped
+fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span {
+ let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap();
+
+ let owner_node = tcx.hir().get(owner_id);
+ let owner_span = match owner_node {
+ hir::Node::Item(item) => match item.kind {
+ hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id),
+ _ => {
+ bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind);
+ }
+ },
+ hir::Node::Block(block) => tcx.hir().span(block.hir_id),
+ _ => {
+ bug!("Drop location span error: need to handle more Node {:?}", owner_node);
+ }
+ };
+ tcx.sess.source_map().end_point(owner_span)
+}
+
struct InferBorrowKind<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
closure_span: Span,
- capture_clause: hir::CaptureBy,
-
- // The kind that we have inferred that the current closure
- // requires. Note that we *always* infer a minimal kind, even if
- // we don't always *use* that in the final result (i.e., sometimes
- // we've taken the closure kind from the expectations instead, and
- // for generators we don't even implement the closure traits
- // really).
- current_closure_kind: ty::ClosureKind,
-
- // If we modified `current_closure_kind`, this field contains a `Some()` with the
- // variable access that caused us to do so.
- current_origin: Option<(Span, Place<'tcx>)>,
-
/// For each Place that is captured by the closure, we track the minimal kind of
/// access we need (ref, ref mut, move, etc) and the expression that resulted in such access.
///
place_with_id, diag_expr_id, mode
);
- match (self.capture_clause, mode) {
- // In non-move closures, we only care about moves
- (hir::CaptureBy::Ref, euv::Copy) => return,
-
- // We want to capture Copy types that read through a ref via a reborrow
- (hir::CaptureBy::Value, euv::Copy)
- if place_with_id.place.deref_tys().any(ty::TyS::is_ref) =>
- {
- return;
- }
-
- (hir::CaptureBy::Ref, euv::Move) | (hir::CaptureBy::Value, euv::Move | euv::Copy) => {}
+ // Copy type being used as ByValue are equivalent to ImmBorrow and don't require any
+ // escalation.
+ match mode {
+ euv::ConsumeMode::Copy => return,
+ euv::ConsumeMode::Move => {}
};
- let place = truncate_capture_for_move(place_with_id.place.clone());
- let place_with_id = PlaceWithHirId { place: place.clone(), hir_id: place_with_id.hir_id };
-
- if !self.capture_information.contains_key(&place) {
- self.init_capture_info_for_place(&place_with_id, diag_expr_id);
- }
-
let tcx = self.fcx.tcx;
let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
upvar_id
let usage_span = tcx.hir().span(diag_expr_id);
- if matches!(mode, euv::Move) {
- // To move out of an upvar, this must be a FnOnce closure
- self.adjust_closure_kind(
- upvar_id.closure_expr_id,
- ty::ClosureKind::FnOnce,
- usage_span,
- place.clone(),
- );
- }
-
let capture_info = ty::CaptureInfo {
capture_kind_expr_id: Some(diag_expr_id),
path_expr_id: Some(diag_expr_id),
ty::ImmBorrow => false,
});
- let tcx = self.fcx.tcx;
-
// if this is an implicit deref of an
// upvar, then we need to modify the
// borrow_kind of the upvar to make sure it
// is inferred to mutable if necessary
self.adjust_upvar_borrow_kind(place_with_id, diag_expr_id, borrow_kind);
-
- if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
- self.adjust_closure_kind(
- upvar_id.closure_expr_id,
- ty::ClosureKind::FnMut,
- tcx.hir().span(diag_expr_id),
- place_with_id.place.clone(),
- );
- }
}
/// We infer the borrow_kind with which to borrow upvars in a stack closure.
};
}
- fn adjust_closure_kind(
- &mut self,
- closure_id: LocalDefId,
- new_kind: ty::ClosureKind,
- upvar_span: Span,
- place: Place<'tcx>,
- ) {
- debug!(
- "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, place={:?})",
- closure_id, new_kind, upvar_span, place
- );
-
- // Is this the closure whose kind is currently being inferred?
- if closure_id.to_def_id() != self.closure_def_id {
- debug!("adjust_closure_kind: not current closure");
- return;
- }
-
- // closures start out as `Fn`.
- let existing_kind = self.current_closure_kind;
-
- debug!(
- "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
- closure_id, existing_kind, new_kind
- );
-
- match (existing_kind, new_kind) {
- (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
- | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn | ty::ClosureKind::FnMut)
- | (ty::ClosureKind::FnOnce, _) => {
- // no change needed
- }
-
- (ty::ClosureKind::Fn, ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce)
- | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
- // new kind is stronger than the old kind
- self.current_closure_kind = new_kind;
- self.current_origin = Some((upvar_span, place));
- }
- }
- }
-
fn init_capture_info_for_place(
&mut self,
place_with_id: &PlaceWithHirId<'tcx>,
if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
assert_eq!(self.closure_def_id.expect_local(), upvar_id.closure_expr_id);
- let capture_kind = self.fcx.init_capture_kind_for_place(
- &place_with_id.place,
- self.capture_clause,
- upvar_id,
- self.closure_span,
- );
+ // Initialize to ImmBorrow
+ // We will escalate the CaptureKind based on any uses we see or in `process_collected_capture_information`.
+ let origin = UpvarRegion(upvar_id, self.closure_span);
+ let upvar_region = self.fcx.next_region_var(origin);
+ let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, region: upvar_region };
+ let capture_kind = ty::UpvarCapture::ByRef(upvar_borrow);
let expr_id = Some(diag_expr_id);
let capture_info = ty::CaptureInfo {
if let PlaceBase::Upvar(_) = place.base {
// We need to restrict Fake Read precision to avoid fake reading unsafe code,
// such as deref of a raw pointer.
- let place = restrict_capture_precision(self.capture_clause, place);
+ let place = restrict_capture_precision(place);
let place =
restrict_repr_packed_field_ref_capture(self.fcx.tcx, self.fcx.param_env, &place);
self.fake_reads.push((place, cause, diag_expr_id));
"consume(place_with_id={:?}, diag_expr_id={:?}, mode={:?})",
place_with_id, diag_expr_id, mode
);
+
if !self.capture_information.contains_key(&place_with_id.place) {
- self.init_capture_info_for_place(place_with_id, diag_expr_id);
+ self.init_capture_info_for_place(&place_with_id, diag_expr_id);
}
- self.adjust_upvar_borrow_kind_for_consume(place_with_id, diag_expr_id, mode);
+ self.adjust_upvar_borrow_kind_for_consume(&place_with_id, diag_expr_id, mode);
}
fn borrow(
);
// We only want repr packed restriction to be applied to reading references into a packed
- // struct, and not when the data is being moved. There for we call this method here instead
+ // struct, and not when the data is being moved. Therefore we call this method here instead
// of in `restrict_capture_precision`.
let place = restrict_repr_packed_field_ref_capture(
self.fcx.tcx,
}
}
-/// Deref of a box isn't captured in move clousres. This is motivated by:
-/// 1. We only want to capture data that is on the stack
-/// 2. One motivation for the user to use a box might be to reduce the amount of data that gets
-/// moved (if size of pointer < size of data). We want to make sure that this optimization that
-/// the user made is respected.
-fn restrict_precision_for_box<'tcx>(
- capture_clause: hir::CaptureBy,
- mut place: Place<'tcx>,
-) -> Place<'tcx> {
- match capture_clause {
- hir::CaptureBy::Ref => {}
- hir::CaptureBy::Value => {
- if ty::TyS::is_box(place.base_ty) {
- place.projections.truncate(0);
- } else {
- // Either the box is the last access or there is a deref applied on the box
- // In either case we want to stop at the box.
- let pos = place.projections.iter().position(|proj| ty::TyS::is_box(proj.ty));
- match pos {
- None => {}
- Some(idx) => {
- place.projections.truncate(idx + 1);
- }
- }
- }
- }
- }
-
- place
-}
-
/// Truncate projections so that following rules are obeyed by the captured `place`:
/// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
/// them completely.
/// - No Index projections are captured, since arrays are captured completely.
-/// - Deref of a box isn't captured in move clousres.
-fn restrict_capture_precision<'tcx>(
- capture_clause: hir::CaptureBy,
- mut place: Place<'tcx>,
-) -> Place<'tcx> {
+fn restrict_capture_precision<'tcx>(mut place: Place<'tcx>) -> Place<'tcx> {
if place.projections.is_empty() {
// Nothing to do here
return place;
place.projections.truncate(length);
- // Dont't capture projections on top of a box in move closures.
- restrict_precision_for_box(capture_clause, place)
+ place
}
-/// Truncates a place so that the resultant capture doesn't move data out of a reference
-fn truncate_capture_for_move(mut place: Place<'tcx>) -> Place<'tcx> {
- if let Some(i) = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref) {
- // We only drop Derefs in case of move closures
- // There might be an index projection or raw ptr ahead, so we don't stop here.
- place.projections.truncate(i);
+/// Take ownership if data being accessed is owned by the variable used to access it
+/// (or if closure attempts to move data that it doesn’t own).
+/// Note: When taking ownership, only capture data found on the stack.
+fn adjust_for_move_closure<'tcx>(
+ mut place: Place<'tcx>,
+ kind: ty::UpvarCapture<'tcx>,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+ let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
+ let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
+
+ match kind {
+ ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
+
+ // If there's any Deref and the data needs to be moved into the closure body,
+ // or it's a Deref of a Box, truncate the path to the first deref
+ _ if first_deref.is_some() => {
+ let place = match first_deref {
+ Some(idx) => {
+ place.projections.truncate(idx);
+ place
+ }
+ None => place,
+ };
+
+ // AMAN: I think we don't need the span inside the ByValue anymore
+ // we have more detailed span in CaptureInfo
+ (place, ty::UpvarCapture::ByValue(None))
+ }
+
+ _ => (place, ty::UpvarCapture::ByValue(None)),
}
+}
- place
+/// Adjust closure capture just that if taking ownership of data, only move data
+/// from enclosing stack frame.
+fn adjust_for_non_move_closure<'tcx>(
+ mut place: Place<'tcx>,
+ kind: ty::UpvarCapture<'tcx>,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+ let contains_deref =
+ place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
+
+ match kind {
+ ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
+ let place = match contains_deref {
+ Some(idx) => {
+ place.projections.truncate(idx);
+ place
+ }
+ // Because of the if guard on the match on `kind`, we should never get here.
+ None => unreachable!(),
+ };
+
+ (place, kind)
+ }
+
+ ty::UpvarCapture::ByValue(..) => (place, kind),
+ ty::UpvarCapture::ByRef(..) => (place, kind),
+ }
}
fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
tcx.hir().name(var_hir_id)
}
-fn should_do_disjoint_capture_migration_analysis(tcx: TyCtxt<'_>, closure_id: hir::HirId) -> bool {
- let (level, _) = tcx.lint_level_at_node(lint::builtin::DISJOINT_CAPTURE_MIGRATION, closure_id);
+fn should_do_rust_2021_incompatible_closure_captures_analysis(
+ tcx: TyCtxt<'_>,
+ closure_id: hir::HirId,
+) -> bool {
+ let (level, _) =
+ tcx.lint_level_at_node(lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES, closure_id);
!matches!(level, lint::Level::Allow)
}
/// - s2: Comma separated names of the variables being migrated.
fn migration_suggestion_for_2229(
tcx: TyCtxt<'_>,
- need_migrations: &Vec<hir::HirId>,
+ need_migrations: &Vec<MigrationDiagnosticInfo>,
) -> (String, String) {
let need_migrations_variables =
- need_migrations.iter().map(|v| var_name(tcx, *v)).collect::<Vec<_>>();
+ need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::<Vec<_>>();
let migration_ref_concat =
need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
}
}
+/// Reduces the precision of the captured place when the precision doesn't yeild any benefit from
+/// borrow checking prespective, allowing us to save us on the size of the capture.
+///
+///
+/// Fields that are read through a shared reference will always be read via a shared ref or a copy,
+/// and therefore capturing precise paths yields no benefit. This optimization truncates the
+/// rightmost deref of the capture if the deref is applied to a shared ref.
+///
+/// Reason we only drop the last deref is because of the following edge case:
+///
+/// ```rust
+/// struct MyStruct<'a> {
+/// a: &'static A,
+/// b: B,
+/// c: C<'a>,
+/// }
+///
+/// fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+/// let c = || drop(&*m.a.field_of_a);
+/// // Here we really do want to capture `*m.a` because that outlives `'static`
+///
+/// // If we capture `m`, then the closure no longer outlives `'static'
+/// // it is constrained to `'a`
+/// }
+/// ```
+fn truncate_capture_for_optimization<'tcx>(place: &Place<'tcx>) -> Place<'tcx> {
+ let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
+
+ // Find the right-most deref (if any). All the projections that come after this
+ // are fields or other "in-place pointer adjustments"; these refer therefore to
+ // data owned by whatever pointer is being dereferenced here.
+ let idx = place.projections.iter().rposition(|proj| ProjectionKind::Deref == proj.kind);
+
+ match idx {
+ // If that pointer is a shared reference, then we don't need those fields.
+ Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => {
+ Place { projections: place.projections[0..=idx].to_vec(), ..place.clone() }
+ }
+ None | Some(_) => place.clone(),
+ }
+}
+
/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
/// user is using Rust Edition 2021 or higher.
///
}
}
GenericParamDefKind::Const { .. } => {
- // FIXME(const_generics_defaults): Figure out if this
- // is the behavior we want, see the comment further below.
if is_our_default(¶m) {
+ // FIXME(const_generics_defaults): This
+ // is incorrect when dealing with unused substs, for example
+ // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
+ // we should eagerly error.
let default_ct = tcx.const_param_default(param.def_id);
- fcx.register_wf_obligation(
- default_ct.into(),
- tcx.def_span(param.def_id),
- ObligationCauseCode::MiscObligation,
- );
+ if !default_ct.needs_subst() {
+ fcx.register_wf_obligation(
+ default_ct.into(),
+ tcx.def_span(param.def_id),
+ ObligationCauseCode::MiscObligation,
+ );
+ }
}
}
// Doesn't have defaults.
tcx.mk_param_from_def(param)
}
GenericParamDefKind::Const { .. } => {
- // FIXME(const_generics_defaults): I(@lcnr) feel like always
- // using the const parameter is the right choice here, even
- // if it needs substs.
- //
- // Before stabilizing this we probably want to get some tests
- // where this makes a difference and figure out what's the exact
- // behavior we want here.
-
// If the param has a default, ...
if is_our_default(param) {
let default_ct = tcx.const_param_default(param.def_id);
crates_to_lint: &mut crates_to_lint,
});
+ let extern_prelude = &tcx.resolutions(()).extern_prelude;
+
for extern_crate in &crates_to_lint {
let def_id = extern_crate.def_id.expect_local();
let id = tcx.hir().local_def_id_to_hir_id(def_id);
// If the extern crate isn't in the extern prelude,
// there is no way it can be written as an `use`.
let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
- if !tcx.extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
+ if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
continue;
}
generator_kind,
codegen_fn_attrs,
collect_mod_item_types,
+ should_inherit_track_caller,
..*providers
};
}
));
}
}
+
+ fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+ // Do not look into const param defaults,
+ // these get checked when they are actually instantiated.
+ //
+ // We do not want the following to error:
+ //
+ // struct Foo<const N: usize, const M: usize = { N + 1 }>;
+ // struct Bar<const N: usize>(Foo<N, 3>);
+ }
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let attrs = tcx.get_attrs(id);
let mut codegen_fn_attrs = CodegenFnAttrs::new();
- if should_inherit_track_caller(tcx, id) {
+ if tcx.should_inherit_track_caller(id) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
}
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline(always)]
- #[doc(alias = "alloc")]
- #[doc(alias = "malloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(x: T) -> Self {
box x
/// [zeroed]: mem::MaybeUninit::zeroed
#[cfg(not(no_global_oom_handling))]
#[inline]
- #[doc(alias = "calloc")]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
Self::new_zeroed_in(Global)
///
/// assert_eq!(heap.len(), 2);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
self.data.len()
/// assert_eq!(map.remove(&1), Some("a"));
/// assert_eq!(map.remove(&1), None);
/// ```
- #[doc(alias = "delete")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
/// a.insert(1, "a");
/// assert_eq!(a.len(), 1);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
pub const fn len(&self) -> usize {
#[inline]
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
- debug_assert!(self.front.is_some());
- unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+ unsafe { self.front.as_mut().unwrap().next_unchecked() }
}
#[inline]
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
- debug_assert!(self.back.is_some());
- unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+ unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
}
}
#[inline]
pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
- debug_assert!(self.front.is_some());
- unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+ unsafe { self.front.as_mut().unwrap().next_unchecked() }
}
#[inline]
pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
- debug_assert!(self.back.is_some());
- unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+ unsafe { self.back.as_mut().unwrap().next_back_unchecked() }
}
}
/// There must be another KV in the direction travelled.
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
super::mem::replace(self, |leaf_edge| {
- let kv = leaf_edge.next_kv();
- debug_assert!(kv.is_ok());
- let kv = unsafe { kv.ok().unwrap_unchecked() };
+ let kv = leaf_edge.next_kv().ok().unwrap();
(kv.next_leaf_edge(), kv.into_kv())
})
}
/// There must be another KV in the direction travelled.
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
super::mem::replace(self, |leaf_edge| {
- let kv = leaf_edge.next_back_kv();
- debug_assert!(kv.is_ok());
- let kv = unsafe { kv.ok().unwrap_unchecked() };
+ let kv = leaf_edge.next_back_kv().ok().unwrap();
(kv.next_back_leaf_edge(), kv.into_kv())
})
}
/// There must be another KV in the direction travelled.
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = super::mem::replace(self, |leaf_edge| {
- let kv = leaf_edge.next_kv();
- debug_assert!(kv.is_ok());
- let kv = unsafe { kv.ok().unwrap_unchecked() };
+ let kv = leaf_edge.next_kv().ok().unwrap();
(unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
});
// Doing this last is faster, according to benchmarks.
/// There must be another KV in the direction travelled.
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = super::mem::replace(self, |leaf_edge| {
- let kv = leaf_edge.next_back_kv();
- debug_assert!(kv.is_ok());
- let kv = unsafe { kv.ok().unwrap_unchecked() };
+ let kv = leaf_edge.next_back_kv().ok().unwrap();
(unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
});
// Doing this last is faster, according to benchmarks.
pub unsafe fn deallocating_next_unchecked(
&mut self,
) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
- super::mem::replace(self, |leaf_edge| unsafe {
- leaf_edge.deallocating_next().unwrap_unchecked()
- })
+ super::mem::replace(self, |leaf_edge| unsafe { leaf_edge.deallocating_next().unwrap() })
}
/// Moves the leaf edge handle to the previous leaf edge and returns the key and value
&mut self,
) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
super::mem::replace(self, |leaf_edge| unsafe {
- leaf_edge.deallocating_next_back().unwrap_unchecked()
+ leaf_edge.deallocating_next_back().unwrap()
})
}
}
/// assert_eq!(set.remove(&2), true);
/// assert_eq!(set.remove(&2), false);
/// ```
- #[doc(alias = "delete")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
where
BTreeSet { map: self.map.split_off(key) }
}
- /// Creates an iterator which uses a closure to determine if a value should be removed.
+ /// Creates an iterator that visits all values in ascending order and uses a closure
+ /// to determine if a value should be removed.
///
- /// If the closure returns true, then the value is removed and yielded.
- /// If the closure returns false, the value will remain in the list and will not be yielded
- /// by the iterator.
+ /// If the closure returns `true`, the value is removed from the set and yielded. If
+ /// the closure returns `false`, or panics, the value remains in the set and will
+ /// not be yielded.
///
- /// If the iterator is only partially consumed or not consumed at all, each of the remaining
- /// values will still be subjected to the closure and removed and dropped if it returns true.
+ /// If the iterator is only partially consumed or not consumed at all, each of the
+ /// remaining values is still subjected to the closure and removed and dropped if it
+ /// returns `true`.
///
- /// It is unspecified how many more values will be subjected to the closure
- /// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the
- /// `DrainFilter` itself is leaked.
+ /// It is unspecified how many more values will be subjected to the closure if a
+ /// panic occurs in the closure, or if a panic occurs while dropping a value, or if
+ /// the `DrainFilter` itself is leaked.
///
/// # Examples
///
/// v.insert(1);
/// assert_eq!(v.len(), 1);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
pub const fn len(&self) -> usize {
/// dl.push_back(3);
/// assert_eq!(dl.len(), 3);
/// ```
- #[doc(alias = "length")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl From<LayoutError> for TryReserveError {
+ /// Always evaluates to [`TryReserveError::CapacityOverflow`].
#[inline]
fn from(_: LayoutError) -> Self {
TryReserveError::CapacityOverflow
/// v.push_back(1);
/// assert_eq!(v.len(), 1);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
count(self.tail, self.head, self.cap())
///
/// [`Vec`]: crate::vec::Vec
#[cfg(not(test))]
-#[doc(alias = "alloc")]
-#[doc(alias = "malloc")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax, liballoc_internals)]
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline]
- #[doc(alias = "alloc")]
- #[doc(alias = "malloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize) -> String {
String { vec: Vec::with_capacity(capacity) }
/// assert_eq!(fancy_f.len(), 4);
/// assert_eq!(fancy_f.chars().count(), 3);
/// ```
- #[doc(alias = "length")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline]
- #[doc(alias = "malloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_in(capacity, Global)
/// assert!(vec.capacity() >= 11);
/// ```
#[cfg(not(no_global_oom_handling))]
- #[doc(alias = "realloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
self.buf.reserve(self.len, additional);
/// assert!(vec.capacity() >= 11);
/// ```
#[cfg(not(no_global_oom_handling))]
- #[doc(alias = "realloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_exact(&mut self, additional: usize) {
self.buf.reserve_exact(self.len, additional);
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
- #[doc(alias = "realloc")]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve(self.len, additional)
/// }
/// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
/// ```
- #[doc(alias = "realloc")]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.buf.try_reserve_exact(self.len, additional)
/// assert!(vec.capacity() >= 3);
/// ```
#[cfg(not(no_global_oom_handling))]
- #[doc(alias = "realloc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn shrink_to_fit(&mut self) {
// The capacity is never less than the length, and there's nothing to do when
/// assert!(vec.capacity() >= 3);
/// ```
#[cfg(not(no_global_oom_handling))]
- #[doc(alias = "realloc")]
#[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
pub fn shrink_to(&mut self, min_capacity: usize) {
if self.capacity() > min_capacity {
/// let a = vec![1, 2, 3];
/// assert_eq!(a.len(), 3);
/// ```
- #[doc(alias = "length")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
--- /dev/null
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
+where
+ A: PartialEq<B>,
+{
+ #[inline]
+ fn eq(&self, other: &[B; N]) -> bool {
+ SpecArrayEq::spec_eq(self, other)
+ }
+ #[inline]
+ fn ne(&self, other: &[B; N]) -> bool {
+ SpecArrayEq::spec_ne(self, other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
+where
+ A: PartialEq<B>,
+{
+ #[inline]
+ fn eq(&self, other: &[B]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &[B]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
+where
+ B: PartialEq<A>,
+{
+ #[inline]
+ fn eq(&self, other: &[A; N]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &[A; N]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<&[B]> for [A; N]
+where
+ A: PartialEq<B>,
+{
+ #[inline]
+ fn eq(&self, other: &&[B]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &&[B]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for &[B]
+where
+ B: PartialEq<A>,
+{
+ #[inline]
+ fn eq(&self, other: &[A; N]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &[A; N]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<&mut [B]> for [A; N]
+where
+ A: PartialEq<B>,
+{
+ #[inline]
+ fn eq(&self, other: &&mut [B]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &&mut [B]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A, B, const N: usize> PartialEq<[A; N]> for &mut [B]
+where
+ B: PartialEq<A>,
+{
+ #[inline]
+ fn eq(&self, other: &[A; N]) -> bool {
+ self[..] == other[..]
+ }
+ #[inline]
+ fn ne(&self, other: &[A; N]) -> bool {
+ self[..] != other[..]
+ }
+}
+
+// NOTE: some less important impls are omitted to reduce code bloat
+// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
+// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Eq, const N: usize> Eq for [T; N] {}
+
+trait SpecArrayEq<Other, const N: usize>: Sized {
+ fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool;
+ fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool;
+}
+
+impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
+ default fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool {
+ a[..] == b[..]
+ }
+ default fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool {
+ a[..] != b[..]
+ }
+}
+
+impl<T: PartialEq<U> + IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T {
+ #[cfg(bootstrap)]
+ fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
+ a[..] == b[..]
+ }
+ #[cfg(not(bootstrap))]
+ fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
+ // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`.
+ unsafe {
+ let b = &*b.as_ptr().cast::<[T; N]>();
+ crate::intrinsics::raw_eq(a, b)
+ }
+ }
+ fn spec_ne(a: &[T; N], b: &[U; N]) -> bool {
+ !Self::spec_eq(a, b)
+ }
+}
+
+/// `U` exists on here mostly because `min_specialization` didn't let me
+/// repeat the `T` type parameter in the above specialization, so instead
+/// the `T == U` constraint comes from the impls on this.
+/// # Safety
+/// - Neither `Self` nor `U` has any padding.
+/// - `Self` and `U` have the same layout.
+/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things)
+#[rustc_specialization_trait]
+unsafe trait IsRawEqComparable<U> {}
+
+macro_rules! is_raw_comparable {
+ ($($t:ty),+) => {$(
+ unsafe impl IsRawEqComparable<$t> for $t {}
+ )+};
+}
+is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
use crate::ops::{Index, IndexMut};
use crate::slice::{Iter, IterMut};
+mod equality;
mod iter;
#[stable(feature = "array_value_iter", since = "1.51.0")]
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
-where
- A: PartialEq<B>,
-{
- #[inline]
- fn eq(&self, other: &[B; N]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &[B; N]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
-where
- A: PartialEq<B>,
-{
- #[inline]
- fn eq(&self, other: &[B]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &[B]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
-where
- B: PartialEq<A>,
-{
- #[inline]
- fn eq(&self, other: &[A; N]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &[A; N]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<&[B]> for [A; N]
-where
- A: PartialEq<B>,
-{
- #[inline]
- fn eq(&self, other: &&[B]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &&[B]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for &[B]
-where
- B: PartialEq<A>,
-{
- #[inline]
- fn eq(&self, other: &[A; N]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &[A; N]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<&mut [B]> for [A; N]
-where
- A: PartialEq<B>,
-{
- #[inline]
- fn eq(&self, other: &&mut [B]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &&mut [B]) -> bool {
- self[..] != other[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B, const N: usize> PartialEq<[A; N]> for &mut [B]
-where
- B: PartialEq<A>,
-{
- #[inline]
- fn eq(&self, other: &[A; N]) -> bool {
- self[..] == other[..]
- }
- #[inline]
- fn ne(&self, other: &[A; N]) -> bool {
- self[..] != other[..]
- }
-}
-
-// NOTE: some less important impls are omitted to reduce code bloat
-// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
-// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq, const N: usize> Eq for [T; N] {}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
#[inline]
/// assert_eq!(false.then_some(0), None);
/// assert_eq!(true.then_some(0), Some(0));
/// ```
- #[unstable(feature = "bool_to_option", issue = "64260")]
+ #[unstable(feature = "bool_to_option", issue = "80967")]
#[inline]
pub fn then_some<T>(self, t: T) -> Option<T> {
if self { Some(t) } else { None }
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
- /// A more user-friendly and stable version of this operation is
- /// [`std::process::abort`](../../std/process/fn.abort.html).
+ /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible,
+ /// as its behavior is more user-friendly and more stable.
+ ///
+ /// The current implementation of `intrinsics::abort` is to invoke an invalid instruction,
+ /// on most platforms.
+ /// On Unix, the
+ /// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
+ /// `SIGBUS`. The precise behaviour is not guaranteed and not stable.
pub fn abort() -> !;
/// Informs the optimizer that this point in the code is not reachable,
/// Allocate at compile time. Should not be called at runtime.
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
pub fn const_allocate(size: usize, align: usize) -> *mut u8;
+
+ /// Determines whether the raw bytes of the two values are equal.
+ ///
+ /// The is particularly handy for arrays, since it allows things like just
+ /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`.
+ ///
+ /// Above some backend-decided threshold this will emit calls to `memcmp`,
+ /// like slice equality does, instead of causing massive code size.
+ ///
+ /// # Safety
+ ///
+ /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized.
+ /// Note that this is a stricter criterion than just the *values* being
+ /// fully-initialized: if `T` has padding, it's UB to call this intrinsic.
+ ///
+ /// (The implementation is allowed to branch on the results of comparisons,
+ /// which is UB if any of their inputs are `undef`.)
+ #[cfg(not(bootstrap))]
+ #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
+ pub fn raw_eq<T>(a: &T, b: &T) -> bool;
}
// Some functions are defined here because they accidentally got made
over elements of type `{A}`",
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
)]
+#[rustc_diagnostic_item = "FromIterator"]
pub trait FromIterator<A>: Sized {
/// Creates a value from an iterator.
///
type Item = I::Item;
type IntoIter = I;
+ #[inline]
fn into_iter(self) -> I {
self
}
///
/// assert_eq!(5, five.len());
/// ```
- #[doc(alias = "length")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn len(&self) -> usize {
/// // we can still use `iter`, as there are more elements.
/// assert_eq!(iter.next(), Some(&3));
/// ```
- #[doc(alias = "every")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn all<F>(&mut self, f: F) -> bool
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(no_coverage)] // rust-lang/rust#84605
#![deny(unsafe_op_in_unsafe_fn)]
-#![deny(or_patterns_back_compat)]
+#![cfg_attr(bootstrap, deny(or_patterns_back_compat))]
+#![cfg_attr(not(bootstrap), deny(rust_2021_incompatible_or_patterns))]
// allow using `core::` in intra-doc links
#[allow(unused_extern_crates)]
/// [ub]: ../../reference/behavior-considered-undefined.html
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
-#[lang = "send"]
#[rustc_on_unimplemented(
message = "`{Self}` cannot be sent between threads safely",
label = "`{Self}` cannot be sent between threads safely"
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
/// let mut x = MaybeUninit::<&i32>::uninit();
/// // Set it to a valid value.
-/// unsafe { x.as_mut_ptr().write(&0); }
+/// x.write(&0);
/// // Extract the initialized data -- this is only allowed *after* properly
/// // initializing `x`!
/// let x = unsafe { x.assume_init() };
/// // this loop, we have a memory leak, but there is no memory safety
/// // issue.
/// for elem in &mut data[..] {
-/// *elem = MaybeUninit::new(vec![42]);
+/// elem.write(vec![42]);
/// }
///
/// // Everything is initialized. Transmute the array to the
/// let mut data_len: usize = 0;
///
/// for elem in &mut data[0..500] {
-/// *elem = MaybeUninit::new(String::from("hello"));
+/// elem.write(String::from("hello"));
/// data_len += 1;
/// }
///
/// (now safely initialized) contents of `self`.
///
/// As the content is stored inside a `MaybeUninit`, the destructor is not
- /// ran for the inner data if the MaybeUninit leaves scope without a call to
+ /// run for the inner data if the MaybeUninit leaves scope without a call to
/// [`assume_init`], [`assume_init_drop`], or similar. Code that receives
/// the mutable reference returned by this function needs to keep this in
/// mind. The safety model of Rust regards leaks as safe, but they are
/// Correct usage of this method:
///
/// ```rust
- /// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u8>>::uninit();
/// This usage of the method causes a leak:
///
/// ```rust
- /// #![feature(maybe_uninit_extra)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<String>::uninit();
/// // x is initialized now:
/// let s = unsafe { x.assume_init() };
/// ```
- #[unstable(feature = "maybe_uninit_extra", issue = "63567")]
- #[rustc_const_unstable(feature = "maybe_uninit_extra", issue = "63567")]
+ ///
+ /// This method can be used to avoid unsafe in some cases. The example below
+ /// shows a part of an implementation of a fixed sized arena that lends out
+ /// pinned references.
+ /// With `write`, we can avoid the need to write through a raw pointer:
+ ///
+ /// ```rust
+ /// #![feature(maybe_uninit_extra)]
+ /// use core::pin::Pin;
+ /// use core::mem::MaybeUninit;
+ ///
+ /// struct PinArena<T> {
+ /// memory: Box<[MaybeUninit<T>]>,
+ /// len: usize,
+ /// }
+ ///
+ /// impl <T> PinArena<T> {
+ /// pub fn capacity(&self) -> usize {
+ /// self.memory.len()
+ /// }
+ /// pub fn push(&mut self, val: T) -> Pin<&mut T> {
+ /// if self.len >= self.capacity() {
+ /// panic!("Attempted to push to a full pin arena!");
+ /// }
+ /// let ref_ = self.memory[self.len].write(val);
+ /// self.len += 1;
+ /// unsafe { Pin::new_unchecked(ref_) }
+ /// }
+ /// }
+ /// ```
+ #[stable(feature = "maybe_uninit_write", since = "1.55.0")]
+ #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")]
#[inline(always)]
pub const fn write(&mut self, val: T) -> &mut T {
*self = MaybeUninit::new(val);
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
- /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
+ /// x.write(vec![0, 1, 2]);
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
/// let x_vec = unsafe { &*x.as_ptr() };
/// assert_eq!(x_vec.len(), 3);
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
- /// unsafe { x.as_mut_ptr().write(vec![0, 1, 2]); }
+ /// x.write(vec![0, 1, 2]);
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
/// // This is okay because we initialized it.
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<bool>::uninit();
- /// unsafe { x.as_mut_ptr().write(true); }
+ /// x.write(true);
/// let x_init = unsafe { x.assume_init() };
/// assert_eq!(x_init, true);
/// ```
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// // Initialize `x`:
- /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
+ /// x.write(vec![1, 2, 3]);
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
/// // create a shared reference to it:
/// let x: &Vec<u32> = unsafe {
/// use std::mem::MaybeUninit;
///
/// let mut array: [MaybeUninit<i32>; 3] = MaybeUninit::uninit_array();
- /// array[0] = MaybeUninit::new(0);
- /// array[1] = MaybeUninit::new(1);
- /// array[2] = MaybeUninit::new(2);
+ /// array[0].write(0);
+ /// array[1].write(1);
+ /// array[2].write(2);
///
/// // SAFETY: Now safe as we initialised all elements
/// let array = unsafe {
--- /dev/null
+mod unchecked {
+ // 0 < val <= u8::MAX
+ pub const fn u8(val: u8) -> u32 {
+ if val >= 100 {
+ 2
+ } else if val >= 10 {
+ 1
+ } else {
+ 0
+ }
+ }
+
+ // 0 < val <= u16::MAX
+ pub const fn u16(val: u16) -> u32 {
+ if val >= 10_000 {
+ 4
+ } else if val >= 1000 {
+ 3
+ } else if val >= 100 {
+ 2
+ } else if val >= 10 {
+ 1
+ } else {
+ 0
+ }
+ }
+
+ // 0 < val < 100_000_000
+ const fn less_than_8(mut val: u32) -> u32 {
+ let mut log = 0;
+ if val >= 10_000 {
+ val /= 10_000;
+ log += 4;
+ }
+ log + if val >= 1000 {
+ 3
+ } else if val >= 100 {
+ 2
+ } else if val >= 10 {
+ 1
+ } else {
+ 0
+ }
+ }
+
+ // 0 < val <= u32::MAX
+ pub const fn u32(mut val: u32) -> u32 {
+ let mut log = 0;
+ if val >= 100_000_000 {
+ val /= 100_000_000;
+ log += 8;
+ }
+ log + less_than_8(val)
+ }
+
+ // 0 < val < 10_000_000_000_000_000
+ const fn less_than_16(mut val: u64) -> u32 {
+ let mut log = 0;
+ if val >= 100_000_000 {
+ val /= 100_000_000;
+ log += 8;
+ }
+ log + less_than_8(val as u32)
+ }
+
+ // 0 < val <= u64::MAX
+ pub const fn u64(mut val: u64) -> u32 {
+ let mut log = 0;
+ if val >= 10_000_000_000_000_000 {
+ val /= 10_000_000_000_000_000;
+ log += 16;
+ }
+ log + less_than_16(val)
+ }
+
+ // 0 < val <= u128::MAX
+ pub const fn u128(mut val: u128) -> u32 {
+ let mut log = 0;
+ if val >= 100_000_000_000_000_000_000_000_000_000_000 {
+ val /= 100_000_000_000_000_000_000_000_000_000_000;
+ log += 32;
+ return log + less_than_8(val as u32);
+ }
+ if val >= 10_000_000_000_000_000 {
+ val /= 10_000_000_000_000_000;
+ log += 16;
+ }
+ log + less_than_16(val as u64)
+ }
+
+ // 0 < val <= i8::MAX
+ pub const fn i8(val: i8) -> u32 {
+ u8(val as u8)
+ }
+
+ // 0 < val <= i16::MAX
+ pub const fn i16(val: i16) -> u32 {
+ u16(val as u16)
+ }
+
+ // 0 < val <= i32::MAX
+ pub const fn i32(val: i32) -> u32 {
+ u32(val as u32)
+ }
+
+ // 0 < val <= i64::MAX
+ pub const fn i64(val: i64) -> u32 {
+ u64(val as u64)
+ }
+
+ // 0 < val <= i128::MAX
+ pub const fn i128(val: i128) -> u32 {
+ u128(val as u128)
+ }
+}
+
+macro_rules! impl_checked {
+ ($T:ident) => {
+ pub const fn $T(val: $T) -> Option<$T> {
+ if val > 0 { Some(unchecked::$T(val) as $T) } else { None }
+ }
+ };
+}
+
+impl_checked! { u8 }
+impl_checked! { u16 }
+impl_checked! { u32 }
+impl_checked! { u64 }
+impl_checked! { u128 }
+impl_checked! { i8 }
+impl_checked! { i16 }
+impl_checked! { i32 }
+impl_checked! { i64 }
+impl_checked! { i128 }
}
}
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// This method may not be optimized owing to implementation details;
+ /// `log2` can produce results more efficiently for base 2, and `log10`
+ /// can produce results more efficiently for base 10.
+ ///
+ /// # Panics
+ ///
+ /// When the number is zero, or if the base is not at least 2; it
+ /// panics in debug mode and the return value is wrapped to 0 in release
+ /// mode (the only situation in which the method can return 0).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log(self, base: Self) -> Self {
+ match self.checked_log(base) {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// # Panics
+ ///
+ /// When the number is zero it panics in debug mode and the return value
+ /// is wrapped to 0 in release mode (the only situation in which the
+ /// method can return 0).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log2(self) -> Self {
+ match self.checked_log2() {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// # Panics
+ ///
+ /// When the number is zero it panics in debug mode and the return value
+ /// is wrapped to 0 in release mode (the only situation in which the
+ /// method can return 0).
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log10(self) -> Self {
+ match self.checked_log10() {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// Returns `None` if the number is negative or zero, or if the base is not at least 2.
+ ///
+ /// This method may not be optimized owing to implementation details;
+ /// `checked_log2` can produce results more efficiently for base 2, and
+ /// `checked_log10` can produce results more efficiently for base 10.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log(self, base: Self) -> Option<Self> {
+ if self <= 0 || base <= 1 {
+ None
+ } else {
+ let mut n = 0;
+ let mut r = self;
+
+ // Optimization for 128 bit wide integers.
+ if Self::BITS == 128 {
+ let b = Self::log2(self) / (Self::log2(base) + 1);
+ n += b;
+ r /= base.pow(b as u32);
+ }
+
+ while r >= base {
+ r /= base;
+ n += 1;
+ }
+ Some(n)
+ }
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// Returns `None` if the number is negative or zero.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log2(self) -> Option<Self> {
+ if self <= 0 {
+ None
+ } else {
+ // SAFETY: We just checked that this number is positive
+ let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+ Some(log)
+ }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// Returns `None` if the number is negative or zero.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log10(self) -> Option<Self> {
+ match int_log10::$ActualT(self as $ActualT) {
+ Some(s) => Some(s as Self),
+ None => None,
+ }
+ }
+
/// Computes the absolute value of `self`.
///
/// # Overflow behavior
mod uint_macros; // import uint_impl!
mod error;
+mod int_log10;
mod nonzero;
mod wrapping;
macro_rules! uint_impl {
- ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr,
+ ($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr,
$rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
$reversed:expr, $le_bytes:expr, $be_bytes:expr,
$to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
}
}
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// This method may not be optimized owing to implementation details;
+ /// `log2` can produce results more efficiently for base 2, and `log10`
+ /// can produce results more efficiently for base 10.
+ ///
+ /// # Panics
+ ///
+ /// When the number is negative, zero, or if the base is not at least 2;
+ /// it panics in debug mode and the return value is wrapped to 0 in
+ /// release mode (the only situation in which the method can return 0).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".log(5), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log(self, base: Self) -> Self {
+ match self.checked_log(base) {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// # Panics
+ ///
+ /// When the number is negative or zero it panics in debug mode and
+ /// the return value is wrapped to 0 in release mode (the only situation in
+ /// which the method can return 0).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".log2(), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log2(self) -> Self {
+ match self.checked_log2() {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// # Panics
+ ///
+ /// When the number is negative or zero it panics in debug mode and the
+ /// return value is wrapped to 0 in release mode (the only situation in
+ /// which the method can return 0).
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".log10(), 1);")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[track_caller]
+ #[rustc_inherit_overflow_checks]
+ #[allow(arithmetic_overflow)]
+ pub const fn log10(self) -> Self {
+ match self.checked_log10() {
+ Some(n) => n,
+ None => {
+ // In debug builds, trigger a panic on None.
+ // This should optimize completely out in release builds.
+ let _ = Self::MAX + 1;
+
+ 0
+ },
+ }
+ }
+
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// Returns `None` if the number is zero, or if the base is not at least 2.
+ ///
+ /// This method may not be optimized owing to implementation details;
+ /// `checked_log2` can produce results more efficiently for base 2, and
+ /// `checked_log10` can produce results more efficiently for base 10.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_log(5), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log(self, base: Self) -> Option<Self> {
+ if self <= 0 || base <= 1 {
+ None
+ } else {
+ let mut n = 0;
+ let mut r = self;
+
+ // Optimization for 128 bit wide integers.
+ if Self::BITS == 128 {
+ let b = Self::log2(self) / (Self::log2(base) + 1);
+ n += b;
+ r /= base.pow(b as u32);
+ }
+
+ while r >= base {
+ r /= base;
+ n += 1;
+ }
+ Some(n)
+ }
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// Returns `None` if the number is zero.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_log2(), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log2(self) -> Option<Self> {
+ if self <= 0 {
+ None
+ } else {
+ // SAFETY: We just checked that this number is positive
+ let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+ Some(log)
+ }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// Returns `None` if the number is zero.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(int_log)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_log10(), Some(1));")]
+ /// ```
+ #[unstable(feature = "int_log", issue = "70887")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_log10(self) -> Option<Self> {
+ match int_log10::$ActualT(self as $ActualT) {
+ Some(s) => Some(s as Self),
+ None => None,
+ }
+ }
+
/// Checked negation. Computes `-self`, returning `None` unless `self ==
/// 0`.
///
/// This destructor consists of two components:
/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type.
/// - The automatically generated "drop glue" which recursively calls the destructors
-/// of the all fields of this value.
+/// of all the fields of this value.
///
/// As Rust automatically calls the destructors of all contained fields,
/// you don't have to implement `Drop` in most cases. But there are some cases where
#[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
- let end = match start.checked_add(self.chunk_size) {
- None => self.v.len(),
- Some(end) => cmp::min(end, self.v.len()),
- };
// SAFETY: the caller guarantees that `i` is in bounds,
// which means that `start` must be in bounds of the
- // underlying `self.v` slice, and we made sure that `end`
+ // underlying `self.v` slice, and we made sure that `len`
// is also in bounds of `self.v`. Thus, `start` cannot overflow
// an `isize`, and the slice constructed by `from_raw_parts`
// is a subslice of `self.v` which is guaranteed to be valid
// for the lifetime `'a` of `self.v`.
- unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
+ unsafe {
+ let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
+ from_raw_parts(self.v.as_ptr().add(start), len)
+ }
}
}
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
- Some(res) => cmp::min(res, self.v.len()),
+ Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
let nth_back = &self.v[start..end];
#[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
- let end = match start.checked_add(self.chunk_size) {
- None => self.v.len(),
- Some(end) => cmp::min(end, self.v.len()),
- };
// SAFETY: see comments for `Chunks::__iterator_get_unchecked`.
//
// Also note that the caller also guarantees that we're never called
// with the same index again, and that no other methods that will
// access this subslice are called, so it is valid for the returned
// slice to be mutable.
- unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
+ unsafe {
+ let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
+ from_raw_parts_mut(self.v.as_mut_ptr().add(start), len)
+ }
}
}
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
- Some(res) => cmp::min(res, self.v.len()),
+ Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
/// let a = [1, 2, 3];
/// assert_eq!(a.len(), 3);
/// ```
- #[doc(alias = "length")]
#[cfg_attr(not(bootstrap), lang = "slice_len_fn")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
/// assert_eq!("ƒoo".len(), 4); // fancy f!
/// assert_eq!("ƒoo".chars().count(), 3);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
#[inline]
///
/// pub fn lock(&self) {
/// // Wait until the old value is `false`.
-/// while self.flag.compare_and_swap(false, true, Ordering::Relaxed) != false {}
+/// while self
+/// .flag
+/// .compare_exchange_weak(false, true, Ordering::Relaxed, Ordering::Relaxed)
+/// .is_err()
+/// {}
/// // This fence synchronizes-with store in `unlock`.
/// fence(Ordering::Acquire);
/// }
/// Without `compiler_fence`, the `assert_eq!` in following code
/// is *not* guaranteed to succeed, despite everything happening in a single thread.
/// To see why, remember that the compiler is free to swap the stores to
-/// `IMPORTANT_VARIABLE` and `IS_READ` since they are both
+/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both
/// `Ordering::Relaxed`. If it does, and the signal handler is invoked right
/// after `IS_READY` is updated, then the signal handler will see
/// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`.
#![feature(try_trait_v2)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
+#![feature(int_log)]
#![feature(iter_advance_by)]
#![feature(iter_partition_in_place)]
#![feature(iter_intersperse)]
#[test]
fn smoke() {
+ #[derive(Clone)]
struct TypeWithDrop;
impl Drop for TypeWithDrop {
fn drop(&mut self) {
let x: Box<ManuallyDrop<[TypeWithDrop]>> =
Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
drop(x);
+
+ // test clone and clone_from implementations
+ let mut x = ManuallyDrop::new(TypeWithDrop);
+ let y = x.clone();
+ x.clone_from(&y);
+ drop(x);
+ drop(y);
}
--- /dev/null
+//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a
+//! separate file because there's both a large number of them, and not all tests
+//! can be run on Android. This is because in Android `log2` uses an imprecise
+//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53
+
+#[test]
+fn checked_log() {
+ assert_eq!(999u32.checked_log(10), Some(2));
+ assert_eq!(1000u32.checked_log(10), Some(3));
+ assert_eq!(555u32.checked_log(13), Some(2));
+ assert_eq!(63u32.checked_log(4), Some(2));
+ assert_eq!(64u32.checked_log(4), Some(3));
+ assert_eq!(10460353203u64.checked_log(3), Some(21));
+ assert_eq!(10460353202u64.checked_log(3), Some(20));
+ assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80));
+ assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79));
+ assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8));
+ assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7));
+
+ assert_eq!(0u8.checked_log(4), None);
+ assert_eq!(0u16.checked_log(4), None);
+ assert_eq!(0i8.checked_log(4), None);
+ assert_eq!(0i16.checked_log(4), None);
+
+ for i in i16::MIN..=0 {
+ assert_eq!(i.checked_log(4), None);
+ }
+ for i in 1..=i16::MAX {
+ assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+ }
+ for i in 1..=u16::MAX {
+ assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+ }
+}
+
+#[test]
+fn checked_log2() {
+ assert_eq!(5u32.checked_log2(), Some(2));
+ assert_eq!(0u64.checked_log2(), None);
+ assert_eq!(128i32.checked_log2(), Some(7));
+ assert_eq!((-55i16).checked_log2(), None);
+
+ assert_eq!(0u8.checked_log2(), None);
+ assert_eq!(0u16.checked_log2(), None);
+ assert_eq!(0i8.checked_log2(), None);
+ assert_eq!(0i16.checked_log2(), None);
+
+ for i in 1..=u8::MAX {
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+ }
+ for i in 1..=u16::MAX {
+ // Guard against Android's imprecise f32::log2 implementation.
+ if i != 8192 && i != 32768 {
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+ }
+ }
+ for i in i8::MIN..=0 {
+ assert_eq!(i.checked_log2(), None);
+ }
+ for i in 1..=i8::MAX {
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+ }
+ for i in i16::MIN..=0 {
+ assert_eq!(i.checked_log2(), None);
+ }
+ for i in 1..=i16::MAX {
+ // Guard against Android's imprecise f32::log2 implementation.
+ if i != 8192 {
+ assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+ }
+ }
+}
+
+// Validate cases that fail on Android's imprecise float log2 implementation.
+#[test]
+#[cfg(not(target_os = "android"))]
+fn checked_log2_not_android() {
+ assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
+ assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
+ assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+}
+
+#[test]
+fn checked_log10() {
+ assert_eq!(0u8.checked_log10(), None);
+ assert_eq!(0u16.checked_log10(), None);
+ assert_eq!(0i8.checked_log10(), None);
+ assert_eq!(0i16.checked_log10(), None);
+
+ for i in i16::MIN..=0 {
+ assert_eq!(i.checked_log10(), None);
+ }
+ for i in 1..=i16::MAX {
+ assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+ }
+ for i in 1..=u16::MAX {
+ assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+ }
+}
+
+macro_rules! log10_loop {
+ ($T:ty, $log10_max:expr) => {
+ assert_eq!(<$T>::MAX.log10(), $log10_max);
+ for i in 0..=$log10_max {
+ let p = (10 as $T).pow(i as u32);
+ if p >= 10 {
+ assert_eq!((p - 9).log10(), i - 1);
+ assert_eq!((p - 1).log10(), i - 1);
+ }
+ assert_eq!(p.log10(), i);
+ assert_eq!((p + 1).log10(), i);
+ if p >= 10 {
+ assert_eq!((p + 9).log10(), i);
+ }
+
+ // also check `x.log(10)`
+ if p >= 10 {
+ assert_eq!((p - 9).log(10), i - 1);
+ assert_eq!((p - 1).log(10), i - 1);
+ }
+ assert_eq!(p.log(10), i);
+ assert_eq!((p + 1).log(10), i);
+ if p >= 10 {
+ assert_eq!((p + 9).log(10), i);
+ }
+ }
+ };
+}
+
+#[test]
+fn log10_u8() {
+ log10_loop! { u8, 2 }
+}
+
+#[test]
+fn log10_u16() {
+ log10_loop! { u16, 4 }
+}
+
+#[test]
+fn log10_u32() {
+ log10_loop! { u32, 9 }
+}
+
+#[test]
+fn log10_u64() {
+ log10_loop! { u64, 19 }
+}
+
+#[test]
+fn log10_u128() {
+ log10_loop! { u128, 38 }
+}
mod bignum;
mod dec2flt;
mod flt2dec;
+mod int_log;
mod ops;
mod wrapping;
/// a.insert(1, "a");
/// assert_eq!(a.len(), 1);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
self.base.len()
/// assert_eq!(map.remove(&1), Some("a"));
/// assert_eq!(map.remove(&1), None);
/// ```
- #[doc(alias = "delete")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
/// v.insert(1);
/// assert_eq!(v.len(), 1);
/// ```
- #[doc(alias = "length")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
/// assert_eq!(set.remove(&2), true);
/// assert_eq!(set.remove(&2), false);
/// ```
- #[doc(alias = "delete")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
/// Returns the square root of a number.
///
- /// Returns NaN if `self` is a negative number.
+ /// Returns NaN if `self` is a negative number other than `-0.0`.
///
/// # Examples
///
/// ```
/// let positive = 4.0_f32;
/// let negative = -4.0_f32;
+ /// let negative_zero = -0.0_f32;
///
/// let abs_difference = (positive.sqrt() - 2.0).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// assert!(negative.sqrt().is_nan());
+ /// assert!(negative_zero.sqrt() == negative_zero);
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
/// Returns the square root of a number.
///
- /// Returns NaN if `self` is a negative number.
+ /// Returns NaN if `self` is a negative number other than `-0.0`.
///
/// # Examples
///
/// ```
/// let positive = 4.0_f64;
/// let negative = -4.0_f64;
+ /// let negative_zero = -0.0_f64;
///
/// let abs_difference = (positive.sqrt() - 2.0).abs();
///
/// assert!(abs_difference < 1e-10);
/// assert!(negative.sqrt().is_nan());
+ /// assert!(negative_zero.sqrt() == negative_zero);
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
/// let os_str = OsStr::new("foo");
/// assert_eq!(os_str.len(), 3);
/// ```
- #[doc(alias = "length")]
#[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn len(&self) -> usize {
/// Ok(())
/// }
/// ```
-#[doc(alias = "delete")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs_imp::unlink(path.as_ref())
///
/// # Platform-specific behavior
///
-/// This function currently corresponds to the `linkat` function with no flags
-/// on Unix and the `CreateHardLink` function on Windows.
+/// This function currently corresponds the `CreateHardLink` function on Windows.
+/// On most Unix systems, it corresponds to the `linkat` function with no flags.
+/// On Android, VxWorks, and Redox, it instead corresponds to the `link` function.
+/// On MacOS, it uses the `linkat` function if it is available, but on very old
+/// systems where `linkat` is not available, `link` is selected at runtime instead.
/// Note that, this [may change in the future][changes].
///
/// [changes]: io#platform-specific-behavior
/// Ok(())
/// }
/// ```
-#[doc(alias = "delete")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs_imp::rmdir(path.as_ref())
/// Ok(())
/// }
/// ```
-#[doc(alias = "delete")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs_imp::remove_dir_all(path.as_ref())
use crate::os::windows::fs::{symlink_dir, symlink_file};
#[cfg(windows)]
use crate::sys::fs::symlink_junction;
+#[cfg(target_os = "macos")]
+use crate::sys::weak::weak;
+#[cfg(target_os = "macos")]
+use libc::{c_char, c_int};
macro_rules! check {
($e:expr) => {
}
}
+#[cfg(target_os = "macos")]
+fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
+ weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
+ linkat.get().is_some()
+}
+
+#[cfg(not(target_os = "macos"))]
+fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
+ return true;
+}
+
#[test]
fn file_test_io_smoke_test() {
let message = "it's alright. have a good time";
if !got_symlink_permission(&tmpdir) {
return;
};
+ if !able_to_not_follow_symlinks_while_hard_linking() {
+ return;
+ }
// Create "file", a file.
check!(fs::File::create(tmpdir.join("file")));
where
T: AsRef<[u8]>,
{
- /// Returns the remaining length.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(cursor_remaining)]
- /// use std::io::Cursor;
- ///
- /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
- ///
- /// assert_eq!(buff.remaining(), 5);
- ///
- /// buff.set_position(2);
- /// assert_eq!(buff.remaining(), 3);
- ///
- /// buff.set_position(4);
- /// assert_eq!(buff.remaining(), 1);
- ///
- /// buff.set_position(6);
- /// assert_eq!(buff.remaining(), 0);
- /// ```
- #[unstable(feature = "cursor_remaining", issue = "86369")]
- pub fn remaining(&self) -> u64 {
- (self.inner.as_ref().len() as u64).checked_sub(self.pos).unwrap_or(0)
- }
-
/// Returns the remaining slice.
///
/// # Examples
pub use self::stdio::set_output_capture;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{stderr, stdin, stdout, Stderr, Stdin, Stdout};
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
pub use self::stdio::{stderr_locked, stdin_locked, stdout_locked};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
/// # Example
///
/// ```no_run
- /// #![feature(seek_rewind)]
/// use std::io::{Read, Seek, Write};
/// use std::fs::OpenOptions;
///
/// f.read_to_string(&mut buf).unwrap();
/// assert_eq!(&buf, hello);
/// ```
- #[unstable(feature = "seek_rewind", issue = "85149")]
+ #[stable(feature = "seek_rewind", since = "1.55.0")]
fn rewind(&mut self) -> Result<()> {
self.seek(SeekFrom::Start(0))?;
Ok(())
/// Ok(())
/// }
/// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stdin_locked() -> StdinLock<'static> {
stdin().into_locked()
}
/// Ok(())
/// }
/// ```
- #[unstable(feature = "stdio_locked", issue = "none")]
+ #[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StdinLock<'static> {
self.lock_any()
}
/// Ok(())
/// }
/// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stdout_locked() -> StdoutLock<'static> {
stdout().into_locked()
}
/// Ok(())
/// }
/// ```
- #[unstable(feature = "stdio_locked", issue = "none")]
+ #[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StdoutLock<'static> {
self.lock_any()
}
/// Ok(())
/// }
/// ```
-#[unstable(feature = "stdio_locked", issue = "none")]
+#[unstable(feature = "stdio_locked", issue = "86845")]
pub fn stderr_locked() -> StderrLock<'static> {
stderr().into_locked()
}
/// Ok(())
/// }
/// ```
- #[unstable(feature = "stdio_locked", issue = "none")]
+ #[unstable(feature = "stdio_locked", issue = "86845")]
pub fn into_locked(self) -> StderrLock<'static> {
self.lock_any()
}
assert_eq!(c.stream_position()?, 8);
assert_eq!(c.stream_position()?, 8);
+ c.rewind()?;
+ assert_eq!(c.stream_position()?, 0);
+ assert_eq!(c.stream_position()?, 0);
+
Ok(())
}
#![feature(hashmap_internals)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]
+#![feature(int_log)]
#![feature(into_future)]
#![feature(intra_doc_pointers)]
#![feature(iter_zip)]
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
// Used for `File::read` on intra-doc links
+use crate::ffi::OsStr;
+use crate::sealed::Sealed;
#[allow(unused_imports)]
use io::{Read, Write};
}
}
+/// Sealed Unix-specific extension methods for [`fs::DirEntry`].
+#[unstable(feature = "dir_entry_ext2", issue = "85573")]
+pub trait DirEntryExt2: Sealed {
+ /// Returns a reference to the underlying `OsStr` of this entry's filename.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(dir_entry_ext2)]
+ /// use std::os::unix::fs::DirEntryExt2;
+ /// use std::{fs, io};
+ ///
+ /// fn main() -> io::Result<()> {
+ /// let mut entries = fs::read_dir(".")?.collect::<Result<Vec<_>, io::Error>>()?;
+ /// entries.sort_unstable_by(|a, b| a.file_name_ref().cmp(b.file_name_ref()));
+ ///
+ /// for p in entries {
+ /// println!("{:?}", p);
+ /// }
+ ///
+ /// Ok(())
+ /// }
+ /// ```
+ fn file_name_ref(&self) -> &OsStr;
+}
+
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for fs::DirEntry {}
+
+#[unstable(feature = "dir_entry_ext2", issue = "85573")]
+impl DirEntryExt2 for fs::DirEntry {
+ fn file_name_ref(&self) -> &OsStr {
+ self.as_inner().file_name_os_str()
+ }
+}
+
/// Creates a new symbolic link on the filesystem.
///
/// The `link` path will be a symbolic link pointing to the `original` path.
#![stable(feature = "process_extensions", since = "1.2.0")]
+use crate::ffi::OsStr;
use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
use crate::process;
use crate::sealed::Sealed;
/// [2]: <https://msdn.microsoft.com/en-us/library/17w5ykft.aspx>
#[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")]
fn force_quotes(&mut self, enabled: bool) -> &mut process::Command;
+
+ /// Append literal text to the command line without any quoting or escaping.
+ ///
+ /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
+ /// `CommandLineToArgvW` escaping rules.
+ #[unstable(feature = "windows_process_extensions_raw_arg", issue = "29494")]
+ fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;
}
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
self.as_inner_mut().force_quotes(enabled);
self
}
+
+ fn raw_arg<S: AsRef<OsStr>>(&mut self, raw_text: S) -> &mut process::Command {
+ self.as_inner_mut().raw_arg(raw_text.as_ref());
+ self
+ }
}
/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be
/// implemented for any closed over variables passed to `catch_unwind`.
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[cfg_attr(not(test), lang = "unwind_safe")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")]
#[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"
/// This is a "helper marker trait" used to provide impl blocks for the
/// [`UnwindSafe`] trait, for more information see that documentation.
#[stable(feature = "catch_unwind", since = "1.9.0")]
-#[cfg_attr(not(test), lang = "ref_unwind_safe")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")]
#[rustc_on_unimplemented(
message = "the type `{Self}` may contain interior mutability and a reference may not be safely \
transferrable across a catch_unwind boundary",
/// process, no destructors on the current stack or any other thread's stack
/// will be run.
///
+/// Rust IO buffers (eg, from `BufWriter`) will not be flushed.
+/// Likewise, C stdio buffers will (on most platforms) not be flushed.
+///
/// This is in contrast to the default behaviour of [`panic!`] which unwinds
/// the current thread's stack and calls all destructors.
/// When `panic="abort"` is set, either as an argument to `rustc` or in a
/// this function at a known point where there are no more destructors left
/// to run.
///
+/// The process's termination will be similar to that from the C `abort()`
+/// function. On Unix, the process will terminate with signal `SIGABRT`, which
+/// typically means that the shell prints "Aborted".
+///
/// # Examples
///
/// ```no_run
use libc::{c_int, c_void, sighandler_t, size_t, ssize_t};
use libc::{ftruncate, pread, pwrite};
-use super::{cvt, cvt_r};
+use super::{cvt, cvt_r, weak::weak};
use crate::io;
// The `log2` and `log2f` functions apparently appeared in android-18, or at
use crate::sys::{cvt, cvt_r};
use crate::sys_common::{AsInner, FromInner};
+#[cfg(any(
+ all(target_os = "linux", target_env = "gnu"),
+ target_os = "macos",
+ target_os = "ios",
+))]
+use crate::sys::weak::syscall;
+#[cfg(target_os = "macos")]
+use crate::sys::weak::weak;
+
use libc::{c_int, mode_t};
+#[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ all(target_os = "linux", target_env = "gnu")
+))]
+use libc::c_char;
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
use libc::dirfd;
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
// Default `stat64` contains no creation time.
unsafe fn try_statx(
fd: c_int,
- path: *const libc::c_char,
+ path: *const c_char,
flags: i32,
mask: u32,
) -> Option<io::Result<FileAttr>> {
syscall! {
fn statx(
fd: c_int,
- pathname: *const libc::c_char,
+ pathname: *const c_char,
flags: c_int,
mask: libc::c_uint,
statxbuf: *mut libc::statx
fn name_bytes(&self) -> &[u8] {
&*self.name
}
+
+ pub fn file_name_os_str(&self) -> &OsStr {
+ OsStr::from_bytes(self.name_bytes())
+ }
}
impl OpenOptions {
cfg_has_statx! {
if let Some(ret) = unsafe { try_statx(
fd,
- b"\0" as *const _ as *const libc::c_char,
+ b"\0" as *const _ as *const c_char,
libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
let link = cstr(link)?;
cfg_if::cfg_if! {
if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
- // VxWorks, Redox, and old versions of Android lack `linkat`, so use
- // `link` instead. POSIX leaves it implementation-defined whether
- // `link` follows symlinks, so rely on the `symlink_hard_link` test
- // in library/std/src/fs/tests.rs to check the behavior.
+ // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves
+ // it implementation-defined whether `link` follows symlinks, so rely on the
+ // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
+ // Android has `linkat` on newer versions, but we happen to know `link`
+ // always has the correct behavior, so it's here as well.
cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+ } else if #[cfg(target_os = "macos")] {
+ // On MacOS, older versions (<=10.9) lack support for linkat while newer
+ // versions have it. We want to use linkat if it is available, so we use weak!
+ // to check. `linkat` is preferable to `link` ecause it gives us a flag to
+ // specify how symlinks should be handled. We pass 0 as the flags argument,
+ // meaning it shouldn't follow symlinks.
+ weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
+
+ if let Some(f) = linkat.get() {
+ cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+ } else {
+ cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+ };
} else {
- // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
- // us a flag to specify how symlinks should be handled. Pass 0 as
- // the flags argument, meaning don't follow symlinks.
+ // Where we can, use `linkat` instead of `link`; see the comment above
+ // this one for details on why.
cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
}
}
fn fclonefileat(
srcfd: libc::c_int,
dst_dirfd: libc::c_int,
- dst: *const libc::c_char,
+ dst: *const c_char,
flags: libc::c_int
) -> libc::c_int
}
use crate::ptr;
use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use crate::sys::cvt;
+use crate::sys::weak::syscall;
use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
#[cfg(test)]
if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
}
-// On Unix-like platforms, libc::abort will unregister signal handlers
-// including the SIGABRT handler, preventing the abort from being blocked, and
-// fclose streams, with the side effect of flushing them so libc buffered
-// output will be printed. Additionally the shell will generally print a more
-// understandable error message like "Abort trap" rather than "Illegal
-// instruction" that intrinsics::abort would cause, as intrinsics::abort is
-// implemented as an illegal instruction.
+// libc::abort() will run the SIGABRT handler. That's fine because anyone who
+// installs a SIGABRT handler already has to expect it to run in Very Bad
+// situations (eg, malloc crashing).
+//
+// Current glibc's abort() function unblocks SIGABRT, raises SIGABRT, clears the
+// SIGABRT handler and raises it again, and then starts to get creative.
+//
+// See the public documentation for `intrinsics::abort()` and `process::abort()`
+// for further discussion.
+//
+// There is confusion about whether libc::abort() flushes stdio streams.
+// libc::abort() is required by ISO C 99 (7.14.1.1p5) to be async-signal-safe,
+// so flushing streams is at least extremely hard, if not entirely impossible.
+//
+// However, some versions of POSIX (eg IEEE Std 1003.1-2001) required abort to
+// do so. In 1003.1-2004 this was fixed.
+//
+// glibc's implementation did the flush, unsafely, before glibc commit
+// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian
+// Weimer. According to glibc's NEWS:
+//
+// The abort function terminates the process immediately, without flushing
+// stdio streams. Previous glibc versions used to flush streams, resulting
+// in deadlocks and further data corruption. This change also affects
+// process aborts as the result of assertion failures.
+//
+// This is an accurate description of the problem. The only solution for
+// program with nontrivial use of C stdio is a fixed libc - one which does not
+// try to flush in abort - since even libc-internal errors, and assertion
+// failures generated from C, will go via abort().
+//
+// On systems with old, buggy, libcs, the impact can be severe for a
+// multithreaded C program. It is much less severe for Rust, because Rust
+// stdlib doesn't use libc stdio buffering. In a typical Rust program, which
+// does not use C stdio, even a buggy libc::abort() is, in fact, safe.
pub fn abort_internal() -> ! {
unsafe { libc::abort() }
}
use crate::sys_common::rwlock::{StaticRWLock, StaticRWLockReadGuard};
use crate::vec;
+#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
+use crate::sys::weak::weak;
+
use libc::{c_char, c_int, c_void};
const TMPBUF_SZ: usize = 128;
use crate::sys::cvt;
use crate::sys::process::process_common::*;
+#[cfg(any(
+ target_os = "macos",
+ target_os = "freebsd",
+ all(target_os = "linux", target_env = "gnu"),
+ all(target_os = "linux", target_env = "musl"),
+))]
+use crate::sys::weak::weak;
+
#[cfg(target_os = "vxworks")]
use libc::RTP_ID as pid_t;
use crate::fs::File;
use crate::io::Read;
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ use crate::sys::weak::syscall;
+
#[cfg(any(target_os = "linux", target_os = "android"))]
fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
// A weak symbol allows interposition, e.g. for perf measurements that want to
use crate::fs::File;
use crate::io::Read;
use crate::sys::os::errno;
+ use crate::sys::weak::weak;
use libc::{c_int, c_void, size_t};
fn getentropy_fill_bytes(v: &mut [u8]) -> bool {
use crate::sys::{os, stack_overflow};
use crate::time::Duration;
+#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
+use crate::sys::weak::weak;
#[cfg(not(any(target_os = "l4re", target_os = "vxworks")))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "l4re")]
use crate::mem;
use crate::sync::atomic::{self, AtomicUsize, Ordering};
-macro_rules! weak {
+// Temporary null documentation to work around #57569 until the fix is beta
+#[cfg_attr(bootstrap, doc = "")]
+pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ #[allow(non_upper_case_globals)]
static $name: crate::sys::weak::Weak<unsafe extern "C" fn($($t),*) -> $ret> =
crate::sys::weak::Weak::new(concat!(stringify!($name), '\0'));
)
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
}
+// Temporary null documentation to work around #57569 until the fix is beta
+#[cfg_attr(bootstrap, doc = "")]
#[cfg(not(any(target_os = "linux", target_os = "android")))]
-macro_rules! syscall {
+pub(crate) macro syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name: $t),*) -> $ret {
use super::os;
)
}
+#[cfg_attr(bootstrap, doc = "")]
#[cfg(any(target_os = "linux", target_os = "android"))]
-macro_rules! syscall {
+pub(crate) macro syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name:$t),*) -> $ret {
+ use weak;
// This looks like a hack, but concat_idents only accepts idents
// (not paths).
use libc::*;
pub struct Command {
program: OsString,
- args: Vec<OsString>,
+ args: Vec<Arg>,
env: CommandEnv,
cwd: Option<OsString>,
flags: u32,
pub stderr: Option<AnonPipe>,
}
+#[derive(Debug)]
+enum Arg {
+ /// Add quotes (if needed)
+ Regular(OsString),
+ /// Append raw string without quoting
+ Raw(OsString),
+}
+
impl Command {
pub fn new(program: &OsStr) -> Command {
Command {
}
pub fn arg(&mut self, arg: &OsStr) {
- self.args.push(arg.to_os_string())
+ self.args.push(Arg::Regular(arg.to_os_string()))
}
pub fn env_mut(&mut self) -> &mut CommandEnv {
&mut self.env
self.force_quotes_enabled = enabled;
}
+ pub fn raw_arg(&mut self, command_str_to_append: &OsStr) {
+ self.args.push(Arg::Raw(command_str_to_append.to_os_string()))
+ }
+
pub fn get_program(&self) -> &OsStr {
&self.program
}
impl fmt::Debug for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:?}", self.program)?;
+ self.program.fmt(f)?;
for arg in &self.args {
- write!(f, " {:?}", arg)?;
+ f.write_str(" ")?;
+ match arg {
+ Arg::Regular(s) => s.fmt(f),
+ Arg::Raw(s) => f.write_str(&s.to_string_lossy()),
+ }?;
}
Ok(())
}
}
}
+enum Quote {
+ // Every arg is quoted
+ Always,
+ // Whitespace and empty args are quoted
+ Auto,
+ // Arg appended without any changes (#29494)
+ Never,
+}
+
// Produces a wide string *without terminating null*; returns an error if
// `prog` or any of the `args` contain a nul.
-fn make_command_line(prog: &OsStr, args: &[OsString], force_quotes: bool) -> io::Result<Vec<u16>> {
+fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Result<Vec<u16>> {
// Encode the command and arguments in a command line string such
// that the spawned process may recover them using CommandLineToArgvW.
let mut cmd: Vec<u16> = Vec::new();
// Always quote the program name so CreateProcess doesn't interpret args as
// part of the name if the binary wasn't found first time.
- append_arg(&mut cmd, prog, true)?;
+ append_arg(&mut cmd, prog, Quote::Always)?;
for arg in args {
cmd.push(' ' as u16);
- append_arg(&mut cmd, arg, force_quotes)?;
+ let (arg, quote) = match arg {
+ Arg::Regular(arg) => (arg, if force_quotes { Quote::Always } else { Quote::Auto }),
+ Arg::Raw(arg) => (arg, Quote::Never),
+ };
+ append_arg(&mut cmd, arg, quote)?;
}
return Ok(cmd);
- fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, force_quotes: bool) -> io::Result<()> {
+ fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
// If an argument has 0 characters then we need to quote it to ensure
// that it actually gets passed through on the command line or otherwise
// it will be dropped entirely when parsed on the other end.
ensure_no_nuls(arg)?;
let arg_bytes = &arg.as_inner().inner.as_inner();
- let quote = force_quotes
- || arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t')
- || arg_bytes.is_empty();
+ let (quote, escape) = match quote {
+ Quote::Always => (true, true),
+ Quote::Auto => {
+ (arg_bytes.iter().any(|c| *c == b' ' || *c == b'\t') || arg_bytes.is_empty(), true)
+ }
+ Quote::Never => (false, false),
+ };
if quote {
cmd.push('"' as u16);
}
let mut backslashes: usize = 0;
for x in arg.encode_wide() {
- if x == '\\' as u16 {
- backslashes += 1;
- } else {
- if x == '"' as u16 {
- // Add n+1 backslashes to total 2n+1 before internal '"'.
- cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+ if escape {
+ if x == '\\' as u16 {
+ backslashes += 1;
+ } else {
+ if x == '"' as u16 {
+ // Add n+1 backslashes to total 2n+1 before internal '"'.
+ cmd.extend((0..=backslashes).map(|_| '\\' as u16));
+ }
+ backslashes = 0;
}
- backslashes = 0;
}
cmd.push(x);
}
}
pub struct CommandArgs<'a> {
- iter: crate::slice::Iter<'a, OsString>,
+ iter: crate::slice::Iter<'a, Arg>,
}
impl<'a> Iterator for CommandArgs<'a> {
type Item = &'a OsStr;
fn next(&mut self) -> Option<&'a OsStr> {
- self.iter.next().map(|s| s.as_ref())
+ self.iter.next().map(|arg| match arg {
+ Arg::Regular(s) | Arg::Raw(s) => s.as_ref(),
+ })
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
use super::make_command_line;
+use super::Arg;
use crate::env;
use crate::ffi::{OsStr, OsString};
use crate::process::Command;
+#[test]
+fn test_raw_args() {
+ let command_line = &make_command_line(
+ OsStr::new("quoted exe"),
+ &[
+ Arg::Regular(OsString::from("quote me")),
+ Arg::Raw(OsString::from("quote me *not*")),
+ Arg::Raw(OsString::from("\t\\")),
+ Arg::Raw(OsString::from("internal \\\"backslash-\"quote")),
+ Arg::Regular(OsString::from("optional-quotes")),
+ ],
+ false,
+ )
+ .unwrap();
+ assert_eq!(
+ String::from_utf16(command_line).unwrap(),
+ "\"quoted exe\" \"quote me\" quote me *not* \t\\ internal \\\"backslash-\"quote optional-quotes"
+ );
+}
+
#[test]
fn test_make_command_line() {
fn test_wrapper(prog: &str, args: &[&str], force_quotes: bool) -> String {
let command_line = &make_command_line(
OsStr::new(prog),
- &args.iter().map(|a| OsString::from(a)).collect::<Vec<OsString>>(),
+ &args.iter().map(|a| Arg::Regular(OsString::from(a))).collect::<Vec<_>>(),
force_quotes,
)
.unwrap();
assert_eq!(test_wrapper("prog", &["aaa", "bbb", "ccc"], false), "\"prog\" aaa bbb ccc");
+ assert_eq!(test_wrapper("prog", &[r"C:\"], false), r#""prog" C:\"#);
+ assert_eq!(test_wrapper("prog", &[r"2slashes\\"], false), r#""prog" 2slashes\\"#);
+ assert_eq!(test_wrapper("prog", &[r" C:\"], false), r#""prog" " C:\\""#);
+ assert_eq!(test_wrapper("prog", &[r" 2slashes\\"], false), r#""prog" " 2slashes\\\\""#);
+
assert_eq!(
test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"], false),
"\"C:\\Program Files\\blah\\blah.exe\" aaa"
/// Cooperatively gives up a timeslice to the OS scheduler.
///
-/// This is used when the programmer knows that the thread will have nothing
-/// to do for some time, and thus avoid wasting computing time.
+/// This calls the underlying OS scheduler's yield primitive, signaling
+/// that the calling thread is willing to give up its remaining timeslice
+/// so that the OS may schedule other threads on the CPU.
///
-/// For example when polling on a resource, it is common to check that it is
-/// available, and if not to yield in order to avoid busy waiting.
+/// A drawback of yielding in a loop is that if the OS does not have any
+/// other ready threads to run on the current CPU, the thread will effectively
+/// busy-wait, which wastes CPU time and energy.
///
-/// Thus the pattern of `yield`ing after a failed poll is rather common when
-/// implementing low-level shared resources or synchronization primitives.
+/// Therefore, when waiting for events of interest, a programmer's first
+/// choice should be to use synchronization devices such as [`channel`]s,
+/// [`Condvar`]s, [`Mutex`]es or [`join`] since these primitives are
+/// implemented in a blocking manner, giving up the CPU until the event
+/// of interest has occurred which avoids repeated yielding.
///
-/// However programmers will usually prefer to use [`channel`]s, [`Condvar`]s,
-/// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid
-/// thinking about thread scheduling.
-///
-/// Note that [`channel`]s for example are implemented using this primitive.
-/// Indeed when you call `send` or `recv`, which are blocking, they will yield
-/// if the channel is not available.
+/// `yield_now` should thus be used only rarely, mostly in situations where
+/// repeated polling is required because there is no other suitable way to
+/// learn when an event of interest has occurred.
///
/// # Examples
///
static mut COUNTER: u64 = 1;
unsafe {
- let _guard = GUARD.lock();
+ let guard = GUARD.lock();
// If we somehow use up all our bits, panic so that we're not
// covering up subtle bugs of IDs being reused.
if COUNTER == u64::MAX {
+ drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
panic!("failed to generate unique thread ID: bitspace exhausted");
}
}
macro_rules! tool_doc {
- ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(, binary=$bin:expr)?) => {
+ ($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?], binary=$bin:expr) => {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $tool {
stage: u32,
cargo.arg("-p").arg($krate);
)+
- $(if !$bin {
+ if !$bin {
cargo.rustdocflag("--document-private-items");
- })?
+ }
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
cargo.rustdocflag("-Zunstable-options");
}
}
-tool_doc!(Rustdoc, "rustdoc-tool", "src/tools/rustdoc", ["rustdoc", "rustdoc-json-types"]);
+tool_doc!(
+ Rustdoc,
+ "rustdoc-tool",
+ "src/tools/rustdoc",
+ ["rustdoc", "rustdoc-json-types"],
+ binary = false
+);
tool_doc!(
Rustfmt,
"rustfmt-nightly",
t!(std::fs::read_dir(dir)).next().is_none()
}
+ if !build.config.submodules {
+ return;
+ }
+
// NOTE: The check for the empty directory is here because when running x.py
// the first time, the llvm submodule won't be checked out. Check it out
// now so we can build it.
let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
cmd.arg(rustdoc.to_str().unwrap())
- .arg(builder.src.join("src/librustdoc/html/static/themes").to_str().unwrap())
+ .arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
.env("RUSTC_STAGE", self.compiler.stage.to_string())
.env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
.env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
-#!/usr/bin/env python
+#!/usr/bin/env python3
# ignore-tidy-linelength
# This is a small script that we use on CI to collect CPU usage statistics of
import sys
import time
-if sys.platform == 'linux2':
+# Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just
+# "linux". We check here with `.startswith` to keep compatibility with older
+# Python versions (especially Python 2.7).
+if sys.platform.startswith('linux'):
class State:
def __init__(self):
with open('/proc/stat', 'r') as file:
/scripts/validate-toolstate.sh && \
/scripts/validate-error-codes.sh && \
# Runs checks to ensure that there are no ES5 issues in our JS code.
- es-check es5 ../src/librustdoc/html/static/*.js && \
- eslint ../src/librustdoc/html/static/*.js
+ es-check es5 ../src/librustdoc/html/static/js/*.js && \
+ eslint ../src/librustdoc/html/static/js/*.js
set -euo pipefail
IFS=$'\n\t'
-python src/ci/cpu-usage-over-time.py &> cpu-usage.csv &
+python3 src/ci/cpu-usage-over-time.py &> cpu-usage.csv &
-Subproject commit 55a26488ddefc8433e73a2e8352d70f7a5c7fc2b
+Subproject commit a90f07f1e9a7fc75dc9105a6c6f16d5c13edceb0
-Subproject commit c74b2a0d6bf55774cf15d69f05dfe05408b8f81a
+Subproject commit 5d57b3832f8d308a9f478ce0a69799548f27ad4d
-Subproject commit cbec77fbd8eea0c13e390dd9eded1ae200e811d1
+Subproject commit 506840eb73b0749336e1d5274e16d6393892ee82
-Subproject commit b9ca313e687c991223e23e5520529815dc281205
+Subproject commit 7a13537f96af4b9b8e3ea296d6e5c3c7ab72ce9f
-Subproject commit d9699fa8f3186440fdaadd703d63d8d42322c176
+Subproject commit ab60513a3a5a0591e237fddff5d027a982648392
% The Rust Reference has moved
We've split up the reference into chapters. Please find it at its new
-home [here](reference/index.html).
+home [here](https://doc.rust-lang.org/stable/reference/introduction.html).
-Subproject commit 805e016c5792ad2adabb66e348233067d5ea9f10
+Subproject commit 028f93a61500fe8f746ee7cc6b204ea6c9f42935
-Subproject commit fe34beddb41dea5cb891032512a8d5b842b99696
+Subproject commit 60e282559104035985331645907c3d9f842312c5
--- /dev/null
+# `exclusive_range_pattern`
+
+The tracking issue for this feature is: [#37854].
+
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `exclusive_range_pattern` feature allows non-inclusive range
+patterns (`0..10`) to be used in appropriate pattern matching
+contexts. It also can be combined with `#![feature(half_open_range_patterns]`
+to be able to use RangeTo patterns (`..10`).
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(exclusive_range_pattern)]
+ let x = 5;
+ match x {
+ 0..10 => println!("single digit"),
+ 10 => println!("ten isn't part of the above range"),
+ _ => println!("nor is everything else.")
+ }
+```
--- /dev/null
+# `half_open_range_patterns`
+
+The tracking issue for this feature is: [#67264]
+It is part of the `#![exclusive_range_pattern]` feature,
+tracked at [#37854].
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `half_open_range_patterns` feature allows RangeTo patterns
+(`..10`) to be used in appropriate pattern matching contexts.
+This requires also enabling the `exclusive_range_pattern` feature.
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+ let x = 5;
+ match x {
+ ..0 => println!("negative!"), // "RangeTo" pattern. Unstable.
+ 0 => println!("zero!"),
+ 1.. => println!("positive!"), // "RangeFrom" pattern. Stable.
+ }
+```
| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |
| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |
| x86 | `kreg` | `k[1-7]` | `Yk` |
+| x86 | `x87_reg` | `st([0-7])` | Only clobbers |
+| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers |
| AArch64 | `reg` | `x[0-30]` | `r` |
| AArch64 | `vreg` | `v[0-31]` | `w` |
| AArch64 | `vreg_low16` | `v[0-15]` | `x` |
+| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
| ARM | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |
| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` |
| NVPTX | `reg64` | None\* | `l` |
| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
| RISC-V | `freg` | `f[0-31]` | `f` |
+| RISC-V | `vreg` | `v[0-31]` | Only clobbers |
| Hexagon | `reg` | `r[0-28]` | `r` |
| PowerPC | `reg` | `r[0-31]` | `r` |
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
>
> Note #4: WebAssembly doesn't have registers, so named registers are not supported.
+>
+> Note #5: Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`.
Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |
| x86 | `kreg` | `axv512f` | `i8`, `i16` |
| x86 | `kreg` | `axv512bw` | `i32`, `i64` |
+| x86 | `mmx_reg` | N/A | Only clobbers |
+| x86 | `x87_reg` | N/A | Only clobbers |
| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
+| AArch64 | `preg` | N/A | Only clobbers |
| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| ARM | `sreg` | `vfp2` | `i32`, `f32` |
| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| RISC-V | `freg` | `f` | `f32` |
| RISC-V | `freg` | `d` | `f64` |
+| RISC-V | `vreg` | N/A | Only clobbers |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
from rust_types import *
-rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True)
_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
return StdStringProvider(valobj)
if rust_type == RustType.STD_OS_STRING:
return StdOsStringProvider(valobj)
- if rust_type == RustType.STD_STR and not rust_enabled:
+ if rust_type == RustType.STD_STR:
return StdStrProvider(valobj)
-
+ if rust_type == RustType.STD_SLICE:
+ return StdSliceProvider(valobj)
if rust_type == RustType.STD_VEC:
return StdVecProvider(valobj)
if rust_type == RustType.STD_VEC_DEQUE:
def display_hint():
return "string"
+def _enumerate_array_elements(element_ptrs):
+ for (i, element_ptr) in enumerate(element_ptrs):
+ key = "[{}]".format(i)
+ element = element_ptr.dereference()
+
+ try:
+ # rust-lang/rust#64343: passing deref expr to `str` allows
+ # catching exception on garbage pointer
+ str(element)
+ except RuntimeError:
+ yield key, "inaccessible"
+
+ break
+
+ yield key, element
+
+class StdSliceProvider:
+ def __init__(self, valobj):
+ self.valobj = valobj
+ self.length = int(valobj["length"])
+ self.data_ptr = valobj["data_ptr"]
+
+ def to_string(self):
+ return "{}(size={})".format(self.valobj.type, self.length)
+
+ def children(self):
+ return _enumerate_array_elements(
+ self.data_ptr + index for index in xrange(self.length)
+ )
+
+ @staticmethod
+ def display_hint():
+ return "array"
class StdVecProvider:
def __init__(self, valobj):
return "Vec(size={})".format(self.length)
def children(self):
- saw_inaccessible = False
- for index in xrange(self.length):
- element_ptr = self.data_ptr + index
- if saw_inaccessible:
- return
- try:
- # rust-lang/rust#64343: passing deref expr to `str` allows
- # catching exception on garbage pointer
- str(element_ptr.dereference())
- yield "[{}]".format(index), element_ptr.dereference()
- except RuntimeError:
- saw_inaccessible = True
- yield str(index), "inaccessible"
+ return _enumerate_array_elements(
+ self.data_ptr + index for index in xrange(self.length)
+ )
@staticmethod
def display_hint():
return "VecDeque(size={})".format(self.size)
def children(self):
- for index in xrange(0, self.size):
- value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference()
- yield "[{}]".format(index), value
+ return _enumerate_array_elements(
+ (self.data_ptr + ((self.tail + index) % self.cap)) for index in xrange(self.size)
+ )
@staticmethod
def display_hint():
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
-type summary add -F lldb_lookup.summary_lookup -e -x -h "^&str$" --category Rust
-type summary add -F lldb_lookup.summary_lookup -e -x -h "^&\\[.+\\]$" --category Rust
+type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust
+type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
<Synthetic Name="[...]"><DisplayString>...</DisplayString></Synthetic>
</Expand>
</Type>
+
+ <!-- Directly tagged enums. $T1 is the type name -->
<Type Name="enum$<*>">
- <Intrinsic Name="tag" Expression="variant0.variant$" />
+ <Intrinsic Name="tag" Expression="discriminant" />
<DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
<DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
<DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
<DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
<Expand>
+ <Synthetic Name="[variant]">
+ <DisplayString>{tag(),en}</DisplayString>
+ </Synthetic>
<ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
<ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
<ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
</Expand>
</Type>
- <!-- $T1 is the name of the enum, $T2 is the low value of the dataful variant tag,
- $T3 is the high value of the dataful variant tag, $T4 is the name of the dataful variant -->
+ <!-- Single variant enums. $T1 is the name of the enum, $T2 is the name of the variant -->
+ <Type Name="enum$<*, *>">
+ <DisplayString>{"$T2",sb}</DisplayString>
+ <Expand>
+ <Synthetic Name="[variant]">
+ <DisplayString>{"$T2",sb}</DisplayString>
+ </Synthetic>
+ <ExpandedItem>$T2</ExpandedItem>
+ </Expand>
+ </Type>
+
+ <!-- Niche-layout enums. $T1 is the name of the enum, $T2 is the low value of the dataful
+ variant tag, $T3 is the high value of the dataful variant tag, $T4 is the name of
+ the dataful variant -->
<Type Name="enum$<*, *, *, *>">
<Intrinsic Name="tag" Expression="discriminant" />
<Intrinsic Name="is_dataful" Expression="tag() >= $T2 && tag() <= $T3" />
<Synthetic Condition="is_dataful()" Name="[variant]">
<DisplayString>{"$T4",sb}</DisplayString>
</Synthetic>
+ <Synthetic Condition="!is_dataful()" Name="[variant]">
+ <DisplayString>{discriminant,en}</DisplayString>
+ </Synthetic>
</Expand>
</Type>
</AutoVisualizer>
</Expand>
</Type>
- <Type Name="core::option::Option<*>" Priority="MediumLow">
- <DisplayString Condition="*(void**)this == nullptr">None</DisplayString>
- <DisplayString>Some({($T1 *)this})</DisplayString>
- <Expand>
- <Item Name="Some" ExcludeView="simple" Condition="*(void**)this != nullptr">($T1 *)this</Item>
- </Expand>
- </Type>
-
<Type Name="core::ptr::non_null::NonNull<*>">
<DisplayString>{(void*) pointer}</DisplayString>
<Expand>
STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$")
-STD_STR_REGEX = re.compile(r"^&str$")
-STD_SLICE_REGEX = re.compile(r"^&\[.+\]$")
+STD_STR_REGEX = re.compile(r"^&(mut )?str$")
+STD_SLICE_REGEX = re.compile(r"^&(mut )?\[.+\]$")
STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$")
STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$")
STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$")
name: None,
attrs: Default::default(),
visibility: Inherited,
- def_id: FakeDefId::new_fake(item_def_id.krate),
+ def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
span: Span::dummy(),
unsafety: hir::Unsafety::Normal,
name: None,
attrs: Default::default(),
visibility: Inherited,
- def_id: FakeDefId::new_fake(item_def_id.krate),
+ def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
span: Span::from_rustc_span(self.cx.tcx.def_span(impl_def_id)),
unsafety: hir::Unsafety::Normal,
use rustc_ast::attr;
use rustc_ast::Path;
+use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::with_default_session_globals;
use rustc_span::DUMMY_SP;
fn word_cfg(s: &str) -> Cfg {
#[test]
fn test_cfg_not() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
assert_eq!(!Cfg::False, Cfg::True);
assert_eq!(!Cfg::True, Cfg::False);
assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test"))));
#[test]
fn test_cfg_and() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut x = Cfg::False;
x &= Cfg::True;
assert_eq!(x, Cfg::False);
#[test]
fn test_cfg_or() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut x = Cfg::True;
x |= Cfg::False;
assert_eq!(x, Cfg::True);
#[test]
fn test_parse_ok() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mi = dummy_meta_item_word("all");
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
#[test]
fn test_parse_err() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
assert!(Cfg::parse(&mi).is_err());
#[test]
fn test_render_short_html() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
assert_eq!(word_cfg("unix").render_short_html(), "Unix");
assert_eq!(name_value_cfg("target_os", "macos").render_short_html(), "macOS");
assert_eq!(name_value_cfg("target_pointer_width", "16").render_short_html(), "16-bit");
#[test]
fn test_render_long_html() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
assert_eq!(
word_cfg("unix").render_long_html(),
"This is supported on <strong>Unix</strong> only."
fn test_simplify_with() {
// This is a tiny subset of things that could be simplified, but it likely covers 90% of
// real world usecases well.
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let foo = word_cfg("foo");
let bar = word_cfg("bar");
let baz = word_cfg("baz");
use rustc_span::symbol::{kw, sym, Symbol};
use crate::clean::{
- self, utils, Attributes, AttributesExt, FakeDefId, GetDefId, NestedAttributesExt, Type,
+ self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
crate fn try_inline(
cx: &mut DocContext<'_>,
parent_module: DefId,
+ import_def_id: Option<DefId>,
res: Res,
name: Symbol,
attrs: Option<Attrs<'_>>,
clean::ConstantItem(build_const(cx, did))
}
Res::Def(DefKind::Macro(kind), did) => {
- let mac = build_macro(cx, did, name);
+ let mac = build_macro(cx, did, name, import_def_id);
let type_kind = match kind {
MacroKind::Bang => ItemType::Macro,
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
cx.inlined.insert(did.into());
- ret.push(clean::Item::from_def_id_and_attrs_and_parts(
- did,
- Some(name),
- kind,
- box attrs,
- cx,
- cfg,
- ));
+ let mut item =
+ clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg);
+ if let Some(import_def_id) = import_def_id {
+ // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
+ item.visibility = cx.tcx.visibility(import_def_id).clean(cx);
+ }
+ ret.push(item);
Some(ret)
}
}
if let Res::PrimTy(p) = item.res {
// Primitive types can't be inlined so generate an import instead.
+ let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
name: None,
attrs: box clean::Attributes::default(),
- def_id: FakeDefId::new_fake(did.krate),
+ def_id: ItemId::Primitive(prim_ty, did.krate),
visibility: clean::Public,
kind: box clean::ImportItem(clean::Import::new_simple(
item.ident.name,
global: false,
res: item.res,
segments: vec![clean::PathSegment {
- name: clean::PrimitiveType::from(p).as_sym(),
+ name: prim_ty.as_sym(),
args: clean::GenericArgs::AngleBracketed {
args: Vec::new(),
bindings: Vec::new(),
)),
cfg: None,
});
- } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
+ } else if let Some(i) =
+ try_inline(cx, did, None, item.res, item.ident.name, None, visited)
+ {
items.extend(i)
}
}
}
}
-fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind {
- let imported_from = cx.tcx.crate_name(did.krate);
- match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
- LoadedMacro::MacroDef(def, _) => {
- if let ast::ItemKind::MacroDef(ref def) = def.kind {
- let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
- let matchers = tts.chunks(4).map(|arm| &arm[0]);
-
- let source = format!(
- "macro_rules! {} {{\n{}}}",
- name,
- utils::render_macro_arms(matchers, ";")
- );
-
- clean::MacroItem(clean::Macro { source, imported_from: Some(imported_from) })
+fn build_macro(
+ cx: &mut DocContext<'_>,
+ def_id: DefId,
+ name: Symbol,
+ import_def_id: Option<DefId>,
+) -> clean::ItemKind {
+ let imported_from = cx.tcx.crate_name(def_id.krate);
+ match cx.enter_resolver(|r| r.cstore().load_macro_untracked(def_id, cx.sess())) {
+ LoadedMacro::MacroDef(item_def, _) => {
+ if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
+ clean::MacroItem(clean::Macro {
+ source: utils::display_macro_source(
+ cx,
+ name,
+ def,
+ def_id,
+ cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
+ ),
+ imported_from: Some(imported_from),
+ })
} else {
unreachable!()
}
if let Some(items) = inline::try_inline(
cx,
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
+ Some(krate.def_id.to_def_id()),
res,
name,
Some(attrs),
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
- let mut denied = !import.vis.node.is_pub()
+ let mut denied = !(import.vis.node.is_pub()
+ || (cx.render_options.document_private && import.vis.node.is_pub_restricted()))
|| pub_underscore
|| attrs.iter().any(|a| {
a.has_name(sym::doc)
}
if !denied {
let mut visited = FxHashSet::default();
+ let import_def_id = import.def_id.to_def_id();
if let Some(mut items) = inline::try_inline(
cx,
cx.tcx.parent_module(import.hir_id()).to_def_id(),
+ Some(import_def_id),
path.res,
name,
Some(attrs),
&mut visited,
) {
items.push(Item::from_def_id_and_parts(
- import.def_id.to_def_id(),
+ import_def_id,
None,
ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
cx,
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let (item, renamed) = self;
let name = renamed.unwrap_or(item.ident.name);
- let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
- // Extract the macro's matchers. They represent the "interface" of the macro.
- let matchers = tts.chunks(4).map(|arm| &arm[0]);
-
- let source = if item.ast.macro_rules {
- format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
- } else {
- let vis = item.vis.clean(cx);
- let def_id = item.def_id.to_def_id();
-
- if matchers.len() <= 1 {
- format!(
- "{}macro {}{} {{\n ...\n}}",
- vis.to_src_with_space(cx.tcx, def_id),
- name,
- matchers.map(render_macro_matcher).collect::<String>(),
- )
- } else {
- format!(
- "{}macro {} {{\n{}}}",
- vis.to_src_with_space(cx.tcx, def_id),
- name,
- render_macro_arms(matchers, ","),
- )
- }
- };
+ let def_id = item.def_id.to_def_id();
Item::from_hir_id_and_parts(
item.hir_id(),
Some(name),
- MacroItem(Macro { source, imported_from: None }),
+ MacroItem(Macro {
+ source: display_macro_source(cx, name, &item.ast, def_id, &item.vis),
+ imported_from: None,
+ }),
cx,
)
}
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
use std::default::Default;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use self::SelfTy::*;
use self::Type::*;
-crate type FakeDefIdSet = FxHashSet<FakeDefId>;
+crate type ItemIdSet = FxHashSet<ItemId>;
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
-crate enum FakeDefId {
- Real(DefId),
- Fake(DefIndex, CrateNum),
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
+crate enum ItemId {
+ /// A "normal" item that uses a [`DefId`] for identification.
+ DefId(DefId),
+ /// Identifier that is used for auto traits.
+ Auto { trait_: DefId, for_: DefId },
+ /// Identifier that is used for blanket implementations.
+ Blanket { impl_id: DefId, for_: DefId },
+ /// Identifier for primitive types.
+ Primitive(PrimitiveType, CrateNum),
}
-impl FakeDefId {
- #[cfg(parallel_compiler)]
- crate fn new_fake(crate: CrateNum) -> Self {
- unimplemented!("")
- }
-
- #[cfg(not(parallel_compiler))]
- crate fn new_fake(krate: CrateNum) -> Self {
- thread_local!(static FAKE_DEF_ID_COUNTER: Cell<usize> = Cell::new(0));
- let id = FAKE_DEF_ID_COUNTER.with(|id| {
- let tmp = id.get();
- id.set(tmp + 1);
- tmp
- });
- Self::Fake(DefIndex::from(id), krate)
- }
-
+impl ItemId {
#[inline]
crate fn is_local(self) -> bool {
match self {
- FakeDefId::Real(id) => id.is_local(),
- FakeDefId::Fake(_, krate) => krate == LOCAL_CRATE,
+ ItemId::Auto { for_: id, .. }
+ | ItemId::Blanket { for_: id, .. }
+ | ItemId::DefId(id) => id.is_local(),
+ ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
}
}
#[inline]
#[track_caller]
- crate fn expect_real(self) -> rustc_hir::def_id::DefId {
- self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self))
+ crate fn expect_def_id(self) -> DefId {
+ self.as_def_id()
+ .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
}
#[inline]
- crate fn as_real(self) -> Option<DefId> {
+ crate fn as_def_id(self) -> Option<DefId> {
match self {
- FakeDefId::Real(id) => Some(id),
- FakeDefId::Fake(_, _) => None,
+ ItemId::DefId(id) => Some(id),
+ _ => None,
}
}
#[inline]
crate fn krate(self) -> CrateNum {
match self {
- FakeDefId::Real(id) => id.krate,
- FakeDefId::Fake(_, krate) => krate,
+ ItemId::Auto { for_: id, .. }
+ | ItemId::Blanket { for_: id, .. }
+ | ItemId::DefId(id) => id.krate,
+ ItemId::Primitive(_, krate) => krate,
}
}
#[inline]
crate fn index(self) -> Option<DefIndex> {
match self {
- FakeDefId::Real(id) => Some(id.index),
- FakeDefId::Fake(_, _) => None,
+ ItemId::DefId(id) => Some(id.index),
+ _ => None,
}
}
}
-impl From<DefId> for FakeDefId {
+impl From<DefId> for ItemId {
fn from(id: DefId) -> Self {
- Self::Real(id)
+ Self::DefId(id)
}
}
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
crate kind: Box<ItemKind>,
- crate def_id: FakeDefId,
+ crate def_id: ItemId,
crate cfg: Option<Arc<Cfg>>,
}
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Item, 48);
+rustc_data_structures::static_assert_size!(Item, 56);
crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
Span::from_rustc_span(def_id.as_local().map_or_else(
impl Item {
crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
- if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) }
+ self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
}
crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
- if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) }
+ self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
}
crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
- if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) }
+ self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
}
crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
- if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() }
+ self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
}
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
kind
{
*span
- } else if self.is_fake() {
- Span::dummy()
} else {
- rustc_span(self.def_id.expect_real(), tcx)
+ self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
}
}
}
crate fn is_crate(&self) -> bool {
- self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
+ self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
}
crate fn is_mod(&self) -> bool {
self.type_() == ItemType::Module
_ => false,
}
}
-
- crate fn is_fake(&self) -> bool {
- matches!(self.def_id, FakeDefId::Fake(_, _))
- }
}
#[derive(Clone, Debug)]
use crate::clean::{
inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+ Visibility,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
+use rustc_ast as ast;
use rustc_ast::tokenstream::TokenTree;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
pub(super) fn render_macro_matcher(matcher: &TokenTree) -> String {
rustc_ast_pretty::pprust::tt_to_string(matcher)
}
+
+pub(super) fn display_macro_source(
+ cx: &mut DocContext<'_>,
+ name: Symbol,
+ def: &ast::MacroDef,
+ def_id: DefId,
+ vis: impl Clean<Visibility>,
+) -> String {
+ let tts: Vec<_> = def.body.inner_tokens().into_trees().collect();
+ // Extract the spans of all matchers. They represent the "interface" of the macro.
+ let matchers = tts.chunks(4).map(|arm| &arm[0]);
+
+ if def.macro_rules {
+ format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(matchers, ";"))
+ } else {
+ let vis = vis.clean(cx);
+
+ if matchers.len() <= 1 {
+ format!(
+ "{}macro {}{} {{\n ...\n}}",
+ vis.to_src_with_space(cx.tcx, def_id),
+ name,
+ matchers.map(render_macro_matcher).collect::<String>(),
+ )
+ } else {
+ format!(
+ "{}macro {} {{\n{}}}",
+ vis.to_src_with_space(cx.tcx, def_id),
+ name,
+ render_macro_arms(matchers, ","),
+ )
+ }
+ }
+}
))
.warn("the theme may appear incorrect when loaded")
.help(&format!(
- "to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
+ "to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
theme_s
))
.emit();
use std::rc::Rc;
use crate::clean::inline::build_external_trait;
-use crate::clean::{self, FakeDefId, TraitWithExtraInfo};
+use crate::clean::{self, ItemId, TraitWithExtraInfo};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
use crate::passes::{self, Condition::*, ConditionalPass};
/// This same cache is used throughout rustdoc, including in [`crate::html::render`].
crate cache: Cache,
/// Used by [`clean::inline`] to tell if an item has already been inlined.
- crate inlined: FxHashSet<FakeDefId>,
+ crate inlined: FxHashSet<ItemId>,
/// Used by `calculate_doc_coverage`.
crate output_format: OutputFormat,
}
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
/// (This avoids a slice-index-out-of-bounds panic.)
- crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: FakeDefId) -> Option<HirId> {
+ crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
match def_id {
- FakeDefId::Real(real_id) => {
+ ItemId::DefId(real_id) => {
real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
- FakeDefId::Fake(_, _) => None,
+ // FIXME: Can this be `Some` for `Auto` or `Blanket`?
+ _ => None,
}
}
}
// Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
// crate already is included.
let result = rustc_driver::catch_fatal_errors(|| {
- rustc_span::with_session_globals(edition, || {
+ rustc_span::create_session_if_not_set_then(edition, |_| {
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::Handler;
use rustc_parse::maybe_new_parser_from_source_str;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
-use crate::clean::{self, FakeDefId, GetDefId};
+use crate::clean::{self, GetDefId, ItemId};
use crate::fold::DocFolder;
use crate::formats::item_type::ItemType;
use crate::formats::Impl;
/// All intra-doc links resolved so far.
///
/// Links are indexed by the DefId of the item they document.
- crate intra_doc_links: BTreeMap<FakeDefId, Vec<clean::ItemLink>>,
+ crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
}
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
// Propagate a trait method's documentation to all implementors of the
// trait.
if let clean::TraitItem(ref t) = *item.kind {
- self.cache.traits.entry(item.def_id.expect_real()).or_insert_with(|| {
+ self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
clean::TraitWithExtraInfo {
trait_: t.clone(),
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
- if !self.cache.paths.contains_key(&item.def_id.expect_real())
- || self.cache.access_levels.is_public(item.def_id.expect_real())
+ if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
+ || self.cache.access_levels.is_public(item.def_id.expect_def_id())
{
self.cache.paths.insert(
- item.def_id.expect_real(),
+ item.def_id.expect_def_id(),
(self.cache.stack.clone(), item.type_()),
);
}
clean::PrimitiveItem(..) => {
self.cache
.paths
- .insert(item.def_id.expect_real(), (self.cache.stack.clone(), item.type_()));
+ .insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
}
clean::ExternCrateItem { .. }
| clean::StructItem(..)
| clean::UnionItem(..)
| clean::VariantItem(..) => {
- self.cache.parent_stack.push(item.def_id.expect_real());
+ self.cache.parent_stack.push(item.def_id.expect_def_id());
self.cache.parent_is_trait_impl = false;
true
}
use rustc_target::spec::abi::Abi;
use crate::clean::{
- self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType,
+ self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType,
};
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
impl clean::Visibility {
crate fn print_with_space<'a, 'tcx: 'a>(
self,
- item_did: FakeDefId,
+ item_did: ItemId,
cx: &'a Context<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
let to_print = match self {
// FIXME(camelid): This may not work correctly if `item_did` is a module.
// However, rustdoc currently never displays a module's
// visibility, so it shouldn't matter.
- let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_real());
+ let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
if vis_did.index == CRATE_DEF_INDEX {
"pub(crate) ".to_owned()
use super::write_code;
use crate::html::format::Buffer;
use expect_test::expect_file;
+use rustc_span::create_default_session_globals_then;
use rustc_span::edition::Edition;
-use rustc_span::with_default_session_globals;
const STYLE: &str = r#"
<style>
#[test]
fn test_html_highlighting() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let src = include_str!("fixtures/sample.rs");
let html = {
let mut out = Buffer::new();
#[test]
fn test_dos_backline() {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let src = "pub fn foo() {\r\n\
println!(\"foo\");\r\n\
}\r\n";
fn init_id_map() -> FxHashMap<String, usize> {
let mut map = FxHashMap::default();
- // This is the list of IDs used by rustdoc templates.
+ // This is the list of IDs used in Javascript.
+ map.insert("help".to_owned(), 1);
+ // This is the list of IDs used in HTML generated in Rust (including the ones
+ // used in tera template files).
map.insert("mainThemeStyle".to_owned(), 1);
map.insert("themeStyle".to_owned(), 1);
map.insert("theme-picker".to_owned(), 1);
map.insert("rustdoc-vars".to_owned(), 1);
map.insert("sidebar-vars".to_owned(), 1);
map.insert("copy-path".to_owned(), 1);
- map.insert("help".to_owned(), 1);
map.insert("TOC".to_owned(), 1);
- map.insert("render-detail".to_owned(), 1);
- // This is the list of IDs used by rustdoc sections.
+ // This is the list of IDs used by rustdoc sections (but still generated by
+ // rustdoc).
map.insert("fields".to_owned(), 1);
map.insert("variants".to_owned(), 1);
map.insert("implementors-list".to_owned(), 1);
map.insert("synthetic-implementors-list".to_owned(), 1);
+ map.insert("foreign-impls".to_owned(), 1);
map.insert("implementations".to_owned(), 1);
map.insert("trait-implementations".to_owned(), 1);
map.insert("synthetic-implementations".to_owned(), 1);
map.insert("provided-methods".to_owned(), 1);
map.insert("implementors".to_owned(), 1);
map.insert("synthetic-implementors".to_owned(), 1);
+ map.insert("trait-implementations-list".to_owned(), 1);
+ map.insert("synthetic-implementations-list".to_owned(), 1);
+ map.insert("blanket-implementations-list".to_owned(), 1);
+ map.insert("deref-methods".to_owned(), 1);
map
}
&self.shared.style_files,
)
} else {
- if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_real()) {
+ if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_def_id()) {
let mut path = String::new();
for name in &names[..names.len() - 1] {
path.push_str(name);
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
-use crate::clean::{self, FakeDefId, GetDefId, RenderedLink, SelfTy};
+use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy};
use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::cache::Cache;
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
AssocItemLink::Anchor(None) => anchor,
AssocItemLink::GotoSource(did, _) => {
- href(did.expect_real(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
+ href(did.expect_def_id(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
}
}
}
ItemType::TyMethod
};
- href(did.expect_real(), cx)
+ href(did.expect_def_id(), cx)
.map(|p| format!("{}#{}.{}", p.0, ty, name))
.unwrap_or_else(|| format!("#{}.{}", ty, name))
}
#[derive(Copy, Clone)]
enum AssocItemLink<'a> {
Anchor(Option<&'a str>),
- GotoSource(FakeDefId, &'a FxHashSet<Symbol>),
+ GotoSource(ItemId, &'a FxHashSet<Symbol>),
}
impl<'a> AssocItemLink<'a> {
write!(
w,
"<h2 id=\"deref-methods\" class=\"small-section-header\">\
- Methods from {trait_}<Target = {type_}>\
+ <span>Methods from {trait_}<Target = {type_}></span>\
<a href=\"#deref-methods\" class=\"anchor\"></a>\
</h2>",
trait_ = trait_.print(cx),
}
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
- let did = it.def_id.expect_real();
+ let did = it.def_id.expect_def_id();
if let Some(v) = cx.cache.impls.get(&did) {
let mut used_links = FxHashSet::default();
let cache = cx.cache();
"</div>",
);
- if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
+ if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
let cache = cx.cache();
let mut res = implementors
.iter()
clean::StructItem(ref s) => item_struct(buf, cx, item, s),
clean::UnionItem(ref s) => item_union(buf, cx, item, s),
clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
- clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t),
+ clean::TypedefItem(ref t, is_associated) => item_typedef(buf, cx, item, t, is_associated),
clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
w,
"<div class=\"item-left\"><code>{}extern crate {} as {};",
myitem.visibility.print_with_space(myitem.def_id, cx),
- anchor(myitem.def_id.expect_real(), &*src.as_str(), cx),
+ anchor(myitem.def_id.expect_def_id(), &*src.as_str(), cx),
myitem.name.as_ref().unwrap(),
),
None => write!(
"<div class=\"item-left\"><code>{}extern crate {};",
myitem.visibility.print_with_space(myitem.def_id, cx),
anchor(
- myitem.def_id.expect_real(),
+ myitem.def_id.expect_def_id(),
&*myitem.name.as_ref().unwrap().as_str(),
cx
),
}
// If there are methods directly on this trait object, render them here.
- render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All);
+ render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
- if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
+ if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
// The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
path = if it.def_id.is_local() {
cx.current.join("/")
} else {
- let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_real()];
+ let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_def_id()];
path[..path.len() - 1].join("/")
},
ty = it.type_(),
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
- render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
- render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
-fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
+fn item_typedef(
+ w: &mut Buffer,
+ cx: &Context<'_>,
+ it: &clean::Item,
+ t: &clean::Typedef,
+ is_associated: bool,
+) {
w.write_str("<pre class=\"rust typedef\">");
render_attributes_in_pre(w, it, "");
+ if !is_associated {
+ write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
+ }
write!(
w,
"type {}{}{where_clause} = {type_};</pre>",
document(w, cx, it, None);
- let def_id = it.def_id.expect_real();
+ let def_id = it.def_id.expect_def_id();
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
document(w, cx, field, Some(it));
}
}
- let def_id = it.def_id.expect_real();
+ let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
}
}
}
- let def_id = it.def_id.expect_real();
+ let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None);
- render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
}
}
}
- let def_id = it.def_id.expect_real();
+ let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
document(w, cx, it, None);
- render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
+++ /dev/null
-Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
-with Reserved Font Name < Fira >,
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
+++ /dev/null
-Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
+++ /dev/null
-Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
+++ /dev/null
-<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
+++ /dev/null
-<svg width="24" height="25" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
--- /dev/null
+/* ignore-tidy-linelength */
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
--- /dev/null
+/*
+This whole CSS file is used only in case rustdoc is rendered with javascript disabled. Since a lot
+of content is hidden by default (depending on the settings too), we have to overwrite some of the
+rules.
+*/
+
+#main .attributes {
+ /* Since there is no toggle (the "[-]") when JS is disabled, no need for this margin either. */
+ margin-left: 0 !important;
+}
+
+#copy-path {
+ /* It requires JS to work so no need to display it in this case. */
+ display: none;
+}
--- /dev/null
+/* See FiraSans-LICENSE.txt for the Fira Sans license. */
+@font-face {
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Fira Sans'),
+ url("FiraSans-Regular.woff2") format("woff2"),
+ url("FiraSans-Regular.woff") format('woff');
+ font-display: swap;
+}
+@font-face {
+ font-family: 'Fira Sans';
+ font-style: normal;
+ font-weight: 500;
+ src: local('Fira Sans Medium'),
+ url("FiraSans-Medium.woff2") format("woff2"),
+ url("FiraSans-Medium.woff") format('woff');
+ font-display: swap;
+}
+
+/* See SourceSerif4-LICENSE.md for the Source Serif 4 license. */
+@font-face {
+ font-family: 'Source Serif 4';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Source Serif 4'),
+ url("SourceSerif4-Regular.ttf.woff2") format("woff2"),
+ url("SourceSerif4-Regular.ttf.woff") format("woff");
+ font-display: swap;
+}
+@font-face {
+ font-family: 'Source Serif 4';
+ font-style: italic;
+ font-weight: 400;
+ src: local('Source Serif 4 Italic'),
+ url("SourceSerif4-It.ttf.woff2") format("woff2"),
+ url("SourceSerif4-It.ttf.woff") format("woff");
+ font-display: swap;
+}
+@font-face {
+ font-family: 'Source Serif 4';
+ font-style: normal;
+ font-weight: 700;
+ src: local('Source Serif 4 Bold'),
+ url("SourceSerif4-Bold.ttf.woff2") format("woff2"),
+ url("SourceSerif4-Bold.ttf.woff") format("woff");
+ font-display: swap;
+}
+
+/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
+@font-face {
+ font-family: 'Source Code Pro';
+ font-style: normal;
+ font-weight: 400;
+ /* Avoid using locally installed font because bad versions are in circulation:
+ * see https://github.com/rust-lang/rust/issues/24355 */
+ src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"),
+ url("SourceCodePro-Regular.ttf.woff") format("woff");
+ font-display: swap;
+}
+@font-face {
+ font-family: 'Source Code Pro';
+ font-style: italic;
+ font-weight: 400;
+ src: url("SourceCodePro-It.ttf.woff2") format("woff2"),
+ url("SourceCodePro-It.ttf.woff") format("woff");
+ font-display: swap;
+}
+@font-face {
+ font-family: 'Source Code Pro';
+ font-style: normal;
+ font-weight: 600;
+ src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),
+ url("SourceCodePro-Semibold.ttf.woff") format("woff");
+ font-display: swap;
+}
+
+/* Avoid using legacy CJK serif fonts in Windows like Batang */
+@font-face {
+ font-family: 'Noto Sans KR';
+ src: url("noto-sans-kr-v13-korean-regular.woff") format("woff");
+ font-display: swap;
+ unicode-range: U+A960-A97F, U+AC00-D7AF, U+D7B0-D7FF;
+}
+
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* This part handles the "default" theme being used depending on the system one. */
+html {
+ content: "";
+}
+@media (prefers-color-scheme: light) {
+ html {
+ content: "light";
+ }
+}
+@media (prefers-color-scheme: dark) {
+ html {
+ content: "dark";
+ }
+}
+
+/* General structure and fonts */
+
+body {
+ font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif;
+ margin: 0;
+ position: relative;
+ padding: 10px 15px 20px 15px;
+
+ -webkit-font-feature-settings: "kern", "liga";
+ -moz-font-feature-settings: "kern", "liga";
+ font-feature-settings: "kern", "liga";
+}
+
+h1 {
+ font-size: 1.5em;
+}
+h2 {
+ font-size: 1.4em;
+}
+h3 {
+ font-size: 1.3em;
+}
+h1, h2, h3, h4 {
+ font-weight: 500;
+ margin: 20px 0 15px 0;
+ padding-bottom: 6px;
+}
+h1.fqn {
+ display: flex;
+ border-bottom: 1px dashed;
+ margin-top: 0;
+
+ /* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
+ above the h1 */
+ padding-left: 1px;
+}
+h1.fqn > .in-band > a:hover {
+ text-decoration: underline;
+}
+h2, h3, h4 {
+ border-bottom: 1px solid;
+}
+.impl,
+.impl-items .method,
+.methods .method,
+.impl-items .type,
+.methods .type,
+.impl-items .associatedconstant,
+.methods .associatedconstant,
+.impl-items .associatedtype,
+.methods .associatedtype {
+ flex-basis: 100%;
+ font-weight: 600;
+ margin-top: 16px;
+ margin-bottom: 10px;
+ position: relative;
+}
+.impl, .method.trait-impl,
+.type.trait-impl,
+.associatedconstant.trait-impl,
+.associatedtype.trait-impl {
+ padding-left: 15px;
+}
+
+div.impl-items > div {
+ padding-left: 0;
+}
+
+h1, h2, h3, h4,
+.sidebar, a.source, .search-input, .search-results .result-name,
+.content table td:first-child > a,
+.item-left > a,
+div.item-list .out-of-band, span.since,
+#source-sidebar, #sidebar-toggle,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before,
+div.impl-items > div:not(.docblock):not(.item-info),
+.content ul.crate a.crate, a.srclink,
+/* This selector is for the items listed in the "all items" page. */
+#main > ul.docblock > li > a {
+ font-family: "Fira Sans", Arial, sans-serif;
+}
+
+.content ul.crate a.crate {
+ font-size: 16px/1.6;
+}
+
+ol, ul {
+ padding-left: 25px;
+}
+ul ul, ol ul, ul ol, ol ol {
+ margin-bottom: .6em;
+}
+
+p {
+ margin: 0 0 .6em 0;
+}
+
+summary {
+ outline: none;
+}
+
+/* Fix some style changes due to normalize.css 8 */
+
+td,
+th {
+ padding: 0;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+
+/* end tweaks for normalize.css 8 */
+
+details:not(.rustdoc-toggle) summary {
+ margin-bottom: .6em;
+}
+
+code, pre, a.test-arrow {
+ font-family: "Source Code Pro", monospace;
+}
+.docblock code, .docblock-short code {
+ border-radius: 3px;
+ padding: 0 0.1em;
+}
+.docblock pre code, .docblock-short pre code {
+ padding: 0;
+ padding-right: 1ex;
+}
+pre {
+ padding: 14px;
+}
+
+.source .content pre {
+ padding: 20px;
+}
+
+img {
+ max-width: 100%;
+}
+
+li {
+ position: relative;
+}
+
+.source .content {
+ margin-top: 50px;
+ max-width: none;
+ overflow: visible;
+ margin-left: 0px;
+}
+
+nav.sub {
+ font-size: 16px;
+ text-transform: uppercase;
+}
+
+.sidebar {
+ width: 200px;
+ position: fixed;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ overflow: auto;
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+ scrollbar-width: initial;
+}
+.sidebar {
+ scrollbar-width: thin;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar {
+ width: 12px;
+}
+.sidebar::-webkit-scrollbar {
+ width: 8px;
+}
+::-webkit-scrollbar-track {
+ -webkit-box-shadow: inset 0;
+}
+
+.sidebar .block > ul > li {
+ margin-right: -10px;
+}
+
+.content, nav {
+ max-width: 960px;
+}
+
+/* Everything else */
+
+.hidden {
+ display: none !important;
+}
+
+.logo-container {
+ height: 100px;
+ width: 100px;
+ position: relative;
+ margin: 20px auto;
+ display: block;
+ margin-top: 10px;
+}
+
+.logo-container > img {
+ max-width: 100px;
+ max-height: 100px;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ display: block;
+}
+
+.sidebar .location {
+ border: 1px solid;
+ font-size: 17px;
+ margin: 30px 10px 20px 10px;
+ text-align: center;
+ word-wrap: break-word;
+}
+
+.sidebar .version {
+ font-size: 15px;
+ text-align: center;
+ border-bottom: 1px solid;
+ overflow-wrap: break-word;
+ word-wrap: break-word; /* deprecated */
+ word-break: break-word; /* Chrome, non-standard */
+}
+
+.location:empty {
+ border: none;
+}
+
+.location a:first-of-type {
+ font-weight: 500;
+}
+.location a:hover {
+ text-decoration: underline;
+}
+
+.block {
+ padding: 0;
+ margin-bottom: 14px;
+}
+.block h2, .block h3 {
+ text-align: center;
+}
+.block ul, .block li {
+ margin: 0 10px;
+ padding: 0;
+ list-style: none;
+}
+
+.block a {
+ display: block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ line-height: 15px;
+ padding: 7px 5px;
+ font-size: 14px;
+ font-weight: 300;
+ transition: border 500ms ease-out;
+}
+
+.sidebar-title {
+ border-top: 1px solid;
+ border-bottom: 1px solid;
+ text-align: center;
+ font-size: 17px;
+ margin-bottom: 5px;
+}
+
+.sidebar-links {
+ margin-bottom: 15px;
+}
+
+.sidebar-links > a {
+ padding-left: 10px;
+ width: 100%;
+}
+
+.sidebar-menu {
+ display: none;
+}
+
+.content {
+ padding: 15px 0;
+}
+
+.source .content pre.rust {
+ white-space: pre;
+ overflow: auto;
+ padding-left: 0;
+}
+
+.rustdoc .example-wrap {
+ display: inline-flex;
+ margin-bottom: 10px;
+}
+
+.example-wrap {
+ position: relative;
+ width: 100%;
+}
+
+.example-wrap > pre.line-number {
+ overflow: initial;
+ border: 1px solid;
+ padding: 13px 8px;
+ text-align: right;
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+}
+
+.rustdoc:not(.source) .example-wrap > pre.rust {
+ width: 100%;
+ overflow-x: auto;
+}
+
+.rustdoc .example-wrap > pre {
+ margin: 0;
+}
+
+#search {
+ margin-left: 230px;
+ position: relative;
+}
+
+#results > table {
+ width: 100%;
+ table-layout: fixed;
+}
+
+.content > .example-wrap pre.line-numbers {
+ position: relative;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.line-numbers span {
+ cursor: pointer;
+}
+
+.docblock-short {
+ overflow-wrap: anywhere;
+}
+.docblock-short p {
+ display: inline;
+}
+
+.docblock-short p {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin: 0;
+}
+/* Wrap non-pre code blocks (`text`) but not (```text```). */
+.docblock > :not(pre) > code,
+.docblock-short > :not(pre) > code {
+ white-space: pre-wrap;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+ border-bottom: 1px solid;
+}
+
+.top-doc .docblock h1 { font-size: 1.3em; }
+.top-doc .docblock h2 { font-size: 1.15em; }
+.top-doc .docblock h3,
+.top-doc .docblock h4,
+.top-doc .docblock h5 {
+ font-size: 1em;
+}
+
+.docblock h1 { font-size: 1em; }
+.docblock h2 { font-size: 0.95em; }
+.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
+
+.docblock {
+ margin-left: 24px;
+ position: relative;
+}
+
+.content .out-of-band {
+ flex-grow: 0;
+ text-align: right;
+ font-size: 23px;
+ margin: 0px;
+ padding: 0 0 0 12px;
+ font-weight: normal;
+}
+
+.method > code, .trait-impl > code, .invisible > code {
+ max-width: calc(100% - 41px);
+ display: block;
+}
+
+.invisible {
+ width: 100%;
+ display: inline-block;
+}
+
+.content .in-band {
+ flex-grow: 1;
+ margin: 0px;
+ padding: 0px;
+}
+
+.in-band > code {
+ display: inline-block;
+}
+
+#main {
+ position: relative;
+}
+#main > .since {
+ top: inherit;
+ font-family: "Fira Sans", Arial, sans-serif;
+}
+
+.content table:not(.table-display) {
+ border-spacing: 0 5px;
+}
+.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 {
+ margin: .5em 0;
+ width: calc(100% - 2px);
+ border: 1px dashed;
+}
+
+.docblock table td {
+ padding: .5em;
+ border: 1px dashed;
+}
+
+.docblock table th {
+ padding: .5em;
+ text-align: left;
+ border: 1px solid;
+}
+
+.fields + table {
+ margin-bottom: 1em;
+}
+
+.content .item-list {
+ list-style-type: none;
+ padding: 0;
+}
+
+.content .multi-column {
+ -moz-column-count: 5;
+ -moz-column-gap: 2.5em;
+ -webkit-column-count: 5;
+ -webkit-column-gap: 2.5em;
+ column-count: 5;
+ column-gap: 2.5em;
+}
+.content .multi-column li { width: 100%; display: inline-block; }
+
+.content > .methods > .method {
+ font-size: 1em;
+ position: relative;
+}
+/* Shift "where ..." part of method or fn definition down a line */
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+ display: block;
+ font-size: 0.8em;
+}
+
+.content .methods > div:not(.notable-traits):not(.method) {
+ margin-left: 40px;
+ margin-bottom: 15px;
+}
+
+.content .docblock > .impl-items {
+ margin-left: 20px;
+ margin-top: -34px;
+}
+.content .docblock >.impl-items .table-display {
+ margin: 0;
+}
+.content .docblock >.impl-items table td {
+ padding: 0;
+}
+.content .docblock > .impl-items .table-display, .impl-items table td {
+ border: none;
+}
+
+.content .item-info code {
+ font-size: 90%;
+}
+
+.content .item-info {
+ position: relative;
+ margin-left: 33px;
+}
+
+.sub-variant > div > .item-info {
+ margin-top: initial;
+}
+
+.content .item-info::before {
+ content: '⬑';
+ font-size: 25px;
+ position: absolute;
+ top: -6px;
+ left: -19px;
+}
+
+.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant,
+.impl-items > .associatedtype, .content .impl-items details > summary > .type,
+.impl-items details > summary > .associatedconstant,
+.impl-items details > summary > .associatedtype {
+ margin-left: 20px;
+}
+
+.content .impl-items .docblock, .content .impl-items .item-info {
+ margin-bottom: .6em;
+}
+
+.content .impl-items > .item-info {
+ margin-left: 40px;
+}
+
+.methods > .item-info, .content .impl-items > .item-info {
+ margin-top: -8px;
+}
+
+.impl-items {
+ flex-basis: 100%;
+}
+
+#main > .item-info {
+ margin-top: 0;
+}
+
+nav:not(.sidebar) {
+ border-bottom: 1px solid;
+ padding-bottom: 10px;
+ margin-bottom: 10px;
+}
+nav.main {
+ padding: 20px 0;
+ text-align: center;
+}
+nav.main .current {
+ border-top: 1px solid;
+ border-bottom: 1px solid;
+}
+nav.main .separator {
+ border: 1px solid;
+ display: inline-block;
+ height: 23px;
+ margin: 0 20px;
+}
+nav.sum { text-align: right; }
+nav.sub form { display: inline; }
+
+nav.sub, .content {
+ margin-left: 230px;
+}
+
+a {
+ text-decoration: none;
+ background: transparent;
+}
+
+.small-section-header {
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+}
+
+.small-section-header:hover > .anchor {
+ display: initial;
+}
+
+.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor,
+.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor,
+.associatedtype.trait-impl:hover > .anchor {
+ display: inline-block;
+ position: absolute;
+}
+.anchor {
+ display: none;
+ position: absolute;
+ left: -7px;
+}
+.anchor.field {
+ left: -5px;
+}
+.small-section-header > .anchor {
+ left: -28px;
+ padding-right: 10px; /* avoid gap that causes hover to disappear */
+}
+.anchor:before {
+ content: '\2002\00a7\2002';
+}
+
+.docblock a:not(.srclink):not(.test-arrow):hover,
+.docblock-short a:not(.srclink):not(.test-arrow):hover, .item-info a {
+ text-decoration: underline;
+}
+
+.invisible > .srclink,
+.method > code + .srclink {
+ position: absolute;
+ top: 0;
+ right: 0;
+ font-size: 17px;
+ font-weight: normal;
+}
+
+.block a.current.crate { font-weight: 500; }
+
+.item-table {
+ display: grid;
+ column-gap: 1.2rem;
+ row-gap: 0.0rem;
+ grid-template-columns: auto 1fr;
+ /* align content left */
+ justify-items: start;
+}
+
+.item-left, .item-right {
+ display: block;
+}
+.item-left {
+ grid-column: 1;
+}
+.item-right {
+ grid-column: 2;
+}
+
+.search-container {
+ position: relative;
+}
+.search-container > div {
+ display: inline-flex;
+ width: calc(100% - 63px);
+}
+#crate-search {
+ min-width: 115px;
+ margin-top: 5px;
+ padding: 6px;
+ padding-right: 19px;
+ flex: none;
+ border: 0;
+ border-right: 0;
+ border-radius: 4px 0 0 4px;
+ outline: none;
+ cursor: pointer;
+ border-right: 1px solid;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ /* Removes default arrow from firefox */
+ text-indent: 0.01px;
+ text-overflow: "";
+ background-repeat: no-repeat;
+ background-color: transparent;
+ background-size: 20px;
+ background-position: calc(100% - 1px) 56%;
+}
+.search-container > .top-button {
+ position: absolute;
+ right: 0;
+ top: 10px;
+}
+.search-input {
+ /* Override Normalize.css: we have margins and do
+ not want to overflow - the `moz` attribute is necessary
+ until Firefox 29, too early to drop at this point */
+ -moz-box-sizing: border-box !important;
+ box-sizing: border-box !important;
+ outline: none;
+ border: none;
+ border-radius: 1px;
+ margin-top: 5px;
+ padding: 10px 16px;
+ font-size: 17px;
+ transition: border-color 300ms ease;
+ transition: border-radius 300ms ease-in-out;
+ transition: box-shadow 300ms ease-in-out;
+ width: 100%;
+}
+
+#crate-search + .search-input {
+ border-radius: 0 1px 1px 0;
+ width: calc(100% - 32px);
+}
+
+.search-input:focus {
+ border-radius: 2px;
+ border: 0;
+ outline: 0;
+}
+
+.search-results {
+ display: none;
+ padding-bottom: 2em;
+}
+
+.search-results.active {
+ display: block;
+ /* prevent overhanging tabs from moving the first result */
+ clear: both;
+}
+
+.search-results .desc > span {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ display: block;
+}
+
+.search-results > a {
+ display: block;
+ width: 100%;
+ /* A little margin ensures the browser's outlining of focused links has room to display. */
+ margin-left: 2px;
+ margin-right: 2px;
+ border-bottom: 1px solid #aaa3;
+}
+
+.search-results > a > div {
+ display: flex;
+ flex-flow: row wrap;
+}
+
+.search-results .result-name, .search-results div.desc, .search-results .result-description {
+ width: 50%;
+}
+.search-results .result-name {
+ padding-right: 1em;
+}
+
+.search-results .result-name > span {
+ display: inline-block;
+ margin: 0;
+ font-weight: normal;
+}
+
+body.blur > :not(#help) {
+ filter: blur(8px);
+ -webkit-filter: blur(8px);
+ opacity: .7;
+}
+
+#help {
+ width: 100%;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+#help > div {
+ flex: 0 0 auto;
+ box-shadow: 0 0 6px rgba(0,0,0,.2);
+ width: 550px;
+ height: auto;
+ border: 1px solid;
+}
+#help dt {
+ float: left;
+ clear: left;
+ display: block;
+ margin-right: 0.5rem;
+}
+#help > div > span {
+ text-align: center;
+ display: block;
+ margin: 10px 0;
+ font-size: 18px;
+ border-bottom: 1px solid #ccc;
+ padding-bottom: 4px;
+ margin-bottom: 6px;
+}
+#help dd { margin: 5px 35px; }
+#help .infos { padding-left: 0; }
+#help h1, #help h2 { margin-top: 0; }
+#help > div div {
+ width: 50%;
+ float: left;
+ padding: 0 20px 20px 17px;;
+}
+
+.stab {
+ border-width: 1px;
+ border-style: solid;
+ padding: 3px;
+ margin-bottom: 5px;
+ font-size: 90%;
+ font-weight: normal;
+}
+.stab p {
+ display: inline;
+}
+
+.stab .emoji {
+ font-size: 1.5em;
+}
+
+/* Black one-pixel outline around emoji shapes */
+.emoji {
+ text-shadow:
+ 1px 0 0 black,
+ -1px 0 0 black,
+ 0 1px 0 black,
+ 0 -1px 0 black;
+}
+
+.module-item .stab,
+.import-item .stab {
+ border-radius: 3px;
+ display: inline-block;
+ font-size: 80%;
+ line-height: 1.2;
+ margin-bottom: 0;
+ margin-left: .3em;
+ padding: 2px;
+ vertical-align: text-bottom;
+}
+
+.module-item.unstable,
+.import-item.unstable {
+ opacity: 0.65;
+}
+
+.since {
+ font-weight: normal;
+ font-size: initial;
+}
+
+.impl-items .since, .impl .since, .methods .since {
+ padding-left: 12px;
+ padding-right: 2px;
+ position: initial;
+}
+
+.impl-items .srclink, .impl .srclink, .methods .srclink {
+ /* Override header settings otherwise it's too bold */
+ font-size: 17px;
+ font-weight: normal;
+}
+
+.rightside {
+ float: right;
+}
+
+.has-srclink {
+ font-size: 16px;
+ margin-bottom: 12px;
+ /* Push the src link out to the right edge consistently */
+ justify-content: space-between;
+}
+
+.variants_table {
+ width: 100%;
+}
+
+.variants_table tbody tr td:first-child {
+ width: 1%; /* make the variant name as small as possible */
+}
+
+td.summary-column {
+ width: 100%;
+}
+
+.summary {
+ padding-right: 0px;
+}
+
+pre.rust .question-mark {
+ font-weight: bold;
+}
+
+a.test-arrow {
+ display: inline-block;
+ position: absolute;
+ padding: 5px 10px 5px 10px;
+ border-radius: 5px;
+ font-size: 130%;
+ top: 5px;
+ right: 5px;
+ z-index: 1;
+}
+a.test-arrow:hover{
+ text-decoration: none;
+}
+
+.section-header:hover a:before {
+ position: absolute;
+ left: -25px;
+ padding-right: 10px; /* avoid gap that causes hover to disappear */
+ content: '\2002\00a7\2002';
+}
+
+.section-header:hover a {
+ text-decoration: none;
+}
+
+.section-header a {
+ color: inherit;
+}
+
+.code-attribute {
+ font-weight: 300;
+}
+
+.since + .srclink {
+ padding-left: 10px;
+}
+
+.item-spacer {
+ width: 100%;
+ height: 12px;
+}
+
+.out-of-band > span.since {
+ position: initial;
+ font-size: 20px;
+ margin-right: 5px;
+}
+
+.sub-variant, .sub-variant > h3 {
+ margin-top: 0px !important;
+ padding-top: 1px;
+}
+
+#main > details > .sub-variant > h3 {
+ font-size: 15px;
+ margin-left: 25px;
+ margin-bottom: 5px;
+}
+
+.sub-variant > div {
+ margin-left: 20px;
+ margin-bottom: 10px;
+}
+
+.sub-variant > div > span {
+ display: block;
+ position: relative;
+}
+
+.toggle-label {
+ display: inline-block;
+ margin-left: 4px;
+ margin-top: 3px;
+}
+
+.docblock > .section-header:first-child {
+ margin-left: 15px;
+ margin-top: 0;
+}
+
+.docblock > .section-header:first-child:hover > a:before {
+ left: -10px;
+}
+
+:target > code {
+ opacity: 1;
+}
+
+:target {
+ padding-right: 3px;
+}
+
+.information {
+ position: absolute;
+ left: -25px;
+ margin-top: 7px;
+ z-index: 1;
+}
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+ cursor: pointer;
+}
+
+.tooltip::after {
+ display: none;
+ text-align: center;
+ padding: 5px 3px 3px 3px;
+ border-radius: 6px;
+ margin-left: 5px;
+ font-size: 16px;
+}
+
+.tooltip.ignore::after {
+ content: "This example is not tested";
+}
+.tooltip.compile_fail::after {
+ content: "This example deliberately fails to compile";
+}
+.tooltip.should_panic::after {
+ content: "This example panics";
+}
+.tooltip.edition::after {
+ content: "This code runs with edition " attr(data-edition);
+}
+
+.tooltip::before {
+ content: " ";
+ position: absolute;
+ top: 50%;
+ left: 16px;
+ margin-top: -5px;
+ border-width: 5px;
+ border-style: solid;
+ display: none;
+}
+
+.tooltip:hover::before, .tooltip:hover::after {
+ display: inline;
+}
+
+.tooltip.compile_fail, .tooltip.should_panic, .tooltip.ignore {
+ font-weight: bold;
+ font-size: 20px;
+}
+
+.notable-traits-tooltip {
+ display: inline-block;
+ cursor: pointer;
+}
+
+.notable-traits:hover .notable-traits-tooltiptext,
+.notable-traits .notable-traits-tooltiptext.force-tooltip {
+ display: inline-block;
+}
+
+.notable-traits .notable-traits-tooltiptext {
+ display: none;
+ padding: 5px 3px 3px 3px;
+ border-radius: 6px;
+ margin-left: 5px;
+ z-index: 10;
+ font-size: 16px;
+ cursor: default;
+ position: absolute;
+ border: 1px solid;
+}
+
+.notable-traits-tooltip::after {
+ /* The margin on the tooltip does not capture hover events,
+ this extends the area of hover enough so that mouse hover is not
+ lost when moving the mouse to the tooltip */
+ content: "\00a0\00a0\00a0";
+}
+
+.notable-traits .notable, .notable-traits .docblock {
+ margin: 0;
+}
+
+.notable-traits .notable {
+ margin: 0;
+ margin-bottom: 13px;
+ font-size: 19px;
+ font-weight: 600;
+}
+
+.notable-traits .docblock code.content{
+ margin: 0;
+ padding: 0;
+ font-size: 20px;
+}
+
+/* Example code has the "Run" button that needs to be positioned relative to the pre */
+pre.rust.rust-example-rendered {
+ position: relative;
+}
+
+pre.rust {
+ tab-size: 4;
+ -moz-tab-size: 4;
+}
+
+.search-failed {
+ text-align: center;
+ margin-top: 20px;
+ display: none;
+}
+
+.search-failed.active {
+ display: block;
+}
+
+.search-failed > ul {
+ text-align: left;
+ max-width: 570px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+#titles {
+ height: 35px;
+}
+
+#titles > button {
+ float: left;
+ width: 33.3%;
+ text-align: center;
+ font-size: 18px;
+ cursor: pointer;
+ border: 0;
+ border-top: 2px solid;
+}
+
+#titles > button:not(:last-child) {
+ margin-right: 1px;
+ width: calc(33.3% - 1px);
+}
+
+#titles > button > div.count {
+ display: inline-block;
+ font-size: 16px;
+}
+
+.notable-traits {
+ cursor: pointer;
+ z-index: 2;
+ margin-left: 5px;
+}
+
+#all-types {
+ text-align: center;
+ border: 1px solid;
+ margin: 0 10px;
+ margin-bottom: 10px;
+ display: block;
+ border-radius: 7px;
+}
+#all-types > p {
+ margin: 5px 0;
+}
+
+#sidebar-toggle {
+ position: fixed;
+ top: 30px;
+ left: 300px;
+ z-index: 10;
+ padding: 3px;
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+ cursor: pointer;
+ font-weight: bold;
+ transition: left .5s;
+ font-size: 1.2em;
+ border: 1px solid;
+ border-left: 0;
+}
+#source-sidebar {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 300px;
+ z-index: 1;
+ overflow: auto;
+ transition: left .5s;
+ border-right: 1px solid;
+}
+#source-sidebar > .title {
+ font-size: 1.5em;
+ text-align: center;
+ border-bottom: 1px solid;
+ margin-bottom: 6px;
+}
+
+.theme-picker {
+ position: absolute;
+ left: 211px;
+ top: 19px;
+}
+
+.theme-picker button {
+ outline: none;
+}
+
+#settings-menu, #help-button {
+ position: absolute;
+ top: 10px;
+}
+
+#settings-menu {
+ right: 0;
+ outline: none;
+}
+
+#theme-picker, #settings-menu, #help-button, #copy-path {
+ padding: 4px;
+ width: 27px;
+ height: 29px;
+ border: 1px solid;
+ border-radius: 3px;
+ cursor: pointer;
+}
+
+#help-button {
+ right: 30px;
+ font-family: "Fira Sans", Arial, sans-serif;
+ text-align: center;
+ font-size: 17px;
+ padding-top: 2px;
+}
+
+#copy-path {
+ background: initial;
+ margin-left: 10px;
+ padding: 0;
+ padding-left: 2px;
+ border: 0;
+}
+
+#theme-choices {
+ display: none;
+ position: absolute;
+ left: 0;
+ top: 28px;
+ border: 1px solid;
+ border-radius: 3px;
+ z-index: 1;
+ cursor: pointer;
+}
+
+#theme-choices > button {
+ border: none;
+ width: 100%;
+ padding: 4px 8px;
+ text-align: center;
+ background: rgba(0,0,0,0);
+}
+
+#theme-choices > button:not(:first-child) {
+ border-top: 1px solid;
+}
+
+kbd {
+ display: inline-block;
+ padding: 3px 5px;
+ font: 15px monospace;
+ line-height: 10px;
+ vertical-align: middle;
+ border: solid 1px;
+ border-radius: 3px;
+ box-shadow: inset 0 -1px 0;
+ cursor: default;
+}
+
+.hidden-by-impl-hider,
+.hidden-by-usual-hider {
+ /* important because of conflicting rule for small screens */
+ display: none !important;
+}
+
+#implementations-list > h3 > span.in-band {
+ width: 100%;
+}
+
+.table-display {
+ width: 100%;
+ border: 0;
+ border-collapse: collapse;
+ border-spacing: 0;
+ font-size: 16px;
+}
+
+.table-display tr td:first-child {
+ padding-right: 0;
+}
+
+.table-display tr td:last-child {
+ float: right;
+}
+.table-display .out-of-band {
+ position: relative;
+ font-size: 19px;
+ display: block;
+}
+#implementors-list > .impl-items .table-display .out-of-band {
+ font-size: 17px;
+}
+
+.table-display td:hover .anchor {
+ display: block;
+ top: 2px;
+ left: -5px;
+}
+
+#main > ul {
+ padding-left: 10px;
+}
+#main > ul > li {
+ list-style: none;
+}
+
+.non-exhaustive {
+ margin-bottom: 1em;
+}
+
+div.children {
+ padding-left: 27px;
+ display: none;
+}
+div.name {
+ cursor: pointer;
+ position: relative;
+ margin-left: 16px;
+}
+div.files > a {
+ display: block;
+ padding: 0 3px;
+}
+div.files > a:hover, div.name:hover {
+ background-color: #a14b4b;
+}
+div.name.expand + .children {
+ display: block;
+}
+div.name::before {
+ content: "\25B6";
+ padding-left: 4px;
+ font-size: 0.7em;
+ position: absolute;
+ left: -16px;
+ top: 4px;
+}
+div.name.expand::before {
+ transform: rotate(90deg);
+ left: -15px;
+ top: 2px;
+}
+
+/* The hideme class is used on summary tags that contain a span with
+ placeholder text shown only when the toggle is closed. For instance,
+ "Expand description" or "Show methods". */
+details.rustdoc-toggle > summary.hideme {
+ cursor: pointer;
+}
+
+details.rustdoc-toggle > summary, details.undocumented > summary {
+ list-style: none;
+}
+details.rustdoc-toggle > summary::-webkit-details-marker,
+details.rustdoc-toggle > summary::marker,
+details.undocumented > summary::-webkit-details-marker,
+details.undocumented > summary::marker {
+ display: none;
+}
+
+details.rustdoc-toggle > summary.hideme > span {
+ margin-left: 9px;
+}
+
+details.rustdoc-toggle > summary::before {
+ content: "[+]";
+ font-weight: 300;
+ font-size: 0.8em;
+ letter-spacing: 1px;
+ cursor: pointer;
+}
+
+details.rustdoc-toggle.top-doc > summary,
+details.rustdoc-toggle.top-doc > summary::before,
+details.rustdoc-toggle.non-exhaustive > summary,
+details.rustdoc-toggle.non-exhaustive > summary::before {
+ font-family: 'Fira Sans';
+ font-size: 16px;
+}
+
+details.non-exhaustive {
+ margin-bottom: 8px;
+}
+
+details.rustdoc-toggle > summary.hideme::before {
+ position: relative;
+}
+
+details.rustdoc-toggle > summary:not(.hideme)::before {
+ position: absolute;
+ left: -23px;
+ top: 3px;
+}
+
+.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
+.undocumented > details.rustdoc-toggle > summary:not(.hideme)::before {
+ position: absolute;
+ left: -2px;
+}
+
+/* When a "hideme" summary is open and the "Expand description" or "Show
+ methods" text is hidden, we want the [-] toggle that remains to not
+ affect the layout of the items to its right. To do that, we use
+ absolute positioning. Note that we also set position: relative
+ on the parent <details> to make this work properly. */
+details.rustdoc-toggle[open] > summary.hideme {
+ position: absolute;
+}
+
+details.rustdoc-toggle, details.undocumented {
+ position: relative;
+}
+
+details.rustdoc-toggle[open] > summary.hideme > span {
+ display: none;
+}
+
+details.rustdoc-toggle[open] > summary::before {
+ content: "[−]";
+ display: inline;
+}
+
+details.undocumented > summary::before {
+ content: "[+] Show hidden undocumented items";
+ cursor: pointer;
+ font-size: 16px;
+ font-weight: 300;
+}
+
+details.undocumented[open] > summary::before {
+ content: "[−] Hide undocumented items";
+}
+
+/* Media Queries */
+
+@media (min-width: 701px) {
+ /* In case there is no documentation before a code block, we need to add some margin at the top
+ to prevent an overlay between the "collapse toggle" and the information tooltip.
+ However, it's not needed with smaller screen width because the doc/code block is always put
+ "one line" below. */
+ .docblock > .information:first-child > .tooltip {
+ margin-top: 16px;
+ }
+}
+
+@media (max-width: 700px) {
+ body {
+ padding-top: 0px;
+ }
+
+ .rustdoc > .sidebar {
+ height: 45px;
+ min-height: 40px;
+ margin: 0;
+ margin-left: -15px;
+ padding: 0 15px;
+ position: static;
+ z-index: 11;
+ }
+
+ .sidebar > .location {
+ float: right;
+ margin: 0px;
+ margin-top: 2px;
+ padding: 3px 10px 1px 10px;
+ min-height: 39px;
+ background: inherit;
+ text-align: left;
+ font-size: 24px;
+ }
+
+ .sidebar .location:empty {
+ padding: 0;
+ }
+
+ .sidebar .logo-container {
+ width: 35px;
+ height: 35px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ float: left;
+ margin-left: 50px;
+ }
+
+ .sidebar .logo-container > img {
+ max-width: 35px;
+ max-height: 35px;
+ }
+
+ .sidebar-menu {
+ position: fixed;
+ z-index: 10;
+ font-size: 2rem;
+ cursor: pointer;
+ width: 45px;
+ left: 0;
+ text-align: center;
+ display: block;
+ border-bottom: 1px solid;
+ border-right: 1px solid;
+ height: 45px;
+ }
+
+ .rustdoc.source > .sidebar > .sidebar-menu {
+ display: none;
+ }
+
+ .sidebar-elems {
+ position: fixed;
+ z-index: 1;
+ left: 0;
+ top: 45px;
+ bottom: 0;
+ overflow-y: auto;
+ border-right: 1px solid;
+ display: none;
+ }
+
+ .sidebar > .block.version {
+ overflow: hidden;
+ border-bottom: none;
+ margin-bottom: 0;
+ height: 100%;
+ padding-left: 12px;
+ }
+ .sidebar > .block.version > div.narrow-helper {
+ float: left;
+ width: 1px;
+ height: 100%;
+ }
+ .sidebar > .block.version > p {
+ /* hide Version text if too narrow */
+ margin: 0;
+ min-width: 55px;
+ /* vertically center */
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+
+ nav.sub {
+ width: calc(100% - 32px);
+ float: right;
+ }
+
+ .content {
+ margin-left: 0px;
+ }
+
+ #main, #search {
+ margin-top: 45px;
+ padding: 0;
+ }
+
+ #search {
+ margin-left: 0;
+ }
+
+ .anchor {
+ display: none !important;
+ }
+
+ .theme-picker {
+ left: 10px;
+ top: 54px;
+ z-index: 1;
+ }
+
+ .notable-traits {
+ position: absolute;
+ left: -22px;
+ top: 24px;
+ }
+
+ #titles > button > div.count {
+ float: left;
+ width: 100%;
+ }
+
+ #titles {
+ height: 50px;
+ }
+
+ .sidebar.mobile {
+ position: fixed;
+ width: 100%;
+ margin-left: 0;
+ background-color: rgba(0,0,0,0);
+ height: 100%;
+ }
+ /*
+ This allows to prevent the version text to overflow the sidebar title on mobile mode when the
+ sidebar is displayed (after clicking on the "hamburger" button).
+ */
+ .sidebar.mobile > div.version {
+ overflow: hidden;
+ max-height: 33px;
+ }
+ .sidebar {
+ width: calc(100% + 30px);
+ }
+
+ .show-it {
+ display: block;
+ width: 246px;
+ }
+
+ .show-it > .block.items {
+ margin: 8px 0;
+ }
+
+ .show-it > .block.items > ul {
+ margin: 0;
+ }
+
+ .show-it > .block.items > ul > li {
+ text-align: center;
+ margin: 2px 0;
+ }
+
+ .show-it > .block.items > ul > li > a {
+ font-size: 21px;
+ }
+
+ /* Because of ios, we need to actually have a full height sidebar title so the
+ * actual sidebar can show up. But then we need to make it transparent so we don't
+ * hide content. The filler just allows to create the background for the sidebar
+ * title. But because of the absolute position, I had to lower the z-index.
+ */
+ #sidebar-filler {
+ position: fixed;
+ left: 45px;
+ width: calc(100% - 45px);
+ top: 0;
+ height: 45px;
+ z-index: -1;
+ border-bottom: 1px solid;
+ }
+
+ #main > details.rustdoc-toggle > summary::before,
+ #main > div > details.rustdoc-toggle > summary::before {
+ left: -11px;
+ }
+
+ #all-types {
+ margin: 10px;
+ }
+
+ #sidebar-toggle {
+ top: 100px;
+ width: 30px;
+ font-size: 1.5rem;
+ text-align: center;
+ padding: 0;
+ }
+
+ #source-sidebar {
+ z-index: 11;
+ }
+
+ #main > .line-numbers {
+ margin-top: 0;
+ }
+
+ .notable-traits .notable-traits-tooltiptext {
+ left: 0;
+ top: 100%;
+ }
+
+ /* We don't display the help button on mobile devices. */
+ #help-button {
+ display: none;
+ }
+
+ /* Display an alternating layout on tablets and phones */
+ .item-table {
+ display: flex;
+ flex-flow: column wrap;
+ }
+ .item-left, .item-right {
+ width: 100%;
+ }
+
+ .search-container > div {
+ width: calc(100% - 32px);
+ }
+
+ /* Display an alternating layout on tablets and phones */
+ .search-results > a {
+ border-bottom: 1px solid #aaa9;
+ padding: 5px 0px;
+ }
+ .search-results .result-name, .search-results div.desc, .search-results .result-description {
+ width: 100%;
+ }
+ .search-results div.desc, .search-results .result-description, .item-right {
+ padding-left: 2em;
+ }
+}
+
+@media print {
+ nav.sub, .content .out-of-band {
+ display: none;
+ }
+}
+
+@media (max-width: 464px) {
+ #titles, #titles > button {
+ height: 73px;
+ }
+
+ /* This is to prevent the search bar from being underneath the <section>
+ * element following it.
+ */
+ #main, #search {
+ margin-top: 100px;
+ }
+
+ #main > table:not(.table-display) td {
+ word-break: break-word;
+ width: 50%;
+ }
+
+ .search-container > div {
+ display: block;
+ width: calc(100% - 37px);
+ }
+
+ #crate-search {
+ width: 100%;
+ border-radius: 4px;
+ border: 0;
+ }
+
+ #crate-search + .search-input {
+ width: calc(100% + 71px);
+ margin-left: -36px;
+ }
+
+ #theme-picker, #settings-menu {
+ padding: 5px;
+ width: 31px;
+ height: 31px;
+ }
+
+ #theme-picker {
+ margin-top: -2px;
+ }
+
+ #settings-menu {
+ top: 7px;
+ }
+
+ .docblock {
+ margin-left: 12px;
+ }
+}
--- /dev/null
+.setting-line {
+ padding: 5px;
+ position: relative;
+}
+
+.setting-line > div {
+ display: inline-block;
+ vertical-align: top;
+ font-size: 17px;
+ padding-top: 2px;
+}
+
+.setting-line > .title {
+ font-size: 19px;
+ width: 100%;
+ max-width: none;
+ border-bottom: 1px solid;
+}
+
+.toggle {
+ position: relative;
+ display: inline-block;
+ width: 45px;
+ height: 27px;
+ margin-right: 20px;
+}
+
+.toggle input {
+ opacity: 0;
+ position: absolute;
+}
+
+.select-wrapper {
+ float: right;
+ position: relative;
+ height: 27px;
+ min-width: 25%;
+}
+
+.select-wrapper select {
+ appearance: none;
+ -moz-appearance: none;
+ -webkit-appearance: none;
+ background: none;
+ border: 2px solid #ccc;
+ padding-right: 28px;
+ width: 100%;
+}
+
+.select-wrapper img {
+ pointer-events: none;
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ background: #ccc;
+ height: 100%;
+ width: 28px;
+ padding: 0px 4px;
+}
+
+.select-wrapper select option {
+ color: initial;
+}
+
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ -webkit-transition: .3s;
+ transition: .3s;
+}
+
+.slider:before {
+ position: absolute;
+ content: "";
+ height: 19px;
+ width: 19px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ -webkit-transition: .3s;
+ transition: .3s;
+}
+
+input:checked + .slider {
+ background-color: #2196F3;
+}
+
+input:focus + .slider {
+ box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
+}
+
+input:checked + .slider:before {
+ -webkit-transform: translateX(19px);
+ -ms-transform: translateX(19px);
+ transform: translateX(19px);
+}
+
+.setting-line > .sub-settings {
+ padding-left: 42px;
+ width: 100%;
+ display: block;
+}
--- /dev/null
+/*
+Based off of the Ayu theme
+Original by Dempfi (https://github.com/dempfi/ayu)
+*/
+
+/* General structure and fonts */
+
+body {
+ background-color: #0f1419;
+ color: #c5c5c5;
+}
+
+h1, h2, h3, h4 {
+ color: white;
+}
+h1.fqn {
+ border-bottom-color: #5c6773;
+}
+h1.fqn a {
+ color: #fff;
+}
+h2, h3, h4 {
+ border-bottom-color: #5c6773;
+}
+h4 {
+ border: none;
+}
+
+.in-band {
+ background-color: #0f1419;
+}
+
+.invisible {
+ background: rgba(0, 0, 0, 0);
+}
+
+code {
+ color: #ffb454;
+}
+h3 > code, h4 > code, h5 > code {
+ color: #e6e1cf;
+}
+pre > code {
+ color: #e6e1cf;
+}
+span code {
+ color: #e6e1cf;
+}
+.docblock a > code {
+ color: #39AFD7 !important;
+}
+.docblock code, .docblock-short code {
+ background-color: #191f26;
+}
+pre, .rustdoc.source .example-wrap {
+ color: #e6e1cf;
+ background-color: #191f26;
+}
+
+.sidebar {
+ background-color: #14191f;
+}
+
+.logo-container.rust-logo > img {
+ filter: drop-shadow(1px 0 0px #fff)
+ drop-shadow(0 1px 0 #fff)
+ drop-shadow(-1px 0 0 #fff)
+ drop-shadow(0 -1px 0 #fff);
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+ scrollbar-color: #5c6773 transparent;
+}
+
+.sidebar {
+ scrollbar-color: #5c6773 transparent;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+ background-color: transparent;
+}
+::-webkit-scrollbar-thumb {
+ background-color: #5c6773;
+}
+.sidebar::-webkit-scrollbar-track {
+ background-color: transparent;
+}
+.sidebar::-webkit-scrollbar-thumb {
+ background-color: #5c6773;
+}
+
+.sidebar .current {
+ background-color: transparent;
+ color: #ffb44c;
+}
+
+.source .sidebar {
+ background-color: #0f1419;
+}
+
+.sidebar .location {
+ border-color: #000;
+ background-color: #0f1419;
+ color: #fff;
+}
+
+.sidebar-elems .location {
+ color: #ff7733;
+}
+
+.sidebar-elems .location a {
+ color: #fff;
+}
+
+.sidebar .version {
+ border-bottom-color: #424c57;
+}
+
+.sidebar-title {
+ border-top-color: #5c6773;
+ border-bottom-color: #5c6773;
+}
+
+.block a:hover {
+ background: transparent;
+ color: #ffb44c;
+}
+
+.line-numbers span { color: #5c6773; }
+.line-numbers .line-highlighted {
+ color: #708090;
+ background-color: rgba(255, 236, 164, 0.06);
+ padding-right: 4px;
+ border-right: 1px solid #ffb44c;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+ border-bottom-color: #5c6773;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+ border-color: #5c6773;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+ color: #c5c5c5;
+}
+
+.search-results a:hover {
+ background-color: #777;
+}
+
+.search-results a:focus {
+ color: #000 !important;
+ background-color: #c6afb3;
+}
+.search-results a {
+ color: #0096cf;
+}
+.search-results a span.desc {
+ color: #c5c5c5;
+}
+
+.content .item-info::before { color: #ccc; }
+
+.content span.foreigntype, .content a.foreigntype { color: #ef57ff; }
+.content span.union, .content a.union { color: #98a01c; }
+.content span.constant, .content a.constant,
+.content span.static, .content a.static { color: #6380a0; }
+.content span.primitive, .content a.primitive { color: #32889b; }
+.content span.traitalias, .content a.traitalias { color: #57d399; }
+.content span.keyword, .content a.keyword { color: #de5249; }
+
+.content span.externcrate, .content span.mod, .content a.mod {
+ color: #acccf9;
+}
+.content span.struct, .content a.struct {
+ color: #ffa0a5;
+}
+.content span.enum, .content a.enum {
+ color: #99e0c9;
+}
+.content span.trait, .content a.trait {
+ color: #39AFD7;
+}
+.content span.type, .content a.type {
+ color: #cfbcf5;
+}
+.content span.fn, .content a.fn, .content span.method,
+.content a.method, .content span.tymethod,
+.content a.tymethod, .content .fnname {
+ color: #fdd687;
+}
+.content span.attr, .content a.attr, .content span.derive,
+.content a.derive, .content span.macro, .content a.macro {
+ color: #a37acc;
+}
+
+pre.rust .comment { color: #788797; }
+pre.rust .doccomment { color: #a1ac88; }
+
+nav:not(.sidebar) {
+ border-bottom-color: #424c57;
+}
+nav.main .current {
+ border-top-color: #5c6773;
+ border-bottom-color: #5c6773;
+}
+nav.main .separator {
+ border: 1px solid #5c6773;
+}
+a {
+ color: #c5c5c5;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+ color: #39AFD7;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+ color: #999;
+}
+
+#crate-search {
+ color: #c5c5c5;
+ background-color: #141920;
+ box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
+ border-color: #424c57;
+}
+
+.search-input {
+ color: #ffffff;
+ background-color: #141920;
+ box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
+ transition: box-shadow 150ms ease-in-out;
+}
+
+#crate-search+.search-input:focus {
+ box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
+}
+
+.search-input:disabled {
+ background-color: #3e3e3e;
+}
+
+.module-item .stab,
+.import-item .stab {
+ color: #000;
+}
+
+.stab.unstable,
+.stab.deprecated,
+.stab.portability {
+ color: #c5c5c5;
+ background: #314559 !important;
+ border-style: none !important;
+ border-radius: 4px;
+ padding: 3px 6px 3px 6px;
+}
+
+.stab.portability > code {
+ color: #e6e1cf;
+ background: none;
+}
+
+#help > div {
+ background: #14191f;
+ box-shadow: 0px 6px 20px 0px black;
+ border: none;
+ border-radius: 4px;
+}
+
+#help > div > span {
+ border-bottom-color: #5c6773;
+}
+
+.since {
+ color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+ color: #788797;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .number, pre.rust .string { color: #b8cc52; }
+pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
+pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .op, pre.rust .lifetime { color: #ff7733; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
+pre.rust .question-mark {
+ color: #ff9011;
+}
+pre.rust .self {
+ color: #36a3d9;
+ font-style: italic;
+}
+pre.rust .attribute {
+ color: #e6e1cf;
+}
+pre.rust .attribute .ident, pre.rust .attribute .op {
+ color: #e6e1cf;
+}
+
+.example-wrap > pre.line-number {
+ color: #5c67736e;
+ border: none;
+}
+
+a.test-arrow {
+ font-size: 100%;
+ color: #788797;
+ border-radius: 4px;
+ background-color: rgba(57, 175, 215, 0.09);
+}
+
+a.test-arrow:hover {
+ background-color: rgba(57, 175, 215, 0.368);
+ color: #c5c5c5;
+}
+
+.toggle-label,
+.code-attribute {
+ color: #999;
+}
+
+:target, :target * {
+ background: rgba(255, 236, 164, 0.06);
+}
+
+:target {
+ border-right: 3px solid rgba(255, 180, 76, 0.85);
+}
+
+pre.compile_fail {
+ border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+ border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+ border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+ border-left: 2px solid #f00;
+}
+
+pre.ignore {
+ border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+ border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+ color: rgba(255,0,0,.5);
+}
+
+.information > .compile_fail:hover {
+ color: #f00;
+}
+
+.tooltip.should_panic {
+ color: rgba(255,0,0,.5);
+}
+
+.information > .should_panic:hover {
+ color: #f00;
+}
+
+.tooltip.ignore {
+ color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+ color: #ff9200;
+}
+
+.search-failed a {
+ color: #39AFD7;
+}
+
+.tooltip::after {
+ background-color: #314559;
+ color: #c5c5c5;
+ border: 1px solid #5c6773;
+}
+
+.tooltip::before {
+ border-color: transparent #314559 transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+ background-color: #314559;
+ border-color: #5c6773;
+}
+
+.notable-traits-tooltiptext .notable {
+ border-bottom-color: #5c6773;
+}
+
+#titles > button.selected {
+ background-color: #141920 !important;
+ border-bottom: 1px solid #ffb44c !important;
+ border-top: none;
+}
+
+#titles > button:not(.selected) {
+ background-color: transparent !important;
+ border: none;
+}
+
+#titles > button:hover {
+ border-bottom: 1px solid rgba(242, 151, 24, 0.3);
+}
+
+#titles > button > div.count {
+ color: #888;
+}
+
+/* rules that this theme does not need to set, here to satisfy the rule checker */
+/* note that a lot of these are partially set in some way (meaning they are set
+individually rather than as a group) */
+/* FIXME: these rules should be at the bottom of the file but currently must be
+above the `@media (max-width: 700px)` rules due to a bug in the css checker */
+/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
+.search-input:focus {}
+.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
+.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
+.content span.struct,.content a.struct,.block a.current.struct {}
+#titles>button:hover,#titles>button.selected {}
+.content span.type,.content a.type,.block a.current.type {}
+.content span.union,.content a.union,.block a.current.union {}
+pre.rust .lifetime {}
+.stab.unstable {}
+h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {}
+.content span.enum,.content a.enum,.block a.current.enum {}
+.content span.constant,.content a.constant,.block a.current.constant,.content span.static,
+.content a.static, .block a.current.static {}
+.content span.keyword,.content a.keyword,.block a.current.keyword {}
+pre.rust .comment {}
+.content span.traitalias,.content a.traitalias,.block a.current.traitalias {}
+.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,
+.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,
+.content .fnname {}
+pre.rust .kw {}
+pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,
+pre.rust .attribute .ident {}
+.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {}
+pre.rust .doccomment {}
+.stab.deprecated {}
+.content a.attr,.content a.derive,.content a.macro {}
+.stab.portability {}
+.content span.primitive,.content a.primitive,.block a.current.primitive {}
+.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod {}
+pre.rust .kw-2,pre.rust .prelude-ty {}
+.content span.trait,.content a.trait,.block a.current.trait {}
+
+.search-results a:focus span {}
+a.result-trait:focus {}
+a.result-traitalias:focus {}
+a.result-mod:focus,
+a.result-externcrate:focus {}
+a.result-mod:focus {}
+a.result-externcrate:focus {}
+a.result-enum:focus {}
+a.result-struct:focus {}
+a.result-union:focus {}
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus {}
+a.result-type:focus {}
+a.result-foreigntype:focus {}
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus {}
+a.result-constant:focus,
+a.result-static:focus {}
+a.result-primitive:focus {}
+a.result-keyword:focus {}
+
+@media (max-width: 700px) {
+ .sidebar-menu {
+ background-color: #14191f;
+ border-bottom-color: #5c6773;
+ border-right-color: #5c6773;
+ }
+
+ .sidebar-elems {
+ background-color: #14191f;
+ border-right-color: #5c6773;
+ }
+
+ #sidebar-filler {
+ background-color: #14191f;
+ border-bottom-color: #5c6773;
+ }
+}
+
+kbd {
+ color: #c5c5c5;
+ background-color: #314559;
+ border-color: #5c6773;
+ border-bottom-color: #5c6773;
+ box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+ border-color: #5c6773;
+ background-color: #0f1419;
+ color: #fff;
+}
+
+#theme-picker > img, #settings-menu > img {
+ filter: invert(100);
+}
+
+#copy-path {
+ color: #fff;
+}
+#copy-path > img {
+ filter: invert(70%);
+}
+#copy-path:hover > img {
+ filter: invert(100%);
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+ border-color: #e0e0e0;
+}
+
+#theme-choices {
+ border-color: #5c6773;
+ background-color: #0f1419;
+}
+
+#theme-choices > button:not(:first-child) {
+ border-top-color: #5c6773;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+ background-color: rgba(110, 110, 110, 0.33);
+}
+
+@media (max-width: 700px) {
+ #theme-picker {
+ background: #0f1419;
+ }
+}
+
+#all-types {
+ background-color: #14191f;
+}
+#all-types:hover {
+ background-color: rgba(70, 70, 70, 0.33);
+}
+
+.search-results .result-name span.alias {
+ color: #c5c5c5;
+}
+.search-results .result-name span.grey {
+ color: #999;
+}
+
+#sidebar-toggle {
+ background-color: #14191f;
+}
+#sidebar-toggle:hover {
+ background-color: rgba(70, 70, 70, 0.33);
+}
+#source-sidebar {
+ background-color: #14191f;
+}
+#source-sidebar > .title {
+ color: #fff;
+ border-bottom-color: #5c6773;
+}
+div.files > a:hover, div.name:hover {
+ background-color: #14191f;
+ color: #ffb44c;
+}
+div.files > .selected {
+ background-color: #14191f;
+ color: #ffb44c;
+}
+.setting-line > .title {
+ border-bottom-color: #5c6773;
+}
+input:checked + .slider {
+ background-color: #ffb454 !important;
+}
--- /dev/null
+body {
+ background-color: #353535;
+ color: #ddd;
+}
+
+h1, h2, h3, h4 {
+ color: #ddd;
+}
+h1.fqn {
+ border-bottom-color: #d2d2d2;
+}
+h2, h3, h4 {
+ border-bottom-color: #d2d2d2;
+}
+
+.in-band {
+ background-color: #353535;
+}
+
+.invisible {
+ background: rgba(0, 0, 0, 0);
+}
+
+.docblock code, .docblock-short code {
+ background-color: #2A2A2A;
+}
+pre, .rustdoc.source .example-wrap {
+ background-color: #2A2A2A;
+}
+
+.sidebar {
+ background-color: #505050;
+}
+
+.logo-container.rust-logo > img {
+ filter: drop-shadow(1px 0 0px #fff)
+ drop-shadow(0 1px 0 #fff)
+ drop-shadow(-1px 0 0 #fff)
+ drop-shadow(0 -1px 0 #fff)
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+ scrollbar-color: rgb(64, 65, 67) #717171;
+}
+.sidebar {
+ scrollbar-color: rgba(32,34,37,.6) transparent;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+ background-color: #717171;
+}
+::-webkit-scrollbar-thumb {
+ background-color: rgba(32, 34, 37, .6);
+}
+.sidebar::-webkit-scrollbar-track {
+ background-color: #717171;
+}
+.sidebar::-webkit-scrollbar-thumb {
+ background-color: rgba(32, 34, 37, .6);
+}
+
+.sidebar .current {
+ background-color: #333;
+}
+
+.source .sidebar {
+ background-color: #353535;
+}
+
+.sidebar .location {
+ border-color: #fff;
+ background: #575757;
+ color: #DDD;
+}
+
+.sidebar .version {
+ border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+ border-top-color: #777;
+ border-bottom-color: #777;
+}
+
+.block a:hover {
+ background: #444;
+}
+
+.line-numbers span { color: #3B91E2; }
+.line-numbers .line-highlighted {
+ background-color: #0a042f !important;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+ border-bottom-color: #DDD;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+ border-color: #ddd;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+ color: #ddd;
+}
+
+.search-results a:hover {
+ background-color: #777;
+}
+
+.search-results a:focus {
+ color: #eee !important;
+ background-color: #616161;
+}
+.search-results a:focus span { color: #eee !important; }
+a.result-trait:focus { background-color: #013191; }
+a.result-traitalias:focus { background-color: #013191; }
+a.result-mod:focus,
+a.result-externcrate:focus { background-color: #afc6e4; }
+a.result-mod:focus { background-color: #803a1b; }
+a.result-externcrate:focus { background-color: #396bac; }
+a.result-enum:focus { background-color: #5b4e68; }
+a.result-struct:focus { background-color: #194e9f; }
+a.result-union:focus { background-color: #b7bd49; }
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus { background-color: #4950ed; }
+a.result-type:focus { background-color: #38902c; }
+a.result-foreigntype:focus { background-color: #b200d6; }
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus { background-color: #217d1c; }
+a.result-constant:focus,
+a.result-static:focus { background-color: #0063cc; }
+a.result-primitive:focus { background-color: #00708a; }
+a.result-keyword:focus { background-color: #884719; }
+
+.content .item-info::before { color: #ccc; }
+
+.content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
+.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
+.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
+.content span.attr, .content a.attr, .block a.current.attr,
+.content span.derive, .content a.derive, .block a.current.derive,
+.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
+.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
+.content span.constant, .content a.constant, .block a.current.constant,
+.content span.static, .content a.static, .block a.current.static { color: #82a5c9; }
+.content span.primitive, .content a.primitive, .block a.current.primitive { color: #43aec7; }
+.content span.externcrate,
+.content span.mod, .content a.mod, .block a.current.mod { color: #bda000; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; }
+.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #b397da; }
+.content span.fn, .content a.fn, .block a.current.fn,
+.content span.method, .content a.method, .block a.current.method,
+.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
+.content .fnname{ color: #2BAB63; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
+
+pre.rust .comment { color: #8d8d8b; }
+pre.rust .doccomment { color: #8ca375; }
+
+nav:not(.sidebar) {
+ border-bottom-color: #4e4e4e;
+}
+nav.main .current {
+ border-top-color: #eee;
+ border-bottom-color: #eee;
+}
+nav.main .separator {
+ border-color: #eee;
+}
+a {
+ color: #ddd;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+ color: #D2991D;
+}
+
+a.test-arrow {
+ color: #dedede;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+ color: #999;
+}
+
+#crate-search {
+ color: #111;
+ background-color: #f0f0f0;
+ border-color: #000;
+ box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+}
+
+.search-input {
+ color: #111;
+ background-color: #f0f0f0;
+ box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
+}
+
+.search-input:focus {
+ border-color: #008dfd;
+}
+
+.search-input:disabled {
+ background-color: #c5c4c4;
+}
+
+#crate-search + .search-input:focus {
+ box-shadow: 0 0 8px 4px #078dd8;
+}
+
+.module-item .stab,
+.import-item .stab {
+ color: #ddd;
+}
+
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
+.stab.portability > code { background: none; }
+
+#help > div {
+ background: #4d4d4d;
+ border-color: #bfbfbf;
+}
+
+#help > div > span {
+ border-bottom-color: #bfbfbf;
+}
+
+#help dt {
+ border-color: #bfbfbf;
+ background: rgba(0,0,0,0);
+}
+
+.since {
+ color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+ color: #ddd;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .kw { color: #ab8ac1; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
+pre.rust .number, pre.rust .string { color: #83a300; }
+pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .attribute, pre.rust .attribute .ident { color: #ee6868; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
+pre.rust .lifetime { color: #d97f26; }
+pre.rust .question-mark {
+ color: #ff9011;
+}
+
+.example-wrap > pre.line-number {
+ border-color: #4a4949;
+}
+
+a.test-arrow {
+ background-color: rgba(78, 139, 202, 0.2);
+}
+
+a.test-arrow:hover{
+ background-color: #4e8bca;
+}
+
+.toggle-label,
+.code-attribute {
+ color: #999;
+}
+
+:target, :target * {
+ background-color: #494a3d;
+}
+
+:target {
+ border-right: 3px solid #bb7410;
+}
+
+pre.compile_fail {
+ border-left: 2px solid rgba(255,0,0,.8);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+ border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+ border-left: 2px solid rgba(255,0,0,.8);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+ border-left: 2px solid #f00;
+}
+
+pre.ignore {
+ border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+ border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+ color: rgba(255,0,0,.8);
+}
+
+.information > .compile_fail:hover {
+ color: #f00;
+}
+
+.tooltip.should_panic {
+ color: rgba(255,0,0,.8);
+}
+
+.information > .should_panic:hover {
+ color: #f00;
+}
+
+.tooltip.ignore {
+ color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+ color: #ff9200;
+}
+
+.search-failed a {
+ color: #0089ff;
+}
+
+.tooltip::after {
+ background-color: #000;
+ color: #fff;
+ border-color: #000;
+}
+
+.tooltip::before {
+ border-color: transparent black transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+ background-color: #111;
+ border-color: #777;
+}
+
+.notable-traits-tooltiptext .notable {
+ border-bottom-color: #d2d2d2;
+}
+
+#titles > button:not(.selected) {
+ background-color: #252525;
+ border-top-color: #252525;
+}
+
+#titles > button:hover, #titles > button.selected {
+ border-top-color: #0089ff;
+ background-color: #353535;
+}
+
+#titles > button > div.count {
+ color: #888;
+}
+
+@media (max-width: 700px) {
+ .sidebar-menu {
+ background-color: #505050;
+ border-bottom-color: #e0e0e0;
+ border-right-color: #e0e0e0;
+ }
+
+ .sidebar-elems {
+ background-color: #505050;
+ border-right-color: #000;
+ }
+
+ #sidebar-filler {
+ background-color: #505050;
+ border-bottom-color: #e0e0e0;
+ }
+}
+
+kbd {
+ color: #000;
+ background-color: #fafbfc;
+ border-color: #d1d5da;
+ border-bottom-color: #c6cbd1;
+ box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+ border-color: #e0e0e0;
+ background: #f0f0f0;
+ color: #000;
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+ border-color: #ffb900;
+}
+
+#copy-path {
+ color: #999;
+}
+#copy-path > img {
+ filter: invert(50%);
+}
+#copy-path:hover > img {
+ filter: invert(65%);
+}
+
+#theme-choices {
+ border-color: #e0e0e0;
+ background-color: #353535;
+}
+
+#theme-choices > button:not(:first-child) {
+ border-top-color: #e0e0e0;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+ background-color: #4e4e4e;
+}
+
+@media (max-width: 700px) {
+ #theme-picker {
+ background: #f0f0f0;
+ }
+}
+
+#all-types {
+ background-color: #505050;
+}
+#all-types:hover {
+ background-color: #606060;
+}
+
+.search-results .result-name span.alias {
+ color: #fff;
+}
+.search-results .result-name span.grey {
+ color: #ccc;
+}
+
+#sidebar-toggle {
+ background-color: #565656;
+}
+#sidebar-toggle:hover {
+ background-color: #676767;
+}
+#source-sidebar {
+ background-color: #565656;
+}
+#source-sidebar > .title {
+ border-bottom-color: #ccc;
+}
+div.files > a:hover, div.name:hover {
+ background-color: #444;
+}
+div.files > .selected {
+ background-color: #333;
+}
+.setting-line > .title {
+ border-bottom-color: #ddd;
+}
--- /dev/null
+/* General structure and fonts */
+
+body {
+ background-color: white;
+ color: black;
+}
+
+h1, h2, h3, h4 {
+ color: black;
+}
+h1.fqn {
+ border-bottom-color: #D5D5D5;
+}
+h2, h3, h4 {
+ border-bottom-color: #DDDDDD;
+}
+
+.in-band {
+ background-color: white;
+}
+
+.invisible {
+ background: rgba(0, 0, 0, 0);
+}
+
+.docblock code, .docblock-short code {
+ background-color: #F5F5F5;
+}
+pre, .rustdoc.source .example-wrap {
+ background-color: #F5F5F5;
+}
+
+.sidebar {
+ background-color: #F1F1F1;
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+ scrollbar-color: rgba(36, 37, 39, 0.6) #e6e6e6;
+}
+
+.sidebar {
+ scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
+}
+
+.logo-container.rust-logo > img {
+ /* No need for a border in here! */
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+ background-color: #ecebeb;
+}
+::-webkit-scrollbar-thumb {
+ background-color: rgba(36, 37, 39, 0.6);
+}
+.sidebar::-webkit-scrollbar-track {
+ background-color: #dcdcdc;
+}
+.sidebar::-webkit-scrollbar-thumb {
+ background-color: rgba(36, 37, 39, 0.6);
+}
+
+.sidebar .current {
+ background-color: #fff;
+}
+
+.source .sidebar {
+ background-color: #fff;
+}
+
+.sidebar .location {
+ border-color: #000;
+ background-color: #fff;
+ color: #333;
+}
+
+.sidebar .version {
+ border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+ border-top-color: #777;
+ border-bottom-color: #777;
+}
+
+.block a:hover {
+ background: #F5F5F5;
+}
+
+.line-numbers span { color: #c67e2d; }
+.line-numbers .line-highlighted {
+ background-color: #f6fdb0 !important;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+ border-bottom-color: #ddd;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+ border-color: #ddd;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+ color: #4E4C4C;
+}
+
+.search-results a:hover {
+ background-color: #ddd;
+}
+
+.search-results a:focus {
+ color: #000 !important;
+ background-color: #ccc;
+}
+.search-results a:focus span { color: #000 !important; }
+a.result-trait:focus { background-color: #c7b6ff; }
+a.result-traitalias:focus { background-color: #c7b6ff; }
+a.result-mod:focus,
+a.result-externcrate:focus { background-color: #afc6e4; }
+a.result-enum:focus { background-color: #b4d1b9; }
+a.result-struct:focus { background-color: #e7b1a0; }
+a.result-union:focus { background-color: #b7bd49; }
+a.result-fn:focus,
+a.result-method:focus,
+a.result-tymethod:focus { background-color: #c6afb3; }
+a.result-type:focus { background-color: #ffc891; }
+a.result-foreigntype:focus { background-color: #f5c4ff; }
+a.result-attr:focus,
+a.result-derive:focus,
+a.result-macro:focus { background-color: #8ce488; }
+a.result-constant:focus,
+a.result-static:focus { background-color: #c3e0ff; }
+a.result-primitive:focus { background-color: #9aecff; }
+a.result-keyword:focus { background-color: #f99650; }
+
+.content .item-info::before { color: #ccc; }
+
+.content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
+.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
+.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
+.content span.attr, .content a.attr, .block a.current.attr,
+.content span.derive, .content a.derive, .block a.current.derive,
+.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
+.content span.union, .content a.union, .block a.current.union { color: #767b27; }
+.content span.constant, .content a.constant, .block a.current.constant,
+.content span.static, .content a.static, .block a.current.static { color: #546e8a; }
+.content span.primitive, .content a.primitive, .block a.current.primitive { color: #2c8093; }
+.content span.externcrate,
+.content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
+.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #6841f1; }
+.content span.fn, .content a.fn, .block a.current.fn,
+.content span.method, .content a.method, .block a.current.method,
+.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
+.content .fnname { color: #9a6e31; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
+
+nav:not(.sidebar) {
+ border-bottom-color: #e0e0e0;
+}
+nav.main .current {
+ border-top-color: #000;
+ border-bottom-color: #000;
+}
+nav.main .separator {
+ border: 1px solid #000;
+}
+a {
+ color: #000;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
+#help a {
+ color: #3873AD;
+}
+
+a.test-arrow {
+ color: #f5f5f5;
+}
+
+details.rustdoc-toggle > summary.hideme > span,
+details.rustdoc-toggle > summary::before,
+details.undocumented > summary::before {
+ color: #999;
+}
+
+#crate-search {
+ color: #555;
+ background-color: white;
+ border-color: #e0e0e0;
+ box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+}
+
+.search-input {
+ color: #555;
+ background-color: white;
+ box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+}
+
+.search-input:focus {
+ border-color: #66afe9;
+}
+
+.search-input:disabled {
+ background-color: #e6e6e6;
+}
+
+#crate-search + .search-input:focus {
+ box-shadow: 0 0 8px #078dd8;
+}
+
+.module-item .stab,
+.import-item .stab {
+ color: #000;
+}
+
+.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
+.stab.portability > code { background: none; }
+
+#help > div {
+ background: #e9e9e9;
+ border-color: #bfbfbf;
+}
+
+#help > div > span {
+ border-bottom-color: #bfbfbf;
+}
+
+.since {
+ color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+ color: black;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .kw { color: #8959A8; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
+pre.rust .number, pre.rust .string { color: #718C00; }
+pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
+pre.rust .comment { color: #8E908C; }
+pre.rust .doccomment { color: #4D4D4C; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
+pre.rust .lifetime { color: #B76514; }
+pre.rust .question-mark {
+ color: #ff9011;
+}
+
+.example-wrap > pre.line-number {
+ border-color: #c7c7c7;
+}
+
+a.test-arrow {
+ background-color: rgba(78, 139, 202, 0.2);
+}
+
+a.test-arrow:hover{
+ background-color: #4e8bca;
+}
+
+.toggle-label,
+.code-attribute {
+ color: #999;
+}
+
+:target, :target * {
+ background: #FDFFD3;
+}
+
+:target {
+ border-right: 3px solid #ffb44c;
+}
+
+pre.compile_fail {
+ border-left: 2px solid rgba(255,0,0,.5);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+ border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+ border-left: 2px solid rgba(255,0,0,.5);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+ border-left: 2px solid #f00;
+}
+
+pre.ignore {
+ border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+ border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+ color: rgba(255,0,0,.5);
+}
+
+.information > .compile_fail:hover {
+ color: #f00;
+}
+
+.tooltip.should_panic {
+ color: rgba(255,0,0,.5);
+}
+
+.information > .should_panic:hover {
+ color: #f00;
+}
+
+.tooltip.ignore {
+ color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+ color: #ff9200;
+}
+
+.search-failed a {
+ color: #0089ff;
+}
+
+.tooltip::after {
+ background-color: #000;
+ color: #fff;
+}
+
+.tooltip::before {
+ border-color: transparent black transparent transparent;
+}
+
+.notable-traits-tooltiptext {
+ background-color: #eee;
+ border-color: #999;
+}
+
+.notable-traits-tooltiptext .notable {
+ border-bottom-color: #DDDDDD;
+}
+
+#titles > button:not(.selected) {
+ background-color: #e6e6e6;
+ border-top-color: #e6e6e6;
+}
+
+#titles > button:hover, #titles > button.selected {
+ background-color: #ffffff;
+ border-top-color: #0089ff;
+}
+
+#titles > button > div.count {
+ color: #888;
+}
+
+@media (max-width: 700px) {
+ .sidebar-menu {
+ background-color: #F1F1F1;
+ border-bottom-color: #e0e0e0;
+ border-right-color: #e0e0e0;
+ }
+
+ .sidebar-elems {
+ background-color: #F1F1F1;
+ border-right-color: #000;
+ }
+
+ #sidebar-filler {
+ background-color: #F1F1F1;
+ border-bottom-color: #e0e0e0;
+ }
+}
+
+kbd {
+ color: #000;
+ background-color: #fafbfc;
+ border-color: #d1d5da;
+ border-bottom-color: #c6cbd1;
+ box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu, #help-button {
+ border-color: #e0e0e0;
+ background-color: #fff;
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus,
+#help-button:hover, #help-button:focus {
+ border-color: #717171;
+}
+
+#copy-path {
+ color: #999;
+}
+#copy-path > img {
+ filter: invert(50%);
+}
+#copy-path:hover > img {
+ filter: invert(35%);
+}
+
+#theme-choices {
+ border-color: #ccc;
+ background-color: #fff;
+}
+
+#theme-choices > button:not(:first-child) {
+ border-top-color: #e0e0e0;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+ background-color: #eee;
+}
+
+@media (max-width: 700px) {
+ #theme-picker {
+ background: #fff;
+ }
+}
+
+#all-types {
+ background-color: #fff;
+}
+#all-types:hover {
+ background-color: #f9f9f9;
+}
+
+.search-results .result-name span.alias {
+ color: #000;
+}
+.search-results .result-name span.grey {
+ color: #999;
+}
+
+#sidebar-toggle {
+ background-color: #F1F1F1;
+}
+#sidebar-toggle:hover {
+ background-color: #E0E0E0;
+}
+#source-sidebar {
+ background-color: #F1F1F1;
+}
+#source-sidebar > .title {
+ border-bottom-color: #ccc;
+}
+div.files > a:hover, div.name:hover {
+ background-color: #E0E0E0;
+}
+div.files > .selected {
+ background-color: #fff;
+}
+.setting-line > .title {
+ border-bottom-color: #D5D5D5;
+}
+++ /dev/null
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
-<defs>
- <style type="text/css"><![CDATA[
- #logo {
- fill-rule: nonzero;
- }
- #logo-teeth {
- stroke: #000000;
- stroke-width: 0.92px;
- }
- @media (prefers-color-scheme: dark) {
- #logo {
- fill: #FFFFFF;
- fill-rule: nonzero;
- }
- #logo-teeth {
- fill: #FFFFFF;
- stroke: #FFFFFF;
- stroke-width: 0.92px;
- }
- }
- ]]></style>
-</defs>
-<path id="logo" d="M15.993,1.54c-7.972,0 -14.461,6.492 -14.461,14.462c0,7.969 6.492,14.461 14.461,14.461c7.97,0 14.462,-6.492 14.462,-14.461c0,-7.97 -6.492,-14.462 -14.462,-14.462Zm-0.021,1.285c0.511,0.013 0.924,0.439 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0.001 0.028,0.001Zm2.178,1.566c3.379,0.633 6.313,2.723 8.016,5.709l-1.123,2.533c-0.193,0.438 0.006,0.952 0.44,1.147l2.16,0.958c0.067,0.675 0.076,1.355 0.025,2.031l-1.202,0c-0.12,0 -0.169,0.08 -0.169,0.196l0,0.551c0,1.297 -0.731,1.582 -1.373,1.652c-0.612,0.07 -1.288,-0.257 -1.374,-0.63c-0.361,-2.029 -0.961,-2.46 -1.909,-3.21c1.178,-0.746 2.401,-1.85 2.401,-3.325c0,-1.594 -1.092,-2.597 -1.835,-3.09c-1.046,-0.688 -2.203,-0.826 -2.515,-0.826l-12.421,0c1.717,-1.918 4.02,-3.218 6.55,-3.696l1.466,1.536c0.33,0.346 0.878,0.361 1.223,0.028l1.64,-1.564Zm-13.522,7.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.951 0.951,-0.951c0.009,0 0.019,0 0.028,0Zm22.685,0.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0 0.028,0.001Zm-20.892,0.153l1.658,0l0,7.477l-3.347,0c-0.414,-1.452 -0.542,-2.97 -0.38,-4.47l2.05,-0.912c0.438,-0.195 0.637,-0.706 0.441,-1.144l-0.422,-0.951Zm6.92,0.079l3.949,0c0.205,0 1.441,0.236 1.441,1.163c0,0.768 -0.948,1.043 -1.728,1.043l-3.665,0l0.003,-2.206Zm0,5.373l3.026,0c0.275,0 1.477,0.079 1.86,1.615c0.119,0.471 0.385,2.007 0.566,2.499c0.18,0.551 0.911,1.652 1.691,1.652l4.938,0c-0.331,0.444 -0.693,0.863 -1.083,1.255l-2.01,-0.432c-0.468,-0.101 -0.93,0.199 -1.031,0.667l-0.477,2.228c-3.104,1.406 -6.672,1.389 -9.762,-0.046l-0.478,-2.228c-0.101,-0.468 -0.56,-0.767 -1.028,-0.667l-1.967,0.423c-0.365,-0.377 -0.704,-0.778 -1.016,-1.2l9.567,0c0.107,0 0.181,-0.018 0.181,-0.119l0,-3.384c0,-0.097 -0.074,-0.119 -0.181,-0.119l-2.799,0l0.003,-2.144Zm-4.415,7.749c0.512,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.952,-0.43 -0.952,-0.952c0,0 0,0 0,0c0,-0.522 0.43,-0.952 0.952,-0.952c0.009,0 0.018,0.001 0.027,0.001Zm14.089,0.043c0.511,0.015 0.924,0.439 0.923,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.009,0 0.018,0 0.028,0.001Z"/><path id="logo-teeth" d="M29.647,16.002c0,7.49 -6.163,13.653 -13.654,13.653c-7.49,0 -13.654,-6.163 -13.654,-13.653c0,-7.491 6.164,-13.654 13.654,-13.654c7.491,0 13.654,6.163 13.654,13.654Zm-0.257,-1.319l2.13,1.319l-2.13,1.318l1.83,1.71l-2.344,0.878l1.463,2.035l-2.475,0.404l1.04,2.282l-2.506,-0.089l0.575,2.442l-2.441,-0.576l0.089,2.506l-2.283,-1.04l-0.403,2.475l-2.035,-1.462l-0.878,2.343l-1.71,-1.829l-1.319,2.129l-1.318,-2.129l-1.71,1.829l-0.878,-2.343l-2.035,1.462l-0.404,-2.475l-2.282,1.04l0.089,-2.506l-2.442,0.576l0.575,-2.442l-2.505,0.089l1.04,-2.282l-2.475,-0.404l1.462,-2.035l-2.343,-0.878l1.829,-1.71l-2.129,-1.318l2.129,-1.319l-1.829,-1.71l2.343,-0.878l-1.462,-2.035l2.475,-0.404l-1.04,-2.282l2.505,0.089l-0.575,-2.441l2.442,0.575l-0.089,-2.506l2.282,1.04l0.404,-2.475l2.035,1.463l0.878,-2.344l1.71,1.83l1.318,-2.13l1.319,2.13l1.71,-1.83l0.878,2.344l2.035,-1.463l0.403,2.475l2.283,-1.04l-0.089,2.506l2.441,-0.575l-0.575,2.441l2.506,-0.089l-1.04,2.282l2.475,0.404l-1.463,2.035l2.344,0.878l-1.83,1.71Z"/></svg>
--- /dev/null
+Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
+with Reserved Font Name < Fira >,
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
--- /dev/null
+Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
--- /dev/null
+Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
--- /dev/null
+Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
\ No newline at end of file
--- /dev/null
+<svg width="24" height="25" viewBox="0 0 24 25" xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard"><path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/><path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/></svg>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;">
+<defs>
+ <style type="text/css"><![CDATA[
+ #logo {
+ fill-rule: nonzero;
+ }
+ #logo-teeth {
+ stroke: #000000;
+ stroke-width: 0.92px;
+ }
+ @media (prefers-color-scheme: dark) {
+ #logo {
+ fill: #FFFFFF;
+ fill-rule: nonzero;
+ }
+ #logo-teeth {
+ fill: #FFFFFF;
+ stroke: #FFFFFF;
+ stroke-width: 0.92px;
+ }
+ }
+ ]]></style>
+</defs>
+<path id="logo" d="M15.993,1.54c-7.972,0 -14.461,6.492 -14.461,14.462c0,7.969 6.492,14.461 14.461,14.461c7.97,0 14.462,-6.492 14.462,-14.461c0,-7.97 -6.492,-14.462 -14.462,-14.462Zm-0.021,1.285c0.511,0.013 0.924,0.439 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0.001 0.028,0.001Zm2.178,1.566c3.379,0.633 6.313,2.723 8.016,5.709l-1.123,2.533c-0.193,0.438 0.006,0.952 0.44,1.147l2.16,0.958c0.067,0.675 0.076,1.355 0.025,2.031l-1.202,0c-0.12,0 -0.169,0.08 -0.169,0.196l0,0.551c0,1.297 -0.731,1.582 -1.373,1.652c-0.612,0.07 -1.288,-0.257 -1.374,-0.63c-0.361,-2.029 -0.961,-2.46 -1.909,-3.21c1.178,-0.746 2.401,-1.85 2.401,-3.325c0,-1.594 -1.092,-2.597 -1.835,-3.09c-1.046,-0.688 -2.203,-0.826 -2.515,-0.826l-12.421,0c1.717,-1.918 4.02,-3.218 6.55,-3.696l1.466,1.536c0.33,0.346 0.878,0.361 1.223,0.028l1.64,-1.564Zm-13.522,7.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.951 0.951,-0.951c0.009,0 0.019,0 0.028,0Zm22.685,0.043c0.511,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.43,0.952 -0.952,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.01,0 0.019,0 0.028,0.001Zm-20.892,0.153l1.658,0l0,7.477l-3.347,0c-0.414,-1.452 -0.542,-2.97 -0.38,-4.47l2.05,-0.912c0.438,-0.195 0.637,-0.706 0.441,-1.144l-0.422,-0.951Zm6.92,0.079l3.949,0c0.205,0 1.441,0.236 1.441,1.163c0,0.768 -0.948,1.043 -1.728,1.043l-3.665,0l0.003,-2.206Zm0,5.373l3.026,0c0.275,0 1.477,0.079 1.86,1.615c0.119,0.471 0.385,2.007 0.566,2.499c0.18,0.551 0.911,1.652 1.691,1.652l4.938,0c-0.331,0.444 -0.693,0.863 -1.083,1.255l-2.01,-0.432c-0.468,-0.101 -0.93,0.199 -1.031,0.667l-0.477,2.228c-3.104,1.406 -6.672,1.389 -9.762,-0.046l-0.478,-2.228c-0.101,-0.468 -0.56,-0.767 -1.028,-0.667l-1.967,0.423c-0.365,-0.377 -0.704,-0.778 -1.016,-1.2l9.567,0c0.107,0 0.181,-0.018 0.181,-0.119l0,-3.384c0,-0.097 -0.074,-0.119 -0.181,-0.119l-2.799,0l0.003,-2.144Zm-4.415,7.749c0.512,0.015 0.924,0.44 0.924,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.952,-0.43 -0.952,-0.952c0,0 0,0 0,0c0,-0.522 0.43,-0.952 0.952,-0.952c0.009,0 0.018,0.001 0.027,0.001Zm14.089,0.043c0.511,0.015 0.924,0.439 0.923,0.951c0,0.522 -0.429,0.952 -0.951,0.952c-0.522,0 -0.951,-0.43 -0.951,-0.952c0,0 0,0 0,0c0,-0.522 0.429,-0.952 0.951,-0.952c0.009,0 0.018,0 0.028,0.001Z"/><path id="logo-teeth" d="M29.647,16.002c0,7.49 -6.163,13.653 -13.654,13.653c-7.49,0 -13.654,-6.163 -13.654,-13.653c0,-7.491 6.164,-13.654 13.654,-13.654c7.491,0 13.654,6.163 13.654,13.654Zm-0.257,-1.319l2.13,1.319l-2.13,1.318l1.83,1.71l-2.344,0.878l1.463,2.035l-2.475,0.404l1.04,2.282l-2.506,-0.089l0.575,2.442l-2.441,-0.576l0.089,2.506l-2.283,-1.04l-0.403,2.475l-2.035,-1.462l-0.878,2.343l-1.71,-1.829l-1.319,2.129l-1.318,-2.129l-1.71,1.829l-0.878,-2.343l-2.035,1.462l-0.404,-2.475l-2.282,1.04l0.089,-2.506l-2.442,0.576l0.575,-2.442l-2.505,0.089l1.04,-2.282l-2.475,-0.404l1.462,-2.035l-2.343,-0.878l1.829,-1.71l-2.129,-1.318l2.129,-1.319l-1.829,-1.71l2.343,-0.878l-1.462,-2.035l2.475,-0.404l-1.04,-2.282l2.505,0.089l-0.575,-2.441l2.442,0.575l-0.089,-2.506l2.282,1.04l0.404,-2.475l2.035,1.463l0.878,-2.344l1.71,1.83l1.318,-2.13l1.319,2.13l1.71,-1.83l0.878,2.344l2.035,-1.463l0.403,2.475l2.283,-1.04l-0.089,2.506l2.441,-0.575l-0.575,2.441l2.506,-0.089l-1.04,2.282l2.475,0.404l-1.463,2.035l2.344,0.878l-1.83,1.71Z"/></svg>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
--- /dev/null
+// Local js definitions:
+/* global addClass, getSettingValue, hasClass, searchState */
+/* global onEach, onEachLazy, removeClass */
+/* global switchTheme, useSystemTheme */
+
+if (!String.prototype.startsWith) {
+ String.prototype.startsWith = function(searchString, position) {
+ position = position || 0;
+ return this.indexOf(searchString, position) === position;
+ };
+}
+if (!String.prototype.endsWith) {
+ String.prototype.endsWith = function(suffix, length) {
+ var l = length || this.length;
+ return this.indexOf(suffix, l - suffix.length) !== -1;
+ };
+}
+
+if (!DOMTokenList.prototype.add) {
+ DOMTokenList.prototype.add = function(className) {
+ if (className && !hasClass(this, className)) {
+ if (this.className && this.className.length > 0) {
+ this.className += " " + className;
+ } else {
+ this.className = className;
+ }
+ }
+ };
+}
+
+if (!DOMTokenList.prototype.remove) {
+ DOMTokenList.prototype.remove = function(className) {
+ if (className && this.className) {
+ this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
+ .trim();
+ }
+ };
+}
+
+(function () {
+ var rustdocVars = document.getElementById("rustdoc-vars");
+ if (rustdocVars) {
+ window.rootPath = rustdocVars.attributes["data-root-path"].value;
+ window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
+ window.searchJS = rustdocVars.attributes["data-search-js"].value;
+ window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
+ }
+ var sidebarVars = document.getElementById("sidebar-vars");
+ if (sidebarVars) {
+ window.sidebarCurrent = {
+ name: sidebarVars.attributes["data-name"].value,
+ ty: sidebarVars.attributes["data-ty"].value,
+ relpath: sidebarVars.attributes["data-relpath"].value,
+ };
+ }
+}());
+
+// Gets the human-readable string for the virtual-key code of the
+// given KeyboardEvent, ev.
+//
+// This function is meant as a polyfill for KeyboardEvent#key,
+// since it is not supported in IE 11 or Chrome for Android. We also test for
+// KeyboardEvent#keyCode because the handleShortcut handler is
+// also registered for the keydown event, because Blink doesn't fire
+// keypress on hitting the Escape key.
+//
+// So I guess you could say things are getting pretty interoperable.
+function getVirtualKey(ev) {
+ if ("key" in ev && typeof ev.key != "undefined") {
+ return ev.key;
+ }
+
+ var c = ev.charCode || ev.keyCode;
+ if (c == 27) {
+ return "Escape";
+ }
+ return String.fromCharCode(c);
+}
+
+var THEME_PICKER_ELEMENT_ID = "theme-picker";
+var THEMES_ELEMENT_ID = "theme-choices";
+
+function getThemesElement() {
+ return document.getElementById(THEMES_ELEMENT_ID);
+}
+
+function getThemePickerElement() {
+ return document.getElementById(THEME_PICKER_ELEMENT_ID);
+}
+
+// Returns the current URL without any query parameter or hash.
+function getNakedUrl() {
+ return window.location.href.split("?")[0].split("#")[0];
+}
+
+function showThemeButtonState() {
+ var themePicker = getThemePickerElement();
+ var themeChoices = getThemesElement();
+
+ themeChoices.style.display = "block";
+ themePicker.style.borderBottomRightRadius = "0";
+ themePicker.style.borderBottomLeftRadius = "0";
+}
+
+function hideThemeButtonState() {
+ var themePicker = getThemePickerElement();
+ var themeChoices = getThemesElement();
+
+ themeChoices.style.display = "none";
+ themePicker.style.borderBottomRightRadius = "3px";
+ themePicker.style.borderBottomLeftRadius = "3px";
+}
+
+// Set up the theme picker list.
+(function () {
+ var themeChoices = getThemesElement();
+ var themePicker = getThemePickerElement();
+ var availableThemes/* INSERT THEMES HERE */;
+
+ function switchThemeButtonState() {
+ if (themeChoices.style.display === "block") {
+ hideThemeButtonState();
+ } else {
+ showThemeButtonState();
+ }
+ }
+
+ function handleThemeButtonsBlur(e) {
+ var active = document.activeElement;
+ var related = e.relatedTarget;
+
+ if (active.id !== THEME_PICKER_ELEMENT_ID &&
+ (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
+ (!related ||
+ (related.id !== THEME_PICKER_ELEMENT_ID &&
+ (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
+ hideThemeButtonState();
+ }
+ }
+
+ themePicker.onclick = switchThemeButtonState;
+ themePicker.onblur = handleThemeButtonsBlur;
+ availableThemes.forEach(function(item) {
+ var but = document.createElement("button");
+ but.textContent = item;
+ but.onclick = function() {
+ switchTheme(window.currentTheme, window.mainTheme, item, true);
+ useSystemTheme(false);
+ };
+ but.onblur = handleThemeButtonsBlur;
+ themeChoices.appendChild(but);
+ });
+}());
+
+(function() {
+ "use strict";
+
+ window.searchState = {
+ loadingText: "Loading search results...",
+ input: document.getElementsByClassName("search-input")[0],
+ outputElement: function() {
+ return document.getElementById("search");
+ },
+ title: document.title,
+ titleBeforeSearch: document.title,
+ timeout: null,
+ // On the search screen, so you remain on the last tab you opened.
+ //
+ // 0 for "In Names"
+ // 1 for "In Parameters"
+ // 2 for "In Return Types"
+ currentTab: 0,
+ // tab and back preserves the element that was focused.
+ focusedByTab: [null, null, null],
+ clearInputTimeout: function() {
+ if (searchState.timeout !== null) {
+ clearTimeout(searchState.timeout);
+ searchState.timeout = null;
+ }
+ },
+ // Sets the focus on the search bar at the top of the page
+ focus: function() {
+ searchState.input.focus();
+ },
+ // Removes the focus from the search bar.
+ defocus: function() {
+ searchState.input.blur();
+ },
+ showResults: function(search) {
+ if (search === null || typeof search === 'undefined') {
+ search = searchState.outputElement();
+ }
+ addClass(main, "hidden");
+ removeClass(search, "hidden");
+ searchState.mouseMovedAfterSearch = false;
+ document.title = searchState.title;
+ },
+ hideResults: function(search) {
+ if (search === null || typeof search === 'undefined') {
+ search = searchState.outputElement();
+ }
+ addClass(search, "hidden");
+ removeClass(main, "hidden");
+ document.title = searchState.titleBeforeSearch;
+ // We also remove the query parameter from the URL.
+ if (searchState.browserSupportsHistoryApi()) {
+ history.replaceState("", window.currentCrate + " - Rust",
+ getNakedUrl() + window.location.hash);
+ }
+ },
+ getQueryStringParams: function() {
+ var params = {};
+ window.location.search.substring(1).split("&").
+ map(function(s) {
+ var pair = s.split("=");
+ params[decodeURIComponent(pair[0])] =
+ typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
+ });
+ return params;
+ },
+ putBackSearch: function(search_input) {
+ var search = searchState.outputElement();
+ if (search_input.value !== "" && hasClass(search, "hidden")) {
+ searchState.showResults(search);
+ if (searchState.browserSupportsHistoryApi()) {
+ var extra = "?search=" + encodeURIComponent(search_input.value);
+ history.replaceState(search_input.value, "",
+ getNakedUrl() + extra + window.location.hash);
+ }
+ document.title = searchState.title;
+ }
+ },
+ browserSupportsHistoryApi: function() {
+ return window.history && typeof window.history.pushState === "function";
+ },
+ setup: function() {
+ var search_input = searchState.input;
+ if (!searchState.input) {
+ return;
+ }
+ function loadScript(url) {
+ var script = document.createElement('script');
+ script.src = url;
+ document.head.append(script);
+ }
+
+ var searchLoaded = false;
+ function loadSearch() {
+ if (!searchLoaded) {
+ searchLoaded = true;
+ loadScript(window.searchJS);
+ loadScript(window.searchIndexJS);
+ }
+ }
+
+ search_input.addEventListener("focus", function() {
+ searchState.putBackSearch(this);
+ search_input.origPlaceholder = searchState.input.placeholder;
+ search_input.placeholder = "Type your search here.";
+ loadSearch();
+ });
+ search_input.addEventListener("blur", function() {
+ search_input.placeholder = searchState.input.origPlaceholder;
+ });
+
+ search_input.removeAttribute('disabled');
+
+ // `crates{version}.js` should always be loaded before this script, so we can use it
+ // safely.
+ searchState.addCrateDropdown(window.ALL_CRATES);
+ var params = searchState.getQueryStringParams();
+ if (params.search !== undefined) {
+ var search = searchState.outputElement();
+ search.innerHTML = "<h3 style=\"text-align: center;\">" +
+ searchState.loadingText + "</h3>";
+ searchState.showResults(search);
+ loadSearch();
+ }
+ },
+ addCrateDropdown: function(crates) {
+ var elem = document.getElementById("crate-search");
+
+ if (!elem) {
+ return;
+ }
+ var savedCrate = getSettingValue("saved-filter-crate");
+ for (var i = 0, len = crates.length; i < len; ++i) {
+ var option = document.createElement("option");
+ option.value = crates[i];
+ option.innerText = crates[i];
+ elem.appendChild(option);
+ // Set the crate filter from saved storage, if the current page has the saved crate
+ // filter.
+ //
+ // If not, ignore the crate filter -- we want to support filtering for crates on
+ // sites like doc.rust-lang.org where the crates may differ from page to page while
+ // on the
+ // same domain.
+ if (crates[i] === savedCrate) {
+ elem.value = savedCrate;
+ }
+ }
+ },
+ };
+
+ function getPageId() {
+ if (window.location.hash) {
+ var tmp = window.location.hash.replace(/^#/, "");
+ if (tmp.length > 0) {
+ return tmp;
+ }
+ }
+ return null;
+ }
+
+ function showSidebar() {
+ var elems = document.getElementsByClassName("sidebar-elems")[0];
+ if (elems) {
+ addClass(elems, "show-it");
+ }
+ var sidebar = document.getElementsByClassName("sidebar")[0];
+ if (sidebar) {
+ addClass(sidebar, "mobile");
+ var filler = document.getElementById("sidebar-filler");
+ if (!filler) {
+ var div = document.createElement("div");
+ div.id = "sidebar-filler";
+ sidebar.appendChild(div);
+ }
+ }
+ }
+
+ function hideSidebar() {
+ var elems = document.getElementsByClassName("sidebar-elems")[0];
+ if (elems) {
+ removeClass(elems, "show-it");
+ }
+ var sidebar = document.getElementsByClassName("sidebar")[0];
+ removeClass(sidebar, "mobile");
+ var filler = document.getElementById("sidebar-filler");
+ if (filler) {
+ filler.remove();
+ }
+ document.getElementsByTagName("body")[0].style.marginTop = "";
+ }
+
+ var toggleAllDocsId = "toggle-all-docs";
+ var main = document.getElementById("main");
+ var savedHash = "";
+
+ function handleHashes(ev) {
+ var elem;
+ var search = searchState.outputElement();
+ if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
+ // This block occurs when clicking on an element in the navbar while
+ // in a search.
+ searchState.hideResults(search);
+ var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
+ if (searchState.browserSupportsHistoryApi()) {
+ // `window.location.search`` contains all the query parameters, not just `search`.
+ history.replaceState(hash, "",
+ getNakedUrl() + window.location.search + "#" + hash);
+ }
+ elem = document.getElementById(hash);
+ if (elem) {
+ elem.scrollIntoView();
+ }
+ }
+ // This part is used in case an element is not visible.
+ if (savedHash !== window.location.hash) {
+ savedHash = window.location.hash;
+ if (savedHash.length === 0) {
+ return;
+ }
+ expandSection(savedHash.slice(1)); // we remove the '#'
+ }
+ }
+
+ function onHashChange(ev) {
+ // If we're in mobile mode, we should hide the sidebar in any case.
+ hideSidebar();
+ handleHashes(ev);
+ }
+
+ function openParentDetails(elem) {
+ while (elem) {
+ if (elem.tagName === "DETAILS") {
+ elem.open = true;
+ }
+ elem = elem.parentNode;
+ }
+ }
+
+ function expandSection(id) {
+ openParentDetails(document.getElementById(id));
+ }
+
+ function getHelpElement(build) {
+ if (build) {
+ buildHelperPopup();
+ }
+ return document.getElementById("help");
+ }
+
+ function displayHelp(display, ev, help) {
+ if (display) {
+ help = help ? help : getHelpElement(true);
+ if (hasClass(help, "hidden")) {
+ ev.preventDefault();
+ removeClass(help, "hidden");
+ addClass(document.body, "blur");
+ }
+ } else {
+ // No need to build the help popup if we want to hide it in case it hasn't been
+ // built yet...
+ help = help ? help : getHelpElement(false);
+ if (help && !hasClass(help, "hidden")) {
+ ev.preventDefault();
+ addClass(help, "hidden");
+ removeClass(document.body, "blur");
+ }
+ }
+ }
+
+ function handleEscape(ev) {
+ var help = getHelpElement(false);
+ var search = searchState.outputElement();
+ if (help && !hasClass(help, "hidden")) {
+ displayHelp(false, ev, help);
+ } else if (search && !hasClass(search, "hidden")) {
+ searchState.clearInputTimeout();
+ ev.preventDefault();
+ searchState.hideResults(search);
+ }
+ searchState.defocus();
+ hideThemeButtonState();
+ }
+
+ var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
+ function handleShortcut(ev) {
+ // Don't interfere with browser shortcuts
+ if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
+ return;
+ }
+
+ if (document.activeElement.tagName === "INPUT") {
+ switch (getVirtualKey(ev)) {
+ case "Escape":
+ handleEscape(ev);
+ break;
+ }
+ } else {
+ switch (getVirtualKey(ev)) {
+ case "Escape":
+ handleEscape(ev);
+ break;
+
+ case "s":
+ case "S":
+ displayHelp(false, ev);
+ ev.preventDefault();
+ searchState.focus();
+ break;
+
+ case "+":
+ case "-":
+ ev.preventDefault();
+ toggleAllDocs();
+ break;
+
+ case "?":
+ displayHelp(true, ev);
+ break;
+
+ case "t":
+ case "T":
+ displayHelp(false, ev);
+ ev.preventDefault();
+ var themePicker = getThemePickerElement();
+ themePicker.click();
+ themePicker.focus();
+ break;
+
+ default:
+ if (getThemePickerElement().parentNode.contains(ev.target)) {
+ handleThemeKeyDown(ev);
+ }
+ }
+ }
+ }
+
+ function handleThemeKeyDown(ev) {
+ var active = document.activeElement;
+ var themes = getThemesElement();
+ switch (getVirtualKey(ev)) {
+ case "ArrowUp":
+ ev.preventDefault();
+ if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
+ active.previousElementSibling.focus();
+ } else {
+ showThemeButtonState();
+ themes.lastElementChild.focus();
+ }
+ break;
+ case "ArrowDown":
+ ev.preventDefault();
+ if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
+ active.nextElementSibling.focus();
+ } else {
+ showThemeButtonState();
+ themes.firstElementChild.focus();
+ }
+ break;
+ case "Enter":
+ case "Return":
+ case "Space":
+ if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
+ ev.preventDefault();
+ showThemeButtonState();
+ themes.firstElementChild.focus();
+ }
+ break;
+ case "Home":
+ ev.preventDefault();
+ themes.firstElementChild.focus();
+ break;
+ case "End":
+ ev.preventDefault();
+ themes.lastElementChild.focus();
+ break;
+ // The escape key is handled in handleEscape, not here,
+ // so that pressing escape will close the menu even if it isn't focused
+ }
+ }
+
+ document.addEventListener("keypress", handleShortcut);
+ document.addEventListener("keydown", handleShortcut);
+
+ (function() {
+ var x = document.getElementsByClassName("version-selector");
+ if (x.length > 0) {
+ x[0].onchange = function() {
+ var i, match,
+ url = document.location.href,
+ stripped = "",
+ len = window.rootPath.match(/\.\.\//g).length + 1;
+
+ for (i = 0; i < len; ++i) {
+ match = url.match(/\/[^/]*$/);
+ if (i < len - 1) {
+ stripped = match[0] + stripped;
+ }
+ url = url.substring(0, url.length - match[0].length);
+ }
+
+ var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
+ url += "/" + selectedVersion + stripped;
+
+ document.location.href = url;
+ };
+ }
+ }());
+
+ // delayed sidebar rendering.
+ window.initSidebarItems = function(items) {
+ var sidebar = document.getElementsByClassName("sidebar-elems")[0];
+ var current = window.sidebarCurrent;
+
+ function addSidebarCrates(crates) {
+ if (!hasClass(document.body, "crate")) {
+ // We only want to list crates on the crate page.
+ return;
+ }
+ // Draw a convenient sidebar of known crates if we have a listing
+ var div = document.createElement("div");
+ div.className = "block crate";
+ div.innerHTML = "<h3>Crates</h3>";
+ var ul = document.createElement("ul");
+ div.appendChild(ul);
+
+ for (var i = 0; i < crates.length; ++i) {
+ var klass = "crate";
+ if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
+ klass += " current";
+ }
+ var link = document.createElement("a");
+ link.href = window.rootPath + crates[i] + "/index.html";
+ link.className = klass;
+ link.textContent = crates[i];
+
+ var li = document.createElement("li");
+ li.appendChild(link);
+ ul.appendChild(li);
+ }
+ sidebar.appendChild(div);
+ }
+
+ function block(shortty, longty) {
+ var filtered = items[shortty];
+ if (!filtered) {
+ return;
+ }
+
+ var div = document.createElement("div");
+ div.className = "block " + shortty;
+ var h3 = document.createElement("h3");
+ h3.textContent = longty;
+ div.appendChild(h3);
+ var ul = document.createElement("ul");
+
+ for (var i = 0, len = filtered.length; i < len; ++i) {
+ var item = filtered[i];
+ var name = item[0];
+ var desc = item[1]; // can be null
+
+ var klass = shortty;
+ if (name === current.name && shortty === current.ty) {
+ klass += " current";
+ }
+ var path;
+ if (shortty === "mod") {
+ path = name + "/index.html";
+ } else {
+ path = shortty + "." + name + ".html";
+ }
+ var link = document.createElement("a");
+ link.href = current.relpath + path;
+ link.title = desc;
+ link.className = klass;
+ link.textContent = name;
+ var li = document.createElement("li");
+ li.appendChild(link);
+ ul.appendChild(li);
+ }
+ div.appendChild(ul);
+ sidebar.appendChild(div);
+ }
+
+ if (sidebar) {
+ var isModule = hasClass(document.body, "mod");
+ if (!isModule) {
+ block("primitive", "Primitive Types");
+ block("mod", "Modules");
+ block("macro", "Macros");
+ block("struct", "Structs");
+ block("enum", "Enums");
+ block("union", "Unions");
+ block("constant", "Constants");
+ block("static", "Statics");
+ block("trait", "Traits");
+ block("fn", "Functions");
+ block("type", "Type Definitions");
+ block("foreigntype", "Foreign Types");
+ block("keyword", "Keywords");
+ block("traitalias", "Trait Aliases");
+ }
+
+ // `crates{version}.js` should always be loaded before this script, so we can use
+ // it safely.
+ addSidebarCrates(window.ALL_CRATES);
+ }
+ };
+
+ window.register_implementors = function(imp) {
+ var implementors = document.getElementById("implementors-list");
+ var synthetic_implementors = document.getElementById("synthetic-implementors-list");
+
+ if (synthetic_implementors) {
+ // This `inlined_types` variable is used to avoid having the same implementation
+ // showing up twice. For example "String" in the "Sync" doc page.
+ //
+ // By the way, this is only used by and useful for traits implemented automatically
+ // (like "Send" and "Sync").
+ var inlined_types = new Set();
+ onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
+ var aliases = el.getAttribute("data-aliases");
+ if (!aliases) {
+ return;
+ }
+ aliases.split(",").forEach(function(alias) {
+ inlined_types.add(alias);
+ });
+ });
+ }
+
+ var libs = Object.getOwnPropertyNames(imp);
+ for (var i = 0, llength = libs.length; i < llength; ++i) {
+ if (libs[i] === window.currentCrate) { continue; }
+ var structs = imp[libs[i]];
+
+ struct_loop:
+ for (var j = 0, slength = structs.length; j < slength; ++j) {
+ var struct = structs[j];
+
+ var list = struct.synthetic ? synthetic_implementors : implementors;
+
+ if (struct.synthetic) {
+ for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
+ if (inlined_types.has(struct.types[k])) {
+ continue struct_loop;
+ }
+ inlined_types.add(struct.types[k]);
+ }
+ }
+
+ var code = document.createElement("code");
+ code.innerHTML = struct.text;
+
+ onEachLazy(code.getElementsByTagName("a"), function(elem) {
+ var href = elem.getAttribute("href");
+
+ if (href && href.indexOf("http") !== 0) {
+ elem.setAttribute("href", window.rootPath + href);
+ }
+ });
+
+ var display = document.createElement("h3");
+ addClass(display, "impl");
+ display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
+ "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
+ "</tbody></table></span>";
+ list.appendChild(display);
+ }
+ }
+ };
+ if (window.pending_implementors) {
+ window.register_implementors(window.pending_implementors);
+ }
+
+ function labelForToggleButton(sectionIsCollapsed) {
+ if (sectionIsCollapsed) {
+ // button will expand the section
+ return "+";
+ }
+ // button will collapse the section
+ // note that this text is also set in the HTML template in ../render/mod.rs
+ return "\u2212"; // "\u2212" is "−" minus sign
+ }
+
+ function toggleAllDocs() {
+ var innerToggle = document.getElementById(toggleAllDocsId);
+ if (!innerToggle) {
+ return;
+ }
+ var sectionIsCollapsed = false;
+ if (hasClass(innerToggle, "will-expand")) {
+ removeClass(innerToggle, "will-expand");
+ onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
+ if (!hasClass(e, "type-contents-toggle")) {
+ e.open = true;
+ }
+ });
+ innerToggle.title = "collapse all docs";
+ } else {
+ addClass(innerToggle, "will-expand");
+ onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
+ if (e.parentNode.id !== "main" ||
+ (!hasClass(e, "implementors-toggle") &&
+ !hasClass(e, "type-contents-toggle")))
+ {
+ e.open = false;
+ }
+ });
+ sectionIsCollapsed = true;
+ innerToggle.title = "expand all docs";
+ }
+ innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
+ }
+
+ function insertAfter(newNode, referenceNode) {
+ referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+ }
+
+ (function() {
+ var toggles = document.getElementById(toggleAllDocsId);
+ if (toggles) {
+ toggles.onclick = toggleAllDocs;
+ }
+
+ var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
+ var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
+ var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
+
+ function setImplementorsTogglesOpen(id, open) {
+ var list = document.getElementById(id);
+ if (list !== null) {
+ onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
+ e.open = open;
+ });
+ }
+ }
+
+ if (hideImplementations) {
+ setImplementorsTogglesOpen("trait-implementations-list", false);
+ setImplementorsTogglesOpen("blanket-implementations-list", false);
+ }
+
+ onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
+ if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
+ e.open = true;
+ }
+ if (hideMethodDocs && hasClass(e, "method-toggle")) {
+ e.open = false;
+ }
+
+ });
+
+ var pageId = getPageId();
+ if (pageId !== null) {
+ expandSection(pageId);
+ }
+ }());
+
+ (function() {
+ // To avoid checking on "rustdoc-line-numbers" value on every loop...
+ var lineNumbersFunc = function() {};
+ if (getSettingValue("line-numbers") === "true") {
+ lineNumbersFunc = function(x) {
+ var count = x.textContent.split("\n").length;
+ var elems = [];
+ for (var i = 0; i < count; ++i) {
+ elems.push(i + 1);
+ }
+ var node = document.createElement("pre");
+ addClass(node, "line-number");
+ node.innerHTML = elems.join("\n");
+ x.parentNode.insertBefore(node, x);
+ };
+ }
+ onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
+ if (hasClass(e, "compile_fail")) {
+ e.addEventListener("mouseover", function() {
+ this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
+ });
+ e.addEventListener("mouseout", function() {
+ this.parentElement.previousElementSibling.childNodes[0].style.color = "";
+ });
+ } else if (hasClass(e, "ignore")) {
+ e.addEventListener("mouseover", function() {
+ this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
+ });
+ e.addEventListener("mouseout", function() {
+ this.parentElement.previousElementSibling.childNodes[0].style.color = "";
+ });
+ }
+ lineNumbersFunc(e);
+ });
+ }());
+
+ function handleClick(id, f) {
+ var elem = document.getElementById(id);
+ if (elem) {
+ elem.addEventListener("click", f);
+ }
+ }
+ handleClick("help-button", function(ev) {
+ displayHelp(true, ev);
+ });
+
+ onEachLazy(document.getElementsByTagName("a"), function(el) {
+ // For clicks on internal links (<A> tags with a hash property), we expand the section we're
+ // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
+ // the height of the document so we wind up scrolled to the wrong place.
+ if (el.hash) {
+ el.addEventListener("click", function() {
+ expandSection(el.hash.slice(1));
+ });
+ }
+ });
+
+ onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
+ e.onclick = function() {
+ this.getElementsByClassName('notable-traits-tooltiptext')[0]
+ .classList.toggle("force-tooltip");
+ };
+ });
+
+ var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
+ if (sidebar_menu) {
+ sidebar_menu.onclick = function() {
+ var sidebar = document.getElementsByClassName("sidebar")[0];
+ if (hasClass(sidebar, "mobile")) {
+ hideSidebar();
+ } else {
+ showSidebar();
+ }
+ };
+ }
+
+ var buildHelperPopup = function() {
+ var popup = document.createElement("aside");
+ addClass(popup, "hidden");
+ popup.id = "help";
+
+ popup.addEventListener("click", function(ev) {
+ if (ev.target === popup) {
+ // Clicked the blurred zone outside the help popup; dismiss help.
+ displayHelp(false, ev);
+ }
+ });
+
+ var book_info = document.createElement("span");
+ book_info.innerHTML = "You can find more information in \
+ <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
+
+ var container = document.createElement("div");
+ var shortcuts = [
+ ["?", "Show this help dialog"],
+ ["S", "Focus the search field"],
+ ["T", "Focus the theme picker menu"],
+ ["↑", "Move up in search results"],
+ ["↓", "Move down in search results"],
+ ["← / →", "Switch result tab (when results focused)"],
+ ["⏎", "Go to active search result"],
+ ["+", "Expand all sections"],
+ ["-", "Collapse all sections"],
+ ].map(function(x) {
+ return "<dt>" +
+ x[0].split(" ")
+ .map(function(y, index) {
+ return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
+ })
+ .join("") + "</dt><dd>" + x[1] + "</dd>";
+ }).join("");
+ var div_shortcuts = document.createElement("div");
+ addClass(div_shortcuts, "shortcuts");
+ div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
+
+ var infos = [
+ "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
+ restrict the search to a given item kind.",
+ "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
+ <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
+ and <code>const</code>.",
+ "Search functions by type signature (e.g., <code>vec -> usize</code> or \
+ <code>* -> vec</code>)",
+ "Search multiple things at once by splitting your query with comma (e.g., \
+ <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
+ "You can look for items with an exact name by putting double quotes around \
+ your request: <code>\"string\"</code>",
+ "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
+ ].map(function(x) {
+ return "<p>" + x + "</p>";
+ }).join("");
+ var div_infos = document.createElement("div");
+ addClass(div_infos, "infos");
+ div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
+
+ container.appendChild(book_info);
+ container.appendChild(div_shortcuts);
+ container.appendChild(div_infos);
+
+ popup.appendChild(container);
+ insertAfter(popup, searchState.outputElement());
+ // So that it's only built once and then it'll do nothing when called!
+ buildHelperPopup = function() {};
+ };
+
+ onHashChange(null);
+ window.addEventListener("hashchange", onHashChange);
+ searchState.setup();
+}());
+
+(function () {
+ var reset_button_timeout = null;
+
+ window.copy_path = function(but) {
+ var parent = but.parentElement;
+ var path = [];
+
+ onEach(parent.childNodes, function(child) {
+ if (child.tagName === 'A') {
+ path.push(child.textContent);
+ }
+ });
+
+ var el = document.createElement('textarea');
+ el.value = 'use ' + path.join('::') + ';';
+ el.setAttribute('readonly', '');
+ // To not make it appear on the screen.
+ el.style.position = 'absolute';
+ el.style.left = '-9999px';
+
+ document.body.appendChild(el);
+ el.select();
+ document.execCommand('copy');
+ document.body.removeChild(el);
+
+ // There is always one children, but multiple childNodes.
+ but.children[0].style.display = 'none';
+
+ var tmp;
+ if (but.childNodes.length < 2) {
+ tmp = document.createTextNode('✓');
+ but.appendChild(tmp);
+ } else {
+ onEachLazy(but.childNodes, function(e) {
+ if (e.nodeType === Node.TEXT_NODE) {
+ tmp = e;
+ return true;
+ }
+ });
+ tmp.textContent = '✓';
+ }
+
+ if (reset_button_timeout !== null) {
+ window.clearTimeout(reset_button_timeout);
+ }
+
+ function reset_button() {
+ tmp.textContent = '';
+ reset_button_timeout = null;
+ but.children[0].style.display = "";
+ }
+
+ reset_button_timeout = window.setTimeout(reset_button, 1000);
+ };
+}());
--- /dev/null
+/* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
+/* global onEachLazy, removeClass, searchState, updateLocalStorage */
+
+(function() {
+// This mapping table should match the discriminants of
+// `rustdoc::html::item_type::ItemType` type in Rust.
+var itemTypes = ["mod",
+ "externcrate",
+ "import",
+ "struct",
+ "enum",
+ "fn",
+ "type",
+ "static",
+ "trait",
+ "impl",
+ "tymethod",
+ "method",
+ "structfield",
+ "variant",
+ "macro",
+ "primitive",
+ "associatedtype",
+ "constant",
+ "associatedconstant",
+ "union",
+ "foreigntype",
+ "keyword",
+ "existential",
+ "attr",
+ "derive",
+ "traitalias"];
+
+// used for special search precedence
+var TY_PRIMITIVE = itemTypes.indexOf("primitive");
+var TY_KEYWORD = itemTypes.indexOf("keyword");
+
+// In the search display, allows to switch between tabs.
+function printTab(nb) {
+ if (nb === 0 || nb === 1 || nb === 2) {
+ searchState.currentTab = nb;
+ }
+ var nb_copy = nb;
+ onEachLazy(document.getElementById("titles").childNodes, function(elem) {
+ if (nb_copy === 0) {
+ addClass(elem, "selected");
+ } else {
+ removeClass(elem, "selected");
+ }
+ nb_copy -= 1;
+ });
+ onEachLazy(document.getElementById("results").childNodes, function(elem) {
+ if (nb === 0) {
+ addClass(elem, "active");
+ } else {
+ removeClass(elem, "active");
+ }
+ nb -= 1;
+ });
+}
+
+function removeEmptyStringsFromArray(x) {
+ for (var i = 0, len = x.length; i < len; ++i) {
+ if (x[i] === "") {
+ x.splice(i, 1);
+ i -= 1;
+ }
+ }
+}
+
+/**
+ * A function to compute the Levenshtein distance between two strings
+ * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
+ * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
+ * This code is an unmodified version of the code written by Marco de Wit
+ * and was found at https://stackoverflow.com/a/18514751/745719
+ */
+var levenshtein_row2 = [];
+function levenshtein(s1, s2) {
+ if (s1 === s2) {
+ return 0;
+ }
+ var s1_len = s1.length, s2_len = s2.length;
+ if (s1_len && s2_len) {
+ var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
+ while (i1 < s1_len) {
+ row[i1] = ++i1;
+ }
+ while (i2 < s2_len) {
+ c2 = s2.charCodeAt(i2);
+ a = i2;
+ ++i2;
+ b = i2;
+ for (i1 = 0; i1 < s1_len; ++i1) {
+ c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
+ a = row[i1];
+ b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
+ row[i1] = b;
+ }
+ }
+ return b;
+ }
+ return s1_len + s2_len;
+}
+
+window.initSearch = function(rawSearchIndex) {
+ var MAX_LEV_DISTANCE = 3;
+ var MAX_RESULTS = 200;
+ var GENERICS_DATA = 2;
+ var NAME = 0;
+ var INPUTS_DATA = 0;
+ var OUTPUT_DATA = 1;
+ var NO_TYPE_FILTER = -1;
+ var currentResults, index, searchIndex;
+ var ALIASES = {};
+ var params = searchState.getQueryStringParams();
+
+ // Populate search bar with query string search term when provided,
+ // but only if the input bar is empty. This avoid the obnoxious issue
+ // where you start trying to do a search, and the index loads, and
+ // suddenly your search is gone!
+ if (searchState.input.value === "") {
+ searchState.input.value = params.search || "";
+ }
+
+ /**
+ * Executes the query and builds an index of results
+ * @param {[Object]} query [The user query]
+ * @param {[type]} searchWords [The list of search words to query
+ * against]
+ * @param {[type]} filterCrates [Crate to search in if defined]
+ * @return {[type]} [A search index of results]
+ */
+ function execQuery(query, searchWords, filterCrates) {
+ function itemTypeFromName(typename) {
+ for (var i = 0, len = itemTypes.length; i < len; ++i) {
+ if (itemTypes[i] === typename) {
+ return i;
+ }
+ }
+ return NO_TYPE_FILTER;
+ }
+
+ var valLower = query.query.toLowerCase(),
+ val = valLower,
+ typeFilter = itemTypeFromName(query.type),
+ results = {}, results_in_args = {}, results_returned = {},
+ split = valLower.split("::");
+
+ removeEmptyStringsFromArray(split);
+
+ function transformResults(results) {
+ var out = [];
+ for (var i = 0, len = results.length; i < len; ++i) {
+ if (results[i].id > -1) {
+ var obj = searchIndex[results[i].id];
+ obj.lev = results[i].lev;
+ var res = buildHrefAndPath(obj);
+ obj.displayPath = pathSplitter(res[0]);
+ obj.fullPath = obj.displayPath + obj.name;
+ // To be sure than it some items aren't considered as duplicate.
+ obj.fullPath += "|" + obj.ty;
+ obj.href = res[1];
+ out.push(obj);
+ if (out.length >= MAX_RESULTS) {
+ break;
+ }
+ }
+ }
+ return out;
+ }
+
+ function sortResults(results, isType) {
+ var ar = [];
+ for (var entry in results) {
+ if (hasOwnPropertyRustdoc(results, entry)) {
+ ar.push(results[entry]);
+ }
+ }
+ results = ar;
+ var i, len, result;
+ for (i = 0, len = results.length; i < len; ++i) {
+ result = results[i];
+ result.word = searchWords[result.id];
+ result.item = searchIndex[result.id] || {};
+ }
+ // if there are no results then return to default and fail
+ if (results.length === 0) {
+ return [];
+ }
+
+ results.sort(function(aaa, bbb) {
+ var a, b;
+
+ // sort by exact match with regard to the last word (mismatch goes later)
+ a = (aaa.word !== val);
+ b = (bbb.word !== val);
+ if (a !== b) { return a - b; }
+
+ // Sort by non levenshtein results and then levenshtein results by the distance
+ // (less changes required to match means higher rankings)
+ a = (aaa.lev);
+ b = (bbb.lev);
+ if (a !== b) { return a - b; }
+
+ // sort by crate (non-current crate goes later)
+ a = (aaa.item.crate !== window.currentCrate);
+ b = (bbb.item.crate !== window.currentCrate);
+ if (a !== b) { return a - b; }
+
+ // sort by item name length (longer goes later)
+ a = aaa.word.length;
+ b = bbb.word.length;
+ if (a !== b) { return a - b; }
+
+ // sort by item name (lexicographically larger goes later)
+ a = aaa.word;
+ b = bbb.word;
+ if (a !== b) { return (a > b ? +1 : -1); }
+
+ // sort by index of keyword in item name (no literal occurrence goes later)
+ a = (aaa.index < 0);
+ b = (bbb.index < 0);
+ if (a !== b) { return a - b; }
+ // (later literal occurrence, if any, goes later)
+ a = aaa.index;
+ b = bbb.index;
+ if (a !== b) { return a - b; }
+
+ // special precedence for primitive and keyword pages
+ if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
+ (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
+ return -1;
+ }
+ if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
+ (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
+ return 1;
+ }
+
+ // sort by description (no description goes later)
+ a = (aaa.item.desc === "");
+ b = (bbb.item.desc === "");
+ if (a !== b) { return a - b; }
+
+ // sort by type (later occurrence in `itemTypes` goes later)
+ a = aaa.item.ty;
+ b = bbb.item.ty;
+ if (a !== b) { return a - b; }
+
+ // sort by path (lexicographically larger goes later)
+ a = aaa.item.path;
+ b = bbb.item.path;
+ if (a !== b) { return (a > b ? +1 : -1); }
+
+ // que sera, sera
+ return 0;
+ });
+
+ for (i = 0, len = results.length; i < len; ++i) {
+ result = results[i];
+
+ // this validation does not make sense when searching by types
+ if (result.dontValidate) {
+ continue;
+ }
+ var name = result.item.name.toLowerCase(),
+ path = result.item.path.toLowerCase(),
+ parent = result.item.parent;
+
+ if (!isType && !validateResult(name, path, split, parent)) {
+ result.id = -1;
+ }
+ }
+ return transformResults(results);
+ }
+
+ function extractGenerics(val) {
+ val = val.toLowerCase();
+ if (val.indexOf("<") !== -1) {
+ var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
+ return {
+ name: val.substring(0, val.indexOf("<")),
+ generics: values.split(/\s*,\s*/),
+ };
+ }
+ return {
+ name: val,
+ generics: [],
+ };
+ }
+
+ function checkGenerics(obj, val) {
+ // The names match, but we need to be sure that all generics kinda
+ // match as well.
+ var tmp_lev, elem_name;
+ if (val.generics.length > 0) {
+ if (obj.length > GENERICS_DATA &&
+ obj[GENERICS_DATA].length >= val.generics.length) {
+ var elems = Object.create(null);
+ var elength = obj[GENERICS_DATA].length;
+ for (var x = 0; x < elength; ++x) {
+ if (!elems[obj[GENERICS_DATA][x]]) {
+ elems[obj[GENERICS_DATA][x]] = 0;
+ }
+ elems[obj[GENERICS_DATA][x]] += 1;
+ }
+ var total = 0;
+ var done = 0;
+ // We need to find the type that matches the most to remove it in order
+ // to move forward.
+ var vlength = val.generics.length;
+ for (x = 0; x < vlength; ++x) {
+ var lev = MAX_LEV_DISTANCE + 1;
+ var firstGeneric = val.generics[x];
+ var match = null;
+ if (elems[firstGeneric]) {
+ match = firstGeneric;
+ lev = 0;
+ } else {
+ for (elem_name in elems) {
+ tmp_lev = levenshtein(elem_name, firstGeneric);
+ if (tmp_lev < lev) {
+ lev = tmp_lev;
+ match = elem_name;
+ }
+ }
+ }
+ if (match !== null) {
+ elems[match] -= 1;
+ if (elems[match] == 0) {
+ delete elems[match];
+ }
+ total += lev;
+ done += 1;
+ } else {
+ return MAX_LEV_DISTANCE + 1;
+ }
+ }
+ return Math.ceil(total / done);
+ }
+ }
+ return MAX_LEV_DISTANCE + 1;
+ }
+
+ // Check for type name and type generics (if any).
+ function checkType(obj, val, literalSearch) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+ var len, x, firstGeneric;
+ if (obj[NAME] === val.name) {
+ if (literalSearch) {
+ if (val.generics && val.generics.length !== 0) {
+ if (obj.length > GENERICS_DATA &&
+ obj[GENERICS_DATA].length > 0) {
+ var elems = Object.create(null);
+ len = obj[GENERICS_DATA].length;
+ for (x = 0; x < len; ++x) {
+ if (!elems[obj[GENERICS_DATA][x]]) {
+ elems[obj[GENERICS_DATA][x]] = 0;
+ }
+ elems[obj[GENERICS_DATA][x]] += 1;
+ }
+
+ var allFound = true;
+ len = val.generics.length;
+ for (x = 0; x < len; ++x) {
+ firstGeneric = val.generics[x];
+ if (elems[firstGeneric]) {
+ elems[firstGeneric] -= 1;
+ } else {
+ allFound = false;
+ break;
+ }
+ }
+ if (allFound) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ } else {
+ // If the type has generics but don't match, then it won't return at this point.
+ // Otherwise, `checkGenerics` will return 0 and it'll return.
+ if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
+ var tmp_lev = checkGenerics(obj, val);
+ if (tmp_lev <= MAX_LEV_DISTANCE) {
+ return tmp_lev;
+ }
+ }
+ }
+ } else if (literalSearch) {
+ if ((!val.generics || val.generics.length === 0) &&
+ obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+ return obj[GENERICS_DATA].some(
+ function(name) {
+ return name === val.name;
+ });
+ }
+ return false;
+ }
+ lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
+ if (lev_distance <= MAX_LEV_DISTANCE) {
+ // The generics didn't match but the name kinda did so we give it
+ // a levenshtein distance value that isn't *this* good so it goes
+ // into the search results but not too high.
+ lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
+ } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+ // We can check if the type we're looking for is inside the generics!
+ var olength = obj[GENERICS_DATA].length;
+ for (x = 0; x < olength; ++x) {
+ lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
+ lev_distance);
+ }
+ }
+ // Now whatever happens, the returned distance is "less good" so we should mark it
+ // as such, and so we add 1 to the distance to make it "less good".
+ return lev_distance + 1;
+ }
+
+ function findArg(obj, val, literalSearch, typeFilter) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+
+ if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
+ var length = obj.type[INPUTS_DATA].length;
+ for (var i = 0; i < length; i++) {
+ var tmp = obj.type[INPUTS_DATA][i];
+ if (!typePassesFilter(typeFilter, tmp[1])) {
+ continue;
+ }
+ tmp = checkType(tmp, val, literalSearch);
+ if (literalSearch) {
+ if (tmp) {
+ return true;
+ }
+ continue;
+ }
+ lev_distance = Math.min(tmp, lev_distance);
+ if (lev_distance === 0) {
+ return 0;
+ }
+ }
+ }
+ return literalSearch ? false : lev_distance;
+ }
+
+ function checkReturned(obj, val, literalSearch, typeFilter) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+
+ if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
+ var ret = obj.type[OUTPUT_DATA];
+ if (typeof ret[0] === "string") {
+ ret = [ret];
+ }
+ for (var x = 0, len = ret.length; x < len; ++x) {
+ var tmp = ret[x];
+ if (!typePassesFilter(typeFilter, tmp[1])) {
+ continue;
+ }
+ tmp = checkType(tmp, val, literalSearch);
+ if (literalSearch) {
+ if (tmp) {
+ return true;
+ }
+ continue;
+ }
+ lev_distance = Math.min(tmp, lev_distance);
+ if (lev_distance === 0) {
+ return 0;
+ }
+ }
+ }
+ return literalSearch ? false : lev_distance;
+ }
+
+ function checkPath(contains, lastElem, ty) {
+ if (contains.length === 0) {
+ return 0;
+ }
+ var ret_lev = MAX_LEV_DISTANCE + 1;
+ var path = ty.path.split("::");
+
+ if (ty.parent && ty.parent.name) {
+ path.push(ty.parent.name.toLowerCase());
+ }
+
+ var length = path.length;
+ var clength = contains.length;
+ if (clength > length) {
+ return MAX_LEV_DISTANCE + 1;
+ }
+ for (var i = 0; i < length; ++i) {
+ if (i + clength > length) {
+ break;
+ }
+ var lev_total = 0;
+ var aborted = false;
+ for (var x = 0; x < clength; ++x) {
+ var lev = levenshtein(path[i + x], contains[x]);
+ if (lev > MAX_LEV_DISTANCE) {
+ aborted = true;
+ break;
+ }
+ lev_total += lev;
+ }
+ if (!aborted) {
+ ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
+ }
+ }
+ return ret_lev;
+ }
+
+ function typePassesFilter(filter, type) {
+ // No filter
+ if (filter <= NO_TYPE_FILTER) return true;
+
+ // Exact match
+ if (filter === type) return true;
+
+ // Match related items
+ var name = itemTypes[type];
+ switch (itemTypes[filter]) {
+ case "constant":
+ return name === "associatedconstant";
+ case "fn":
+ return name === "method" || name === "tymethod";
+ case "type":
+ return name === "primitive" || name === "associatedtype";
+ case "trait":
+ return name === "traitalias";
+ }
+
+ // No match
+ return false;
+ }
+
+ function createAliasFromItem(item) {
+ return {
+ crate: item.crate,
+ name: item.name,
+ path: item.path,
+ desc: item.desc,
+ ty: item.ty,
+ parent: item.parent,
+ type: item.type,
+ is_alias: true,
+ };
+ }
+
+ function handleAliases(ret, query, filterCrates) {
+ // We separate aliases and crate aliases because we want to have current crate
+ // aliases to be before the others in the displayed results.
+ var aliases = [];
+ var crateAliases = [];
+ if (filterCrates !== undefined) {
+ if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
+ var query_aliases = ALIASES[filterCrates][query.search];
+ var len = query_aliases.length;
+ for (var i = 0; i < len; ++i) {
+ aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+ }
+ }
+ } else {
+ Object.keys(ALIASES).forEach(function(crate) {
+ if (ALIASES[crate][query.search]) {
+ var pushTo = crate === window.currentCrate ? crateAliases : aliases;
+ var query_aliases = ALIASES[crate][query.search];
+ var len = query_aliases.length;
+ for (var i = 0; i < len; ++i) {
+ pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+ }
+ }
+ });
+ }
+
+ var sortFunc = function(aaa, bbb) {
+ if (aaa.path < bbb.path) {
+ return 1;
+ } else if (aaa.path === bbb.path) {
+ return 0;
+ }
+ return -1;
+ };
+ crateAliases.sort(sortFunc);
+ aliases.sort(sortFunc);
+
+ var pushFunc = function(alias) {
+ alias.alias = query.raw;
+ var res = buildHrefAndPath(alias);
+ alias.displayPath = pathSplitter(res[0]);
+ alias.fullPath = alias.displayPath + alias.name;
+ alias.href = res[1];
+
+ ret.others.unshift(alias);
+ if (ret.others.length > MAX_RESULTS) {
+ ret.others.pop();
+ }
+ };
+ onEach(aliases, pushFunc);
+ onEach(crateAliases, pushFunc);
+ }
+
+ // quoted values mean literal search
+ var nSearchWords = searchWords.length;
+ var i, it;
+ var ty;
+ var fullId;
+ var returned;
+ var in_args;
+ var len;
+ if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
+ val.charAt(val.length - 1) === val.charAt(0))
+ {
+ val = extractGenerics(val.substr(1, val.length - 2));
+ for (i = 0; i < nSearchWords; ++i) {
+ if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+ continue;
+ }
+ in_args = findArg(searchIndex[i], val, true, typeFilter);
+ returned = checkReturned(searchIndex[i], val, true, typeFilter);
+ ty = searchIndex[i];
+ fullId = ty.id;
+
+ if (searchWords[i] === val.name
+ && typePassesFilter(typeFilter, searchIndex[i].ty)
+ && results[fullId] === undefined) {
+ results[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (in_args && results_in_args[fullId] === undefined) {
+ results_in_args[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (returned && results_returned[fullId] === undefined) {
+ results_returned[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ }
+ query.inputs = [val];
+ query.output = val;
+ query.search = val;
+ // searching by type
+ } else if (val.search("->") > -1) {
+ var trimmer = function(s) { return s.trim(); };
+ var parts = val.split("->").map(trimmer);
+ var input = parts[0];
+ // sort inputs so that order does not matter
+ var inputs = input.split(",").map(trimmer).sort();
+ for (i = 0, len = inputs.length; i < len; ++i) {
+ inputs[i] = extractGenerics(inputs[i]);
+ }
+ var output = extractGenerics(parts[1]);
+
+ for (i = 0; i < nSearchWords; ++i) {
+ if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+ continue;
+ }
+ var type = searchIndex[i].type;
+ ty = searchIndex[i];
+ if (!type) {
+ continue;
+ }
+ fullId = ty.id;
+
+ returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
+ if (output.name === "*" || returned) {
+ in_args = false;
+ var is_module = false;
+
+ if (input === "*") {
+ is_module = true;
+ } else {
+ var allFound = true;
+ for (it = 0, len = inputs.length; allFound && it < len; it++) {
+ allFound = checkType(type, inputs[it], true);
+ }
+ in_args = allFound;
+ }
+ if (in_args) {
+ results_in_args[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (returned) {
+ results_returned[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (is_module) {
+ results[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ }
+ }
+ query.inputs = inputs.map(function(input) {
+ return input.name;
+ });
+ query.output = output.name;
+ } else {
+ query.inputs = [val];
+ query.output = val;
+ query.search = val;
+ // gather matching search results up to a certain maximum
+ val = val.replace(/_/g, "");
+
+ var valGenerics = extractGenerics(val);
+
+ var paths = valLower.split("::");
+ removeEmptyStringsFromArray(paths);
+ val = paths[paths.length - 1];
+ var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
+
+ var lev, j;
+ for (j = 0; j < nSearchWords; ++j) {
+ ty = searchIndex[j];
+ if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
+ continue;
+ }
+ var lev_add = 0;
+ if (paths.length > 1) {
+ lev = checkPath(contains, paths[paths.length - 1], ty);
+ if (lev > MAX_LEV_DISTANCE) {
+ continue;
+ } else if (lev > 0) {
+ lev_add = lev / 10;
+ }
+ }
+
+ returned = MAX_LEV_DISTANCE + 1;
+ in_args = MAX_LEV_DISTANCE + 1;
+ var index = -1;
+ // we want lev results to go lower than others
+ lev = MAX_LEV_DISTANCE + 1;
+ fullId = ty.id;
+
+ if (searchWords[j].indexOf(split[i]) > -1 ||
+ searchWords[j].indexOf(val) > -1 ||
+ ty.normalizedName.indexOf(val) > -1)
+ {
+ // filter type: ... queries
+ if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
+ index = ty.normalizedName.indexOf(val);
+ }
+ }
+ if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
+ if (typePassesFilter(typeFilter, ty.ty)) {
+ lev += 1;
+ } else {
+ lev = MAX_LEV_DISTANCE + 1;
+ }
+ }
+ in_args = findArg(ty, valGenerics, false, typeFilter);
+ returned = checkReturned(ty, valGenerics, false, typeFilter);
+
+ lev += lev_add;
+ if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
+ if (val.length < 6) {
+ lev -= 1;
+ } else {
+ lev = 0;
+ }
+ }
+ if (in_args <= MAX_LEV_DISTANCE) {
+ if (results_in_args[fullId] === undefined) {
+ results_in_args[fullId] = {
+ id: j,
+ index: index,
+ lev: in_args,
+ };
+ }
+ results_in_args[fullId].lev =
+ Math.min(results_in_args[fullId].lev, in_args);
+ }
+ if (returned <= MAX_LEV_DISTANCE) {
+ if (results_returned[fullId] === undefined) {
+ results_returned[fullId] = {
+ id: j,
+ index: index,
+ lev: returned,
+ };
+ }
+ results_returned[fullId].lev =
+ Math.min(results_returned[fullId].lev, returned);
+ }
+ if (typePassesFilter(typeFilter, ty.ty) &&
+ (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
+ if (index !== -1 && paths.length < 2) {
+ lev = 0;
+ }
+ if (results[fullId] === undefined) {
+ results[fullId] = {
+ id: j,
+ index: index,
+ lev: lev,
+ };
+ }
+ results[fullId].lev = Math.min(results[fullId].lev, lev);
+ }
+ }
+ }
+
+ var ret = {
+ "in_args": sortResults(results_in_args, true),
+ "returned": sortResults(results_returned, true),
+ "others": sortResults(results, false),
+ };
+ handleAliases(ret, query, filterCrates);
+ return ret;
+ }
+
+ /**
+ * Validate performs the following boolean logic. For example:
+ * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
+ * exists in (name || path || parent) OR => ("file" && "open") exists in
+ * (name || path )
+ *
+ * This could be written functionally, but I wanted to minimise
+ * functions on stack.
+ *
+ * @param {[string]} name [The name of the result]
+ * @param {[string]} path [The path of the result]
+ * @param {[string]} keys [The keys to be used (["file", "open"])]
+ * @param {[object]} parent [The parent of the result]
+ * @return {boolean} [Whether the result is valid or not]
+ */
+ function validateResult(name, path, keys, parent) {
+ for (var i = 0, len = keys.length; i < len; ++i) {
+ // each check is for validation so we negate the conditions and invalidate
+ if (!(
+ // check for an exact name match
+ name.indexOf(keys[i]) > -1 ||
+ // then an exact path match
+ path.indexOf(keys[i]) > -1 ||
+ // next if there is a parent, check for exact parent match
+ (parent !== undefined && parent.name !== undefined &&
+ parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
+ // lastly check to see if the name was a levenshtein match
+ levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function getQuery(raw) {
+ var matches, type, query;
+ query = raw;
+
+ matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
+ if (matches) {
+ type = matches[1].replace(/^const$/, "constant");
+ query = query.substring(matches[0].length);
+ }
+
+ return {
+ raw: raw,
+ query: query,
+ type: type,
+ id: query + type
+ };
+ }
+
+ function nextTab(direction) {
+ var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
+ searchState.focusedByTab[searchState.currentTab] = document.activeElement;
+ printTab(next);
+ focusSearchResult();
+ }
+
+ // Focus the first search result on the active tab, or the result that
+ // was focused last time this tab was active.
+ function focusSearchResult() {
+ var target = searchState.focusedByTab[searchState.currentTab] ||
+ document.querySelectorAll(".search-results.active a").item(0) ||
+ document.querySelectorAll("#titles > button").item(searchState.currentTab);
+ if (target) {
+ target.focus();
+ }
+ }
+
+ function buildHrefAndPath(item) {
+ var displayPath;
+ var href;
+ var type = itemTypes[item.ty];
+ var name = item.name;
+ var path = item.path;
+
+ if (type === "mod") {
+ displayPath = path + "::";
+ href = window.rootPath + path.replace(/::/g, "/") + "/" +
+ name + "/index.html";
+ } else if (type === "primitive" || type === "keyword") {
+ displayPath = "";
+ href = window.rootPath + path.replace(/::/g, "/") +
+ "/" + type + "." + name + ".html";
+ } else if (type === "externcrate") {
+ displayPath = "";
+ href = window.rootPath + name + "/index.html";
+ } else if (item.parent !== undefined) {
+ var myparent = item.parent;
+ var anchor = "#" + type + "." + name;
+ var parentType = itemTypes[myparent.ty];
+ var pageType = parentType;
+ var pageName = myparent.name;
+
+ if (parentType === "primitive") {
+ displayPath = myparent.name + "::";
+ } else if (type === "structfield" && parentType === "variant") {
+ // Structfields belonging to variants are special: the
+ // final path element is the enum name.
+ var enumNameIdx = item.path.lastIndexOf("::");
+ var enumName = item.path.substr(enumNameIdx + 2);
+ path = item.path.substr(0, enumNameIdx);
+ displayPath = path + "::" + enumName + "::" + myparent.name + "::";
+ anchor = "#variant." + myparent.name + ".field." + name;
+ pageType = "enum";
+ pageName = enumName;
+ } else {
+ displayPath = path + "::" + myparent.name + "::";
+ }
+ href = window.rootPath + path.replace(/::/g, "/") +
+ "/" + pageType +
+ "." + pageName +
+ ".html" + anchor;
+ } else {
+ displayPath = item.path + "::";
+ href = window.rootPath + item.path.replace(/::/g, "/") +
+ "/" + type + "." + name + ".html";
+ }
+ return [displayPath, href];
+ }
+
+ function escape(content) {
+ var h1 = document.createElement("h1");
+ h1.textContent = content;
+ return h1.innerHTML;
+ }
+
+ function pathSplitter(path) {
+ var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
+ if (tmp.endsWith("<span>")) {
+ return tmp.slice(0, tmp.length - 6);
+ }
+ return tmp;
+ }
+
+ function addTab(array, query, display) {
+ var extraClass = "";
+ if (display === true) {
+ extraClass = " active";
+ }
+
+ var output = document.createElement("div");
+ var duplicates = {};
+ var length = 0;
+ if (array.length > 0) {
+ output.className = "search-results " + extraClass;
+
+ array.forEach(function(item) {
+ if (item.is_alias !== true) {
+ if (duplicates[item.fullPath]) {
+ return;
+ }
+ duplicates[item.fullPath] = true;
+ }
+
+ var name = item.name;
+ var type = itemTypes[item.ty];
+
+ length += 1;
+
+ var extra = "";
+ if (type === "primitive") {
+ extra = " <i>(primitive type)</i>";
+ } else if (type === "keyword") {
+ extra = " <i>(keyword)</i>";
+ }
+
+ var link = document.createElement("a");
+ link.className = "result-" + type;
+ link.href = item.href;
+
+ var wrapper = document.createElement("div");
+ var resultName = document.createElement("div");
+ resultName.className = "result-name";
+
+ if (item.is_alias) {
+ var alias = document.createElement("span");
+ alias.className = "alias";
+
+ var bold = document.createElement("b");
+ bold.innerText = item.alias;
+ alias.appendChild(bold);
+
+ alias.insertAdjacentHTML(
+ "beforeend",
+ "<span class=\"grey\"><i> - see </i></span>");
+
+ resultName.appendChild(alias);
+ }
+ resultName.insertAdjacentHTML(
+ "beforeend",
+ item.displayPath + "<span class=\"" + type + "\">" + name + extra + "</span>");
+ wrapper.appendChild(resultName);
+
+ var description = document.createElement("div");
+ description.className = "desc";
+ var spanDesc = document.createElement("span");
+ spanDesc.insertAdjacentHTML("beforeend", item.desc);
+
+ description.appendChild(spanDesc);
+ wrapper.appendChild(description);
+ link.appendChild(wrapper);
+ output.appendChild(link);
+ });
+ } else {
+ output.className = "search-failed" + extraClass;
+ output.innerHTML = "No results :(<br/>" +
+ "Try on <a href=\"https://duckduckgo.com/?q=" +
+ encodeURIComponent("rust " + query.query) +
+ "\">DuckDuckGo</a>?<br/><br/>" +
+ "Or try looking in one of these:<ul><li>The <a " +
+ "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
+ " for technical details about the language.</li><li><a " +
+ "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
+ "Example</a> for expository code examples.</a></li><li>The <a " +
+ "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
+ "introductions to language features and the language itself.</li><li><a " +
+ "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
+ " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>";
+ }
+ return [output, length];
+ }
+
+ function makeTabHeader(tabNb, text, nbElems) {
+ if (searchState.currentTab === tabNb) {
+ return "<button class=\"selected\">" + text +
+ " <div class=\"count\">(" + nbElems + ")</div></button>";
+ }
+ return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
+ }
+
+ function showResults(results, go_to_first) {
+ var search = searchState.outputElement();
+ if (go_to_first || (results.others.length === 1
+ && getSettingValue("go-to-only-result") === "true"
+ // By default, the search DOM element is "empty" (meaning it has no children not
+ // text content). Once a search has been run, it won't be empty, even if you press
+ // ESC or empty the search input (which also "cancels" the search).
+ && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)))
+ {
+ var elem = document.createElement("a");
+ elem.href = results.others[0].href;
+ removeClass(elem, "active");
+ // For firefox, we need the element to be in the DOM so it can be clicked.
+ document.body.appendChild(elem);
+ elem.click();
+ return;
+ }
+ var query = getQuery(searchState.input.value);
+
+ currentResults = query.id;
+
+ var ret_others = addTab(results.others, query);
+ var ret_in_args = addTab(results.in_args, query, false);
+ var ret_returned = addTab(results.returned, query, false);
+
+ // Navigate to the relevant tab if the current tab is empty, like in case users search
+ // for "-> String". If they had selected another tab previously, they have to click on
+ // it again.
+ var currentTab = searchState.currentTab;
+ if ((currentTab === 0 && ret_others[1] === 0) ||
+ (currentTab === 1 && ret_in_args[1] === 0) ||
+ (currentTab === 2 && ret_returned[1] === 0)) {
+ if (ret_others[1] !== 0) {
+ currentTab = 0;
+ } else if (ret_in_args[1] !== 0) {
+ currentTab = 1;
+ } else if (ret_returned[1] !== 0) {
+ currentTab = 2;
+ }
+ }
+
+ var output = "<h1>Results for " + escape(query.query) +
+ (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
+ "<div id=\"titles\">" +
+ makeTabHeader(0, "In Names", ret_others[1]) +
+ makeTabHeader(1, "In Parameters", ret_in_args[1]) +
+ makeTabHeader(2, "In Return Types", ret_returned[1]) +
+ "</div>";
+
+ var resultsElem = document.createElement("div");
+ resultsElem.id = "results";
+ resultsElem.appendChild(ret_others[0]);
+ resultsElem.appendChild(ret_in_args[0]);
+ resultsElem.appendChild(ret_returned[0]);
+
+ search.innerHTML = output;
+ search.appendChild(resultsElem);
+ // Reset focused elements.
+ searchState.focusedByTab = [null, null, null];
+ searchState.showResults(search);
+ var elems = document.getElementById("titles").childNodes;
+ elems[0].onclick = function() { printTab(0); };
+ elems[1].onclick = function() { printTab(1); };
+ elems[2].onclick = function() { printTab(2); };
+ printTab(currentTab);
+ }
+
+ function execSearch(query, searchWords, filterCrates) {
+ function getSmallest(arrays, positions, notDuplicates) {
+ var start = null;
+
+ for (var it = 0, len = positions.length; it < len; ++it) {
+ if (arrays[it].length > positions[it] &&
+ (start === null || start > arrays[it][positions[it]].lev) &&
+ !notDuplicates[arrays[it][positions[it]].fullPath]) {
+ start = arrays[it][positions[it]].lev;
+ }
+ }
+ return start;
+ }
+
+ function mergeArrays(arrays) {
+ var ret = [];
+ var positions = [];
+ var notDuplicates = {};
+
+ for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
+ positions.push(0);
+ }
+ while (ret.length < MAX_RESULTS) {
+ var smallest = getSmallest(arrays, positions, notDuplicates);
+
+ if (smallest === null) {
+ break;
+ }
+ for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
+ if (arrays[x].length > positions[x] &&
+ arrays[x][positions[x]].lev === smallest &&
+ !notDuplicates[arrays[x][positions[x]].fullPath]) {
+ ret.push(arrays[x][positions[x]]);
+ notDuplicates[arrays[x][positions[x]].fullPath] = true;
+ positions[x] += 1;
+ }
+ }
+ }
+ return ret;
+ }
+
+ // Split search query by ",", while respecting angle bracket nesting.
+ // Since "<" is an alias for the Ord family of traits, it also uses
+ // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
+ //
+ // tokenizeQuery("A<B, C>, D") == ["A<B, C>", "D"]
+ // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"]
+ function tokenizeQuery(raw) {
+ var i, matched;
+ var l = raw.length;
+ var depth = 0;
+ var nextAngle = /(<|>)/g;
+ var ret = [];
+ var start = 0;
+ for (i = 0; i < l; ++i) {
+ switch (raw[i]) {
+ case "<":
+ nextAngle.lastIndex = i + 1;
+ matched = nextAngle.exec(raw);
+ if (matched && matched[1] === '>') {
+ depth += 1;
+ }
+ break;
+ case ">":
+ if (depth > 0) {
+ depth -= 1;
+ }
+ break;
+ case ",":
+ if (depth === 0) {
+ ret.push(raw.substring(start, i));
+ start = i + 1;
+ }
+ break;
+ }
+ }
+ if (start !== i) {
+ ret.push(raw.substring(start, i));
+ }
+ return ret;
+ }
+
+ var queries = tokenizeQuery(query.raw);
+ var results = {
+ "in_args": [],
+ "returned": [],
+ "others": [],
+ };
+
+ for (var i = 0, len = queries.length; i < len; ++i) {
+ query = queries[i].trim();
+ if (query.length !== 0) {
+ var tmp = execQuery(getQuery(query), searchWords, filterCrates);
+
+ results.in_args.push(tmp.in_args);
+ results.returned.push(tmp.returned);
+ results.others.push(tmp.others);
+ }
+ }
+ if (queries.length > 1) {
+ return {
+ "in_args": mergeArrays(results.in_args),
+ "returned": mergeArrays(results.returned),
+ "others": mergeArrays(results.others),
+ };
+ }
+ return {
+ "in_args": results.in_args[0],
+ "returned": results.returned[0],
+ "others": results.others[0],
+ };
+ }
+
+ function getFilterCrates() {
+ var elem = document.getElementById("crate-search");
+
+ if (elem && elem.value !== "All crates" &&
+ hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
+ {
+ return elem.value;
+ }
+ return undefined;
+ }
+
+ function search(e, forced) {
+ var params = searchState.getQueryStringParams();
+ var query = getQuery(searchState.input.value.trim());
+
+ if (e) {
+ e.preventDefault();
+ }
+
+ if (query.query.length === 0) {
+ return;
+ }
+ if (!forced && query.id === currentResults) {
+ if (query.query.length > 0) {
+ searchState.putBackSearch(searchState.input);
+ }
+ return;
+ }
+
+ // Update document title to maintain a meaningful browser history
+ searchState.title = "Results for " + query.query + " - Rust";
+
+ // Because searching is incremental by character, only the most
+ // recent search query is added to the browser history.
+ if (searchState.browserSupportsHistoryApi()) {
+ var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
+ window.location.hash;
+ if (!history.state && !params.search) {
+ history.pushState(query, "", newURL);
+ } else {
+ history.replaceState(query, "", newURL);
+ }
+ }
+
+ var filterCrates = getFilterCrates();
+ showResults(execSearch(query, index, filterCrates), params.go_to_first);
+ }
+
+ function buildIndex(rawSearchIndex) {
+ searchIndex = [];
+ var searchWords = [];
+ var i, word;
+ var currentIndex = 0;
+ var id = 0;
+
+ for (var crate in rawSearchIndex) {
+ if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
+ continue;
+ }
+
+ var crateSize = 0;
+
+ searchWords.push(crate);
+ // This object should have exactly the same set of fields as the "row"
+ // object defined below. Your JavaScript runtime will thank you.
+ // https://mathiasbynens.be/notes/shapes-ics
+ var crateRow = {
+ crate: crate,
+ ty: 1, // == ExternCrate
+ name: crate,
+ path: "",
+ desc: rawSearchIndex[crate].doc,
+ parent: undefined,
+ type: null,
+ id: id,
+ normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
+ };
+ id += 1;
+ searchIndex.push(crateRow);
+ currentIndex += 1;
+
+ // an array of (Number) item types
+ var itemTypes = rawSearchIndex[crate].t;
+ // an array of (String) item names
+ var itemNames = rawSearchIndex[crate].n;
+ // an array of (String) full paths (or empty string for previous path)
+ var itemPaths = rawSearchIndex[crate].q;
+ // an array of (String) descriptions
+ var itemDescs = rawSearchIndex[crate].d;
+ // an array of (Number) the parent path index + 1 to `paths`, or 0 if none
+ var itemParentIdxs = rawSearchIndex[crate].i;
+ // an array of (Object | null) the type of the function, if any
+ var itemFunctionSearchTypes = rawSearchIndex[crate].f;
+ // an array of [(Number) item type,
+ // (String) name]
+ var paths = rawSearchIndex[crate].p;
+ // a array of [(String) alias name
+ // [Number] index to items]
+ var aliases = rawSearchIndex[crate].a;
+
+ // convert `rawPaths` entries into object form
+ var len = paths.length;
+ for (i = 0; i < len; ++i) {
+ paths[i] = {ty: paths[i][0], name: paths[i][1]};
+ }
+
+ // convert `item*` into an object form, and construct word indices.
+ //
+ // before any analysis is performed lets gather the search terms to
+ // search against apart from the rest of the data. This is a quick
+ // operation that is cached for the life of the page state so that
+ // all other search operations have access to this cached data for
+ // faster analysis operations
+ len = itemTypes.length;
+ var lastPath = "";
+ for (i = 0; i < len; ++i) {
+ // This object should have exactly the same set of fields as the "crateRow"
+ // object defined above.
+ if (typeof itemNames[i] === "string") {
+ word = itemNames[i].toLowerCase();
+ searchWords.push(word);
+ } else {
+ word = "";
+ searchWords.push("");
+ }
+ var row = {
+ crate: crate,
+ ty: itemTypes[i],
+ name: itemNames[i],
+ path: itemPaths[i] ? itemPaths[i] : lastPath,
+ desc: itemDescs[i],
+ parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
+ type: itemFunctionSearchTypes[i],
+ id: id,
+ normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
+ };
+ id += 1;
+ searchIndex.push(row);
+ lastPath = row.path;
+ crateSize += 1;
+ }
+
+ if (aliases) {
+ ALIASES[crate] = {};
+ var j, local_aliases;
+ for (var alias_name in aliases) {
+ if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
+ continue;
+ }
+
+ if (!hasOwnPropertyRustdoc(ALIASES[crate], alias_name)) {
+ ALIASES[crate][alias_name] = [];
+ }
+ local_aliases = aliases[alias_name];
+ for (j = 0, len = local_aliases.length; j < len; ++j) {
+ ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
+ }
+ }
+ }
+ currentIndex += crateSize;
+ }
+ return searchWords;
+ }
+
+ function registerSearchEvents() {
+ var searchAfter500ms = function() {
+ searchState.clearInputTimeout();
+ if (searchState.input.value.length === 0) {
+ if (searchState.browserSupportsHistoryApi()) {
+ history.replaceState("", window.currentCrate + " - Rust",
+ getNakedUrl() + window.location.hash);
+ }
+ searchState.hideResults();
+ } else {
+ searchState.timeout = setTimeout(search, 500);
+ }
+ };
+ searchState.input.onkeyup = searchAfter500ms;
+ searchState.input.oninput = searchAfter500ms;
+ document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
+ e.preventDefault();
+ searchState.clearInputTimeout();
+ search();
+ };
+ searchState.input.onchange = function(e) {
+ if (e.target !== document.activeElement) {
+ // To prevent doing anything when it's from a blur event.
+ return;
+ }
+ // Do NOT e.preventDefault() here. It will prevent pasting.
+ searchState.clearInputTimeout();
+ // zero-timeout necessary here because at the time of event handler execution the
+ // pasted content is not in the input field yet. Shouldn’t make any difference for
+ // change, though.
+ setTimeout(search, 0);
+ };
+ searchState.input.onpaste = searchState.input.onchange;
+
+ searchState.outputElement().addEventListener("keydown", function(e) {
+ // We only handle unmodified keystrokes here. We don't want to interfere with,
+ // for instance, alt-left and alt-right for history navigation.
+ if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
+ return;
+ }
+ // up and down arrow select next/previous search result, or the
+ // search box if we're already at the top.
+ if (e.which === 38) { // up
+ var previous = document.activeElement.previousElementSibling;
+ if (previous) {
+ previous.focus();
+ } else {
+ searchState.focus();
+ }
+ e.preventDefault();
+ } else if (e.which === 40) { // down
+ var next = document.activeElement.nextElementSibling;
+ if (next) {
+ next.focus();
+ }
+ var rect = document.activeElement.getBoundingClientRect();
+ if (window.innerHeight - rect.bottom < rect.height) {
+ window.scrollBy(0, rect.height);
+ }
+ e.preventDefault();
+ } else if (e.which === 37) { // left
+ nextTab(-1);
+ e.preventDefault();
+ } else if (e.which === 39) { // right
+ nextTab(1);
+ e.preventDefault();
+ }
+ });
+
+ searchState.input.addEventListener("keydown", function(e) {
+ if (e.which === 40) { // down
+ focusSearchResult();
+ e.preventDefault();
+ }
+ });
+
+
+ var selectCrate = document.getElementById("crate-search");
+ if (selectCrate) {
+ selectCrate.onchange = function() {
+ updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
+ // In case you "cut" the entry from the search input, then change the crate filter
+ // before paste back the previous search, you get the old search results without
+ // the filter. To prevent this, we need to remove the previous results.
+ currentResults = null;
+ search(undefined, true);
+ };
+ }
+
+ // Push and pop states are used to add search results to the browser
+ // history.
+ if (searchState.browserSupportsHistoryApi()) {
+ // Store the previous <title> so we can revert back to it later.
+ var previousTitle = document.title;
+
+ window.addEventListener("popstate", function(e) {
+ var params = searchState.getQueryStringParams();
+ // Revert to the previous title manually since the History
+ // API ignores the title parameter.
+ document.title = previousTitle;
+ // When browsing forward to search results the previous
+ // search will be repeated, so the currentResults are
+ // cleared to ensure the search is successful.
+ currentResults = null;
+ // Synchronize search bar with query string state and
+ // perform the search. This will empty the bar if there's
+ // nothing there, which lets you really go back to a
+ // previous state with nothing in the bar.
+ if (params.search && params.search.length > 0) {
+ searchState.input.value = params.search;
+ // Some browsers fire "onpopstate" for every page load
+ // (Chrome), while others fire the event only when actually
+ // popping a state (Firefox), which is why search() is
+ // called both here and at the end of the startSearch()
+ // function.
+ search(e);
+ } else {
+ searchState.input.value = "";
+ // When browsing back from search results the main page
+ // visibility must be reset.
+ searchState.hideResults();
+ }
+ });
+ }
+
+ // This is required in firefox to avoid this problem: Navigating to a search result
+ // with the keyboard, hitting enter, and then hitting back would take you back to
+ // the doc page, rather than the search that should overlay it.
+ // This was an interaction between the back-forward cache and our handlers
+ // that try to sync state between the URL and the search input. To work around it,
+ // do a small amount of re-init on page show.
+ window.onpageshow = function(){
+ var qSearch = searchState.getQueryStringParams().search;
+ if (searchState.input.value === "" && qSearch) {
+ searchState.input.value = qSearch;
+ }
+ search();
+ };
+ }
+
+ index = buildIndex(rawSearchIndex);
+ registerSearchEvents();
+ // If there's a search term in the URL, execute the search now.
+ if (searchState.getQueryStringParams().search) {
+ search();
+ }
+};
+
+if (window.searchIndex !== undefined) {
+ initSearch(window.searchIndex);
+}
+
+})();
--- /dev/null
+// Local js definitions:
+/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
+
+(function () {
+ function changeSetting(settingName, value) {
+ updateLocalStorage("rustdoc-" + settingName, value);
+
+ switch (settingName) {
+ case "preferred-dark-theme":
+ case "preferred-light-theme":
+ case "use-system-theme":
+ updateSystemTheme();
+ break;
+ }
+ }
+
+ function handleKey(ev) {
+ // Don't interfere with browser shortcuts
+ if (ev.ctrlKey || ev.altKey || ev.metaKey) {
+ return;
+ }
+ switch (getVirtualKey(ev)) {
+ case "Enter":
+ case "Return":
+ case "Space":
+ ev.target.checked = !ev.target.checked;
+ ev.preventDefault();
+ break;
+ }
+ }
+
+ function setEvents() {
+ onEachLazy(document.getElementsByClassName("slider"), function(elem) {
+ var toggle = elem.previousElementSibling;
+ var settingId = toggle.id;
+ var settingValue = getSettingValue(settingId);
+ if (settingValue !== null) {
+ toggle.checked = settingValue === "true";
+ }
+ toggle.onchange = function() {
+ changeSetting(this.id, this.checked);
+ };
+ toggle.onkeyup = handleKey;
+ toggle.onkeyrelease = handleKey;
+ });
+ onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
+ var select = elem.getElementsByTagName("select")[0];
+ var settingId = select.id;
+ var settingValue = getSettingValue(settingId);
+ if (settingValue !== null) {
+ select.value = settingValue;
+ }
+ select.onchange = function() {
+ changeSetting(this.id, this.value);
+ };
+ });
+ }
+
+ window.addEventListener("DOMContentLoaded", setEvents);
+})();
--- /dev/null
+// From rust:
+/* global search, sourcesIndex */
+
+// Local js definitions:
+/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
+/* global updateLocalStorage */
+(function() {
+
+function getCurrentFilePath() {
+ var parts = window.location.pathname.split("/");
+ var rootPathParts = window.rootPath.split("/");
+
+ for (var i = 0, len = rootPathParts.length; i < len; ++i) {
+ if (rootPathParts[i] === "..") {
+ parts.pop();
+ }
+ }
+ var file = window.location.pathname.substring(parts.join("/").length);
+ if (file.startsWith("/")) {
+ file = file.substring(1);
+ }
+ return file.substring(0, file.length - 5);
+}
+
+function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
+ var name = document.createElement("div");
+ name.className = "name";
+
+ fullPath += elem["name"] + "/";
+
+ name.onclick = function() {
+ if (hasClass(this, "expand")) {
+ removeClass(this, "expand");
+ } else {
+ addClass(this, "expand");
+ }
+ };
+ name.innerText = elem["name"];
+
+ var i, len;
+
+ var children = document.createElement("div");
+ children.className = "children";
+ var folders = document.createElement("div");
+ folders.className = "folders";
+ if (elem.dirs) {
+ for (i = 0, len = elem.dirs.length; i < len; ++i) {
+ if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
+ hasFoundFile)) {
+ addClass(name, "expand");
+ hasFoundFile = true;
+ }
+ }
+ }
+ children.appendChild(folders);
+
+ var files = document.createElement("div");
+ files.className = "files";
+ if (elem.files) {
+ for (i = 0, len = elem.files.length; i < len; ++i) {
+ var file = document.createElement("a");
+ file.innerText = elem.files[i];
+ file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
+ if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
+ file.className = "selected";
+ addClass(name, "expand");
+ hasFoundFile = true;
+ }
+ files.appendChild(file);
+ }
+ }
+ search.fullPath = fullPath;
+ children.appendChild(files);
+ parent.appendChild(name);
+ parent.appendChild(children);
+ return hasFoundFile && currentFile.startsWith(fullPath);
+}
+
+function toggleSidebar() {
+ var sidebar = document.getElementById("source-sidebar");
+ var child = this.children[0].children[0];
+ if (child.innerText === ">") {
+ sidebar.style.left = "";
+ this.style.left = "";
+ child.innerText = "<";
+ updateLocalStorage("rustdoc-source-sidebar-show", "true");
+ } else {
+ sidebar.style.left = "-300px";
+ this.style.left = "0";
+ child.innerText = ">";
+ updateLocalStorage("rustdoc-source-sidebar-show", "false");
+ }
+}
+
+function createSidebarToggle() {
+ var sidebarToggle = document.createElement("div");
+ sidebarToggle.id = "sidebar-toggle";
+ sidebarToggle.onclick = toggleSidebar;
+
+ var inner1 = document.createElement("div");
+ inner1.style.position = "relative";
+
+ var inner2 = document.createElement("div");
+ inner2.style.paddingTop = "3px";
+ if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
+ inner2.innerText = "<";
+ } else {
+ inner2.innerText = ">";
+ sidebarToggle.style.left = "0";
+ }
+
+ inner1.appendChild(inner2);
+ sidebarToggle.appendChild(inner1);
+ return sidebarToggle;
+}
+
+// This function is called from "source-files.js", generated in `html/render/mod.rs`.
+// eslint-disable-next-line no-unused-vars
+function createSourceSidebar() {
+ if (!window.rootPath.endsWith("/")) {
+ window.rootPath += "/";
+ }
+ var main = document.getElementById("main");
+
+ var sidebarToggle = createSidebarToggle();
+ main.insertBefore(sidebarToggle, main.firstChild);
+
+ var sidebar = document.createElement("div");
+ sidebar.id = "source-sidebar";
+ if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
+ sidebar.style.left = "-300px";
+ }
+
+ var currentFile = getCurrentFilePath();
+ var hasFoundFile = false;
+
+ var title = document.createElement("div");
+ title.className = "title";
+ title.innerText = "Files";
+ sidebar.appendChild(title);
+ Object.keys(sourcesIndex).forEach(function(key) {
+ sourcesIndex[key].name = key;
+ hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
+ currentFile, hasFoundFile);
+ });
+
+ main.insertBefore(sidebar, main.firstChild);
+ // Focus on the current file in the source files sidebar.
+ var selected_elem = sidebar.getElementsByClassName("selected")[0];
+ if (typeof selected_elem !== "undefined") {
+ selected_elem.focus();
+ }
+}
+
+var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
+
+function highlightSourceLines(scrollTo, match) {
+ if (typeof match === "undefined") {
+ match = window.location.hash.match(lineNumbersRegex);
+ }
+ if (!match) {
+ return;
+ }
+ var from = parseInt(match[1], 10);
+ var to = from;
+ if (typeof match[2] !== "undefined") {
+ to = parseInt(match[2], 10);
+ }
+ if (to < from) {
+ var tmp = to;
+ to = from;
+ from = tmp;
+ }
+ var elem = document.getElementById(from);
+ if (!elem) {
+ return;
+ }
+ if (scrollTo) {
+ var x = document.getElementById(from);
+ if (x) {
+ x.scrollIntoView();
+ }
+ }
+ onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
+ onEachLazy(e.getElementsByTagName("span"), function(i_e) {
+ removeClass(i_e, "line-highlighted");
+ });
+ });
+ for (var i = from; i <= to; ++i) {
+ elem = document.getElementById(i);
+ if (!elem) {
+ break;
+ }
+ addClass(elem, "line-highlighted");
+ }
+}
+
+var handleSourceHighlight = (function() {
+ var prev_line_id = 0;
+
+ var set_fragment = function(name) {
+ var x = window.scrollX,
+ y = window.scrollY;
+ if (searchState.browserSupportsHistoryApi()) {
+ history.replaceState(null, null, "#" + name);
+ highlightSourceLines(true);
+ } else {
+ location.replace("#" + name);
+ }
+ // Prevent jumps when selecting one or many lines
+ window.scrollTo(x, y);
+ };
+
+ return function(ev) {
+ var cur_line_id = parseInt(ev.target.id, 10);
+ ev.preventDefault();
+
+ if (ev.shiftKey && prev_line_id) {
+ // Swap selection if needed
+ if (prev_line_id > cur_line_id) {
+ var tmp = prev_line_id;
+ prev_line_id = cur_line_id;
+ cur_line_id = tmp;
+ }
+
+ set_fragment(prev_line_id + "-" + cur_line_id);
+ } else {
+ prev_line_id = cur_line_id;
+
+ set_fragment(cur_line_id);
+ }
+ };
+}());
+
+window.addEventListener("hashchange", function() {
+ var match = window.location.hash.match(lineNumbersRegex);
+ if (match) {
+ return highlightSourceLines(false, match);
+ }
+});
+
+onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
+ el.addEventListener("click", handleSourceHighlight);
+});
+
+highlightSourceLines(true);
+
+window.createSourceSidebar = createSourceSidebar;
+})();
--- /dev/null
+// From rust:
+/* global resourcesSuffix */
+var darkThemes = ["dark", "ayu"];
+window.currentTheme = document.getElementById("themeStyle");
+window.mainTheme = document.getElementById("mainThemeStyle");
+
+var settingsDataset = (function () {
+ var settingsElement = document.getElementById("default-settings");
+ if (settingsElement === null) {
+ return null;
+ }
+ var dataset = settingsElement.dataset;
+ if (dataset === undefined) {
+ return null;
+ }
+ return dataset;
+})();
+
+function getSettingValue(settingName) {
+ var current = getCurrentValue('rustdoc-' + settingName);
+ if (current !== null) {
+ return current;
+ }
+ if (settingsDataset !== null) {
+ var def = settingsDataset[settingName.replace(/-/g,'_')];
+ if (def !== undefined) {
+ return def;
+ }
+ }
+ return null;
+}
+
+var localStoredTheme = getSettingValue("theme");
+
+var savedHref = [];
+
+// eslint-disable-next-line no-unused-vars
+function hasClass(elem, className) {
+ return elem && elem.classList && elem.classList.contains(className);
+}
+
+// eslint-disable-next-line no-unused-vars
+function addClass(elem, className) {
+ if (!elem || !elem.classList) {
+ return;
+ }
+ elem.classList.add(className);
+}
+
+// eslint-disable-next-line no-unused-vars
+function removeClass(elem, className) {
+ if (!elem || !elem.classList) {
+ return;
+ }
+ elem.classList.remove(className);
+}
+
+function onEach(arr, func, reversed) {
+ if (arr && arr.length > 0 && func) {
+ var length = arr.length;
+ var i;
+ if (reversed) {
+ for (i = length - 1; i >= 0; --i) {
+ if (func(arr[i])) {
+ return true;
+ }
+ }
+ } else {
+ for (i = 0; i < length; ++i) {
+ if (func(arr[i])) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+function onEachLazy(lazyArray, func, reversed) {
+ return onEach(
+ Array.prototype.slice.call(lazyArray),
+ func,
+ reversed);
+}
+
+// eslint-disable-next-line no-unused-vars
+function hasOwnPropertyRustdoc(obj, property) {
+ return Object.prototype.hasOwnProperty.call(obj, property);
+}
+
+function updateLocalStorage(name, value) {
+ try {
+ window.localStorage.setItem(name, value);
+ } catch(e) {
+ // localStorage is not accessible, do nothing
+ }
+}
+
+function getCurrentValue(name) {
+ try {
+ return window.localStorage.getItem(name);
+ } catch(e) {
+ return null;
+ }
+}
+
+function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
+ var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
+ var fullNewTheme = newTheme + resourcesSuffix + ".css";
+ var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
+
+ // If this new value comes from a system setting or from the previously
+ // saved theme, no need to save it.
+ if (saveTheme) {
+ updateLocalStorage("rustdoc-theme", newTheme);
+ }
+
+ if (styleElem.href === newHref) {
+ return;
+ }
+
+ var found = false;
+ if (savedHref.length === 0) {
+ onEachLazy(document.getElementsByTagName("link"), function(el) {
+ savedHref.push(el.href);
+ });
+ }
+ onEach(savedHref, function(el) {
+ if (el === newHref) {
+ found = true;
+ return true;
+ }
+ });
+ if (found) {
+ styleElem.href = newHref;
+ }
+}
+
+// This function is called from "main.js".
+// eslint-disable-next-line no-unused-vars
+function useSystemTheme(value) {
+ if (value === undefined) {
+ value = true;
+ }
+
+ updateLocalStorage("rustdoc-use-system-theme", value);
+
+ // update the toggle if we're on the settings page
+ var toggle = document.getElementById("use-system-theme");
+ if (toggle && toggle instanceof HTMLInputElement) {
+ toggle.checked = value;
+ }
+}
+
+var updateSystemTheme = (function() {
+ if (!window.matchMedia) {
+ // fallback to the CSS computed value
+ return function() {
+ var cssTheme = getComputedStyle(document.documentElement)
+ .getPropertyValue('content');
+
+ switchTheme(
+ window.currentTheme,
+ window.mainTheme,
+ JSON.parse(cssTheme) || "light",
+ true
+ );
+ };
+ }
+
+ // only listen to (prefers-color-scheme: dark) because light is the default
+ var mql = window.matchMedia("(prefers-color-scheme: dark)");
+
+ function handlePreferenceChange(mql) {
+ // maybe the user has disabled the setting in the meantime!
+ if (getSettingValue("use-system-theme") !== "false") {
+ var lightTheme = getSettingValue("preferred-light-theme") || "light";
+ var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
+
+ if (mql.matches) {
+ // prefers a dark theme
+ switchTheme(window.currentTheme, window.mainTheme, darkTheme, true);
+ } else {
+ // prefers a light theme, or has no preference
+ switchTheme(window.currentTheme, window.mainTheme, lightTheme, true);
+ }
+
+ // note: we save the theme so that it doesn't suddenly change when
+ // the user disables "use-system-theme" and reloads the page or
+ // navigates to another page
+ }
+ }
+
+ mql.addListener(handlePreferenceChange);
+
+ return function() {
+ handlePreferenceChange(mql);
+ };
+})();
+
+if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
+ // update the preferred dark theme if the user is already using a dark theme
+ // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
+ if (getSettingValue("use-system-theme") === null
+ && getSettingValue("preferred-dark-theme") === null
+ && darkThemes.indexOf(localStoredTheme) >= 0) {
+ updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
+ }
+
+ // call the function to initialize the theme at least once!
+ updateSystemTheme();
+} else {
+ switchTheme(
+ window.currentTheme,
+ window.mainTheme,
+ getSettingValue("theme") || "light",
+ false
+ );
+}
+++ /dev/null
-// Local js definitions:
-/* global addClass, getSettingValue, hasClass, searchState */
-/* global onEach, onEachLazy, removeClass */
-/* global switchTheme, useSystemTheme */
-
-if (!String.prototype.startsWith) {
- String.prototype.startsWith = function(searchString, position) {
- position = position || 0;
- return this.indexOf(searchString, position) === position;
- };
-}
-if (!String.prototype.endsWith) {
- String.prototype.endsWith = function(suffix, length) {
- var l = length || this.length;
- return this.indexOf(suffix, l - suffix.length) !== -1;
- };
-}
-
-if (!DOMTokenList.prototype.add) {
- DOMTokenList.prototype.add = function(className) {
- if (className && !hasClass(this, className)) {
- if (this.className && this.className.length > 0) {
- this.className += " " + className;
- } else {
- this.className = className;
- }
- }
- };
-}
-
-if (!DOMTokenList.prototype.remove) {
- DOMTokenList.prototype.remove = function(className) {
- if (className && this.className) {
- this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
- .trim();
- }
- };
-}
-
-(function () {
- var rustdocVars = document.getElementById("rustdoc-vars");
- if (rustdocVars) {
- window.rootPath = rustdocVars.attributes["data-root-path"].value;
- window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
- window.searchJS = rustdocVars.attributes["data-search-js"].value;
- window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value;
- }
- var sidebarVars = document.getElementById("sidebar-vars");
- if (sidebarVars) {
- window.sidebarCurrent = {
- name: sidebarVars.attributes["data-name"].value,
- ty: sidebarVars.attributes["data-ty"].value,
- relpath: sidebarVars.attributes["data-relpath"].value,
- };
- }
-}());
-
-// Gets the human-readable string for the virtual-key code of the
-// given KeyboardEvent, ev.
-//
-// This function is meant as a polyfill for KeyboardEvent#key,
-// since it is not supported in IE 11 or Chrome for Android. We also test for
-// KeyboardEvent#keyCode because the handleShortcut handler is
-// also registered for the keydown event, because Blink doesn't fire
-// keypress on hitting the Escape key.
-//
-// So I guess you could say things are getting pretty interoperable.
-function getVirtualKey(ev) {
- if ("key" in ev && typeof ev.key != "undefined") {
- return ev.key;
- }
-
- var c = ev.charCode || ev.keyCode;
- if (c == 27) {
- return "Escape";
- }
- return String.fromCharCode(c);
-}
-
-var THEME_PICKER_ELEMENT_ID = "theme-picker";
-var THEMES_ELEMENT_ID = "theme-choices";
-
-function getThemesElement() {
- return document.getElementById(THEMES_ELEMENT_ID);
-}
-
-function getThemePickerElement() {
- return document.getElementById(THEME_PICKER_ELEMENT_ID);
-}
-
-// Returns the current URL without any query parameter or hash.
-function getNakedUrl() {
- return window.location.href.split("?")[0].split("#")[0];
-}
-
-function showThemeButtonState() {
- var themePicker = getThemePickerElement();
- var themeChoices = getThemesElement();
-
- themeChoices.style.display = "block";
- themePicker.style.borderBottomRightRadius = "0";
- themePicker.style.borderBottomLeftRadius = "0";
-}
-
-function hideThemeButtonState() {
- var themePicker = getThemePickerElement();
- var themeChoices = getThemesElement();
-
- themeChoices.style.display = "none";
- themePicker.style.borderBottomRightRadius = "3px";
- themePicker.style.borderBottomLeftRadius = "3px";
-}
-
-// Set up the theme picker list.
-(function () {
- var themeChoices = getThemesElement();
- var themePicker = getThemePickerElement();
- var availableThemes/* INSERT THEMES HERE */;
-
- function switchThemeButtonState() {
- if (themeChoices.style.display === "block") {
- hideThemeButtonState();
- } else {
- showThemeButtonState();
- }
- }
-
- function handleThemeButtonsBlur(e) {
- var active = document.activeElement;
- var related = e.relatedTarget;
-
- if (active.id !== THEME_PICKER_ELEMENT_ID &&
- (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
- (!related ||
- (related.id !== THEME_PICKER_ELEMENT_ID &&
- (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
- hideThemeButtonState();
- }
- }
-
- themePicker.onclick = switchThemeButtonState;
- themePicker.onblur = handleThemeButtonsBlur;
- availableThemes.forEach(function(item) {
- var but = document.createElement("button");
- but.textContent = item;
- but.onclick = function() {
- switchTheme(window.currentTheme, window.mainTheme, item, true);
- useSystemTheme(false);
- };
- but.onblur = handleThemeButtonsBlur;
- themeChoices.appendChild(but);
- });
-}());
-
-(function() {
- "use strict";
-
- window.searchState = {
- loadingText: "Loading search results...",
- input: document.getElementsByClassName("search-input")[0],
- outputElement: function() {
- return document.getElementById("search");
- },
- title: document.title,
- titleBeforeSearch: document.title,
- timeout: null,
- // On the search screen, so you remain on the last tab you opened.
- //
- // 0 for "In Names"
- // 1 for "In Parameters"
- // 2 for "In Return Types"
- currentTab: 0,
- // tab and back preserves the element that was focused.
- focusedByTab: [null, null, null],
- clearInputTimeout: function() {
- if (searchState.timeout !== null) {
- clearTimeout(searchState.timeout);
- searchState.timeout = null;
- }
- },
- // Sets the focus on the search bar at the top of the page
- focus: function() {
- searchState.input.focus();
- },
- // Removes the focus from the search bar.
- defocus: function() {
- searchState.input.blur();
- },
- showResults: function(search) {
- if (search === null || typeof search === 'undefined') {
- search = searchState.outputElement();
- }
- addClass(main, "hidden");
- removeClass(search, "hidden");
- searchState.mouseMovedAfterSearch = false;
- document.title = searchState.title;
- },
- hideResults: function(search) {
- if (search === null || typeof search === 'undefined') {
- search = searchState.outputElement();
- }
- addClass(search, "hidden");
- removeClass(main, "hidden");
- document.title = searchState.titleBeforeSearch;
- // We also remove the query parameter from the URL.
- if (searchState.browserSupportsHistoryApi()) {
- history.replaceState("", window.currentCrate + " - Rust",
- getNakedUrl() + window.location.hash);
- }
- },
- getQueryStringParams: function() {
- var params = {};
- window.location.search.substring(1).split("&").
- map(function(s) {
- var pair = s.split("=");
- params[decodeURIComponent(pair[0])] =
- typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
- });
- return params;
- },
- putBackSearch: function(search_input) {
- var search = searchState.outputElement();
- if (search_input.value !== "" && hasClass(search, "hidden")) {
- searchState.showResults(search);
- if (searchState.browserSupportsHistoryApi()) {
- var extra = "?search=" + encodeURIComponent(search_input.value);
- history.replaceState(search_input.value, "",
- getNakedUrl() + extra + window.location.hash);
- }
- document.title = searchState.title;
- }
- },
- browserSupportsHistoryApi: function() {
- return window.history && typeof window.history.pushState === "function";
- },
- setup: function() {
- var search_input = searchState.input;
- if (!searchState.input) {
- return;
- }
- function loadScript(url) {
- var script = document.createElement('script');
- script.src = url;
- document.head.append(script);
- }
-
- var searchLoaded = false;
- function loadSearch() {
- if (!searchLoaded) {
- searchLoaded = true;
- loadScript(window.searchJS);
- loadScript(window.searchIndexJS);
- }
- }
-
- search_input.addEventListener("focus", function() {
- searchState.putBackSearch(this);
- search_input.origPlaceholder = searchState.input.placeholder;
- search_input.placeholder = "Type your search here.";
- loadSearch();
- });
- search_input.addEventListener("blur", function() {
- search_input.placeholder = searchState.input.origPlaceholder;
- });
-
- search_input.removeAttribute('disabled');
-
- // `crates{version}.js` should always be loaded before this script, so we can use it
- // safely.
- searchState.addCrateDropdown(window.ALL_CRATES);
- var params = searchState.getQueryStringParams();
- if (params.search !== undefined) {
- var search = searchState.outputElement();
- search.innerHTML = "<h3 style=\"text-align: center;\">" +
- searchState.loadingText + "</h3>";
- searchState.showResults(search);
- loadSearch();
- }
- },
- addCrateDropdown: function(crates) {
- var elem = document.getElementById("crate-search");
-
- if (!elem) {
- return;
- }
- var savedCrate = getSettingValue("saved-filter-crate");
- for (var i = 0, len = crates.length; i < len; ++i) {
- var option = document.createElement("option");
- option.value = crates[i];
- option.innerText = crates[i];
- elem.appendChild(option);
- // Set the crate filter from saved storage, if the current page has the saved crate
- // filter.
- //
- // If not, ignore the crate filter -- we want to support filtering for crates on
- // sites like doc.rust-lang.org where the crates may differ from page to page while
- // on the
- // same domain.
- if (crates[i] === savedCrate) {
- elem.value = savedCrate;
- }
- }
- },
- };
-
- function getPageId() {
- if (window.location.hash) {
- var tmp = window.location.hash.replace(/^#/, "");
- if (tmp.length > 0) {
- return tmp;
- }
- }
- return null;
- }
-
- function showSidebar() {
- var elems = document.getElementsByClassName("sidebar-elems")[0];
- if (elems) {
- addClass(elems, "show-it");
- }
- var sidebar = document.getElementsByClassName("sidebar")[0];
- if (sidebar) {
- addClass(sidebar, "mobile");
- var filler = document.getElementById("sidebar-filler");
- if (!filler) {
- var div = document.createElement("div");
- div.id = "sidebar-filler";
- sidebar.appendChild(div);
- }
- }
- }
-
- function hideSidebar() {
- var elems = document.getElementsByClassName("sidebar-elems")[0];
- if (elems) {
- removeClass(elems, "show-it");
- }
- var sidebar = document.getElementsByClassName("sidebar")[0];
- removeClass(sidebar, "mobile");
- var filler = document.getElementById("sidebar-filler");
- if (filler) {
- filler.remove();
- }
- document.getElementsByTagName("body")[0].style.marginTop = "";
- }
-
- var toggleAllDocsId = "toggle-all-docs";
- var main = document.getElementById("main");
- var savedHash = "";
-
- function handleHashes(ev) {
- var elem;
- var search = searchState.outputElement();
- if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
- // This block occurs when clicking on an element in the navbar while
- // in a search.
- searchState.hideResults(search);
- var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
- if (searchState.browserSupportsHistoryApi()) {
- // `window.location.search`` contains all the query parameters, not just `search`.
- history.replaceState(hash, "",
- getNakedUrl() + window.location.search + "#" + hash);
- }
- elem = document.getElementById(hash);
- if (elem) {
- elem.scrollIntoView();
- }
- }
- // This part is used in case an element is not visible.
- if (savedHash !== window.location.hash) {
- savedHash = window.location.hash;
- if (savedHash.length === 0) {
- return;
- }
- expandSection(savedHash.slice(1)); // we remove the '#'
- }
- }
-
- function onHashChange(ev) {
- // If we're in mobile mode, we should hide the sidebar in any case.
- hideSidebar();
- handleHashes(ev);
- }
-
- function openParentDetails(elem) {
- while (elem) {
- if (elem.tagName === "DETAILS") {
- elem.open = true;
- }
- elem = elem.parentNode;
- }
- }
-
- function expandSection(id) {
- openParentDetails(document.getElementById(id));
- }
-
- function getHelpElement(build) {
- if (build) {
- buildHelperPopup();
- }
- return document.getElementById("help");
- }
-
- function displayHelp(display, ev, help) {
- if (display) {
- help = help ? help : getHelpElement(true);
- if (hasClass(help, "hidden")) {
- ev.preventDefault();
- removeClass(help, "hidden");
- addClass(document.body, "blur");
- }
- } else {
- // No need to build the help popup if we want to hide it in case it hasn't been
- // built yet...
- help = help ? help : getHelpElement(false);
- if (help && !hasClass(help, "hidden")) {
- ev.preventDefault();
- addClass(help, "hidden");
- removeClass(document.body, "blur");
- }
- }
- }
-
- function handleEscape(ev) {
- var help = getHelpElement(false);
- var search = searchState.outputElement();
- if (help && !hasClass(help, "hidden")) {
- displayHelp(false, ev, help);
- } else if (search && !hasClass(search, "hidden")) {
- searchState.clearInputTimeout();
- ev.preventDefault();
- searchState.hideResults(search);
- }
- searchState.defocus();
- hideThemeButtonState();
- }
-
- var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
- function handleShortcut(ev) {
- // Don't interfere with browser shortcuts
- if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) {
- return;
- }
-
- if (document.activeElement.tagName === "INPUT") {
- switch (getVirtualKey(ev)) {
- case "Escape":
- handleEscape(ev);
- break;
- }
- } else {
- switch (getVirtualKey(ev)) {
- case "Escape":
- handleEscape(ev);
- break;
-
- case "s":
- case "S":
- displayHelp(false, ev);
- ev.preventDefault();
- searchState.focus();
- break;
-
- case "+":
- case "-":
- ev.preventDefault();
- toggleAllDocs();
- break;
-
- case "?":
- displayHelp(true, ev);
- break;
-
- case "t":
- case "T":
- displayHelp(false, ev);
- ev.preventDefault();
- var themePicker = getThemePickerElement();
- themePicker.click();
- themePicker.focus();
- break;
-
- default:
- if (getThemePickerElement().parentNode.contains(ev.target)) {
- handleThemeKeyDown(ev);
- }
- }
- }
- }
-
- function handleThemeKeyDown(ev) {
- var active = document.activeElement;
- var themes = getThemesElement();
- switch (getVirtualKey(ev)) {
- case "ArrowUp":
- ev.preventDefault();
- if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
- active.previousElementSibling.focus();
- } else {
- showThemeButtonState();
- themes.lastElementChild.focus();
- }
- break;
- case "ArrowDown":
- ev.preventDefault();
- if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
- active.nextElementSibling.focus();
- } else {
- showThemeButtonState();
- themes.firstElementChild.focus();
- }
- break;
- case "Enter":
- case "Return":
- case "Space":
- if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
- ev.preventDefault();
- showThemeButtonState();
- themes.firstElementChild.focus();
- }
- break;
- case "Home":
- ev.preventDefault();
- themes.firstElementChild.focus();
- break;
- case "End":
- ev.preventDefault();
- themes.lastElementChild.focus();
- break;
- // The escape key is handled in handleEscape, not here,
- // so that pressing escape will close the menu even if it isn't focused
- }
- }
-
- document.addEventListener("keypress", handleShortcut);
- document.addEventListener("keydown", handleShortcut);
-
- (function() {
- var x = document.getElementsByClassName("version-selector");
- if (x.length > 0) {
- x[0].onchange = function() {
- var i, match,
- url = document.location.href,
- stripped = "",
- len = window.rootPath.match(/\.\.\//g).length + 1;
-
- for (i = 0; i < len; ++i) {
- match = url.match(/\/[^/]*$/);
- if (i < len - 1) {
- stripped = match[0] + stripped;
- }
- url = url.substring(0, url.length - match[0].length);
- }
-
- var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
- url += "/" + selectedVersion + stripped;
-
- document.location.href = url;
- };
- }
- }());
-
- // delayed sidebar rendering.
- window.initSidebarItems = function(items) {
- var sidebar = document.getElementsByClassName("sidebar-elems")[0];
- var current = window.sidebarCurrent;
-
- function addSidebarCrates(crates) {
- if (!hasClass(document.body, "crate")) {
- // We only want to list crates on the crate page.
- return;
- }
- // Draw a convenient sidebar of known crates if we have a listing
- var div = document.createElement("div");
- div.className = "block crate";
- div.innerHTML = "<h3>Crates</h3>";
- var ul = document.createElement("ul");
- div.appendChild(ul);
-
- for (var i = 0; i < crates.length; ++i) {
- var klass = "crate";
- if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
- klass += " current";
- }
- var link = document.createElement("a");
- link.href = window.rootPath + crates[i] + "/index.html";
- link.className = klass;
- link.textContent = crates[i];
-
- var li = document.createElement("li");
- li.appendChild(link);
- ul.appendChild(li);
- }
- sidebar.appendChild(div);
- }
-
- function block(shortty, longty) {
- var filtered = items[shortty];
- if (!filtered) {
- return;
- }
-
- var div = document.createElement("div");
- div.className = "block " + shortty;
- var h3 = document.createElement("h3");
- h3.textContent = longty;
- div.appendChild(h3);
- var ul = document.createElement("ul");
-
- for (var i = 0, len = filtered.length; i < len; ++i) {
- var item = filtered[i];
- var name = item[0];
- var desc = item[1]; // can be null
-
- var klass = shortty;
- if (name === current.name && shortty === current.ty) {
- klass += " current";
- }
- var path;
- if (shortty === "mod") {
- path = name + "/index.html";
- } else {
- path = shortty + "." + name + ".html";
- }
- var link = document.createElement("a");
- link.href = current.relpath + path;
- link.title = desc;
- link.className = klass;
- link.textContent = name;
- var li = document.createElement("li");
- li.appendChild(link);
- ul.appendChild(li);
- }
- div.appendChild(ul);
- sidebar.appendChild(div);
- }
-
- if (sidebar) {
- var isModule = hasClass(document.body, "mod");
- if (!isModule) {
- block("primitive", "Primitive Types");
- block("mod", "Modules");
- block("macro", "Macros");
- block("struct", "Structs");
- block("enum", "Enums");
- block("union", "Unions");
- block("constant", "Constants");
- block("static", "Statics");
- block("trait", "Traits");
- block("fn", "Functions");
- block("type", "Type Definitions");
- block("foreigntype", "Foreign Types");
- block("keyword", "Keywords");
- block("traitalias", "Trait Aliases");
- }
-
- // `crates{version}.js` should always be loaded before this script, so we can use
- // it safely.
- addSidebarCrates(window.ALL_CRATES);
- }
- };
-
- window.register_implementors = function(imp) {
- var implementors = document.getElementById("implementors-list");
- var synthetic_implementors = document.getElementById("synthetic-implementors-list");
-
- if (synthetic_implementors) {
- // This `inlined_types` variable is used to avoid having the same implementation
- // showing up twice. For example "String" in the "Sync" doc page.
- //
- // By the way, this is only used by and useful for traits implemented automatically
- // (like "Send" and "Sync").
- var inlined_types = new Set();
- onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
- var aliases = el.getAttribute("data-aliases");
- if (!aliases) {
- return;
- }
- aliases.split(",").forEach(function(alias) {
- inlined_types.add(alias);
- });
- });
- }
-
- var libs = Object.getOwnPropertyNames(imp);
- for (var i = 0, llength = libs.length; i < llength; ++i) {
- if (libs[i] === window.currentCrate) { continue; }
- var structs = imp[libs[i]];
-
- struct_loop:
- for (var j = 0, slength = structs.length; j < slength; ++j) {
- var struct = structs[j];
-
- var list = struct.synthetic ? synthetic_implementors : implementors;
-
- if (struct.synthetic) {
- for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
- if (inlined_types.has(struct.types[k])) {
- continue struct_loop;
- }
- inlined_types.add(struct.types[k]);
- }
- }
-
- var code = document.createElement("code");
- code.innerHTML = struct.text;
-
- onEachLazy(code.getElementsByTagName("a"), function(elem) {
- var href = elem.getAttribute("href");
-
- if (href && href.indexOf("http") !== 0) {
- elem.setAttribute("href", window.rootPath + href);
- }
- });
-
- var display = document.createElement("h3");
- addClass(display, "impl");
- display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
- "<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
- "</tbody></table></span>";
- list.appendChild(display);
- }
- }
- };
- if (window.pending_implementors) {
- window.register_implementors(window.pending_implementors);
- }
-
- function labelForToggleButton(sectionIsCollapsed) {
- if (sectionIsCollapsed) {
- // button will expand the section
- return "+";
- }
- // button will collapse the section
- // note that this text is also set in the HTML template in ../render/mod.rs
- return "\u2212"; // "\u2212" is "−" minus sign
- }
-
- function toggleAllDocs() {
- var innerToggle = document.getElementById(toggleAllDocsId);
- if (!innerToggle) {
- return;
- }
- var sectionIsCollapsed = false;
- if (hasClass(innerToggle, "will-expand")) {
- removeClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
- if (!hasClass(e, "type-contents-toggle")) {
- e.open = true;
- }
- });
- innerToggle.title = "collapse all docs";
- } else {
- addClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function(e) {
- if (e.parentNode.id !== "main" ||
- (!hasClass(e, "implementors-toggle") &&
- !hasClass(e, "type-contents-toggle")))
- {
- e.open = false;
- }
- });
- sectionIsCollapsed = true;
- innerToggle.title = "expand all docs";
- }
- innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
- }
-
- function insertAfter(newNode, referenceNode) {
- referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
- }
-
- (function() {
- var toggles = document.getElementById(toggleAllDocsId);
- if (toggles) {
- toggles.onclick = toggleAllDocs;
- }
-
- var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
- var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
- var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
-
- function setImplementorsTogglesOpen(id, open) {
- var list = document.getElementById(id);
- if (list !== null) {
- onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
- e.open = open;
- });
- }
- }
-
- if (hideImplementations) {
- setImplementorsTogglesOpen("trait-implementations-list", false);
- setImplementorsTogglesOpen("blanket-implementations-list", false);
- }
-
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
- if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
- e.open = true;
- }
- if (hideMethodDocs && hasClass(e, "method-toggle")) {
- e.open = false;
- }
-
- });
-
- var pageId = getPageId();
- if (pageId !== null) {
- expandSection(pageId);
- }
- }());
-
- (function() {
- // To avoid checking on "rustdoc-line-numbers" value on every loop...
- var lineNumbersFunc = function() {};
- if (getSettingValue("line-numbers") === "true") {
- lineNumbersFunc = function(x) {
- var count = x.textContent.split("\n").length;
- var elems = [];
- for (var i = 0; i < count; ++i) {
- elems.push(i + 1);
- }
- var node = document.createElement("pre");
- addClass(node, "line-number");
- node.innerHTML = elems.join("\n");
- x.parentNode.insertBefore(node, x);
- };
- }
- onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
- if (hasClass(e, "compile_fail")) {
- e.addEventListener("mouseover", function() {
- this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
- });
- e.addEventListener("mouseout", function() {
- this.parentElement.previousElementSibling.childNodes[0].style.color = "";
- });
- } else if (hasClass(e, "ignore")) {
- e.addEventListener("mouseover", function() {
- this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
- });
- e.addEventListener("mouseout", function() {
- this.parentElement.previousElementSibling.childNodes[0].style.color = "";
- });
- }
- lineNumbersFunc(e);
- });
- }());
-
- function handleClick(id, f) {
- var elem = document.getElementById(id);
- if (elem) {
- elem.addEventListener("click", f);
- }
- }
- handleClick("help-button", function(ev) {
- displayHelp(true, ev);
- });
-
- onEachLazy(document.getElementsByTagName("a"), function(el) {
- // For clicks on internal links (<A> tags with a hash property), we expand the section we're
- // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
- // the height of the document so we wind up scrolled to the wrong place.
- if (el.hash) {
- el.addEventListener("click", function() {
- expandSection(el.hash.slice(1));
- });
- }
- });
-
- onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
- e.onclick = function() {
- this.getElementsByClassName('notable-traits-tooltiptext')[0]
- .classList.toggle("force-tooltip");
- };
- });
-
- var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
- if (sidebar_menu) {
- sidebar_menu.onclick = function() {
- var sidebar = document.getElementsByClassName("sidebar")[0];
- if (hasClass(sidebar, "mobile")) {
- hideSidebar();
- } else {
- showSidebar();
- }
- };
- }
-
- var buildHelperPopup = function() {
- var popup = document.createElement("aside");
- addClass(popup, "hidden");
- popup.id = "help";
-
- popup.addEventListener("click", function(ev) {
- if (ev.target === popup) {
- // Clicked the blurred zone outside the help popup; dismiss help.
- displayHelp(false, ev);
- }
- });
-
- var book_info = document.createElement("span");
- book_info.innerHTML = "You can find more information in \
- <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
-
- var container = document.createElement("div");
- var shortcuts = [
- ["?", "Show this help dialog"],
- ["S", "Focus the search field"],
- ["T", "Focus the theme picker menu"],
- ["↑", "Move up in search results"],
- ["↓", "Move down in search results"],
- ["← / →", "Switch result tab (when results focused)"],
- ["⏎", "Go to active search result"],
- ["+", "Expand all sections"],
- ["-", "Collapse all sections"],
- ].map(function(x) {
- return "<dt>" +
- x[0].split(" ")
- .map(function(y, index) {
- return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
- })
- .join("") + "</dt><dd>" + x[1] + "</dd>";
- }).join("");
- var div_shortcuts = document.createElement("div");
- addClass(div_shortcuts, "shortcuts");
- div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
-
- var infos = [
- "Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
- restrict the search to a given item kind.",
- "Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
- <code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
- and <code>const</code>.",
- "Search functions by type signature (e.g., <code>vec -> usize</code> or \
- <code>* -> vec</code>)",
- "Search multiple things at once by splitting your query with comma (e.g., \
- <code>str,u8</code> or <code>String,struct:Vec,test</code>)",
- "You can look for items with an exact name by putting double quotes around \
- your request: <code>\"string\"</code>",
- "Look for items inside another one by searching for a path: <code>vec::Vec</code>",
- ].map(function(x) {
- return "<p>" + x + "</p>";
- }).join("");
- var div_infos = document.createElement("div");
- addClass(div_infos, "infos");
- div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
-
- container.appendChild(book_info);
- container.appendChild(div_shortcuts);
- container.appendChild(div_infos);
-
- popup.appendChild(container);
- insertAfter(popup, searchState.outputElement());
- // So that it's only built once and then it'll do nothing when called!
- buildHelperPopup = function() {};
- };
-
- onHashChange(null);
- window.addEventListener("hashchange", onHashChange);
- searchState.setup();
-}());
-
-(function () {
- var reset_button_timeout = null;
-
- window.copy_path = function(but) {
- var parent = but.parentElement;
- var path = [];
-
- onEach(parent.childNodes, function(child) {
- if (child.tagName === 'A') {
- path.push(child.textContent);
- }
- });
-
- var el = document.createElement('textarea');
- el.value = 'use ' + path.join('::') + ';';
- el.setAttribute('readonly', '');
- // To not make it appear on the screen.
- el.style.position = 'absolute';
- el.style.left = '-9999px';
-
- document.body.appendChild(el);
- el.select();
- document.execCommand('copy');
- document.body.removeChild(el);
-
- // There is always one children, but multiple childNodes.
- but.children[0].style.display = 'none';
-
- var tmp;
- if (but.childNodes.length < 2) {
- tmp = document.createTextNode('✓');
- but.appendChild(tmp);
- } else {
- onEachLazy(but.childNodes, function(e) {
- if (e.nodeType === Node.TEXT_NODE) {
- tmp = e;
- return true;
- }
- });
- tmp.textContent = '✓';
- }
-
- if (reset_button_timeout !== null) {
- window.clearTimeout(reset_button_timeout);
- }
-
- function reset_button() {
- tmp.textContent = '';
- reset_button_timeout = null;
- but.children[0].style.display = "";
- }
-
- reset_button_timeout = window.setTimeout(reset_button, 1000);
- };
-}());
+++ /dev/null
-/* ignore-tidy-linelength */
-/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
+++ /dev/null
-/*
-This whole CSS file is used only in case rustdoc is rendered with javascript disabled. Since a lot
-of content is hidden by default (depending on the settings too), we have to overwrite some of the
-rules.
-*/
-
-#main .attributes {
- /* Since there is no toggle (the "[-]") when JS is disabled, no need for this margin either. */
- margin-left: 0 !important;
-}
-
-#copy-path {
- /* It requires JS to work so no need to display it in this case. */
- display: none;
-}
+++ /dev/null
-Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-
-This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
+++ /dev/null
-/* See FiraSans-LICENSE.txt for the Fira Sans license. */
-@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 400;
- src: local('Fira Sans'),
- url("FiraSans-Regular.woff2") format("woff2"),
- url("FiraSans-Regular.woff") format('woff');
- font-display: swap;
-}
-@font-face {
- font-family: 'Fira Sans';
- font-style: normal;
- font-weight: 500;
- src: local('Fira Sans Medium'),
- url("FiraSans-Medium.woff2") format("woff2"),
- url("FiraSans-Medium.woff") format('woff');
- font-display: swap;
-}
-
-/* See SourceSerif4-LICENSE.md for the Source Serif 4 license. */
-@font-face {
- font-family: 'Source Serif 4';
- font-style: normal;
- font-weight: 400;
- src: local('Source Serif 4'),
- url("SourceSerif4-Regular.ttf.woff2") format("woff2"),
- url("SourceSerif4-Regular.ttf.woff") format("woff");
- font-display: swap;
-}
-@font-face {
- font-family: 'Source Serif 4';
- font-style: italic;
- font-weight: 400;
- src: local('Source Serif 4 Italic'),
- url("SourceSerif4-It.ttf.woff2") format("woff2"),
- url("SourceSerif4-It.ttf.woff") format("woff");
- font-display: swap;
-}
-@font-face {
- font-family: 'Source Serif 4';
- font-style: normal;
- font-weight: 700;
- src: local('Source Serif 4 Bold'),
- url("SourceSerif4-Bold.ttf.woff2") format("woff2"),
- url("SourceSerif4-Bold.ttf.woff") format("woff");
- font-display: swap;
-}
-
-/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
-@font-face {
- font-family: 'Source Code Pro';
- font-style: normal;
- font-weight: 400;
- /* Avoid using locally installed font because bad versions are in circulation:
- * see https://github.com/rust-lang/rust/issues/24355 */
- src: url("SourceCodePro-Regular.ttf.woff2") format("woff2"),
- url("SourceCodePro-Regular.ttf.woff") format("woff");
- font-display: swap;
-}
-@font-face {
- font-family: 'Source Code Pro';
- font-style: italic;
- font-weight: 400;
- src: url("SourceCodePro-It.ttf.woff2") format("woff2"),
- url("SourceCodePro-It.ttf.woff") format("woff");
- font-display: swap;
-}
-@font-face {
- font-family: 'Source Code Pro';
- font-style: normal;
- font-weight: 600;
- src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),
- url("SourceCodePro-Semibold.ttf.woff") format("woff");
- font-display: swap;
-}
-
-/* Avoid using legacy CJK serif fonts in Windows like Batang */
-@font-face {
- font-family: 'Noto Sans KR';
- src: url("noto-sans-kr-v13-korean-regular.woff") format("woff");
- font-display: swap;
- unicode-range: U+A960-A97F, U+AC00-D7AF, U+D7B0-D7FF;
-}
-
-* {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-/* This part handles the "default" theme being used depending on the system one. */
-html {
- content: "";
-}
-@media (prefers-color-scheme: light) {
- html {
- content: "light";
- }
-}
-@media (prefers-color-scheme: dark) {
- html {
- content: "dark";
- }
-}
-
-/* General structure and fonts */
-
-body {
- font: 16px/1.4 "Source Serif 4", "Noto Sans KR", serif;
- margin: 0;
- position: relative;
- padding: 10px 15px 20px 15px;
-
- -webkit-font-feature-settings: "kern", "liga";
- -moz-font-feature-settings: "kern", "liga";
- font-feature-settings: "kern", "liga";
-}
-
-h1 {
- font-size: 1.5em;
-}
-h2 {
- font-size: 1.4em;
-}
-h3 {
- font-size: 1.3em;
-}
-h1, h2, h3, h4 {
- font-weight: 500;
- margin: 20px 0 15px 0;
- padding-bottom: 6px;
-}
-h1.fqn {
- display: flex;
- border-bottom: 1px dashed;
- margin-top: 0;
-
- /* workaround to keep flex from breaking below 700 px width due to the float: right on the nav
- above the h1 */
- padding-left: 1px;
-}
-h1.fqn > .in-band > a:hover {
- text-decoration: underline;
-}
-h2, h3, h4 {
- border-bottom: 1px solid;
-}
-.impl,
-.impl-items .method,
-.methods .method,
-.impl-items .type,
-.methods .type,
-.impl-items .associatedconstant,
-.methods .associatedconstant,
-.impl-items .associatedtype,
-.methods .associatedtype {
- flex-basis: 100%;
- font-weight: 600;
- margin-top: 16px;
- margin-bottom: 10px;
- position: relative;
-}
-.impl, .method.trait-impl,
-.type.trait-impl,
-.associatedconstant.trait-impl,
-.associatedtype.trait-impl {
- padding-left: 15px;
-}
-
-div.impl-items > div {
- padding-left: 0;
-}
-
-h1, h2, h3, h4,
-.sidebar, a.source, .search-input, .search-results .result-name,
-.content table td:first-child > a,
-.item-left > a,
-div.item-list .out-of-band, span.since,
-#source-sidebar, #sidebar-toggle,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before,
-div.impl-items > div:not(.docblock):not(.item-info),
-.content ul.crate a.crate, a.srclink,
-/* This selector is for the items listed in the "all items" page. */
-#main > ul.docblock > li > a {
- font-family: "Fira Sans", Arial, sans-serif;
-}
-
-.content ul.crate a.crate {
- font-size: 16px/1.6;
-}
-
-ol, ul {
- padding-left: 25px;
-}
-ul ul, ol ul, ul ol, ol ol {
- margin-bottom: .6em;
-}
-
-p {
- margin: 0 0 .6em 0;
-}
-
-summary {
- outline: none;
-}
-
-/* Fix some style changes due to normalize.css 8 */
-
-td,
-th {
- padding: 0;
-}
-
-table {
- border-collapse: collapse;
-}
-
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit;
- font: inherit;
- margin: 0;
-}
-
-/* end tweaks for normalize.css 8 */
-
-details:not(.rustdoc-toggle) summary {
- margin-bottom: .6em;
-}
-
-code, pre, a.test-arrow {
- font-family: "Source Code Pro", monospace;
-}
-.docblock code, .docblock-short code {
- border-radius: 3px;
- padding: 0 0.1em;
-}
-.docblock pre code, .docblock-short pre code {
- padding: 0;
- padding-right: 1ex;
-}
-pre {
- padding: 14px;
-}
-
-.source .content pre {
- padding: 20px;
-}
-
-img {
- max-width: 100%;
-}
-
-li {
- position: relative;
-}
-
-.source .content {
- margin-top: 50px;
- max-width: none;
- overflow: visible;
- margin-left: 0px;
-}
-
-nav.sub {
- font-size: 16px;
- text-transform: uppercase;
-}
-
-.sidebar {
- width: 200px;
- position: fixed;
- left: 0;
- top: 0;
- bottom: 0;
- overflow: auto;
-}
-
-/* Improve the scrollbar display on firefox */
-* {
- scrollbar-width: initial;
-}
-.sidebar {
- scrollbar-width: thin;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar {
- width: 12px;
-}
-.sidebar::-webkit-scrollbar {
- width: 8px;
-}
-::-webkit-scrollbar-track {
- -webkit-box-shadow: inset 0;
-}
-
-.sidebar .block > ul > li {
- margin-right: -10px;
-}
-
-.content, nav {
- max-width: 960px;
-}
-
-/* Everything else */
-
-.hidden {
- display: none !important;
-}
-
-.logo-container {
- height: 100px;
- width: 100px;
- position: relative;
- margin: 20px auto;
- display: block;
- margin-top: 10px;
-}
-
-.logo-container > img {
- max-width: 100px;
- max-height: 100px;
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- display: block;
-}
-
-.sidebar .location {
- border: 1px solid;
- font-size: 17px;
- margin: 30px 10px 20px 10px;
- text-align: center;
- word-wrap: break-word;
-}
-
-.sidebar .version {
- font-size: 15px;
- text-align: center;
- border-bottom: 1px solid;
- overflow-wrap: break-word;
- word-wrap: break-word; /* deprecated */
- word-break: break-word; /* Chrome, non-standard */
-}
-
-.location:empty {
- border: none;
-}
-
-.location a:first-of-type {
- font-weight: 500;
-}
-.location a:hover {
- text-decoration: underline;
-}
-
-.block {
- padding: 0;
- margin-bottom: 14px;
-}
-.block h2, .block h3 {
- text-align: center;
-}
-.block ul, .block li {
- margin: 0 10px;
- padding: 0;
- list-style: none;
-}
-
-.block a {
- display: block;
- text-overflow: ellipsis;
- overflow: hidden;
- line-height: 15px;
- padding: 7px 5px;
- font-size: 14px;
- font-weight: 300;
- transition: border 500ms ease-out;
-}
-
-.sidebar-title {
- border-top: 1px solid;
- border-bottom: 1px solid;
- text-align: center;
- font-size: 17px;
- margin-bottom: 5px;
-}
-
-.sidebar-links {
- margin-bottom: 15px;
-}
-
-.sidebar-links > a {
- padding-left: 10px;
- width: 100%;
-}
-
-.sidebar-menu {
- display: none;
-}
-
-.content {
- padding: 15px 0;
-}
-
-.source .content pre.rust {
- white-space: pre;
- overflow: auto;
- padding-left: 0;
-}
-
-.rustdoc .example-wrap {
- display: inline-flex;
- margin-bottom: 10px;
-}
-
-.example-wrap {
- position: relative;
- width: 100%;
-}
-
-.example-wrap > pre.line-number {
- overflow: initial;
- border: 1px solid;
- padding: 13px 8px;
- text-align: right;
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
-}
-
-.rustdoc:not(.source) .example-wrap > pre.rust {
- width: 100%;
- overflow-x: auto;
-}
-
-.rustdoc .example-wrap > pre {
- margin: 0;
-}
-
-#search {
- margin-left: 230px;
- position: relative;
-}
-
-#results > table {
- width: 100%;
- table-layout: fixed;
-}
-
-.content > .example-wrap pre.line-numbers {
- position: relative;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.line-numbers span {
- cursor: pointer;
-}
-
-.docblock-short {
- overflow-wrap: anywhere;
-}
-.docblock-short p {
- display: inline;
-}
-
-.docblock-short p {
- overflow: hidden;
- text-overflow: ellipsis;
- margin: 0;
-}
-/* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock > :not(pre) > code,
-.docblock-short > :not(pre) > code {
- white-space: pre-wrap;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
- border-bottom: 1px solid;
-}
-
-.top-doc .docblock h1 { font-size: 1.3em; }
-.top-doc .docblock h2 { font-size: 1.15em; }
-.top-doc .docblock h3,
-.top-doc .docblock h4,
-.top-doc .docblock h5 {
- font-size: 1em;
-}
-
-.docblock h1 { font-size: 1em; }
-.docblock h2 { font-size: 0.95em; }
-.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
-
-.docblock {
- margin-left: 24px;
- position: relative;
-}
-
-.content .out-of-band {
- flex-grow: 0;
- text-align: right;
- font-size: 23px;
- margin: 0px;
- padding: 0 0 0 12px;
- font-weight: normal;
-}
-
-.method > code, .trait-impl > code, .invisible > code {
- max-width: calc(100% - 41px);
- display: block;
-}
-
-.invisible {
- width: 100%;
- display: inline-block;
-}
-
-.content .in-band {
- flex-grow: 1;
- margin: 0px;
- padding: 0px;
-}
-
-.in-band > code {
- display: inline-block;
-}
-
-#main {
- position: relative;
-}
-#main > .since {
- top: inherit;
- font-family: "Fira Sans", Arial, sans-serif;
-}
-
-.content table:not(.table-display) {
- border-spacing: 0 5px;
-}
-.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 {
- margin: .5em 0;
- width: calc(100% - 2px);
- border: 1px dashed;
-}
-
-.docblock table td {
- padding: .5em;
- border: 1px dashed;
-}
-
-.docblock table th {
- padding: .5em;
- text-align: left;
- border: 1px solid;
-}
-
-.fields + table {
- margin-bottom: 1em;
-}
-
-.content .item-list {
- list-style-type: none;
- padding: 0;
-}
-
-.content .multi-column {
- -moz-column-count: 5;
- -moz-column-gap: 2.5em;
- -webkit-column-count: 5;
- -webkit-column-gap: 2.5em;
- column-count: 5;
- column-gap: 2.5em;
-}
-.content .multi-column li { width: 100%; display: inline-block; }
-
-.content > .methods > .method {
- font-size: 1em;
- position: relative;
-}
-/* Shift "where ..." part of method or fn definition down a line */
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
- display: block;
- font-size: 0.8em;
-}
-
-.content .methods > div:not(.notable-traits):not(.method) {
- margin-left: 40px;
- margin-bottom: 15px;
-}
-
-.content .docblock > .impl-items {
- margin-left: 20px;
- margin-top: -34px;
-}
-.content .docblock >.impl-items .table-display {
- margin: 0;
-}
-.content .docblock >.impl-items table td {
- padding: 0;
-}
-.content .docblock > .impl-items .table-display, .impl-items table td {
- border: none;
-}
-
-.content .item-info code {
- font-size: 90%;
-}
-
-.content .item-info {
- position: relative;
- margin-left: 33px;
-}
-
-.sub-variant > div > .item-info {
- margin-top: initial;
-}
-
-.content .item-info::before {
- content: '⬑';
- font-size: 25px;
- position: absolute;
- top: -6px;
- left: -19px;
-}
-
-.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant,
-.impl-items > .associatedtype, .content .impl-items details > summary > .type,
-.impl-items details > summary > .associatedconstant,
-.impl-items details > summary > .associatedtype {
- margin-left: 20px;
-}
-
-.content .impl-items .docblock, .content .impl-items .item-info {
- margin-bottom: .6em;
-}
-
-.content .impl-items > .item-info {
- margin-left: 40px;
-}
-
-.methods > .item-info, .content .impl-items > .item-info {
- margin-top: -8px;
-}
-
-.impl-items {
- flex-basis: 100%;
-}
-
-#main > .item-info {
- margin-top: 0;
-}
-
-nav:not(.sidebar) {
- border-bottom: 1px solid;
- padding-bottom: 10px;
- margin-bottom: 10px;
-}
-nav.main {
- padding: 20px 0;
- text-align: center;
-}
-nav.main .current {
- border-top: 1px solid;
- border-bottom: 1px solid;
-}
-nav.main .separator {
- border: 1px solid;
- display: inline-block;
- height: 23px;
- margin: 0 20px;
-}
-nav.sum { text-align: right; }
-nav.sub form { display: inline; }
-
-nav.sub, .content {
- margin-left: 230px;
-}
-
-a {
- text-decoration: none;
- background: transparent;
-}
-
-.small-section-header {
- display: flex;
- justify-content: space-between;
- position: relative;
-}
-
-.small-section-header:hover > .anchor {
- display: initial;
-}
-
-.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor,
-.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor,
-.associatedtype.trait-impl:hover > .anchor {
- display: inline-block;
- position: absolute;
-}
-.anchor {
- display: none;
- position: absolute;
- left: -7px;
-}
-.anchor.field {
- left: -5px;
-}
-.small-section-header > .anchor {
- left: -28px;
- padding-right: 10px; /* avoid gap that causes hover to disappear */
-}
-.anchor:before {
- content: '\2002\00a7\2002';
-}
-
-.docblock a:not(.srclink):not(.test-arrow):hover,
-.docblock-short a:not(.srclink):not(.test-arrow):hover, .item-info a {
- text-decoration: underline;
-}
-
-.invisible > .srclink,
-.method > code + .srclink {
- position: absolute;
- top: 0;
- right: 0;
- font-size: 17px;
- font-weight: normal;
-}
-
-.block a.current.crate { font-weight: 500; }
-
-.item-table {
- display: grid;
- column-gap: 1.2rem;
- row-gap: 0.0rem;
- grid-template-columns: auto 1fr;
- /* align content left */
- justify-items: start;
-}
-
-.item-left, .item-right {
- display: block;
-}
-.item-left {
- grid-column: 1;
-}
-.item-right {
- grid-column: 2;
-}
-
-.search-container {
- position: relative;
-}
-.search-container > div {
- display: inline-flex;
- width: calc(100% - 63px);
-}
-#crate-search {
- min-width: 115px;
- margin-top: 5px;
- padding: 6px;
- padding-right: 19px;
- flex: none;
- border: 0;
- border-right: 0;
- border-radius: 4px 0 0 4px;
- outline: none;
- cursor: pointer;
- border-right: 1px solid;
- -moz-appearance: none;
- -webkit-appearance: none;
- /* Removes default arrow from firefox */
- text-indent: 0.01px;
- text-overflow: "";
- background-repeat: no-repeat;
- background-color: transparent;
- background-size: 20px;
- background-position: calc(100% - 1px) 56%;
-}
-.search-container > .top-button {
- position: absolute;
- right: 0;
- top: 10px;
-}
-.search-input {
- /* Override Normalize.css: we have margins and do
- not want to overflow - the `moz` attribute is necessary
- until Firefox 29, too early to drop at this point */
- -moz-box-sizing: border-box !important;
- box-sizing: border-box !important;
- outline: none;
- border: none;
- border-radius: 1px;
- margin-top: 5px;
- padding: 10px 16px;
- font-size: 17px;
- transition: border-color 300ms ease;
- transition: border-radius 300ms ease-in-out;
- transition: box-shadow 300ms ease-in-out;
- width: 100%;
-}
-
-#crate-search + .search-input {
- border-radius: 0 1px 1px 0;
- width: calc(100% - 32px);
-}
-
-.search-input:focus {
- border-radius: 2px;
- border: 0;
- outline: 0;
-}
-
-.search-results {
- display: none;
- padding-bottom: 2em;
-}
-
-.search-results.active {
- display: block;
- /* prevent overhanging tabs from moving the first result */
- clear: both;
-}
-
-.search-results .desc > span {
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- display: block;
-}
-
-.search-results > a {
- display: block;
- width: 100%;
- /* A little margin ensures the browser's outlining of focused links has room to display. */
- margin-left: 2px;
- margin-right: 2px;
- border-bottom: 1px solid #aaa3;
-}
-
-.search-results > a > div {
- display: flex;
- flex-flow: row wrap;
-}
-
-.search-results .result-name, .search-results div.desc, .search-results .result-description {
- width: 50%;
-}
-.search-results .result-name {
- padding-right: 1em;
-}
-
-.search-results .result-name > span {
- display: inline-block;
- margin: 0;
- font-weight: normal;
-}
-
-body.blur > :not(#help) {
- filter: blur(8px);
- -webkit-filter: blur(8px);
- opacity: .7;
-}
-
-#help {
- width: 100%;
- height: 100vh;
- position: fixed;
- top: 0;
- left: 0;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-#help > div {
- flex: 0 0 auto;
- box-shadow: 0 0 6px rgba(0,0,0,.2);
- width: 550px;
- height: auto;
- border: 1px solid;
-}
-#help dt {
- float: left;
- clear: left;
- display: block;
- margin-right: 0.5rem;
-}
-#help > div > span {
- text-align: center;
- display: block;
- margin: 10px 0;
- font-size: 18px;
- border-bottom: 1px solid #ccc;
- padding-bottom: 4px;
- margin-bottom: 6px;
-}
-#help dd { margin: 5px 35px; }
-#help .infos { padding-left: 0; }
-#help h1, #help h2 { margin-top: 0; }
-#help > div div {
- width: 50%;
- float: left;
- padding: 0 20px 20px 17px;;
-}
-
-.stab {
- border-width: 1px;
- border-style: solid;
- padding: 3px;
- margin-bottom: 5px;
- font-size: 90%;
- font-weight: normal;
-}
-.stab p {
- display: inline;
-}
-
-.stab .emoji {
- font-size: 1.5em;
-}
-
-/* Black one-pixel outline around emoji shapes */
-.emoji {
- text-shadow:
- 1px 0 0 black,
- -1px 0 0 black,
- 0 1px 0 black,
- 0 -1px 0 black;
-}
-
-.module-item .stab,
-.import-item .stab {
- border-radius: 3px;
- display: inline-block;
- font-size: 80%;
- line-height: 1.2;
- margin-bottom: 0;
- margin-left: .3em;
- padding: 2px;
- vertical-align: text-bottom;
-}
-
-.module-item.unstable,
-.import-item.unstable {
- opacity: 0.65;
-}
-
-.since {
- font-weight: normal;
- font-size: initial;
-}
-
-.impl-items .since, .impl .since, .methods .since {
- padding-left: 12px;
- padding-right: 2px;
- position: initial;
-}
-
-.impl-items .srclink, .impl .srclink, .methods .srclink {
- /* Override header settings otherwise it's too bold */
- font-size: 17px;
- font-weight: normal;
-}
-
-.rightside {
- float: right;
-}
-
-.has-srclink {
- font-size: 16px;
- margin-bottom: 12px;
- /* Push the src link out to the right edge consistently */
- justify-content: space-between;
-}
-
-.variants_table {
- width: 100%;
-}
-
-.variants_table tbody tr td:first-child {
- width: 1%; /* make the variant name as small as possible */
-}
-
-td.summary-column {
- width: 100%;
-}
-
-.summary {
- padding-right: 0px;
-}
-
-pre.rust .question-mark {
- font-weight: bold;
-}
-
-a.test-arrow {
- display: inline-block;
- position: absolute;
- padding: 5px 10px 5px 10px;
- border-radius: 5px;
- font-size: 130%;
- top: 5px;
- right: 5px;
- z-index: 1;
-}
-a.test-arrow:hover{
- text-decoration: none;
-}
-
-.section-header:hover a:before {
- position: absolute;
- left: -25px;
- padding-right: 10px; /* avoid gap that causes hover to disappear */
- content: '\2002\00a7\2002';
-}
-
-.section-header:hover a {
- text-decoration: none;
-}
-
-.section-header a {
- color: inherit;
-}
-
-.code-attribute {
- font-weight: 300;
-}
-
-.since + .srclink {
- padding-left: 10px;
-}
-
-.item-spacer {
- width: 100%;
- height: 12px;
-}
-
-.out-of-band > span.since {
- position: initial;
- font-size: 20px;
- margin-right: 5px;
-}
-
-.sub-variant, .sub-variant > h3 {
- margin-top: 0px !important;
- padding-top: 1px;
-}
-
-#main > details > .sub-variant > h3 {
- font-size: 15px;
- margin-left: 25px;
- margin-bottom: 5px;
-}
-
-.sub-variant > div {
- margin-left: 20px;
- margin-bottom: 10px;
-}
-
-.sub-variant > div > span {
- display: block;
- position: relative;
-}
-
-.toggle-label {
- display: inline-block;
- margin-left: 4px;
- margin-top: 3px;
-}
-
-.docblock > .section-header:first-child {
- margin-left: 15px;
- margin-top: 0;
-}
-
-.docblock > .section-header:first-child:hover > a:before {
- left: -10px;
-}
-
-#main > .variant, #main > .structfield {
- display: block;
-}
-
-
-:target > code {
- opacity: 1;
-}
-
-:target {
- padding-right: 3px;
-}
-
-.information {
- position: absolute;
- left: -25px;
- margin-top: 7px;
- z-index: 1;
-}
-
-.tooltip {
- position: relative;
- display: inline-block;
- cursor: pointer;
-}
-
-.tooltip::after {
- display: none;
- text-align: center;
- padding: 5px 3px 3px 3px;
- border-radius: 6px;
- margin-left: 5px;
- font-size: 16px;
-}
-
-.tooltip.ignore::after {
- content: "This example is not tested";
-}
-.tooltip.compile_fail::after {
- content: "This example deliberately fails to compile";
-}
-.tooltip.should_panic::after {
- content: "This example panics";
-}
-.tooltip.edition::after {
- content: "This code runs with edition " attr(data-edition);
-}
-
-.tooltip::before {
- content: " ";
- position: absolute;
- top: 50%;
- left: 16px;
- margin-top: -5px;
- border-width: 5px;
- border-style: solid;
- display: none;
-}
-
-.tooltip:hover::before, .tooltip:hover::after {
- display: inline;
-}
-
-.tooltip.compile_fail, .tooltip.should_panic, .tooltip.ignore {
- font-weight: bold;
- font-size: 20px;
-}
-
-.notable-traits-tooltip {
- display: inline-block;
- cursor: pointer;
-}
-
-.notable-traits:hover .notable-traits-tooltiptext,
-.notable-traits .notable-traits-tooltiptext.force-tooltip {
- display: inline-block;
-}
-
-.notable-traits .notable-traits-tooltiptext {
- display: none;
- padding: 5px 3px 3px 3px;
- border-radius: 6px;
- margin-left: 5px;
- z-index: 10;
- font-size: 16px;
- cursor: default;
- position: absolute;
- border: 1px solid;
-}
-
-.notable-traits-tooltip::after {
- /* The margin on the tooltip does not capture hover events,
- this extends the area of hover enough so that mouse hover is not
- lost when moving the mouse to the tooltip */
- content: "\00a0\00a0\00a0";
-}
-
-.notable-traits .notable, .notable-traits .docblock {
- margin: 0;
-}
-
-.notable-traits .notable {
- margin: 0;
- margin-bottom: 13px;
- font-size: 19px;
- font-weight: 600;
-}
-
-.notable-traits .docblock code.content{
- margin: 0;
- padding: 0;
- font-size: 20px;
-}
-
-/* Example code has the "Run" button that needs to be positioned relative to the pre */
-pre.rust.rust-example-rendered {
- position: relative;
-}
-
-pre.rust {
- tab-size: 4;
- -moz-tab-size: 4;
-}
-
-.search-failed {
- text-align: center;
- margin-top: 20px;
- display: none;
-}
-
-.search-failed.active {
- display: block;
-}
-
-.search-failed > ul {
- text-align: left;
- max-width: 570px;
- margin-left: auto;
- margin-right: auto;
-}
-
-#titles {
- height: 35px;
-}
-
-#titles > button {
- float: left;
- width: 33.3%;
- text-align: center;
- font-size: 18px;
- cursor: pointer;
- border: 0;
- border-top: 2px solid;
-}
-
-#titles > button:not(:last-child) {
- margin-right: 1px;
- width: calc(33.3% - 1px);
-}
-
-#titles > button > div.count {
- display: inline-block;
- font-size: 16px;
-}
-
-.notable-traits {
- cursor: pointer;
- z-index: 2;
- margin-left: 5px;
-}
-
-#all-types {
- text-align: center;
- border: 1px solid;
- margin: 0 10px;
- margin-bottom: 10px;
- display: block;
- border-radius: 7px;
-}
-#all-types > p {
- margin: 5px 0;
-}
-
-#sidebar-toggle {
- position: fixed;
- top: 30px;
- left: 300px;
- z-index: 10;
- padding: 3px;
- border-top-right-radius: 3px;
- border-bottom-right-radius: 3px;
- cursor: pointer;
- font-weight: bold;
- transition: left .5s;
- font-size: 1.2em;
- border: 1px solid;
- border-left: 0;
-}
-#source-sidebar {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- width: 300px;
- z-index: 1;
- overflow: auto;
- transition: left .5s;
- border-right: 1px solid;
-}
-#source-sidebar > .title {
- font-size: 1.5em;
- text-align: center;
- border-bottom: 1px solid;
- margin-bottom: 6px;
-}
-
-.theme-picker {
- position: absolute;
- left: 211px;
- top: 19px;
-}
-
-.theme-picker button {
- outline: none;
-}
-
-#settings-menu, #help-button {
- position: absolute;
- top: 10px;
-}
-
-#settings-menu {
- right: 0;
- outline: none;
-}
-
-#theme-picker, #settings-menu, #help-button, #copy-path {
- padding: 4px;
- width: 27px;
- height: 29px;
- border: 1px solid;
- border-radius: 3px;
- cursor: pointer;
-}
-
-#help-button {
- right: 30px;
- font-family: "Fira Sans", Arial, sans-serif;
- text-align: center;
- font-size: 17px;
- padding-top: 2px;
-}
-
-#copy-path {
- background: initial;
- margin-left: 10px;
- padding: 0;
- padding-left: 2px;
- border: 0;
-}
-
-#theme-choices {
- display: none;
- position: absolute;
- left: 0;
- top: 28px;
- border: 1px solid;
- border-radius: 3px;
- z-index: 1;
- cursor: pointer;
-}
-
-#theme-choices > button {
- border: none;
- width: 100%;
- padding: 4px 8px;
- text-align: center;
- background: rgba(0,0,0,0);
-}
-
-#theme-choices > button:not(:first-child) {
- border-top: 1px solid;
-}
-
-kbd {
- display: inline-block;
- padding: 3px 5px;
- font: 15px monospace;
- line-height: 10px;
- vertical-align: middle;
- border: solid 1px;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0;
- cursor: default;
-}
-
-.hidden-by-impl-hider,
-.hidden-by-usual-hider {
- /* important because of conflicting rule for small screens */
- display: none !important;
-}
-
-#implementations-list > h3 > span.in-band {
- width: 100%;
-}
-
-.table-display {
- width: 100%;
- border: 0;
- border-collapse: collapse;
- border-spacing: 0;
- font-size: 16px;
-}
-
-.table-display tr td:first-child {
- padding-right: 0;
-}
-
-.table-display tr td:last-child {
- float: right;
-}
-.table-display .out-of-band {
- position: relative;
- font-size: 19px;
- display: block;
-}
-#implementors-list > .impl-items .table-display .out-of-band {
- font-size: 17px;
-}
-
-.table-display td:hover .anchor {
- display: block;
- top: 2px;
- left: -5px;
-}
-
-#main > ul {
- padding-left: 10px;
-}
-#main > ul > li {
- list-style: none;
-}
-
-.non-exhaustive {
- margin-bottom: 1em;
-}
-
-div.children {
- padding-left: 27px;
- display: none;
-}
-div.name {
- cursor: pointer;
- position: relative;
- margin-left: 16px;
-}
-div.files > a {
- display: block;
- padding: 0 3px;
-}
-div.files > a:hover, div.name:hover {
- background-color: #a14b4b;
-}
-div.name.expand + .children {
- display: block;
-}
-div.name::before {
- content: "\25B6";
- padding-left: 4px;
- font-size: 0.7em;
- position: absolute;
- left: -16px;
- top: 4px;
-}
-div.name.expand::before {
- transform: rotate(90deg);
- left: -15px;
- top: 2px;
-}
-
-/* The hideme class is used on summary tags that contain a span with
- placeholder text shown only when the toggle is closed. For instance,
- "Expand description" or "Show methods". */
-details.rustdoc-toggle > summary.hideme {
- cursor: pointer;
-}
-
-details.rustdoc-toggle > summary, details.undocumented > summary {
- list-style: none;
-}
-details.rustdoc-toggle > summary::-webkit-details-marker,
-details.rustdoc-toggle > summary::marker,
-details.undocumented > summary::-webkit-details-marker,
-details.undocumented > summary::marker {
- display: none;
-}
-
-details.rustdoc-toggle > summary.hideme > span {
- margin-left: 9px;
-}
-
-details.rustdoc-toggle > summary::before {
- content: "[+]";
- font-weight: 300;
- font-size: 0.8em;
- letter-spacing: 1px;
- cursor: pointer;
-}
-
-details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.top-doc > summary::before,
-details.rustdoc-toggle.non-exhaustive > summary,
-details.rustdoc-toggle.non-exhaustive > summary::before {
- font-family: 'Fira Sans';
- font-size: 16px;
-}
-
-details.non-exhaustive {
- margin-bottom: 8px;
-}
-
-details.rustdoc-toggle > summary.hideme::before {
- position: relative;
-}
-
-details.rustdoc-toggle > summary:not(.hideme)::before {
- position: absolute;
- left: -23px;
- top: 3px;
-}
-
-.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
-.undocumented > details.rustdoc-toggle > summary:not(.hideme)::before {
- position: absolute;
- left: -2px;
-}
-
-/* When a "hideme" summary is open and the "Expand description" or "Show
- methods" text is hidden, we want the [-] toggle that remains to not
- affect the layout of the items to its right. To do that, we use
- absolute positioning. Note that we also set position: relative
- on the parent <details> to make this work properly. */
-details.rustdoc-toggle[open] > summary.hideme {
- position: absolute;
-}
-
-details.rustdoc-toggle, details.undocumented {
- position: relative;
-}
-
-details.rustdoc-toggle[open] > summary.hideme > span {
- display: none;
-}
-
-details.rustdoc-toggle[open] > summary::before {
- content: "[−]";
- display: inline;
-}
-
-details.undocumented > summary::before {
- content: "[+] Show hidden undocumented items";
- cursor: pointer;
- font-size: 16px;
- font-weight: 300;
-}
-
-details.undocumented[open] > summary::before {
- content: "[−] Hide undocumented items";
-}
-
-/* Media Queries */
-
-@media (min-width: 701px) {
- /* In case there is no documentation before a code block, we need to add some margin at the top
- to prevent an overlay between the "collapse toggle" and the information tooltip.
- However, it's not needed with smaller screen width because the doc/code block is always put
- "one line" below. */
- .docblock > .information:first-child > .tooltip {
- margin-top: 16px;
- }
-}
-
-@media (max-width: 700px) {
- body {
- padding-top: 0px;
- }
-
- .rustdoc > .sidebar {
- height: 45px;
- min-height: 40px;
- margin: 0;
- margin-left: -15px;
- padding: 0 15px;
- position: static;
- z-index: 11;
- }
-
- .sidebar > .location {
- float: right;
- margin: 0px;
- margin-top: 2px;
- padding: 3px 10px 1px 10px;
- min-height: 39px;
- background: inherit;
- text-align: left;
- font-size: 24px;
- }
-
- .sidebar .location:empty {
- padding: 0;
- }
-
- .sidebar .logo-container {
- width: 35px;
- height: 35px;
- margin-top: 5px;
- margin-bottom: 5px;
- float: left;
- margin-left: 50px;
- }
-
- .sidebar .logo-container > img {
- max-width: 35px;
- max-height: 35px;
- }
-
- .sidebar-menu {
- position: fixed;
- z-index: 10;
- font-size: 2rem;
- cursor: pointer;
- width: 45px;
- left: 0;
- text-align: center;
- display: block;
- border-bottom: 1px solid;
- border-right: 1px solid;
- height: 45px;
- }
-
- .rustdoc.source > .sidebar > .sidebar-menu {
- display: none;
- }
-
- .sidebar-elems {
- position: fixed;
- z-index: 1;
- left: 0;
- top: 45px;
- bottom: 0;
- overflow-y: auto;
- border-right: 1px solid;
- display: none;
- }
-
- .sidebar > .block.version {
- overflow: hidden;
- border-bottom: none;
- margin-bottom: 0;
- height: 100%;
- padding-left: 12px;
- }
- .sidebar > .block.version > div.narrow-helper {
- float: left;
- width: 1px;
- height: 100%;
- }
- .sidebar > .block.version > p {
- /* hide Version text if too narrow */
- margin: 0;
- min-width: 55px;
- /* vertically center */
- display: flex;
- align-items: center;
- height: 100%;
- }
-
- nav.sub {
- width: calc(100% - 32px);
- float: right;
- }
-
- .content {
- margin-left: 0px;
- }
-
- #main, #search {
- margin-top: 45px;
- padding: 0;
- }
-
- #search {
- margin-left: 0;
- }
-
- .anchor {
- display: none !important;
- }
-
- .theme-picker {
- left: 10px;
- top: 54px;
- z-index: 1;
- }
-
- .notable-traits {
- position: absolute;
- left: -22px;
- top: 24px;
- }
-
- #titles > button > div.count {
- float: left;
- width: 100%;
- }
-
- #titles {
- height: 50px;
- }
-
- .sidebar.mobile {
- position: fixed;
- width: 100%;
- margin-left: 0;
- background-color: rgba(0,0,0,0);
- height: 100%;
- }
- /*
- This allows to prevent the version text to overflow the sidebar title on mobile mode when the
- sidebar is displayed (after clicking on the "hamburger" button).
- */
- .sidebar.mobile > div.version {
- overflow: hidden;
- max-height: 33px;
- }
- .sidebar {
- width: calc(100% + 30px);
- }
-
- .show-it {
- display: block;
- width: 246px;
- }
-
- .show-it > .block.items {
- margin: 8px 0;
- }
-
- .show-it > .block.items > ul {
- margin: 0;
- }
-
- .show-it > .block.items > ul > li {
- text-align: center;
- margin: 2px 0;
- }
-
- .show-it > .block.items > ul > li > a {
- font-size: 21px;
- }
-
- /* Because of ios, we need to actually have a full height sidebar title so the
- * actual sidebar can show up. But then we need to make it transparent so we don't
- * hide content. The filler just allows to create the background for the sidebar
- * title. But because of the absolute position, I had to lower the z-index.
- */
- #sidebar-filler {
- position: fixed;
- left: 45px;
- width: calc(100% - 45px);
- top: 0;
- height: 45px;
- z-index: -1;
- border-bottom: 1px solid;
- }
-
- #main > details.rustdoc-toggle > summary::before,
- #main > div > details.rustdoc-toggle > summary::before {
- left: -11px;
- }
-
- #all-types {
- margin: 10px;
- }
-
- #sidebar-toggle {
- top: 100px;
- width: 30px;
- font-size: 1.5rem;
- text-align: center;
- padding: 0;
- }
-
- #source-sidebar {
- z-index: 11;
- }
-
- #main > .line-numbers {
- margin-top: 0;
- }
-
- .notable-traits .notable-traits-tooltiptext {
- left: 0;
- top: 100%;
- }
-
- /* We don't display the help button on mobile devices. */
- #help-button {
- display: none;
- }
-
- /* Display an alternating layout on tablets and phones */
- .item-table {
- display: flex;
- flex-flow: column wrap;
- }
- .item-left, .item-right {
- width: 100%;
- }
-
- .search-container > div {
- width: calc(100% - 32px);
- }
-
- /* Display an alternating layout on tablets and phones */
- .search-results > a {
- border-bottom: 1px solid #aaa9;
- padding: 5px 0px;
- }
- .search-results .result-name, .search-results div.desc, .search-results .result-description {
- width: 100%;
- }
- .search-results div.desc, .search-results .result-description, .item-right {
- padding-left: 2em;
- }
-}
-
-@media print {
- nav.sub, .content .out-of-band {
- display: none;
- }
-}
-
-@media (max-width: 464px) {
- #titles, #titles > button {
- height: 73px;
- }
-
- /* This is to prevent the search bar from being underneath the <section>
- * element following it.
- */
- #main, #search {
- margin-top: 100px;
- }
-
- #main > table:not(.table-display) td {
- word-break: break-word;
- width: 50%;
- }
-
- .search-container > div {
- display: block;
- width: calc(100% - 37px);
- }
-
- #crate-search {
- width: 100%;
- border-radius: 4px;
- border: 0;
- }
-
- #crate-search + .search-input {
- width: calc(100% + 71px);
- margin-left: -36px;
- }
-
- #theme-picker, #settings-menu {
- padding: 5px;
- width: 31px;
- height: 31px;
- }
-
- #theme-picker {
- margin-top: -2px;
- }
-
- #settings-menu {
- top: 7px;
- }
-
- .docblock {
- margin-left: 12px;
- }
-}
+++ /dev/null
-/* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
-/* global onEachLazy, removeClass, searchState, updateLocalStorage */
-
-(function() {
-// This mapping table should match the discriminants of
-// `rustdoc::html::item_type::ItemType` type in Rust.
-var itemTypes = ["mod",
- "externcrate",
- "import",
- "struct",
- "enum",
- "fn",
- "type",
- "static",
- "trait",
- "impl",
- "tymethod",
- "method",
- "structfield",
- "variant",
- "macro",
- "primitive",
- "associatedtype",
- "constant",
- "associatedconstant",
- "union",
- "foreigntype",
- "keyword",
- "existential",
- "attr",
- "derive",
- "traitalias"];
-
-// used for special search precedence
-var TY_PRIMITIVE = itemTypes.indexOf("primitive");
-var TY_KEYWORD = itemTypes.indexOf("keyword");
-
-// In the search display, allows to switch between tabs.
-function printTab(nb) {
- if (nb === 0 || nb === 1 || nb === 2) {
- searchState.currentTab = nb;
- }
- var nb_copy = nb;
- onEachLazy(document.getElementById("titles").childNodes, function(elem) {
- if (nb_copy === 0) {
- addClass(elem, "selected");
- } else {
- removeClass(elem, "selected");
- }
- nb_copy -= 1;
- });
- onEachLazy(document.getElementById("results").childNodes, function(elem) {
- if (nb === 0) {
- addClass(elem, "active");
- } else {
- removeClass(elem, "active");
- }
- nb -= 1;
- });
-}
-
-function removeEmptyStringsFromArray(x) {
- for (var i = 0, len = x.length; i < len; ++i) {
- if (x[i] === "") {
- x.splice(i, 1);
- i -= 1;
- }
- }
-}
-
-/**
- * A function to compute the Levenshtein distance between two strings
- * Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
- * Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
- * This code is an unmodified version of the code written by Marco de Wit
- * and was found at https://stackoverflow.com/a/18514751/745719
- */
-var levenshtein_row2 = [];
-function levenshtein(s1, s2) {
- if (s1 === s2) {
- return 0;
- }
- var s1_len = s1.length, s2_len = s2.length;
- if (s1_len && s2_len) {
- var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
- while (i1 < s1_len) {
- row[i1] = ++i1;
- }
- while (i2 < s2_len) {
- c2 = s2.charCodeAt(i2);
- a = i2;
- ++i2;
- b = i2;
- for (i1 = 0; i1 < s1_len; ++i1) {
- c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
- a = row[i1];
- b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
- row[i1] = b;
- }
- }
- return b;
- }
- return s1_len + s2_len;
-}
-
-window.initSearch = function(rawSearchIndex) {
- var MAX_LEV_DISTANCE = 3;
- var MAX_RESULTS = 200;
- var GENERICS_DATA = 2;
- var NAME = 0;
- var INPUTS_DATA = 0;
- var OUTPUT_DATA = 1;
- var NO_TYPE_FILTER = -1;
- var currentResults, index, searchIndex;
- var ALIASES = {};
- var params = searchState.getQueryStringParams();
-
- // Populate search bar with query string search term when provided,
- // but only if the input bar is empty. This avoid the obnoxious issue
- // where you start trying to do a search, and the index loads, and
- // suddenly your search is gone!
- if (searchState.input.value === "") {
- searchState.input.value = params.search || "";
- }
-
- /**
- * Executes the query and builds an index of results
- * @param {[Object]} query [The user query]
- * @param {[type]} searchWords [The list of search words to query
- * against]
- * @param {[type]} filterCrates [Crate to search in if defined]
- * @return {[type]} [A search index of results]
- */
- function execQuery(query, searchWords, filterCrates) {
- function itemTypeFromName(typename) {
- for (var i = 0, len = itemTypes.length; i < len; ++i) {
- if (itemTypes[i] === typename) {
- return i;
- }
- }
- return NO_TYPE_FILTER;
- }
-
- var valLower = query.query.toLowerCase(),
- val = valLower,
- typeFilter = itemTypeFromName(query.type),
- results = {}, results_in_args = {}, results_returned = {},
- split = valLower.split("::");
-
- removeEmptyStringsFromArray(split);
-
- function transformResults(results) {
- var out = [];
- for (var i = 0, len = results.length; i < len; ++i) {
- if (results[i].id > -1) {
- var obj = searchIndex[results[i].id];
- obj.lev = results[i].lev;
- var res = buildHrefAndPath(obj);
- obj.displayPath = pathSplitter(res[0]);
- obj.fullPath = obj.displayPath + obj.name;
- // To be sure than it some items aren't considered as duplicate.
- obj.fullPath += "|" + obj.ty;
- obj.href = res[1];
- out.push(obj);
- if (out.length >= MAX_RESULTS) {
- break;
- }
- }
- }
- return out;
- }
-
- function sortResults(results, isType) {
- var ar = [];
- for (var entry in results) {
- if (hasOwnPropertyRustdoc(results, entry)) {
- ar.push(results[entry]);
- }
- }
- results = ar;
- var i, len, result;
- for (i = 0, len = results.length; i < len; ++i) {
- result = results[i];
- result.word = searchWords[result.id];
- result.item = searchIndex[result.id] || {};
- }
- // if there are no results then return to default and fail
- if (results.length === 0) {
- return [];
- }
-
- results.sort(function(aaa, bbb) {
- var a, b;
-
- // sort by exact match with regard to the last word (mismatch goes later)
- a = (aaa.word !== val);
- b = (bbb.word !== val);
- if (a !== b) { return a - b; }
-
- // Sort by non levenshtein results and then levenshtein results by the distance
- // (less changes required to match means higher rankings)
- a = (aaa.lev);
- b = (bbb.lev);
- if (a !== b) { return a - b; }
-
- // sort by crate (non-current crate goes later)
- a = (aaa.item.crate !== window.currentCrate);
- b = (bbb.item.crate !== window.currentCrate);
- if (a !== b) { return a - b; }
-
- // sort by item name length (longer goes later)
- a = aaa.word.length;
- b = bbb.word.length;
- if (a !== b) { return a - b; }
-
- // sort by item name (lexicographically larger goes later)
- a = aaa.word;
- b = bbb.word;
- if (a !== b) { return (a > b ? +1 : -1); }
-
- // sort by index of keyword in item name (no literal occurrence goes later)
- a = (aaa.index < 0);
- b = (bbb.index < 0);
- if (a !== b) { return a - b; }
- // (later literal occurrence, if any, goes later)
- a = aaa.index;
- b = bbb.index;
- if (a !== b) { return a - b; }
-
- // special precedence for primitive and keyword pages
- if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
- (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
- return -1;
- }
- if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
- (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
- return 1;
- }
-
- // sort by description (no description goes later)
- a = (aaa.item.desc === "");
- b = (bbb.item.desc === "");
- if (a !== b) { return a - b; }
-
- // sort by type (later occurrence in `itemTypes` goes later)
- a = aaa.item.ty;
- b = bbb.item.ty;
- if (a !== b) { return a - b; }
-
- // sort by path (lexicographically larger goes later)
- a = aaa.item.path;
- b = bbb.item.path;
- if (a !== b) { return (a > b ? +1 : -1); }
-
- // que sera, sera
- return 0;
- });
-
- for (i = 0, len = results.length; i < len; ++i) {
- result = results[i];
-
- // this validation does not make sense when searching by types
- if (result.dontValidate) {
- continue;
- }
- var name = result.item.name.toLowerCase(),
- path = result.item.path.toLowerCase(),
- parent = result.item.parent;
-
- if (!isType && !validateResult(name, path, split, parent)) {
- result.id = -1;
- }
- }
- return transformResults(results);
- }
-
- function extractGenerics(val) {
- val = val.toLowerCase();
- if (val.indexOf("<") !== -1) {
- var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
- return {
- name: val.substring(0, val.indexOf("<")),
- generics: values.split(/\s*,\s*/),
- };
- }
- return {
- name: val,
- generics: [],
- };
- }
-
- function getObjectNameFromId(id) {
- if (typeof id === "number") {
- return searchIndex[id].name;
- }
- return id;
- }
-
- function checkGenerics(obj, val) {
- // The names match, but we need to be sure that all generics kinda
- // match as well.
- var tmp_lev, elem_name;
- if (val.generics.length > 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length >= val.generics.length) {
- var elems = Object.create(null);
- var elength = obj[GENERICS_DATA].length;
- for (var x = 0; x < elength; ++x) {
- if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) {
- elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0;
- }
- elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
- }
- var total = 0;
- var done = 0;
- // We need to find the type that matches the most to remove it in order
- // to move forward.
- var vlength = val.generics.length;
- for (x = 0; x < vlength; ++x) {
- var lev = MAX_LEV_DISTANCE + 1;
- var firstGeneric = getObjectNameFromId(val.generics[x]);
- var match = null;
- if (elems[firstGeneric]) {
- match = firstGeneric;
- lev = 0;
- } else {
- for (elem_name in elems) {
- tmp_lev = levenshtein(elem_name, firstGeneric);
- if (tmp_lev < lev) {
- lev = tmp_lev;
- match = elem_name;
- }
- }
- }
- if (match !== null) {
- elems[match] -= 1;
- if (elems[match] == 0) {
- delete elems[match];
- }
- total += lev;
- done += 1;
- } else {
- return MAX_LEV_DISTANCE + 1;
- }
- }
- return Math.ceil(total / done);
- }
- }
- return MAX_LEV_DISTANCE + 1;
- }
-
- // Check for type name and type generics (if any).
- function checkType(obj, val, literalSearch) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
- var len, x, firstGeneric;
- if (obj[NAME] === val.name) {
- if (literalSearch) {
- if (val.generics && val.generics.length !== 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length > 0) {
- var elems = Object.create(null);
- len = obj[GENERICS_DATA].length;
- for (x = 0; x < len; ++x) {
- if (!elems[getObjectNameFromId(obj[GENERICS_DATA][x])]) {
- elems[getObjectNameFromId(obj[GENERICS_DATA][x])] = 0;
- }
- elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
- }
-
- var allFound = true;
- len = val.generics.length;
- for (x = 0; x < len; ++x) {
- firstGeneric = getObjectNameFromId(val.generics[x]);
- if (elems[firstGeneric]) {
- elems[firstGeneric] -= 1;
- } else {
- allFound = false;
- break;
- }
- }
- if (allFound) {
- return true;
- }
- }
- return false;
- }
- return true;
- } else {
- // If the type has generics but don't match, then it won't return at this point.
- // Otherwise, `checkGenerics` will return 0 and it'll return.
- if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
- var tmp_lev = checkGenerics(obj, val);
- if (tmp_lev <= MAX_LEV_DISTANCE) {
- return tmp_lev;
- }
- }
- }
- } else if (literalSearch) {
- if ((!val.generics || val.generics.length === 0) &&
- obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- return obj[GENERICS_DATA].some(
- function(name) {
- return name === val.name;
- });
- }
- return false;
- }
- lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
- if (lev_distance <= MAX_LEV_DISTANCE) {
- // The generics didn't match but the name kinda did so we give it
- // a levenshtein distance value that isn't *this* good so it goes
- // into the search results but not too high.
- lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
- } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- // We can check if the type we're looking for is inside the generics!
- var olength = obj[GENERICS_DATA].length;
- for (x = 0; x < olength; ++x) {
- lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
- lev_distance);
- }
- }
- // Now whatever happens, the returned distance is "less good" so we should mark it
- // as such, and so we add 1 to the distance to make it "less good".
- return lev_distance + 1;
- }
-
- function findArg(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
-
- if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
- var length = obj.type[INPUTS_DATA].length;
- for (var i = 0; i < length; i++) {
- var tmp = obj.type[INPUTS_DATA][i];
- if (!typePassesFilter(typeFilter, tmp[1])) {
- continue;
- }
- tmp = checkType(tmp, val, literalSearch);
- if (literalSearch) {
- if (tmp) {
- return true;
- }
- continue;
- }
- lev_distance = Math.min(tmp, lev_distance);
- if (lev_distance === 0) {
- return 0;
- }
- }
- }
- return literalSearch ? false : lev_distance;
- }
-
- function checkReturned(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
-
- if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
- var ret = obj.type[OUTPUT_DATA];
- if (typeof ret[0] === "string") {
- ret = [ret];
- }
- for (var x = 0, len = ret.length; x < len; ++x) {
- var tmp = ret[x];
- if (!typePassesFilter(typeFilter, tmp[1])) {
- continue;
- }
- tmp = checkType(tmp, val, literalSearch);
- if (literalSearch) {
- if (tmp) {
- return true;
- }
- continue;
- }
- lev_distance = Math.min(tmp, lev_distance);
- if (lev_distance === 0) {
- return 0;
- }
- }
- }
- return literalSearch ? false : lev_distance;
- }
-
- function checkPath(contains, lastElem, ty) {
- if (contains.length === 0) {
- return 0;
- }
- var ret_lev = MAX_LEV_DISTANCE + 1;
- var path = ty.path.split("::");
-
- if (ty.parent && ty.parent.name) {
- path.push(ty.parent.name.toLowerCase());
- }
-
- var length = path.length;
- var clength = contains.length;
- if (clength > length) {
- return MAX_LEV_DISTANCE + 1;
- }
- for (var i = 0; i < length; ++i) {
- if (i + clength > length) {
- break;
- }
- var lev_total = 0;
- var aborted = false;
- for (var x = 0; x < clength; ++x) {
- var lev = levenshtein(path[i + x], contains[x]);
- if (lev > MAX_LEV_DISTANCE) {
- aborted = true;
- break;
- }
- lev_total += lev;
- }
- if (!aborted) {
- ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
- }
- }
- return ret_lev;
- }
-
- function typePassesFilter(filter, type) {
- // No filter
- if (filter <= NO_TYPE_FILTER) return true;
-
- // Exact match
- if (filter === type) return true;
-
- // Match related items
- var name = itemTypes[type];
- switch (itemTypes[filter]) {
- case "constant":
- return name === "associatedconstant";
- case "fn":
- return name === "method" || name === "tymethod";
- case "type":
- return name === "primitive" || name === "associatedtype";
- case "trait":
- return name === "traitalias";
- }
-
- // No match
- return false;
- }
-
- function createAliasFromItem(item) {
- return {
- crate: item.crate,
- name: item.name,
- path: item.path,
- desc: item.desc,
- ty: item.ty,
- parent: item.parent,
- type: item.type,
- is_alias: true,
- };
- }
-
- function handleAliases(ret, query, filterCrates) {
- // We separate aliases and crate aliases because we want to have current crate
- // aliases to be before the others in the displayed results.
- var aliases = [];
- var crateAliases = [];
- if (filterCrates !== undefined) {
- if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
- var query_aliases = ALIASES[filterCrates][query.search];
- var len = query_aliases.length;
- for (var i = 0; i < len; ++i) {
- aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
- }
- }
- } else {
- Object.keys(ALIASES).forEach(function(crate) {
- if (ALIASES[crate][query.search]) {
- var pushTo = crate === window.currentCrate ? crateAliases : aliases;
- var query_aliases = ALIASES[crate][query.search];
- var len = query_aliases.length;
- for (var i = 0; i < len; ++i) {
- pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
- }
- }
- });
- }
-
- var sortFunc = function(aaa, bbb) {
- if (aaa.path < bbb.path) {
- return 1;
- } else if (aaa.path === bbb.path) {
- return 0;
- }
- return -1;
- };
- crateAliases.sort(sortFunc);
- aliases.sort(sortFunc);
-
- var pushFunc = function(alias) {
- alias.alias = query.raw;
- var res = buildHrefAndPath(alias);
- alias.displayPath = pathSplitter(res[0]);
- alias.fullPath = alias.displayPath + alias.name;
- alias.href = res[1];
-
- ret.others.unshift(alias);
- if (ret.others.length > MAX_RESULTS) {
- ret.others.pop();
- }
- };
- onEach(aliases, pushFunc);
- onEach(crateAliases, pushFunc);
- }
-
- // quoted values mean literal search
- var nSearchWords = searchWords.length;
- var i, it;
- var ty;
- var fullId;
- var returned;
- var in_args;
- var len;
- if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
- val.charAt(val.length - 1) === val.charAt(0))
- {
- val = extractGenerics(val.substr(1, val.length - 2));
- for (i = 0; i < nSearchWords; ++i) {
- if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
- continue;
- }
- in_args = findArg(searchIndex[i], val, true, typeFilter);
- returned = checkReturned(searchIndex[i], val, true, typeFilter);
- ty = searchIndex[i];
- fullId = ty.id;
-
- if (searchWords[i] === val.name
- && typePassesFilter(typeFilter, searchIndex[i].ty)
- && results[fullId] === undefined) {
- results[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- if (in_args && results_in_args[fullId] === undefined) {
- results_in_args[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- if (returned && results_returned[fullId] === undefined) {
- results_returned[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- }
- query.inputs = [val];
- query.output = val;
- query.search = val;
- // searching by type
- } else if (val.search("->") > -1) {
- var trimmer = function(s) { return s.trim(); };
- var parts = val.split("->").map(trimmer);
- var input = parts[0];
- // sort inputs so that order does not matter
- var inputs = input.split(",").map(trimmer).sort();
- for (i = 0, len = inputs.length; i < len; ++i) {
- inputs[i] = extractGenerics(inputs[i]);
- }
- var output = extractGenerics(parts[1]);
-
- for (i = 0; i < nSearchWords; ++i) {
- if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
- continue;
- }
- var type = searchIndex[i].type;
- ty = searchIndex[i];
- if (!type) {
- continue;
- }
- fullId = ty.id;
-
- returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
- if (output.name === "*" || returned) {
- in_args = false;
- var is_module = false;
-
- if (input === "*") {
- is_module = true;
- } else {
- var allFound = true;
- for (it = 0, len = inputs.length; allFound && it < len; it++) {
- allFound = checkType(type, inputs[it], true);
- }
- in_args = allFound;
- }
- if (in_args) {
- results_in_args[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- if (returned) {
- results_returned[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- if (is_module) {
- results[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- };
- }
- }
- }
- query.inputs = inputs.map(function(input) {
- return input.name;
- });
- query.output = output.name;
- } else {
- query.inputs = [val];
- query.output = val;
- query.search = val;
- // gather matching search results up to a certain maximum
- val = val.replace(/_/g, "");
-
- var valGenerics = extractGenerics(val);
-
- var paths = valLower.split("::");
- removeEmptyStringsFromArray(paths);
- val = paths[paths.length - 1];
- var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
-
- var lev, j;
- for (j = 0; j < nSearchWords; ++j) {
- ty = searchIndex[j];
- if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
- continue;
- }
- var lev_add = 0;
- if (paths.length > 1) {
- lev = checkPath(contains, paths[paths.length - 1], ty);
- if (lev > MAX_LEV_DISTANCE) {
- continue;
- } else if (lev > 0) {
- lev_add = lev / 10;
- }
- }
-
- returned = MAX_LEV_DISTANCE + 1;
- in_args = MAX_LEV_DISTANCE + 1;
- var index = -1;
- // we want lev results to go lower than others
- lev = MAX_LEV_DISTANCE + 1;
- fullId = ty.id;
-
- if (searchWords[j].indexOf(split[i]) > -1 ||
- searchWords[j].indexOf(val) > -1 ||
- ty.normalizedName.indexOf(val) > -1)
- {
- // filter type: ... queries
- if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
- index = ty.normalizedName.indexOf(val);
- }
- }
- if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
- if (typePassesFilter(typeFilter, ty.ty)) {
- lev += 1;
- } else {
- lev = MAX_LEV_DISTANCE + 1;
- }
- }
- in_args = findArg(ty, valGenerics, false, typeFilter);
- returned = checkReturned(ty, valGenerics, false, typeFilter);
-
- lev += lev_add;
- if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
- if (val.length < 6) {
- lev -= 1;
- } else {
- lev = 0;
- }
- }
- if (in_args <= MAX_LEV_DISTANCE) {
- if (results_in_args[fullId] === undefined) {
- results_in_args[fullId] = {
- id: j,
- index: index,
- lev: in_args,
- };
- }
- results_in_args[fullId].lev =
- Math.min(results_in_args[fullId].lev, in_args);
- }
- if (returned <= MAX_LEV_DISTANCE) {
- if (results_returned[fullId] === undefined) {
- results_returned[fullId] = {
- id: j,
- index: index,
- lev: returned,
- };
- }
- results_returned[fullId].lev =
- Math.min(results_returned[fullId].lev, returned);
- }
- if (typePassesFilter(typeFilter, ty.ty) &&
- (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
- if (index !== -1 && paths.length < 2) {
- lev = 0;
- }
- if (results[fullId] === undefined) {
- results[fullId] = {
- id: j,
- index: index,
- lev: lev,
- };
- }
- results[fullId].lev = Math.min(results[fullId].lev, lev);
- }
- }
- }
-
- var ret = {
- "in_args": sortResults(results_in_args, true),
- "returned": sortResults(results_returned, true),
- "others": sortResults(results, false),
- };
- handleAliases(ret, query, filterCrates);
- return ret;
- }
-
- /**
- * Validate performs the following boolean logic. For example:
- * "File::open" will give IF A PARENT EXISTS => ("file" && "open")
- * exists in (name || path || parent) OR => ("file" && "open") exists in
- * (name || path )
- *
- * This could be written functionally, but I wanted to minimise
- * functions on stack.
- *
- * @param {[string]} name [The name of the result]
- * @param {[string]} path [The path of the result]
- * @param {[string]} keys [The keys to be used (["file", "open"])]
- * @param {[object]} parent [The parent of the result]
- * @return {boolean} [Whether the result is valid or not]
- */
- function validateResult(name, path, keys, parent) {
- for (var i = 0, len = keys.length; i < len; ++i) {
- // each check is for validation so we negate the conditions and invalidate
- if (!(
- // check for an exact name match
- name.indexOf(keys[i]) > -1 ||
- // then an exact path match
- path.indexOf(keys[i]) > -1 ||
- // next if there is a parent, check for exact parent match
- (parent !== undefined && parent.name !== undefined &&
- parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
- // lastly check to see if the name was a levenshtein match
- levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
- return false;
- }
- }
- return true;
- }
-
- function getQuery(raw) {
- var matches, type, query;
- query = raw;
-
- matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
- if (matches) {
- type = matches[1].replace(/^const$/, "constant");
- query = query.substring(matches[0].length);
- }
-
- return {
- raw: raw,
- query: query,
- type: type,
- id: query + type
- };
- }
-
- function nextTab(direction) {
- var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
- searchState.focusedByTab[searchState.currentTab] = document.activeElement;
- printTab(next);
- focusSearchResult();
- }
-
- // Focus the first search result on the active tab, or the result that
- // was focused last time this tab was active.
- function focusSearchResult() {
- var target = searchState.focusedByTab[searchState.currentTab] ||
- document.querySelectorAll(".search-results.active a").item(0) ||
- document.querySelectorAll("#titles > button").item(searchState.currentTab);
- if (target) {
- target.focus();
- }
- }
-
- function buildHrefAndPath(item) {
- var displayPath;
- var href;
- var type = itemTypes[item.ty];
- var name = item.name;
- var path = item.path;
-
- if (type === "mod") {
- displayPath = path + "::";
- href = window.rootPath + path.replace(/::/g, "/") + "/" +
- name + "/index.html";
- } else if (type === "primitive" || type === "keyword") {
- displayPath = "";
- href = window.rootPath + path.replace(/::/g, "/") +
- "/" + type + "." + name + ".html";
- } else if (type === "externcrate") {
- displayPath = "";
- href = window.rootPath + name + "/index.html";
- } else if (item.parent !== undefined) {
- var myparent = item.parent;
- var anchor = "#" + type + "." + name;
- var parentType = itemTypes[myparent.ty];
- var pageType = parentType;
- var pageName = myparent.name;
-
- if (parentType === "primitive") {
- displayPath = myparent.name + "::";
- } else if (type === "structfield" && parentType === "variant") {
- // Structfields belonging to variants are special: the
- // final path element is the enum name.
- var enumNameIdx = item.path.lastIndexOf("::");
- var enumName = item.path.substr(enumNameIdx + 2);
- path = item.path.substr(0, enumNameIdx);
- displayPath = path + "::" + enumName + "::" + myparent.name + "::";
- anchor = "#variant." + myparent.name + ".field." + name;
- pageType = "enum";
- pageName = enumName;
- } else {
- displayPath = path + "::" + myparent.name + "::";
- }
- href = window.rootPath + path.replace(/::/g, "/") +
- "/" + pageType +
- "." + pageName +
- ".html" + anchor;
- } else {
- displayPath = item.path + "::";
- href = window.rootPath + item.path.replace(/::/g, "/") +
- "/" + type + "." + name + ".html";
- }
- return [displayPath, href];
- }
-
- function escape(content) {
- var h1 = document.createElement("h1");
- h1.textContent = content;
- return h1.innerHTML;
- }
-
- function pathSplitter(path) {
- var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
- if (tmp.endsWith("<span>")) {
- return tmp.slice(0, tmp.length - 6);
- }
- return tmp;
- }
-
- function addTab(array, query, display) {
- var extraClass = "";
- if (display === true) {
- extraClass = " active";
- }
-
- var output = document.createElement("div");
- var duplicates = {};
- var length = 0;
- if (array.length > 0) {
- output.className = "search-results " + extraClass;
-
- array.forEach(function(item) {
- if (item.is_alias !== true) {
- if (duplicates[item.fullPath]) {
- return;
- }
- duplicates[item.fullPath] = true;
- }
-
- var name = item.name;
- var type = itemTypes[item.ty];
-
- length += 1;
-
- var extra = "";
- if (type === "primitive") {
- extra = " <i>(primitive type)</i>";
- } else if (type === "keyword") {
- extra = " <i>(keyword)</i>";
- }
-
- var link = document.createElement("a");
- link.className = "result-" + type;
- link.href = item.href;
-
- var wrapper = document.createElement("div");
- var resultName = document.createElement("div");
- resultName.className = "result-name";
-
- if (item.is_alias) {
- var alias = document.createElement("span");
- alias.className = "alias";
-
- var bold = document.createElement("b");
- bold.innerText = item.alias;
- alias.appendChild(bold);
-
- alias.insertAdjacentHTML(
- "beforeend",
- "<span class=\"grey\"><i> - see </i></span>");
-
- resultName.appendChild(alias);
- }
- resultName.insertAdjacentHTML(
- "beforeend",
- item.displayPath + "<span class=\"" + type + "\">" + name + extra + "</span>");
- wrapper.appendChild(resultName);
-
- var description = document.createElement("div");
- description.className = "desc";
- var spanDesc = document.createElement("span");
- spanDesc.insertAdjacentHTML("beforeend", item.desc);
-
- description.appendChild(spanDesc);
- wrapper.appendChild(description);
- link.appendChild(wrapper);
- output.appendChild(link);
- });
- } else {
- output.className = "search-failed" + extraClass;
- output.innerHTML = "No results :(<br/>" +
- "Try on <a href=\"https://duckduckgo.com/?q=" +
- encodeURIComponent("rust " + query.query) +
- "\">DuckDuckGo</a>?<br/><br/>" +
- "Or try looking in one of these:<ul><li>The <a " +
- "href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
- " for technical details about the language.</li><li><a " +
- "href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
- "Example</a> for expository code examples.</a></li><li>The <a " +
- "href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
- "introductions to language features and the language itself.</li><li><a " +
- "href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
- " <a href=\"https://crates.io/\">crates.io</a>.</li></ul>";
- }
- return [output, length];
- }
-
- function makeTabHeader(tabNb, text, nbElems) {
- if (searchState.currentTab === tabNb) {
- return "<button class=\"selected\">" + text +
- " <div class=\"count\">(" + nbElems + ")</div></button>";
- }
- return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
- }
-
- function showResults(results, go_to_first) {
- var search = searchState.outputElement();
- if (go_to_first || (results.others.length === 1
- && getSettingValue("go-to-only-result") === "true"
- // By default, the search DOM element is "empty" (meaning it has no children not
- // text content). Once a search has been run, it won't be empty, even if you press
- // ESC or empty the search input (which also "cancels" the search).
- && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)))
- {
- var elem = document.createElement("a");
- elem.href = results.others[0].href;
- removeClass(elem, "active");
- // For firefox, we need the element to be in the DOM so it can be clicked.
- document.body.appendChild(elem);
- elem.click();
- return;
- }
- var query = getQuery(searchState.input.value);
-
- currentResults = query.id;
-
- var ret_others = addTab(results.others, query);
- var ret_in_args = addTab(results.in_args, query, false);
- var ret_returned = addTab(results.returned, query, false);
-
- // Navigate to the relevant tab if the current tab is empty, like in case users search
- // for "-> String". If they had selected another tab previously, they have to click on
- // it again.
- var currentTab = searchState.currentTab;
- if ((currentTab === 0 && ret_others[1] === 0) ||
- (currentTab === 1 && ret_in_args[1] === 0) ||
- (currentTab === 2 && ret_returned[1] === 0)) {
- if (ret_others[1] !== 0) {
- currentTab = 0;
- } else if (ret_in_args[1] !== 0) {
- currentTab = 1;
- } else if (ret_returned[1] !== 0) {
- currentTab = 2;
- }
- }
-
- var output = "<h1>Results for " + escape(query.query) +
- (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
- "<div id=\"titles\">" +
- makeTabHeader(0, "In Names", ret_others[1]) +
- makeTabHeader(1, "In Parameters", ret_in_args[1]) +
- makeTabHeader(2, "In Return Types", ret_returned[1]) +
- "</div>";
-
- var resultsElem = document.createElement("div");
- resultsElem.id = "results";
- resultsElem.appendChild(ret_others[0]);
- resultsElem.appendChild(ret_in_args[0]);
- resultsElem.appendChild(ret_returned[0]);
-
- search.innerHTML = output;
- search.appendChild(resultsElem);
- // Reset focused elements.
- searchState.focusedByTab = [null, null, null];
- searchState.showResults(search);
- var elems = document.getElementById("titles").childNodes;
- elems[0].onclick = function() { printTab(0); };
- elems[1].onclick = function() { printTab(1); };
- elems[2].onclick = function() { printTab(2); };
- printTab(currentTab);
- }
-
- function execSearch(query, searchWords, filterCrates) {
- function getSmallest(arrays, positions, notDuplicates) {
- var start = null;
-
- for (var it = 0, len = positions.length; it < len; ++it) {
- if (arrays[it].length > positions[it] &&
- (start === null || start > arrays[it][positions[it]].lev) &&
- !notDuplicates[arrays[it][positions[it]].fullPath]) {
- start = arrays[it][positions[it]].lev;
- }
- }
- return start;
- }
-
- function mergeArrays(arrays) {
- var ret = [];
- var positions = [];
- var notDuplicates = {};
-
- for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
- positions.push(0);
- }
- while (ret.length < MAX_RESULTS) {
- var smallest = getSmallest(arrays, positions, notDuplicates);
-
- if (smallest === null) {
- break;
- }
- for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
- if (arrays[x].length > positions[x] &&
- arrays[x][positions[x]].lev === smallest &&
- !notDuplicates[arrays[x][positions[x]].fullPath]) {
- ret.push(arrays[x][positions[x]]);
- notDuplicates[arrays[x][positions[x]].fullPath] = true;
- positions[x] += 1;
- }
- }
- }
- return ret;
- }
-
- // Split search query by ",", while respecting angle bracket nesting.
- // Since "<" is an alias for the Ord family of traits, it also uses
- // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
- //
- // tokenizeQuery("A<B, C>, D") == ["A<B, C>", "D"]
- // tokenizeQuery("A<B, C, D") == ["A<B", "C", "D"]
- function tokenizeQuery(raw) {
- var i, matched;
- var l = raw.length;
- var depth = 0;
- var nextAngle = /(<|>)/g;
- var ret = [];
- var start = 0;
- for (i = 0; i < l; ++i) {
- switch (raw[i]) {
- case "<":
- nextAngle.lastIndex = i + 1;
- matched = nextAngle.exec(raw);
- if (matched && matched[1] === '>') {
- depth += 1;
- }
- break;
- case ">":
- if (depth > 0) {
- depth -= 1;
- }
- break;
- case ",":
- if (depth === 0) {
- ret.push(raw.substring(start, i));
- start = i + 1;
- }
- break;
- }
- }
- if (start !== i) {
- ret.push(raw.substring(start, i));
- }
- return ret;
- }
-
- var queries = tokenizeQuery(query.raw);
- var results = {
- "in_args": [],
- "returned": [],
- "others": [],
- };
-
- for (var i = 0, len = queries.length; i < len; ++i) {
- query = queries[i].trim();
- if (query.length !== 0) {
- var tmp = execQuery(getQuery(query), searchWords, filterCrates);
-
- results.in_args.push(tmp.in_args);
- results.returned.push(tmp.returned);
- results.others.push(tmp.others);
- }
- }
- if (queries.length > 1) {
- return {
- "in_args": mergeArrays(results.in_args),
- "returned": mergeArrays(results.returned),
- "others": mergeArrays(results.others),
- };
- }
- return {
- "in_args": results.in_args[0],
- "returned": results.returned[0],
- "others": results.others[0],
- };
- }
-
- function getFilterCrates() {
- var elem = document.getElementById("crate-search");
-
- if (elem && elem.value !== "All crates" &&
- hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
- {
- return elem.value;
- }
- return undefined;
- }
-
- function search(e, forced) {
- var params = searchState.getQueryStringParams();
- var query = getQuery(searchState.input.value.trim());
-
- if (e) {
- e.preventDefault();
- }
-
- if (query.query.length === 0) {
- return;
- }
- if (!forced && query.id === currentResults) {
- if (query.query.length > 0) {
- searchState.putBackSearch(searchState.input);
- }
- return;
- }
-
- // Update document title to maintain a meaningful browser history
- searchState.title = "Results for " + query.query + " - Rust";
-
- // Because searching is incremental by character, only the most
- // recent search query is added to the browser history.
- if (searchState.browserSupportsHistoryApi()) {
- var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
- window.location.hash;
- if (!history.state && !params.search) {
- history.pushState(query, "", newURL);
- } else {
- history.replaceState(query, "", newURL);
- }
- }
-
- var filterCrates = getFilterCrates();
- showResults(execSearch(query, index, filterCrates), params.go_to_first);
- }
-
- function buildIndex(rawSearchIndex) {
- searchIndex = [];
- var searchWords = [];
- var i, word;
- var currentIndex = 0;
- var id = 0;
-
- for (var crate in rawSearchIndex) {
- if (!hasOwnPropertyRustdoc(rawSearchIndex, crate)) {
- continue;
- }
-
- var crateSize = 0;
-
- searchWords.push(crate);
- // This object should have exactly the same set of fields as the "row"
- // object defined below. Your JavaScript runtime will thank you.
- // https://mathiasbynens.be/notes/shapes-ics
- var crateRow = {
- crate: crate,
- ty: 1, // == ExternCrate
- name: crate,
- path: "",
- desc: rawSearchIndex[crate].doc,
- parent: undefined,
- type: null,
- id: id,
- normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
- };
- id += 1;
- searchIndex.push(crateRow);
- currentIndex += 1;
-
- // an array of (Number) item types
- var itemTypes = rawSearchIndex[crate].t;
- // an array of (String) item names
- var itemNames = rawSearchIndex[crate].n;
- // an array of (String) full paths (or empty string for previous path)
- var itemPaths = rawSearchIndex[crate].q;
- // an array of (String) descriptions
- var itemDescs = rawSearchIndex[crate].d;
- // an array of (Number) the parent path index + 1 to `paths`, or 0 if none
- var itemParentIdxs = rawSearchIndex[crate].i;
- // an array of (Object | null) the type of the function, if any
- var itemFunctionSearchTypes = rawSearchIndex[crate].f;
- // an array of [(Number) item type,
- // (String) name]
- var paths = rawSearchIndex[crate].p;
- // a array of [(String) alias name
- // [Number] index to items]
- var aliases = rawSearchIndex[crate].a;
-
- // convert `rawPaths` entries into object form
- var len = paths.length;
- for (i = 0; i < len; ++i) {
- paths[i] = {ty: paths[i][0], name: paths[i][1]};
- }
-
- // convert `item*` into an object form, and construct word indices.
- //
- // before any analysis is performed lets gather the search terms to
- // search against apart from the rest of the data. This is a quick
- // operation that is cached for the life of the page state so that
- // all other search operations have access to this cached data for
- // faster analysis operations
- len = itemTypes.length;
- var lastPath = "";
- for (i = 0; i < len; ++i) {
- // This object should have exactly the same set of fields as the "crateRow"
- // object defined above.
- if (typeof itemNames[i] === "string") {
- word = itemNames[i].toLowerCase();
- searchWords.push(word);
- } else {
- word = "";
- searchWords.push("");
- }
- var row = {
- crate: crate,
- ty: itemTypes[i],
- name: itemNames[i],
- path: itemPaths[i] ? itemPaths[i] : lastPath,
- desc: itemDescs[i],
- parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
- type: itemFunctionSearchTypes[i],
- id: id,
- normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
- };
- id += 1;
- searchIndex.push(row);
- lastPath = row.path;
- crateSize += 1;
- }
-
- if (aliases) {
- ALIASES[crate] = {};
- var j, local_aliases;
- for (var alias_name in aliases) {
- if (!hasOwnPropertyRustdoc(aliases, alias_name)) {
- continue;
- }
-
- if (!hasOwnPropertyRustdoc(ALIASES[crate], alias_name)) {
- ALIASES[crate][alias_name] = [];
- }
- local_aliases = aliases[alias_name];
- for (j = 0, len = local_aliases.length; j < len; ++j) {
- ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
- }
- }
- }
- currentIndex += crateSize;
- }
- return searchWords;
- }
-
- function registerSearchEvents() {
- var searchAfter500ms = function() {
- searchState.clearInputTimeout();
- if (searchState.input.value.length === 0) {
- if (searchState.browserSupportsHistoryApi()) {
- history.replaceState("", window.currentCrate + " - Rust",
- getNakedUrl() + window.location.hash);
- }
- searchState.hideResults();
- } else {
- searchState.timeout = setTimeout(search, 500);
- }
- };
- searchState.input.onkeyup = searchAfter500ms;
- searchState.input.oninput = searchAfter500ms;
- document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
- e.preventDefault();
- searchState.clearInputTimeout();
- search();
- };
- searchState.input.onchange = function(e) {
- if (e.target !== document.activeElement) {
- // To prevent doing anything when it's from a blur event.
- return;
- }
- // Do NOT e.preventDefault() here. It will prevent pasting.
- searchState.clearInputTimeout();
- // zero-timeout necessary here because at the time of event handler execution the
- // pasted content is not in the input field yet. Shouldn’t make any difference for
- // change, though.
- setTimeout(search, 0);
- };
- searchState.input.onpaste = searchState.input.onchange;
-
- searchState.outputElement().addEventListener("keydown", function(e) {
- // We only handle unmodified keystrokes here. We don't want to interfere with,
- // for instance, alt-left and alt-right for history navigation.
- if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
- return;
- }
- // up and down arrow select next/previous search result, or the
- // search box if we're already at the top.
- if (e.which === 38) { // up
- var previous = document.activeElement.previousElementSibling;
- if (previous) {
- previous.focus();
- } else {
- searchState.focus();
- }
- e.preventDefault();
- } else if (e.which === 40) { // down
- var next = document.activeElement.nextElementSibling;
- if (next) {
- next.focus();
- }
- var rect = document.activeElement.getBoundingClientRect();
- if (window.innerHeight - rect.bottom < rect.height) {
- window.scrollBy(0, rect.height);
- }
- e.preventDefault();
- } else if (e.which === 37) { // left
- nextTab(-1);
- e.preventDefault();
- } else if (e.which === 39) { // right
- nextTab(1);
- e.preventDefault();
- }
- });
-
- searchState.input.addEventListener("keydown", function(e) {
- if (e.which === 40) { // down
- focusSearchResult();
- e.preventDefault();
- }
- });
-
-
- var selectCrate = document.getElementById("crate-search");
- if (selectCrate) {
- selectCrate.onchange = function() {
- updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
- // In case you "cut" the entry from the search input, then change the crate filter
- // before paste back the previous search, you get the old search results without
- // the filter. To prevent this, we need to remove the previous results.
- currentResults = null;
- search(undefined, true);
- };
- }
-
- // Push and pop states are used to add search results to the browser
- // history.
- if (searchState.browserSupportsHistoryApi()) {
- // Store the previous <title> so we can revert back to it later.
- var previousTitle = document.title;
-
- window.addEventListener("popstate", function(e) {
- var params = searchState.getQueryStringParams();
- // Revert to the previous title manually since the History
- // API ignores the title parameter.
- document.title = previousTitle;
- // When browsing forward to search results the previous
- // search will be repeated, so the currentResults are
- // cleared to ensure the search is successful.
- currentResults = null;
- // Synchronize search bar with query string state and
- // perform the search. This will empty the bar if there's
- // nothing there, which lets you really go back to a
- // previous state with nothing in the bar.
- if (params.search && params.search.length > 0) {
- searchState.input.value = params.search;
- // Some browsers fire "onpopstate" for every page load
- // (Chrome), while others fire the event only when actually
- // popping a state (Firefox), which is why search() is
- // called both here and at the end of the startSearch()
- // function.
- search(e);
- } else {
- searchState.input.value = "";
- // When browsing back from search results the main page
- // visibility must be reset.
- searchState.hideResults();
- }
- });
- }
-
- // This is required in firefox to avoid this problem: Navigating to a search result
- // with the keyboard, hitting enter, and then hitting back would take you back to
- // the doc page, rather than the search that should overlay it.
- // This was an interaction between the back-forward cache and our handlers
- // that try to sync state between the URL and the search input. To work around it,
- // do a small amount of re-init on page show.
- window.onpageshow = function(){
- var qSearch = searchState.getQueryStringParams().search;
- if (searchState.input.value === "" && qSearch) {
- searchState.input.value = qSearch;
- }
- search();
- };
- }
-
- index = buildIndex(rawSearchIndex);
- registerSearchEvents();
- // If there's a search term in the URL, execute the search now.
- if (searchState.getQueryStringParams().search) {
- search();
- }
-};
-
-if (window.searchIndex !== undefined) {
- initSearch(window.searchIndex);
-}
-
-})();
+++ /dev/null
-.setting-line {
- padding: 5px;
- position: relative;
-}
-
-.setting-line > div {
- display: inline-block;
- vertical-align: top;
- font-size: 17px;
- padding-top: 2px;
-}
-
-.setting-line > .title {
- font-size: 19px;
- width: 100%;
- max-width: none;
- border-bottom: 1px solid;
-}
-
-.toggle {
- position: relative;
- display: inline-block;
- width: 45px;
- height: 27px;
- margin-right: 20px;
-}
-
-.toggle input {
- opacity: 0;
- position: absolute;
-}
-
-.select-wrapper {
- float: right;
- position: relative;
- height: 27px;
- min-width: 25%;
-}
-
-.select-wrapper select {
- appearance: none;
- -moz-appearance: none;
- -webkit-appearance: none;
- background: none;
- border: 2px solid #ccc;
- padding-right: 28px;
- width: 100%;
-}
-
-.select-wrapper img {
- pointer-events: none;
- position: absolute;
- right: 0;
- bottom: 0;
- background: #ccc;
- height: 100%;
- width: 28px;
- padding: 0px 4px;
-}
-
-.select-wrapper select option {
- color: initial;
-}
-
-.slider {
- position: absolute;
- cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: #ccc;
- -webkit-transition: .3s;
- transition: .3s;
-}
-
-.slider:before {
- position: absolute;
- content: "";
- height: 19px;
- width: 19px;
- left: 4px;
- bottom: 4px;
- background-color: white;
- -webkit-transition: .3s;
- transition: .3s;
-}
-
-input:checked + .slider {
- background-color: #2196F3;
-}
-
-input:focus + .slider {
- box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
-
-input:checked + .slider:before {
- -webkit-transform: translateX(19px);
- -ms-transform: translateX(19px);
- transform: translateX(19px);
-}
-
-.setting-line > .sub-settings {
- padding-left: 42px;
- width: 100%;
- display: block;
-}
+++ /dev/null
-// Local js definitions:
-/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */
-
-(function () {
- function changeSetting(settingName, value) {
- updateLocalStorage("rustdoc-" + settingName, value);
-
- switch (settingName) {
- case "preferred-dark-theme":
- case "preferred-light-theme":
- case "use-system-theme":
- updateSystemTheme();
- break;
- }
- }
-
- function handleKey(ev) {
- // Don't interfere with browser shortcuts
- if (ev.ctrlKey || ev.altKey || ev.metaKey) {
- return;
- }
- switch (getVirtualKey(ev)) {
- case "Enter":
- case "Return":
- case "Space":
- ev.target.checked = !ev.target.checked;
- ev.preventDefault();
- break;
- }
- }
-
- function setEvents() {
- onEachLazy(document.getElementsByClassName("slider"), function(elem) {
- var toggle = elem.previousElementSibling;
- var settingId = toggle.id;
- var settingValue = getSettingValue(settingId);
- if (settingValue !== null) {
- toggle.checked = settingValue === "true";
- }
- toggle.onchange = function() {
- changeSetting(this.id, this.checked);
- };
- toggle.onkeyup = handleKey;
- toggle.onkeyrelease = handleKey;
- });
- onEachLazy(document.getElementsByClassName("select-wrapper"), function(elem) {
- var select = elem.getElementsByTagName("select")[0];
- var settingId = select.id;
- var settingValue = getSettingValue(settingId);
- if (settingValue !== null) {
- select.value = settingValue;
- }
- select.onchange = function() {
- changeSetting(this.id, this.value);
- };
- });
- }
-
- window.addEventListener("DOMContentLoaded", setEvents);
-})();
+++ /dev/null
-// From rust:
-/* global search, sourcesIndex */
-
-// Local js definitions:
-/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
-/* global updateLocalStorage */
-(function() {
-
-function getCurrentFilePath() {
- var parts = window.location.pathname.split("/");
- var rootPathParts = window.rootPath.split("/");
-
- for (var i = 0, len = rootPathParts.length; i < len; ++i) {
- if (rootPathParts[i] === "..") {
- parts.pop();
- }
- }
- var file = window.location.pathname.substring(parts.join("/").length);
- if (file.startsWith("/")) {
- file = file.substring(1);
- }
- return file.substring(0, file.length - 5);
-}
-
-function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
- var name = document.createElement("div");
- name.className = "name";
-
- fullPath += elem["name"] + "/";
-
- name.onclick = function() {
- if (hasClass(this, "expand")) {
- removeClass(this, "expand");
- } else {
- addClass(this, "expand");
- }
- };
- name.innerText = elem["name"];
-
- var i, len;
-
- var children = document.createElement("div");
- children.className = "children";
- var folders = document.createElement("div");
- folders.className = "folders";
- if (elem.dirs) {
- for (i = 0, len = elem.dirs.length; i < len; ++i) {
- if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
- hasFoundFile)) {
- addClass(name, "expand");
- hasFoundFile = true;
- }
- }
- }
- children.appendChild(folders);
-
- var files = document.createElement("div");
- files.className = "files";
- if (elem.files) {
- for (i = 0, len = elem.files.length; i < len; ++i) {
- var file = document.createElement("a");
- file.innerText = elem.files[i];
- file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
- if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
- file.className = "selected";
- addClass(name, "expand");
- hasFoundFile = true;
- }
- files.appendChild(file);
- }
- }
- search.fullPath = fullPath;
- children.appendChild(files);
- parent.appendChild(name);
- parent.appendChild(children);
- return hasFoundFile && currentFile.startsWith(fullPath);
-}
-
-function toggleSidebar() {
- var sidebar = document.getElementById("source-sidebar");
- var child = this.children[0].children[0];
- if (child.innerText === ">") {
- sidebar.style.left = "";
- this.style.left = "";
- child.innerText = "<";
- updateLocalStorage("rustdoc-source-sidebar-show", "true");
- } else {
- sidebar.style.left = "-300px";
- this.style.left = "0";
- child.innerText = ">";
- updateLocalStorage("rustdoc-source-sidebar-show", "false");
- }
-}
-
-function createSidebarToggle() {
- var sidebarToggle = document.createElement("div");
- sidebarToggle.id = "sidebar-toggle";
- sidebarToggle.onclick = toggleSidebar;
-
- var inner1 = document.createElement("div");
- inner1.style.position = "relative";
-
- var inner2 = document.createElement("div");
- inner2.style.paddingTop = "3px";
- if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
- inner2.innerText = "<";
- } else {
- inner2.innerText = ">";
- sidebarToggle.style.left = "0";
- }
-
- inner1.appendChild(inner2);
- sidebarToggle.appendChild(inner1);
- return sidebarToggle;
-}
-
-// This function is called from "source-files.js", generated in `html/render/mod.rs`.
-// eslint-disable-next-line no-unused-vars
-function createSourceSidebar() {
- if (!window.rootPath.endsWith("/")) {
- window.rootPath += "/";
- }
- var main = document.getElementById("main");
-
- var sidebarToggle = createSidebarToggle();
- main.insertBefore(sidebarToggle, main.firstChild);
-
- var sidebar = document.createElement("div");
- sidebar.id = "source-sidebar";
- if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
- sidebar.style.left = "-300px";
- }
-
- var currentFile = getCurrentFilePath();
- var hasFoundFile = false;
-
- var title = document.createElement("div");
- title.className = "title";
- title.innerText = "Files";
- sidebar.appendChild(title);
- Object.keys(sourcesIndex).forEach(function(key) {
- sourcesIndex[key].name = key;
- hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
- currentFile, hasFoundFile);
- });
-
- main.insertBefore(sidebar, main.firstChild);
- // Focus on the current file in the source files sidebar.
- var selected_elem = sidebar.getElementsByClassName("selected")[0];
- if (typeof selected_elem !== "undefined") {
- selected_elem.focus();
- }
-}
-
-var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
-
-function highlightSourceLines(scrollTo, match) {
- if (typeof match === "undefined") {
- match = window.location.hash.match(lineNumbersRegex);
- }
- if (!match) {
- return;
- }
- var from = parseInt(match[1], 10);
- var to = from;
- if (typeof match[2] !== "undefined") {
- to = parseInt(match[2], 10);
- }
- if (to < from) {
- var tmp = to;
- to = from;
- from = tmp;
- }
- var elem = document.getElementById(from);
- if (!elem) {
- return;
- }
- if (scrollTo) {
- var x = document.getElementById(from);
- if (x) {
- x.scrollIntoView();
- }
- }
- onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
- onEachLazy(e.getElementsByTagName("span"), function(i_e) {
- removeClass(i_e, "line-highlighted");
- });
- });
- for (var i = from; i <= to; ++i) {
- elem = document.getElementById(i);
- if (!elem) {
- break;
- }
- addClass(elem, "line-highlighted");
- }
-}
-
-var handleSourceHighlight = (function() {
- var prev_line_id = 0;
-
- var set_fragment = function(name) {
- var x = window.scrollX,
- y = window.scrollY;
- if (searchState.browserSupportsHistoryApi()) {
- history.replaceState(null, null, "#" + name);
- highlightSourceLines(true);
- } else {
- location.replace("#" + name);
- }
- // Prevent jumps when selecting one or many lines
- window.scrollTo(x, y);
- };
-
- return function(ev) {
- var cur_line_id = parseInt(ev.target.id, 10);
- ev.preventDefault();
-
- if (ev.shiftKey && prev_line_id) {
- // Swap selection if needed
- if (prev_line_id > cur_line_id) {
- var tmp = prev_line_id;
- prev_line_id = cur_line_id;
- cur_line_id = tmp;
- }
-
- set_fragment(prev_line_id + "-" + cur_line_id);
- } else {
- prev_line_id = cur_line_id;
-
- set_fragment(cur_line_id);
- }
- };
-}());
-
-window.addEventListener("hashchange", function() {
- var match = window.location.hash.match(lineNumbersRegex);
- if (match) {
- return highlightSourceLines(false, match);
- }
-});
-
-onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
- el.addEventListener("click", handleSourceHighlight);
-});
-
-highlightSourceLines(true);
-
-window.createSourceSidebar = createSourceSidebar;
-})();
+++ /dev/null
-// From rust:
-/* global resourcesSuffix */
-var darkThemes = ["dark", "ayu"];
-window.currentTheme = document.getElementById("themeStyle");
-window.mainTheme = document.getElementById("mainThemeStyle");
-
-var settingsDataset = (function () {
- var settingsElement = document.getElementById("default-settings");
- if (settingsElement === null) {
- return null;
- }
- var dataset = settingsElement.dataset;
- if (dataset === undefined) {
- return null;
- }
- return dataset;
-})();
-
-function getSettingValue(settingName) {
- var current = getCurrentValue('rustdoc-' + settingName);
- if (current !== null) {
- return current;
- }
- if (settingsDataset !== null) {
- var def = settingsDataset[settingName.replace(/-/g,'_')];
- if (def !== undefined) {
- return def;
- }
- }
- return null;
-}
-
-var localStoredTheme = getSettingValue("theme");
-
-var savedHref = [];
-
-// eslint-disable-next-line no-unused-vars
-function hasClass(elem, className) {
- return elem && elem.classList && elem.classList.contains(className);
-}
-
-// eslint-disable-next-line no-unused-vars
-function addClass(elem, className) {
- if (!elem || !elem.classList) {
- return;
- }
- elem.classList.add(className);
-}
-
-// eslint-disable-next-line no-unused-vars
-function removeClass(elem, className) {
- if (!elem || !elem.classList) {
- return;
- }
- elem.classList.remove(className);
-}
-
-function onEach(arr, func, reversed) {
- if (arr && arr.length > 0 && func) {
- var length = arr.length;
- var i;
- if (reversed) {
- for (i = length - 1; i >= 0; --i) {
- if (func(arr[i])) {
- return true;
- }
- }
- } else {
- for (i = 0; i < length; ++i) {
- if (func(arr[i])) {
- return true;
- }
- }
- }
- }
- return false;
-}
-
-function onEachLazy(lazyArray, func, reversed) {
- return onEach(
- Array.prototype.slice.call(lazyArray),
- func,
- reversed);
-}
-
-// eslint-disable-next-line no-unused-vars
-function hasOwnPropertyRustdoc(obj, property) {
- return Object.prototype.hasOwnProperty.call(obj, property);
-}
-
-function updateLocalStorage(name, value) {
- try {
- window.localStorage.setItem(name, value);
- } catch(e) {
- // localStorage is not accessible, do nothing
- }
-}
-
-function getCurrentValue(name) {
- try {
- return window.localStorage.getItem(name);
- } catch(e) {
- return null;
- }
-}
-
-function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
- var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
- var fullNewTheme = newTheme + resourcesSuffix + ".css";
- var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
-
- // If this new value comes from a system setting or from the previously
- // saved theme, no need to save it.
- if (saveTheme) {
- updateLocalStorage("rustdoc-theme", newTheme);
- }
-
- if (styleElem.href === newHref) {
- return;
- }
-
- var found = false;
- if (savedHref.length === 0) {
- onEachLazy(document.getElementsByTagName("link"), function(el) {
- savedHref.push(el.href);
- });
- }
- onEach(savedHref, function(el) {
- if (el === newHref) {
- found = true;
- return true;
- }
- });
- if (found) {
- styleElem.href = newHref;
- }
-}
-
-// This function is called from "main.js".
-// eslint-disable-next-line no-unused-vars
-function useSystemTheme(value) {
- if (value === undefined) {
- value = true;
- }
-
- updateLocalStorage("rustdoc-use-system-theme", value);
-
- // update the toggle if we're on the settings page
- var toggle = document.getElementById("use-system-theme");
- if (toggle && toggle instanceof HTMLInputElement) {
- toggle.checked = value;
- }
-}
-
-var updateSystemTheme = (function() {
- if (!window.matchMedia) {
- // fallback to the CSS computed value
- return function() {
- var cssTheme = getComputedStyle(document.documentElement)
- .getPropertyValue('content');
-
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- JSON.parse(cssTheme) || "light",
- true
- );
- };
- }
-
- // only listen to (prefers-color-scheme: dark) because light is the default
- var mql = window.matchMedia("(prefers-color-scheme: dark)");
-
- function handlePreferenceChange(mql) {
- // maybe the user has disabled the setting in the meantime!
- if (getSettingValue("use-system-theme") !== "false") {
- var lightTheme = getSettingValue("preferred-light-theme") || "light";
- var darkTheme = getSettingValue("preferred-dark-theme") || "dark";
-
- if (mql.matches) {
- // prefers a dark theme
- switchTheme(window.currentTheme, window.mainTheme, darkTheme, true);
- } else {
- // prefers a light theme, or has no preference
- switchTheme(window.currentTheme, window.mainTheme, lightTheme, true);
- }
-
- // note: we save the theme so that it doesn't suddenly change when
- // the user disables "use-system-theme" and reloads the page or
- // navigates to another page
- }
- }
-
- mql.addListener(handlePreferenceChange);
-
- return function() {
- handlePreferenceChange(mql);
- };
-})();
-
-if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
- // update the preferred dark theme if the user is already using a dark theme
- // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
- if (getSettingValue("use-system-theme") === null
- && getSettingValue("preferred-dark-theme") === null
- && darkThemes.indexOf(localStoredTheme) >= 0) {
- updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
- }
-
- // call the function to initialize the theme at least once!
- updateSystemTheme();
-} else {
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- getSettingValue("theme") || "light",
- false
- );
-}
+++ /dev/null
-/*
-Based off of the Ayu theme
-Original by Dempfi (https://github.com/dempfi/ayu)
-*/
-
-/* General structure and fonts */
-
-body {
- background-color: #0f1419;
- color: #c5c5c5;
-}
-
-h1, h2, h3, h4 {
- color: white;
-}
-h1.fqn {
- border-bottom-color: #5c6773;
-}
-h1.fqn a {
- color: #fff;
-}
-h2, h3, h4 {
- border-bottom-color: #5c6773;
-}
-h4 {
- border: none;
-}
-
-.in-band {
- background-color: #0f1419;
-}
-
-.invisible {
- background: rgba(0, 0, 0, 0);
-}
-
-code {
- color: #ffb454;
-}
-h3 > code, h4 > code, h5 > code {
- color: #e6e1cf;
-}
-pre > code {
- color: #e6e1cf;
-}
-span code {
- color: #e6e1cf;
-}
-.docblock a > code {
- color: #39AFD7 !important;
-}
-.docblock code, .docblock-short code {
- background-color: #191f26;
-}
-pre, .rustdoc.source .example-wrap {
- color: #e6e1cf;
- background-color: #191f26;
-}
-
-.sidebar {
- background-color: #14191f;
-}
-
-.logo-container.rust-logo > img {
- filter: drop-shadow(1px 0 0px #fff)
- drop-shadow(0 1px 0 #fff)
- drop-shadow(-1px 0 0 #fff)
- drop-shadow(0 -1px 0 #fff);
-}
-
-/* Improve the scrollbar display on firefox */
-* {
- scrollbar-color: #5c6773 transparent;
-}
-
-.sidebar {
- scrollbar-color: #5c6773 transparent;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
- background-color: transparent;
-}
-::-webkit-scrollbar-thumb {
- background-color: #5c6773;
-}
-.sidebar::-webkit-scrollbar-track {
- background-color: transparent;
-}
-.sidebar::-webkit-scrollbar-thumb {
- background-color: #5c6773;
-}
-
-.sidebar .current {
- background-color: transparent;
- color: #ffb44c;
-}
-
-.source .sidebar {
- background-color: #0f1419;
-}
-
-.sidebar .location {
- border-color: #000;
- background-color: #0f1419;
- color: #fff;
-}
-
-.sidebar-elems .location {
- color: #ff7733;
-}
-
-.sidebar-elems .location a {
- color: #fff;
-}
-
-.sidebar .version {
- border-bottom-color: #424c57;
-}
-
-.sidebar-title {
- border-top-color: #5c6773;
- border-bottom-color: #5c6773;
-}
-
-.block a:hover {
- background: transparent;
- color: #ffb44c;
-}
-
-.line-numbers span { color: #5c6773; }
-.line-numbers .line-highlighted {
- color: #708090;
- background-color: rgba(255, 236, 164, 0.06);
- padding-right: 4px;
- border-right: 1px solid #ffb44c;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
- border-bottom-color: #5c6773;
-}
-
-.docblock table, .docblock table td, .docblock table th {
- border-color: #5c6773;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
- color: #c5c5c5;
-}
-
-.search-results a:hover {
- background-color: #777;
-}
-
-.search-results a:focus {
- color: #000 !important;
- background-color: #c6afb3;
-}
-.search-results a {
- color: #0096cf;
-}
-.search-results a span.desc {
- color: #c5c5c5;
-}
-
-.content .item-info::before { color: #ccc; }
-
-.content span.foreigntype, .content a.foreigntype { color: #ef57ff; }
-.content span.union, .content a.union { color: #98a01c; }
-.content span.constant, .content a.constant,
-.content span.static, .content a.static { color: #6380a0; }
-.content span.primitive, .content a.primitive { color: #32889b; }
-.content span.traitalias, .content a.traitalias { color: #57d399; }
-.content span.keyword, .content a.keyword { color: #de5249; }
-
-.content span.externcrate, .content span.mod, .content a.mod {
- color: #acccf9;
-}
-.content span.struct, .content a.struct {
- color: #ffa0a5;
-}
-.content span.enum, .content a.enum {
- color: #99e0c9;
-}
-.content span.trait, .content a.trait {
- color: #39AFD7;
-}
-.content span.type, .content a.type {
- color: #cfbcf5;
-}
-.content span.fn, .content a.fn, .content span.method,
-.content a.method, .content span.tymethod,
-.content a.tymethod, .content .fnname {
- color: #fdd687;
-}
-.content span.attr, .content a.attr, .content span.derive,
-.content a.derive, .content span.macro, .content a.macro {
- color: #a37acc;
-}
-
-pre.rust .comment { color: #788797; }
-pre.rust .doccomment { color: #a1ac88; }
-
-nav:not(.sidebar) {
- border-bottom-color: #424c57;
-}
-nav.main .current {
- border-top-color: #5c6773;
- border-bottom-color: #5c6773;
-}
-nav.main .separator {
- border: 1px solid #5c6773;
-}
-a {
- color: #c5c5c5;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
- color: #39AFD7;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
- color: #999;
-}
-
-#crate-search {
- color: #c5c5c5;
- background-color: #141920;
- box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
- border-color: #424c57;
-}
-
-.search-input {
- color: #ffffff;
- background-color: #141920;
- box-shadow: 0 0 0 1px #424c57,0 0 0 2px transparent;
- transition: box-shadow 150ms ease-in-out;
-}
-
-#crate-search+.search-input:focus {
- box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
-}
-
-.search-input:disabled {
- background-color: #3e3e3e;
-}
-
-.module-item .stab,
-.import-item .stab {
- color: #000;
-}
-
-.stab.unstable,
-.stab.deprecated,
-.stab.portability {
- color: #c5c5c5;
- background: #314559 !important;
- border-style: none !important;
- border-radius: 4px;
- padding: 3px 6px 3px 6px;
-}
-
-.stab.portability > code {
- color: #e6e1cf;
- background: none;
-}
-
-#help > div {
- background: #14191f;
- box-shadow: 0px 6px 20px 0px black;
- border: none;
- border-radius: 4px;
-}
-
-#help > div > span {
- border-bottom-color: #5c6773;
-}
-
-.since {
- color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
- color: #788797;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .number, pre.rust .string { color: #b8cc52; }
-pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
-pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .op, pre.rust .lifetime { color: #ff7733; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-pre.rust .self {
- color: #36a3d9;
- font-style: italic;
-}
-pre.rust .attribute {
- color: #e6e1cf;
-}
-pre.rust .attribute .ident, pre.rust .attribute .op {
- color: #e6e1cf;
-}
-
-.example-wrap > pre.line-number {
- color: #5c67736e;
- border: none;
-}
-
-a.test-arrow {
- font-size: 100%;
- color: #788797;
- border-radius: 4px;
- background-color: rgba(57, 175, 215, 0.09);
-}
-
-a.test-arrow:hover {
- background-color: rgba(57, 175, 215, 0.368);
- color: #c5c5c5;
-}
-
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
-:target, :target * {
- background: rgba(255, 236, 164, 0.06);
-}
-
-:target {
- border-right: 3px solid rgba(255, 180, 76, 0.85);
-}
-
-pre.compile_fail {
- border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
- border-left: 2px solid #f00;
-}
-
-pre.should_panic {
- border-left: 2px solid rgba(255,0,0,.4);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
- border-left: 2px solid #f00;
-}
-
-pre.ignore {
- border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
- border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
- color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
- color: #f00;
-}
-
-.tooltip.should_panic {
- color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
- color: #f00;
-}
-
-.tooltip.ignore {
- color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
- color: #ff9200;
-}
-
-.search-failed a {
- color: #39AFD7;
-}
-
-.tooltip::after {
- background-color: #314559;
- color: #c5c5c5;
- border: 1px solid #5c6773;
-}
-
-.tooltip::before {
- border-color: transparent #314559 transparent transparent;
-}
-
-.notable-traits-tooltiptext {
- background-color: #314559;
- border-color: #5c6773;
-}
-
-.notable-traits-tooltiptext .notable {
- border-bottom-color: #5c6773;
-}
-
-#titles > button.selected {
- background-color: #141920 !important;
- border-bottom: 1px solid #ffb44c !important;
- border-top: none;
-}
-
-#titles > button:not(.selected) {
- background-color: transparent !important;
- border: none;
-}
-
-#titles > button:hover {
- border-bottom: 1px solid rgba(242, 151, 24, 0.3);
-}
-
-#titles > button > div.count {
- color: #888;
-}
-
-/* rules that this theme does not need to set, here to satisfy the rule checker */
-/* note that a lot of these are partially set in some way (meaning they are set
-individually rather than as a group) */
-/* FIXME: these rules should be at the bottom of the file but currently must be
-above the `@media (max-width: 700px)` rules due to a bug in the css checker */
-/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-.search-input:focus {}
-.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,
-.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
-.content span.struct,.content a.struct,.block a.current.struct {}
-#titles>button:hover,#titles>button.selected {}
-.content span.type,.content a.type,.block a.current.type {}
-.content span.union,.content a.union,.block a.current.union {}
-pre.rust .lifetime {}
-.stab.unstable {}
-h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {}
-.content span.enum,.content a.enum,.block a.current.enum {}
-.content span.constant,.content a.constant,.block a.current.constant,.content span.static,
-.content a.static, .block a.current.static {}
-.content span.keyword,.content a.keyword,.block a.current.keyword {}
-pre.rust .comment {}
-.content span.traitalias,.content a.traitalias,.block a.current.traitalias {}
-.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,
-.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,
-.content .fnname {}
-pre.rust .kw {}
-pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,
-pre.rust .attribute .ident {}
-.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {}
-pre.rust .doccomment {}
-.stab.deprecated {}
-.content a.attr,.content a.derive,.content a.macro {}
-.stab.portability {}
-.content span.primitive,.content a.primitive,.block a.current.primitive {}
-.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod {}
-pre.rust .kw-2,pre.rust .prelude-ty {}
-.content span.trait,.content a.trait,.block a.current.trait {}
-
-.search-results a:focus span {}
-a.result-trait:focus {}
-a.result-traitalias:focus {}
-a.result-mod:focus,
-a.result-externcrate:focus {}
-a.result-mod:focus {}
-a.result-externcrate:focus {}
-a.result-enum:focus {}
-a.result-struct:focus {}
-a.result-union:focus {}
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus {}
-a.result-type:focus {}
-a.result-foreigntype:focus {}
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus {}
-a.result-constant:focus,
-a.result-static:focus {}
-a.result-primitive:focus {}
-a.result-keyword:focus {}
-
-@media (max-width: 700px) {
- .sidebar-menu {
- background-color: #14191f;
- border-bottom-color: #5c6773;
- border-right-color: #5c6773;
- }
-
- .sidebar-elems {
- background-color: #14191f;
- border-right-color: #5c6773;
- }
-
- #sidebar-filler {
- background-color: #14191f;
- border-bottom-color: #5c6773;
- }
-}
-
-kbd {
- color: #c5c5c5;
- background-color: #314559;
- border-color: #5c6773;
- border-bottom-color: #5c6773;
- box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
- border-color: #5c6773;
- background-color: #0f1419;
- color: #fff;
-}
-
-#theme-picker > img, #settings-menu > img {
- filter: invert(100);
-}
-
-#copy-path {
- color: #fff;
-}
-#copy-path > img {
- filter: invert(70%);
-}
-#copy-path:hover > img {
- filter: invert(100%);
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
- border-color: #e0e0e0;
-}
-
-#theme-choices {
- border-color: #5c6773;
- background-color: #0f1419;
-}
-
-#theme-choices > button:not(:first-child) {
- border-top-color: #5c6773;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
- background-color: rgba(110, 110, 110, 0.33);
-}
-
-@media (max-width: 700px) {
- #theme-picker {
- background: #0f1419;
- }
-}
-
-#all-types {
- background-color: #14191f;
-}
-#all-types:hover {
- background-color: rgba(70, 70, 70, 0.33);
-}
-
-.search-results .result-name span.alias {
- color: #c5c5c5;
-}
-.search-results .result-name span.grey {
- color: #999;
-}
-
-#sidebar-toggle {
- background-color: #14191f;
-}
-#sidebar-toggle:hover {
- background-color: rgba(70, 70, 70, 0.33);
-}
-#source-sidebar {
- background-color: #14191f;
-}
-#source-sidebar > .title {
- color: #fff;
- border-bottom-color: #5c6773;
-}
-div.files > a:hover, div.name:hover {
- background-color: #14191f;
- color: #ffb44c;
-}
-div.files > .selected {
- background-color: #14191f;
- color: #ffb44c;
-}
-.setting-line > .title {
- border-bottom-color: #5c6773;
-}
-input:checked + .slider {
- background-color: #ffb454 !important;
-}
+++ /dev/null
-body {
- background-color: #353535;
- color: #ddd;
-}
-
-h1, h2, h3, h4 {
- color: #ddd;
-}
-h1.fqn {
- border-bottom-color: #d2d2d2;
-}
-h2, h3, h4 {
- border-bottom-color: #d2d2d2;
-}
-
-.in-band {
- background-color: #353535;
-}
-
-.invisible {
- background: rgba(0, 0, 0, 0);
-}
-
-.docblock code, .docblock-short code {
- background-color: #2A2A2A;
-}
-pre, .rustdoc.source .example-wrap {
- background-color: #2A2A2A;
-}
-
-.sidebar {
- background-color: #505050;
-}
-
-.logo-container.rust-logo > img {
- filter: drop-shadow(1px 0 0px #fff)
- drop-shadow(0 1px 0 #fff)
- drop-shadow(-1px 0 0 #fff)
- drop-shadow(0 -1px 0 #fff)
-}
-
-/* Improve the scrollbar display on firefox */
-* {
- scrollbar-color: rgb(64, 65, 67) #717171;
-}
-.sidebar {
- scrollbar-color: rgba(32,34,37,.6) transparent;
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
- background-color: #717171;
-}
-::-webkit-scrollbar-thumb {
- background-color: rgba(32, 34, 37, .6);
-}
-.sidebar::-webkit-scrollbar-track {
- background-color: #717171;
-}
-.sidebar::-webkit-scrollbar-thumb {
- background-color: rgba(32, 34, 37, .6);
-}
-
-.sidebar .current {
- background-color: #333;
-}
-
-.source .sidebar {
- background-color: #353535;
-}
-
-.sidebar .location {
- border-color: #fff;
- background: #575757;
- color: #DDD;
-}
-
-.sidebar .version {
- border-bottom-color: #DDD;
-}
-
-.sidebar-title {
- border-top-color: #777;
- border-bottom-color: #777;
-}
-
-.block a:hover {
- background: #444;
-}
-
-.line-numbers span { color: #3B91E2; }
-.line-numbers .line-highlighted {
- background-color: #0a042f !important;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
- border-bottom-color: #DDD;
-}
-
-.docblock table, .docblock table td, .docblock table th {
- border-color: #ddd;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
- color: #ddd;
-}
-
-.search-results a:hover {
- background-color: #777;
-}
-
-.search-results a:focus {
- color: #eee !important;
- background-color: #616161;
-}
-.search-results a:focus span { color: #eee !important; }
-a.result-trait:focus { background-color: #013191; }
-a.result-traitalias:focus { background-color: #013191; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #afc6e4; }
-a.result-mod:focus { background-color: #803a1b; }
-a.result-externcrate:focus { background-color: #396bac; }
-a.result-enum:focus { background-color: #5b4e68; }
-a.result-struct:focus { background-color: #194e9f; }
-a.result-union:focus { background-color: #b7bd49; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #4950ed; }
-a.result-type:focus { background-color: #38902c; }
-a.result-foreigntype:focus { background-color: #b200d6; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #217d1c; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #0063cc; }
-a.result-primitive:focus { background-color: #00708a; }
-a.result-keyword:focus { background-color: #884719; }
-
-.content .item-info::before { color: #ccc; }
-
-.content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
-.content span.type, .content a.type, .block a.current.type { color: #ff7f00; }
-.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #dd7de8; }
-.content span.attr, .content a.attr, .block a.current.attr,
-.content span.derive, .content a.derive, .block a.current.derive,
-.content span.macro, .content a.macro, .block a.current.macro { color: #09bd00; }
-.content span.union, .content a.union, .block a.current.union { color: #a6ae37; }
-.content span.constant, .content a.constant, .block a.current.constant,
-.content span.static, .content a.static, .block a.current.static { color: #82a5c9; }
-.content span.primitive, .content a.primitive, .block a.current.primitive { color: #43aec7; }
-.content span.externcrate,
-.content span.mod, .content a.mod, .block a.current.mod { color: #bda000; }
-.content span.trait, .content a.trait, .block a.current.trait { color: #b78cf2; }
-.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #b397da; }
-.content span.fn, .content a.fn, .block a.current.fn,
-.content span.method, .content a.method, .block a.current.method,
-.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
-.content .fnname{ color: #2BAB63; }
-.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
-
-pre.rust .comment { color: #8d8d8b; }
-pre.rust .doccomment { color: #8ca375; }
-
-nav:not(.sidebar) {
- border-bottom-color: #4e4e4e;
-}
-nav.main .current {
- border-top-color: #eee;
- border-bottom-color: #eee;
-}
-nav.main .separator {
- border-color: #eee;
-}
-a {
- color: #ddd;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
- color: #D2991D;
-}
-
-a.test-arrow {
- color: #dedede;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
- color: #999;
-}
-
-#crate-search {
- color: #111;
- background-color: #f0f0f0;
- border-color: #000;
- box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
-}
-
-.search-input {
- color: #111;
- background-color: #f0f0f0;
- box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
-}
-
-.search-input:focus {
- border-color: #008dfd;
-}
-
-.search-input:disabled {
- background-color: #c5c4c4;
-}
-
-#crate-search + .search-input:focus {
- box-shadow: 0 0 8px 4px #078dd8;
-}
-
-.module-item .stab,
-.import-item .stab {
- color: #ddd;
-}
-
-.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
-.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
-.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
-.stab.portability > code { background: none; }
-
-#help > div {
- background: #4d4d4d;
- border-color: #bfbfbf;
-}
-
-#help > div > span {
- border-bottom-color: #bfbfbf;
-}
-
-#help dt {
- border-color: #bfbfbf;
- background: rgba(0,0,0,0);
-}
-
-.since {
- color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
- color: #ddd;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #ab8ac1; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
-pre.rust .number, pre.rust .string { color: #83a300; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #ee6868; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #d97f26; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
- border-color: #4a4949;
-}
-
-a.test-arrow {
- background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
- background-color: #4e8bca;
-}
-
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
-:target, :target * {
- background-color: #494a3d;
-}
-
-:target {
- border-right: 3px solid #bb7410;
-}
-
-pre.compile_fail {
- border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
- border-left: 2px solid #f00;
-}
-
-pre.should_panic {
- border-left: 2px solid rgba(255,0,0,.8);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
- border-left: 2px solid #f00;
-}
-
-pre.ignore {
- border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
- border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
- color: rgba(255,0,0,.8);
-}
-
-.information > .compile_fail:hover {
- color: #f00;
-}
-
-.tooltip.should_panic {
- color: rgba(255,0,0,.8);
-}
-
-.information > .should_panic:hover {
- color: #f00;
-}
-
-.tooltip.ignore {
- color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
- color: #ff9200;
-}
-
-.search-failed a {
- color: #0089ff;
-}
-
-.tooltip::after {
- background-color: #000;
- color: #fff;
- border-color: #000;
-}
-
-.tooltip::before {
- border-color: transparent black transparent transparent;
-}
-
-.notable-traits-tooltiptext {
- background-color: #111;
- border-color: #777;
-}
-
-.notable-traits-tooltiptext .notable {
- border-bottom-color: #d2d2d2;
-}
-
-#titles > button:not(.selected) {
- background-color: #252525;
- border-top-color: #252525;
-}
-
-#titles > button:hover, #titles > button.selected {
- border-top-color: #0089ff;
- background-color: #353535;
-}
-
-#titles > button > div.count {
- color: #888;
-}
-
-@media (max-width: 700px) {
- .sidebar-menu {
- background-color: #505050;
- border-bottom-color: #e0e0e0;
- border-right-color: #e0e0e0;
- }
-
- .sidebar-elems {
- background-color: #505050;
- border-right-color: #000;
- }
-
- #sidebar-filler {
- background-color: #505050;
- border-bottom-color: #e0e0e0;
- }
-}
-
-kbd {
- color: #000;
- background-color: #fafbfc;
- border-color: #d1d5da;
- border-bottom-color: #c6cbd1;
- box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
- border-color: #e0e0e0;
- background: #f0f0f0;
- color: #000;
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
- border-color: #ffb900;
-}
-
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(65%);
-}
-
-#theme-choices {
- border-color: #e0e0e0;
- background-color: #353535;
-}
-
-#theme-choices > button:not(:first-child) {
- border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
- background-color: #4e4e4e;
-}
-
-@media (max-width: 700px) {
- #theme-picker {
- background: #f0f0f0;
- }
-}
-
-#all-types {
- background-color: #505050;
-}
-#all-types:hover {
- background-color: #606060;
-}
-
-.search-results .result-name span.alias {
- color: #fff;
-}
-.search-results .result-name span.grey {
- color: #ccc;
-}
-
-#sidebar-toggle {
- background-color: #565656;
-}
-#sidebar-toggle:hover {
- background-color: #676767;
-}
-#source-sidebar {
- background-color: #565656;
-}
-#source-sidebar > .title {
- border-bottom-color: #ccc;
-}
-div.files > a:hover, div.name:hover {
- background-color: #444;
-}
-div.files > .selected {
- background-color: #333;
-}
-.setting-line > .title {
- border-bottom-color: #ddd;
-}
+++ /dev/null
-/* General structure and fonts */
-
-body {
- background-color: white;
- color: black;
-}
-
-h1, h2, h3, h4 {
- color: black;
-}
-h1.fqn {
- border-bottom-color: #D5D5D5;
-}
-h2, h3, h4 {
- border-bottom-color: #DDDDDD;
-}
-
-.in-band {
- background-color: white;
-}
-
-.invisible {
- background: rgba(0, 0, 0, 0);
-}
-
-.docblock code, .docblock-short code {
- background-color: #F5F5F5;
-}
-pre, .rustdoc.source .example-wrap {
- background-color: #F5F5F5;
-}
-
-.sidebar {
- background-color: #F1F1F1;
-}
-
-/* Improve the scrollbar display on firefox */
-* {
- scrollbar-color: rgba(36, 37, 39, 0.6) #e6e6e6;
-}
-
-.sidebar {
- scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
-}
-
-.logo-container.rust-logo > img {
- /* No need for a border in here! */
-}
-
-/* Improve the scrollbar display on webkit-based browsers */
-::-webkit-scrollbar-track {
- background-color: #ecebeb;
-}
-::-webkit-scrollbar-thumb {
- background-color: rgba(36, 37, 39, 0.6);
-}
-.sidebar::-webkit-scrollbar-track {
- background-color: #dcdcdc;
-}
-.sidebar::-webkit-scrollbar-thumb {
- background-color: rgba(36, 37, 39, 0.6);
-}
-
-.sidebar .current {
- background-color: #fff;
-}
-
-.source .sidebar {
- background-color: #fff;
-}
-
-.sidebar .location {
- border-color: #000;
- background-color: #fff;
- color: #333;
-}
-
-.sidebar .version {
- border-bottom-color: #DDD;
-}
-
-.sidebar-title {
- border-top-color: #777;
- border-bottom-color: #777;
-}
-
-.block a:hover {
- background: #F5F5F5;
-}
-
-.line-numbers span { color: #c67e2d; }
-.line-numbers .line-highlighted {
- background-color: #f6fdb0 !important;
-}
-
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
- border-bottom-color: #ddd;
-}
-
-.docblock table, .docblock table td, .docblock table th {
- border-color: #ddd;
-}
-
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
- color: #4E4C4C;
-}
-
-.search-results a:hover {
- background-color: #ddd;
-}
-
-.search-results a:focus {
- color: #000 !important;
- background-color: #ccc;
-}
-.search-results a:focus span { color: #000 !important; }
-a.result-trait:focus { background-color: #c7b6ff; }
-a.result-traitalias:focus { background-color: #c7b6ff; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #afc6e4; }
-a.result-enum:focus { background-color: #b4d1b9; }
-a.result-struct:focus { background-color: #e7b1a0; }
-a.result-union:focus { background-color: #b7bd49; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #c6afb3; }
-a.result-type:focus { background-color: #ffc891; }
-a.result-foreigntype:focus { background-color: #f5c4ff; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #8ce488; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #c3e0ff; }
-a.result-primitive:focus { background-color: #9aecff; }
-a.result-keyword:focus { background-color: #f99650; }
-
-.content .item-info::before { color: #ccc; }
-
-.content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
-.content span.type, .content a.type, .block a.current.type { color: #ba5d00; }
-.content span.foreigntype, .content a.foreigntype, .block a.current.foreigntype { color: #cd00e2; }
-.content span.attr, .content a.attr, .block a.current.attr,
-.content span.derive, .content a.derive, .block a.current.derive,
-.content span.macro, .content a.macro, .block a.current.macro { color: #068000; }
-.content span.union, .content a.union, .block a.current.union { color: #767b27; }
-.content span.constant, .content a.constant, .block a.current.constant,
-.content span.static, .content a.static, .block a.current.static { color: #546e8a; }
-.content span.primitive, .content a.primitive, .block a.current.primitive { color: #2c8093; }
-.content span.externcrate,
-.content span.mod, .content a.mod, .block a.current.mod { color: #4d76ae; }
-.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
-.content span.traitalias, .content a.traitalias, .block a.current.traitalias { color: #6841f1; }
-.content span.fn, .content a.fn, .block a.current.fn,
-.content span.method, .content a.method, .block a.current.method,
-.content span.tymethod, .content a.tymethod, .block a.current.tymethod,
-.content .fnname { color: #9a6e31; }
-.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
-
-nav:not(.sidebar) {
- border-bottom-color: #e0e0e0;
-}
-nav.main .current {
- border-top-color: #000;
- border-bottom-color: #000;
-}
-nav.main .separator {
- border: 1px solid #000;
-}
-a {
- color: #000;
-}
-
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
-.docblock-short a:not(.srclink):not(.test-arrow), .item-info a,
-#help a {
- color: #3873AD;
-}
-
-a.test-arrow {
- color: #f5f5f5;
-}
-
-details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
-details.undocumented > summary::before {
- color: #999;
-}
-
-#crate-search {
- color: #555;
- background-color: white;
- border-color: #e0e0e0;
- box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-}
-
-.search-input {
- color: #555;
- background-color: white;
- box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-}
-
-.search-input:focus {
- border-color: #66afe9;
-}
-
-.search-input:disabled {
- background-color: #e6e6e6;
-}
-
-#crate-search + .search-input:focus {
- box-shadow: 0 0 8px #078dd8;
-}
-
-.module-item .stab,
-.import-item .stab {
- color: #000;
-}
-
-.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
-.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
-.stab.portability > code { background: none; }
-
-#help > div {
- background: #e9e9e9;
- border-color: #bfbfbf;
-}
-
-#help > div > span {
- border-bottom-color: #bfbfbf;
-}
-
-.since {
- color: grey;
-}
-
-tr.result span.primitive::after, tr.result span.keyword::after {
- color: black;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #8959A8; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
-pre.rust .number, pre.rust .string { color: #718C00; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
-pre.rust .comment { color: #8E908C; }
-pre.rust .doccomment { color: #4D4D4C; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #B76514; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
- border-color: #c7c7c7;
-}
-
-a.test-arrow {
- background-color: rgba(78, 139, 202, 0.2);
-}
-
-a.test-arrow:hover{
- background-color: #4e8bca;
-}
-
-.toggle-label,
-.code-attribute {
- color: #999;
-}
-
-:target, :target * {
- background: #FDFFD3;
-}
-
-:target {
- border-right: 3px solid #ffb44c;
-}
-
-pre.compile_fail {
- border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.compile_fail:hover, .information:hover + pre.compile_fail {
- border-left: 2px solid #f00;
-}
-
-pre.should_panic {
- border-left: 2px solid rgba(255,0,0,.5);
-}
-
-pre.should_panic:hover, .information:hover + pre.should_panic {
- border-left: 2px solid #f00;
-}
-
-pre.ignore {
- border-left: 2px solid rgba(255,142,0,.6);
-}
-
-pre.ignore:hover, .information:hover + pre.ignore {
- border-left: 2px solid #ff9200;
-}
-
-.tooltip.compile_fail {
- color: rgba(255,0,0,.5);
-}
-
-.information > .compile_fail:hover {
- color: #f00;
-}
-
-.tooltip.should_panic {
- color: rgba(255,0,0,.5);
-}
-
-.information > .should_panic:hover {
- color: #f00;
-}
-
-.tooltip.ignore {
- color: rgba(255,142,0,.6);
-}
-
-.information > .ignore:hover {
- color: #ff9200;
-}
-
-.search-failed a {
- color: #0089ff;
-}
-
-.tooltip::after {
- background-color: #000;
- color: #fff;
-}
-
-.tooltip::before {
- border-color: transparent black transparent transparent;
-}
-
-.notable-traits-tooltiptext {
- background-color: #eee;
- border-color: #999;
-}
-
-.notable-traits-tooltiptext .notable {
- border-bottom-color: #DDDDDD;
-}
-
-#titles > button:not(.selected) {
- background-color: #e6e6e6;
- border-top-color: #e6e6e6;
-}
-
-#titles > button:hover, #titles > button.selected {
- background-color: #ffffff;
- border-top-color: #0089ff;
-}
-
-#titles > button > div.count {
- color: #888;
-}
-
-@media (max-width: 700px) {
- .sidebar-menu {
- background-color: #F1F1F1;
- border-bottom-color: #e0e0e0;
- border-right-color: #e0e0e0;
- }
-
- .sidebar-elems {
- background-color: #F1F1F1;
- border-right-color: #000;
- }
-
- #sidebar-filler {
- background-color: #F1F1F1;
- border-bottom-color: #e0e0e0;
- }
-}
-
-kbd {
- color: #000;
- background-color: #fafbfc;
- border-color: #d1d5da;
- border-bottom-color: #c6cbd1;
- box-shadow-color: #c6cbd1;
-}
-
-#theme-picker, #settings-menu, #help-button {
- border-color: #e0e0e0;
- background-color: #fff;
-}
-
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
-#help-button:hover, #help-button:focus {
- border-color: #717171;
-}
-
-#copy-path {
- color: #999;
-}
-#copy-path > img {
- filter: invert(50%);
-}
-#copy-path:hover > img {
- filter: invert(35%);
-}
-
-#theme-choices {
- border-color: #ccc;
- background-color: #fff;
-}
-
-#theme-choices > button:not(:first-child) {
- border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
- background-color: #eee;
-}
-
-@media (max-width: 700px) {
- #theme-picker {
- background: #fff;
- }
-}
-
-#all-types {
- background-color: #fff;
-}
-#all-types:hover {
- background-color: #f9f9f9;
-}
-
-.search-results .result-name span.alias {
- color: #000;
-}
-.search-results .result-name span.grey {
- color: #999;
-}
-
-#sidebar-toggle {
- background-color: #F1F1F1;
-}
-#sidebar-toggle:hover {
- background-color: #E0E0E0;
-}
-#source-sidebar {
- background-color: #F1F1F1;
-}
-#source-sidebar > .title {
- border-bottom-color: #ccc;
-}
-div.files > a:hover, div.name:hover {
- background-color: #E0E0E0;
-}
-div.files > .selected {
- background-color: #fff;
-}
-.setting-line > .title {
- border-bottom-color: #D5D5D5;
-}
+++ /dev/null
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
//! directly written to a `Write` handle.
/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
-crate static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css");
+crate static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css");
/// The file contents of `settings.css`, responsible for the items on the settings page.
-crate static SETTINGS_CSS: &str = include_str!("static/settings.css");
+crate static SETTINGS_CSS: &str = include_str!("static/css/settings.css");
/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
-crate static NOSCRIPT_CSS: &str = include_str!("static/noscript.css");
+crate static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css");
/// The file contents of `normalize.css`, included to even out standard elements between browser
/// implementations.
-crate static NORMALIZE_CSS: &str = include_str!("static/normalize.css");
+crate static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css");
/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
/// including search behavior and docblock folding, among others.
-crate static MAIN_JS: &str = include_str!("static/main.js");
+crate static MAIN_JS: &str = include_str!("static/js/main.js");
/// The file contents of `search.js`, which contains the search behavior.
-crate static SEARCH_JS: &str = include_str!("static/search.js");
+crate static SEARCH_JS: &str = include_str!("static/js/search.js");
/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
/// page.
-crate static SETTINGS_JS: &str = include_str!("static/settings.js");
+crate static SETTINGS_JS: &str = include_str!("static/js/settings.js");
/// The file contents of `storage.js`, which contains functionality related to browser Local
/// Storage, used to store documentation settings.
-crate static STORAGE_JS: &str = include_str!("static/storage.js");
+crate static STORAGE_JS: &str = include_str!("static/js/storage.js");
/// The file contents of `brush.svg`, the icon used for the theme-switch button.
-crate static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg");
+crate static BRUSH_SVG: &[u8] = include_bytes!("static/images/brush.svg");
/// The file contents of `wheel.svg`, the icon used for the settings button.
-crate static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg");
+crate static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg");
/// The file contents of `clipboard.svg`, the icon used for the "copy path" button.
-crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/clipboard.svg");
+crate static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg");
/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
-crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg");
+crate static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg");
/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
/// output.
crate static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
/// The contents of `rust-logo.png`, the default icon of the documentation.
-crate static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png");
+crate static RUST_LOGO: &[u8] = include_bytes!("static/images/rust-logo.png");
/// The default documentation favicons (SVG and PNG fallbacks)
-crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/favicon.svg");
-crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
-crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");
+crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg");
+crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png");
+crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png");
crate static PAGE: &str = include_str!("templates/page.html");
crate mod themes {
/// The "light" theme, selected by default when no setting is available. Used as the basis for
/// the `--check-theme` functionality.
- crate static LIGHT: &str = include_str!("static/themes/light.css");
+ crate static LIGHT: &str = include_str!("static/css/themes/light.css");
/// The "dark" theme.
- crate static DARK: &str = include_str!("static/themes/dark.css");
+ crate static DARK: &str = include_str!("static/css/themes/dark.css");
/// The "ayu" theme.
- crate static AYU: &str = include_str!("static/themes/ayu.css");
+ crate static AYU: &str = include_str!("static/css/themes/ayu.css");
}
/// Files related to the Fira Sans font.
crate mod fira_sans {
/// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
- crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff");
+ crate static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff");
/// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
- crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2");
+ crate static REGULAR2: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2");
/// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
- crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff");
+ crate static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff");
/// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
- crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2");
+ crate static MEDIUM2: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2");
/// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
- crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt");
+ crate static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt");
}
/// Files related to the Source Serif 4 font.
crate mod source_serif_4 {
/// The file `SourceSerif4-Regular.ttf.woff`, the Regular variant of the Source Serif 4 font.
- crate static REGULAR: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff");
+ crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff");
/// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in
/// woff2.
- crate static REGULAR2: &[u8] = include_bytes!("static/SourceSerif4-Regular.ttf.woff2");
+ crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2");
/// The file `SourceSerif4-Bold.ttf.woff`, the Bold variant of the Source Serif 4 font.
- crate static BOLD: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff");
+ crate static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff");
/// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in
/// woff2.
- crate static BOLD2: &[u8] = include_bytes!("static/SourceSerif4-Bold.ttf.woff2");
+ crate static BOLD2: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2");
/// The file `SourceSerif4-It.ttf.woff`, the Italic variant of the Source Serif 4 font.
- crate static ITALIC: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff");
+ crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff");
/// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in
/// woff2.
- crate static ITALIC2: &[u8] = include_bytes!("static/SourceSerif4-It.ttf.woff2");
+ crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2");
/// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
- crate static LICENSE: &[u8] = include_bytes!("static/SourceSerif4-LICENSE.md");
+ crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md");
}
/// Files related to the Source Code Pro font.
crate mod source_code_pro {
/// The file `SourceCodePro-Regular.ttf.woff`, the Regular variant of the Source Code Pro font.
- crate static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff");
+ crate static REGULAR: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff");
/// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font
/// in woff2.
- crate static REGULAR2: &[u8] = include_bytes!("static/SourceCodePro-Regular.ttf.woff2");
+ crate static REGULAR2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2");
/// The file `SourceCodePro-Semibold.ttf.woff`, the Semibold variant of the Source Code Pro
/// font.
- crate static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff");
+ crate static SEMIBOLD: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff");
/// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro
/// font in woff2.
- crate static SEMIBOLD2: &[u8] = include_bytes!("static/SourceCodePro-Semibold.ttf.woff2");
+ crate static SEMIBOLD2: &[u8] = include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2");
/// The file `SourceCodePro-It.ttf.woff`, the Italic variant of the Source Code Pro font.
- crate static ITALIC: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff");
+ crate static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff");
/// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in
/// woff2.
- crate static ITALIC2: &[u8] = include_bytes!("static/SourceCodePro-It.ttf.woff2");
+ crate static ITALIC2: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2");
/// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
- crate static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
+ crate static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt");
}
crate mod noto_sans_kr {
/// The file `noto-sans-kr-v13-korean-regular.woff`, the Regular variant of the Noto Sans KR
/// font.
- crate static REGULAR: &[u8] = include_bytes!("static/noto-sans-kr-v13-korean-regular.woff");
+ crate static REGULAR: &[u8] =
+ include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular.woff");
/// The file `noto-sans-kr-v13-korean-regular-LICENSE.txt`, the license text of the Noto Sans KR
/// font.
crate static LICENSE: &[u8] =
- include_bytes!("static/noto-sans-kr-v13-korean-regular-LICENSE.txt");
+ include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt");
}
/// Files related to the sidebar in rustdoc sources.
crate mod sidebar {
/// File script to handle sidebar.
- crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
+ crate static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js");
}
#![allow(rustc::default_hash_types)]
use std::convert::From;
+use std::fmt;
use rustc_ast::ast;
-use rustc_hir::def::CtorKind;
+use rustc_hir::{def::CtorKind, def_id::DefId};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::Pos;
use rustdoc_json_types::*;
use crate::clean::utils::print_const_expr;
-use crate::clean::{self, FakeDefId};
+use crate::clean::{self, ItemId};
use crate::formats::item_type::ItemType;
use crate::json::JsonRenderer;
use std::collections::HashSet;
.into_iter()
.flatten()
.filter_map(|clean::ItemLink { link, did, .. }| {
- did.map(|did| (link.clone(), from_def_id(did.into())))
+ did.map(|did| (link.clone(), from_item_id(did.into())))
})
.collect();
let docs = item.attrs.collapsed_doc_value();
_ => from_clean_item(item, self.tcx),
};
Some(Item {
- id: from_def_id(def_id),
+ id: from_item_id(def_id),
crate_id: def_id.krate().as_u32(),
name: name.map(|sym| sym.to_string()),
span: self.convert_span(span),
Inherited => Visibility::Default,
Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
Restricted(did) => Visibility::Restricted {
- parent: from_def_id(did.into()),
+ parent: from_item_id(did.into()),
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
},
}
}
}
-crate fn from_def_id(did: FakeDefId) -> Id {
+crate fn from_item_id(did: ItemId) -> Id {
+ struct DisplayDefId(DefId);
+
+ impl fmt::Display for DisplayDefId {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index))
+ }
+ }
+
match did {
- FakeDefId::Real(did) => Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))),
- // We need to differentiate real and fake ids, because the indices might overlap for fake
- // and real DefId's, which would cause two different Id's treated as they were the same.
- FakeDefId::Fake(idx, krate) => Id(format!("F{}:{}", krate.as_u32(), u32::from(idx))),
+ ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
+ ItemId::Blanket { for_, impl_id } => {
+ Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
+ }
+ ItemId::Auto { for_, trait_ } => {
+ Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_)))
+ }
+ ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
}
}
match ty {
ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath {
name: path.whole_name(),
- id: from_def_id(did.into()),
+ id: from_item_id(did.into()),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
param_names: Vec::new(),
},
Type::ResolvedPath {
name: path.whole_name(),
- id: from_def_id(id.into()),
+ id: from_item_id(id.into()),
args: path
.segments
.last()
Simple(s) => Import {
source: import.source.path.whole_name(),
name: s.to_string(),
- id: import.source.did.map(FakeDefId::from).map(from_def_id),
+ id: import.source.did.map(ItemId::from).map(from_item_id),
glob: false,
},
Glob => Import {
source: import.source.path.whole_name(),
name: import.source.path.last_name().to_string(),
- id: import.source.did.map(FakeDefId::from).map(from_def_id),
+ id: import.source.did.map(ItemId::from).map(from_item_id),
glob: true,
},
}
}
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
- items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect()
+ items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
}
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
-use crate::json::conversions::{from_def_id, IntoWithTcx};
+use crate::json::conversions::{from_item_id, IntoWithTcx};
#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
- from_def_id(item.def_id)
+ from_item_id(item.def_id)
})
.collect()
})
let item = &i.impl_item;
if item.def_id.is_local() {
self.item(item.clone()).unwrap();
- Some(from_def_id(item.def_id))
+ Some(from_item_id(item.def_id))
} else {
None
}
let trait_item = &trait_item.trait_;
trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
Some((
- from_def_id(id.into()),
+ from_item_id(id.into()),
types::Item {
- id: from_def_id(id.into()),
+ id: from_item_id(id.into()),
crate_id: id.krate.as_u32(),
name: self
.cache
let id = item.def_id;
if let Some(mut new_item) = self.convert_item(item) {
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
- t.implementors = self.get_trait_implementors(id.expect_real())
+ t.implementors = self.get_trait_implementors(id.expect_def_id())
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
- s.impls = self.get_impls(id.expect_real())
+ s.impls = self.get_impls(id.expect_def_id())
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
- e.impls = self.get_impls(id.expect_real())
+ e.impls = self.get_impls(id.expect_def_id())
}
- let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
+ let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
// to make sure the items are unique. The main place this happens is when an item, is
.chain(self.cache.external_paths.clone().into_iter())
.map(|(k, (path, kind))| {
(
- from_def_id(k.into()),
+ from_item_id(k.into()),
types::ItemSummary {
crate_id: k.krate.as_u32(),
path,
let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable;
let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable;
vec![
- stable("h", |o| o.optflag("h", "help", "show this help message")),
- stable("V", |o| o.optflag("V", "version", "print rustdoc's version")),
- stable("v", |o| o.optflag("v", "verbose", "use verbose output")),
+ stable("h", |o| o.optflagmulti("h", "help", "show this help message")),
+ stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")),
+ stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")),
stable("r", |o| {
o.optopt("r", "input-format", "the input type of the specified file", "[rust]")
}),
)
}),
stable("plugins", |o| o.optmulti("", "plugins", "removed", "PLUGINS")),
- stable("no-default", |o| o.optflag("", "no-defaults", "don't run the default passes")),
+ stable("no-default", |o| o.optflagmulti("", "no-defaults", "don't run the default passes")),
stable("document-private-items", |o| {
- o.optflag("", "document-private-items", "document private items")
+ o.optflagmulti("", "document-private-items", "document private items")
}),
unstable("document-hidden-items", |o| {
- o.optflag("", "document-hidden-items", "document items that have doc(hidden)")
+ o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)")
}),
- stable("test", |o| o.optflag("", "test", "run code examples as tests")),
+ stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")),
stable("test-args", |o| {
o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS")
}),
o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL")
}),
stable("markdown-no-toc", |o| {
- o.optflag("", "markdown-no-toc", "don't include table of contents")
+ o.optflagmulti("", "markdown-no-toc", "don't include table of contents")
}),
stable("e", |o| {
o.optopt(
)
}),
unstable("display-warnings", |o| {
- o.optflag("", "display-warnings", "to print code warnings when testing doc")
+ o.optflagmulti("", "display-warnings", "to print code warnings when testing doc")
}),
stable("crate-version", |o| {
o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
}),
unstable("sort-modules-by-appearance", |o| {
- o.optflag(
+ o.optflagmulti(
"",
"sort-modules-by-appearance",
"sort modules by where they appear in the program, rather than alphabetically",
o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG")
}),
unstable("disable-minification", |o| {
- o.optflag("", "disable-minification", "Disable minification applied on JS files")
+ o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
}),
stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")),
stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")),
o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
}),
unstable("enable-index-page", |o| {
- o.optflag("", "enable-index-page", "To enable generation of the index page")
+ o.optflagmulti("", "enable-index-page", "To enable generation of the index page")
}),
unstable("static-root-path", |o| {
o.optopt(
)
}),
unstable("disable-per-crate-search", |o| {
- o.optflag(
+ o.optflagmulti(
"",
"disable-per-crate-search",
"disables generating the crate selector on the search box",
)
}),
unstable("show-coverage", |o| {
- o.optflag(
+ o.optflagmulti(
"",
"show-coverage",
"calculate percentage of public items with documentation",
)
}),
unstable("enable-per-target-ignores", |o| {
- o.optflag(
+ o.optflagmulti(
"",
"enable-per-target-ignores",
"parse ignore-foo for ignoring doctests on a per-target basis",
unstable("test-builder", |o| {
o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH")
}),
- unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")),
+ unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")),
unstable("generate-redirect-map", |o| {
- o.optflag(
+ o.optflagmulti(
"",
"generate-redirect-map",
"Generate JSON file at the top level instead of generating HTML redirection files",
"[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]",
)
}),
- unstable("no-run", |o| o.optflag("", "no-run", "Compile doctests without running them")),
+ unstable("no-run", |o| {
+ o.optflagmulti("", "no-run", "Compile doctests without running them")
+ }),
unstable("show-type-layout", |o| {
- o.optflag("", "show-type-layout", "Include the memory layout of types in the docs")
+ o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs")
}),
]
}
let filename = i.span(self.ctx.tcx).filename(self.ctx.sess());
let has_doc_example = tests.found_tests != 0;
- // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+ // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
let hir_id = self
.ctx
.tcx
.hir()
- .local_def_id_to_hir_id(i.def_id.expect_real().expect_local());
+ .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
// `missing_docs` is allow-by-default, so don't treat this as ignoring the item
// unless the user had an explicit `allow`
return;
}
- let local_id = match item.def_id.as_real().and_then(|x| x.as_local()) {
+ let local_id = match item.def_id.as_def_id().and_then(|x| x.as_local()) {
Some(id) => id,
// We don't need to check the syntax for other crates so returning
// without doing anything should not be a problem.
let sp = item.attr_span(self.cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new_did(
self.cx.tcx,
- item.def_id.expect_real(),
+ item.def_id.expect_def_id(),
sp,
);
for code_block in markdown::rust_code_blocks(&dox, &extra) {
fn fold_item(&mut self, item: Item) -> Option<Item> {
use rustc_middle::ty::DefIdTree;
- let parent_node = if item.is_fake() {
- None
- } else {
- find_nearest_parent_module(self.cx.tcx, item.def_id.expect_real())
- };
-
+ let parent_node =
+ item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
if parent_node.is_some() {
trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
}
// find item's parent to resolve `Self` in item's docs below
debug!("looking for the `Self` type");
- let self_id = if item.is_fake() {
- None
- // Checking if the item is a field in an enum variant
- } else if (matches!(self.cx.tcx.def_kind(item.def_id.expect_real()), DefKind::Field)
- && matches!(
- self.cx.tcx.def_kind(self.cx.tcx.parent(item.def_id.expect_real()).unwrap()),
- DefKind::Variant
- ))
- {
- self.cx
- .tcx
- .parent(item.def_id.expect_real())
- .and_then(|item_id| self.cx.tcx.parent(item_id))
- } else if matches!(
- self.cx.tcx.def_kind(item.def_id.expect_real()),
- DefKind::AssocConst
- | DefKind::AssocFn
- | DefKind::AssocTy
- | DefKind::Variant
- | DefKind::Field
- ) {
- self.cx.tcx.parent(item.def_id.expect_real())
- // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
- // Fixing this breaks `fn render_deref_methods`.
- // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
- // regardless of what rustdoc wants to call it.
- } else if let Some(parent) = self.cx.tcx.parent(item.def_id.expect_real()) {
- let parent_kind = self.cx.tcx.def_kind(parent);
- Some(if parent_kind == DefKind::Impl { parent } else { item.def_id.expect_real() })
- } else {
- Some(item.def_id.expect_real())
+ let self_id = match item.def_id.as_def_id() {
+ None => None,
+ Some(did)
+ if (matches!(self.cx.tcx.def_kind(did), DefKind::Field)
+ && matches!(
+ self.cx.tcx.def_kind(self.cx.tcx.parent(did).unwrap()),
+ DefKind::Variant
+ )) =>
+ {
+ self.cx.tcx.parent(did).and_then(|item_id| self.cx.tcx.parent(item_id))
+ }
+ Some(did)
+ if matches!(
+ self.cx.tcx.def_kind(did),
+ DefKind::AssocConst
+ | DefKind::AssocFn
+ | DefKind::AssocTy
+ | DefKind::Variant
+ | DefKind::Field
+ ) =>
+ {
+ self.cx.tcx.parent(did)
+ }
+ Some(did) => match self.cx.tcx.parent(did) {
+ // HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
+ // Fixing this breaks `fn render_deref_methods`.
+ // As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
+ // regardless of what rustdoc wants to call it.
+ Some(parent) => {
+ let parent_kind = self.cx.tcx.def_kind(parent);
+ Some(if parent_kind == DefKind::Impl { parent } else { did })
+ }
+ None => Some(did),
+ },
};
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
let inner_docs = item.inner_docs(self.cx.tcx);
if item.is_mod() && inner_docs {
- self.mod_ids.push(item.def_id.expect_real());
+ self.mod_ids.push(item.def_id.expect_def_id());
}
// We want to resolve in the lexical scope of the documentation.
Some(if item.is_mod() {
if !inner_docs {
- self.mod_ids.push(item.def_id.expect_real());
+ self.mod_ids.push(item.def_id.expect_def_id());
}
let ret = self.fold_item_recur(item);
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
if let Some((src_id, dst_id)) = id
.as_local()
- // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+ // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
.and_then(|dst_id| {
- item.def_id.expect_real().as_local().map(|src_id| (src_id, dst_id))
+ item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
})
{
let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
fn fold_item(&mut self, i: Item) -> Option<Item> {
if i.is_struct() || i.is_enum() || i.is_union() {
// FIXME(eddyb) is this `doc(hidden)` check needed?
- if !self.cx.tcx.get_attrs(i.def_id.expect_real()).lists(sym::doc).has_word(sym::hidden)
+ if !self
+ .cx
+ .tcx
+ .get_attrs(i.def_id.expect_def_id())
+ .lists(sym::doc)
+ .has_word(sym::hidden)
{
self.impls
- .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_real()));
+ .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
}
}
#[derive(Default)]
struct ItemCollector {
- items: FxHashSet<FakeDefId>,
+ items: FxHashSet<ItemId>,
}
impl ItemCollector {
struct BadImplStripper {
prims: FxHashSet<PrimitiveType>,
- items: FxHashSet<FakeDefId>,
+ items: FxHashSet<ItemId>,
}
impl BadImplStripper {
}
}
- fn keep_impl_with_def_id(&self, did: FakeDefId) -> bool {
+ fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
self.items.contains(&did)
}
}
}
crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
- if !cx.cache.access_levels.is_public(item.def_id.expect_real())
+ if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
|| matches!(
*item.kind,
clean::StructFieldItem(_)
{
return false;
}
- // The `expect_real()` should be okay because `local_def_id_to_hir_id`
+ // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_real().expect_local());
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
|| inherits_doc_hidden(cx.tcx, hir_id)
{
|lint| lint.build("missing code example in this documentation").emit(),
);
}
- } else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id.expect_real())
+ } else if tests.found_tests > 0
+ && !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
{
cx.tcx.struct_span_lint_hir(
crate::lint::PRIVATE_DOC_TESTS,
use std::mem;
use crate::clean;
-use crate::clean::{FakeDefIdSet, Item, NestedAttributesExt};
+use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
/// Strip items marked `#[doc(hidden)]`
crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
- let mut retained = FakeDefIdSet::default();
+ let mut retained = ItemIdSet::default();
// strip all #[doc(hidden)] items
let krate = {
}
struct Stripper<'a> {
- retained: &'a mut FakeDefIdSet,
+ retained: &'a mut ItemIdSet,
update_retained: bool,
}
-use crate::clean::{self, FakeDefIdSet};
+use crate::clean::{self, ItemIdSet};
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper};
/// crate, specified by the `xcrate` flag.
crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
// This stripper collects all *retained* nodes.
- let mut retained = FakeDefIdSet::default();
+ let mut retained = ItemIdSet::default();
// strip all private items
{
use rustc_middle::middle::privacy::AccessLevels;
use std::mem;
-use crate::clean::{self, FakeDefIdSet, GetDefId, Item};
+use crate::clean::{self, GetDefId, Item, ItemIdSet};
use crate::fold::{strip_item, DocFolder};
crate struct Stripper<'a> {
- crate retained: &'a mut FakeDefIdSet,
+ crate retained: &'a mut ItemIdSet,
crate access_levels: &'a AccessLevels<DefId>,
crate update_retained: bool,
}
| clean::TraitAliasItem(..)
| clean::ForeignTypeItem => {
if i.def_id.is_local() {
- if !self.access_levels.is_exported(i.def_id.expect_real()) {
+ if !self.access_levels.is_exported(i.def_id.expect_def_id()) {
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
return None;
}
/// This stripper discards all impls which reference stripped items
crate struct ImplStripper<'a> {
- crate retained: &'a FakeDefIdSet,
+ crate retained: &'a ItemIdSet,
}
impl<'a> DocFolder for ImplStripper<'a> {
use super::*;
+use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Symbol;
-use rustc_span::with_default_session_globals;
fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
vec![DocFragment {
#[track_caller]
fn run_test(input: &str, expected: &str) {
- with_default_session_globals(|| {
+ create_default_session_globals_then(|| {
let mut s = create_doc_fragment(input);
unindent_fragments(&mut s);
assert_eq!(&s.iter().collect::<String>(), expected);
#[test]
fn test_with_minification() {
- let text = include_str!("../html/static/themes/dark.css");
+ let text = include_str!("../html/static/css/themes/dark.css");
let minified = minifier::css::minify(&text).expect("CSS minification failed");
let against = load_css_paths(text.as_bytes());
--- /dev/null
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @array_eq_value
+#[no_mangle]
+pub fn array_eq_value(a: [u16; 6], b: [u16; 6]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: %2 = icmp eq i96 %0, %1
+ // CHECK-NEXT: ret i1 %2
+ a == b
+}
+
+// CHECK-LABEL: @array_eq_ref
+#[no_mangle]
+pub fn array_eq_ref(a: &[u16; 6], b: &[u16; 6]) -> bool {
+ // CHECK: start:
+ // CHECK: load i96, i96* %{{.+}}, align 2
+ // CHECK: load i96, i96* %{{.+}}, align 2
+ // CHECK: icmp eq i96
+ // CHECK-NEXT: ret
+ a == b
+}
+
+// CHECK-LABEL: @array_eq_value_still_passed_by_pointer
+#[no_mangle]
+pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(18) %{{.+}}, i8* nonnull dereferenceable(18) %{{.+}}, i64 18)
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+ // CHECK-NEXT: ret i1 %[[EQ]]
+ a == b
+}
+
+// CHECK-LABEL: @array_eq_long
+#[no_mangle]
+pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(2468) %{{.+}}, i8* nonnull dereferenceable(2468) %{{.+}}, i64 2468)
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
+ // CHECK-NEXT: ret i1 %[[EQ]]
+ a == b
+}
+
+// CHECK-LABEL: @array_eq_zero(i128 %0)
+#[no_mangle]
+pub fn array_eq_zero(x: [u16; 8]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i128 %0, 0
+ // CHECK-NEXT: ret i1 %[[EQ]]
+ x == [0; 8]
+}
--- /dev/null
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm)]
+
+// CHECK-LABEL: @x87_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn x87_clobber() {
+ asm!("foo", out("st") _);
+}
+
+// CHECK-LABEL: @mmx_clobber
+// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}
+#[no_mangle]
+pub unsafe fn mmx_clobber() {
+ asm!("bar", out("mm0") _, out("mm1") _);
+}
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
-// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
-// CHECK-SAME: flags: DIFlagArtificial
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
+// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
fn main() {
let _dummy = async_fn_test();
// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
-// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
-// CHECK-SAME: flags: DIFlagArtificial
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: )
+// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "discriminant", scope: [[GEN]],
+// CHECK-NOT: flags: DIFlagArtificial
fn main() {
let _dummy = generator_test();
#![crate_type = "lib"]
-// #71602: check that slice equality just generates a single bcmp
+// #71602 reported a simple array comparison just generating a loop.
+// This was originally fixed by ensuring it generates a single bcmp,
+// but we now generate it as a load instead. `is_zero_slice` was
+// tweaked to still test the case of comparison against a slice,
+// and `is_zero_array` tests the new array-specific behaviour.
// CHECK-LABEL: @is_zero_slice
#[no_mangle]
pub fn is_zero_slice(data: &[u8; 4]) -> bool {
- // CHECK: start:
+ // CHECK: :
// CHECK-NEXT: %{{.+}} = getelementptr {{.+}}
// CHECK-NEXT: %[[BCMP:.+]] = tail call i32 @{{bcmp|memcmp}}({{.+}})
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[BCMP]], 0
// CHECK-NEXT: ret i1 %[[EQ]]
+ &data[..] == [0; 4]
+}
+
+// CHECK-LABEL: @is_zero_array
+#[no_mangle]
+pub fn is_zero_array(data: &[u8; 4]) -> bool {
+ // CHECK: start:
+ // CHECK-NEXT: %[[PTR:.+]] = bitcast [4 x i8]* {{.+}} to i32*
+ // CHECK-NEXT: %[[LOAD:.+]] = load i32, i32* %[[PTR]], align 1
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[LOAD]], 0
+ // CHECK-NEXT: ret i1 %[[EQ]]
*data == [0; 4]
}
-// compile-flags: -C opt-level=0
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind)]
+#[lang="sized"]
+trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `stdcall` and `stdcall-unwind`
// extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
// optimizations above to prevent LLVM from inferring the attribute.
-#![crate_type = "lib"]
-#![feature(c_unwind)]
-
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "stdcall" fn rust_item_that_cannot_unwind() {
-// compile-flags: -C opt-level=0
-// ignore-arm thiscall isn't supported
-// ignore-aarch64 thiscall isn't supported
-// ignore-riscv64 thiscall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes
+#![no_core]
+#![feature(no_core, lang_items, c_unwind, abi_thiscall)]
+#[lang="sized"]
+trait Sized { }
// Test that `nounwind` atributes are correctly applied to exported `thiscall` and
// `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We
// disable optimizations above to prevent LLVM from inferring the attribute.
-#![crate_type = "lib"]
-#![feature(abi_thiscall)]
-#![feature(c_unwind)]
-
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
#[no_mangle]
pub extern "thiscall" fn rust_item_that_cannot_unwind() {
// only-cdb
+// ignore-tidy-linelength
// compile-flags:-g
// cdb-command: g
// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
-// so the best we can do is to make sure we are generating the right debuginfo
+// so the best we can do is to make sure we are generating the right debuginfo.
+// Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers)
+// to disable the natvis for a given expression. We also provide the `-r2` flag
+// to expand the expression 2 levels.
// cdb-command: dx -r2 a,!
// cdb-check:a,! [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *]
// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
+// cdb-command: dx -r2 h,!
+// cdb-check:h,! : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
+// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
+// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
+// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option]
+
// cdb-command: dx h
// cdb-check:h : Some [Type: enum$<core::option::Option<u32> >]
-// cdb-check: [+0x000] variant$ : Some (0x1) [Type: core::option::Option]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [variant] : Some
// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int]
+// cdb-command: dx -r2 i,!
+// cdb-check:i,! : None [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [+0x000] variant0 [Type: enum$<core::option::Option<u32> >::None]
+// cdb-check: [+0x000] variant1 [Type: enum$<core::option::Option<u32> >::Some]
+// cdb-check: [+0x004] __0 : 0x[...] [Type: unsigned int]
+// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option]
+
// cdb-command: dx i
// cdb-check:i : None [Type: enum$<core::option::Option<u32> >]
-// cdb-check: [+0x000] variant$ : None (0x0) [Type: core::option::Option]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [variant] : None
// cdb-command: dx j
// cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
// cdb-check: [+0x000] __0 [Type: alloc::string::String]
// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
+// cdb-command: dx -r2 l,!
+// cdb-check:l,! : $T2 [Type: enum$<core::result::Result<u32, enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check: [+0x000] Ok [Type: enum$<core::result::Result<u32, enum$<msvc_pretty_enums::Empty> >, Ok>::Ok]
+// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int]
+
pub enum CStyleEnum {
Low = 2,
High = 16,
Tag2,
}
+pub enum Empty { }
+
fn main() {
let a = Some(CStyleEnum::Low);
let b = Option::<CStyleEnum>::None;
let i = Option::<u32>::None;
let j = CStyleEnum::High;
let k = Some("IAMA optional string!".to_string());
+ let l = Result::<u32, Empty>::Ok(42);
zzz(); // #break
}
// gdb-check:$1 = Vec(size=1000000000) = {[...]...}
// gdb-command: print slice
-// gdb-check:$2 = &[u8] {data_ptr: [...], length: 1000000000}
+// gdb-check:$2 = &[u8](size=1000000000) = {[...]...}
#![allow(unused_variables)]
--- /dev/null
+// ignore-android: FIXME(#10381)
+// ignore-windows
+// compile-flags:-g
+
+// gdb-command: run
+
+// gdb-command: print slice
+// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2}
+// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2}
+
+// gdb-command: print mut_slice
+// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7}
+// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7}
+
+// gdb-command: print str_slice
+// gdb-check: $3 = "string slice"
+
+// gdb-command: print mut_str_slice
+// gdb-check: $4 = "mutable string slice"
+
+// lldb-command: run
+
+// lldb-command: print slice
+// lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 }
+
+// lldb-command: print mut_slice
+// lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 }
+
+// lldb-command: print str_slice
+// lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 }
+
+// lldb-command: print mut_str_slice
+// lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 }
+
+fn b() {}
+
+fn main() {
+ let slice: &[i32] = &[0, 1, 2];
+ let mut_slice: &mut [i32] = &mut [2, 3, 5, 7];
+
+ let str_slice: &str = "string slice";
+ let mut mut_str_slice_buffer = String::from("mutable string slice");
+ let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str();
+
+ b(); // #break
+}
// cdb-command: dx some
// cdb-check:some : Some [Type: enum$<core::option::Option<i16> >]
-// cdb-check: [...] variant$ : Some (0x1) [Type: core::option::Option]
-// cdb-check: [...] __0 : 8 [Type: short]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i16> >]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x002] __0 : 8 [Type: short]
// cdb-command: dx none
// cdb-check:none : None [Type: enum$<core::option::Option<i64> >]
-// cdb-check: [...] variant$ : None (0x0) [Type: core::option::Option]
+// cdb-check: [<Raw View>] [Type: enum$<core::option::Option<i64> >]
+// cdb-check: [variant] : None
// cdb-command: dx some_string
// NOTE: cdb fails to interpret debug info of Option enums on i686.
--- /dev/null
+// edition:2018
+// revisions: rpass1
+
+
+// Regression test for #86753. The `type_implements_trait` query (since moved to a method)
+// was encountering an ICE during incremental testing when hashing its arguments.
+#![warn(rust_2021_compatibility)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Poll, Context};
+
+struct LocalSet {}
+struct RunUntil<'a, F> {
+ _local_set: &'a LocalSet,
+ _future: F,
+}
+impl<'a, F> RunUntil<'a, F> {
+ fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> {
+ unimplemented!()
+ }
+}
+
+struct Projection<'pin, 'a, F>
+where
+ RunUntil<'a, F>: 'pin,
+{
+ pub local_set: &'pin mut &'a LocalSet,
+ pub future: Pin<&'pin mut F>,
+}
+
+impl LocalSet {
+ fn with<T>(&self, _f: impl FnOnce() -> T) -> T {
+ unimplemented!()
+ }
+}
+impl<T: Future> Future for RunUntil<'_, T> {
+ type Output = T::Output;
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ let me = self.project();
+ me.local_set.with(|| {
+ let _ = cx.waker();
+ let f = me.future;
+ let _ = f.poll(cx);
+ Poll::Pending
+ })
+ }
+}
+
+fn main() {}
- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
+ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
+ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
- // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
- // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + val: Unevaluated(FOO, [], None)
// mir::Constant
// + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
_2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
_1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/ref_deref.rs:5:6: 5:10
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
+ // + val: Unevaluated(main, [], Some(promoted[0]))
+ // mir::Constant
+ // + span: $DIR/ref_deref.rs:5:6: 5:10
-+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
_1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
- StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/ref_deref_project.rs:5:6: 5:17
- // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
+ // + val: Unevaluated(main, [], Some(promoted[0]))
+ // mir::Constant
+ // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
- StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/slice_len.rs:5:6: 5:19
- // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/slice_len.rs:5:6: 5:19
- // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
// + val: Unevaluated(bar, [], Some(promoted[1]))
// mir::Constant
// + span: $DIR/inline-retag.rs:12:7: 12:9
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
Retag(_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
_4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
Retag(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
// + val: Unevaluated(bar, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/inline-retag.rs:12:11: 12:14
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
_7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
Retag(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(discriminant, [T], Some(promoted[2]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:70:42: 70:44
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
_7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
_6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
// + val: Unevaluated(discriminant, [T], Some(promoted[1]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:71:42: 71:45
- // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
+ // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
_11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
_10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
// + val: Unevaluated(discriminant, [T], Some(promoted[0]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:72:42: 72:47
- // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
_15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
_14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
// + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/match_false_edges.rs:16:14: 16:15
- // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
_4 = &shallow _2; // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
StorageLive(_7); // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
// + val: Unevaluated(array_casts, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_14); // scope 1 at $DIR/retag.rs:40:31: 43:6
_14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:40:31: 43:6
// closure
- // + def_id: DefId(0:14 ~ retag[317d]::main::{closure#0})
+ // + def_id: DefId(0:14 ~ retag[13e7]::main::{closure#0})
// + substs: [
// i8,
// for<'r> extern "rust-call" fn((&'r i32,)) -> &'r i32,
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/retag.rs:47:21: 47:23
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_28); // scope 7 at $DIR/retag.rs:47:21: 47:23
_23 = &(*_28); // scope 7 at $DIR/retag.rs:47:21: 47:23
Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23
extern crate rustc_symbol_mangling;
extern crate rustc_target;
-use rustc_codegen_ssa::back::linker::LinkerInfo;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
use rustc_data_structures::fx::FxHashMap;
allocator_module: None,
metadata_module: None,
metadata,
- linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()),
- crate_info: CrateInfo::new(tcx),
+ crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()),
})
}
OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes"
all:
- cp $(S)/src/librustdoc/html/static/themes/light.css $(TMPDIR)/test.css
+ cp $(S)/src/librustdoc/html/static/css/themes/light.css $(TMPDIR)/test.css
$(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css
$(HTMLDOCCK) $(OUTPUT_DIR) foo.rs
--- /dev/null
+# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
+
+# only-i686-pc-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
+ $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.txt output.txt
+else
+ $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
--- /dev/null
+extern crate raw_dylib_alt_calling_convention_test;
+
+fn main() {
+ raw_dylib_alt_calling_convention_test::library_function();
+}
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+
+struct S {
+ uint8_t x;
+ int32_t y;
+};
+
+struct S2 {
+ int32_t x;
+ uint8_t y;
+};
+
+struct S3 {
+ uint8_t x[5];
+};
+
+__declspec(dllexport) void __stdcall stdcall_fn_1(int i) {
+ printf("stdcall_fn_1(%d)\n", i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_2(uint8_t i, float f) {
+ printf("stdcall_fn_2(%d, %.1f)\n", i, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_3(double d) {
+ printf("stdcall_fn_3(%.1f)\n", d);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_4(uint8_t i, uint8_t j, float f) {
+ printf("stdcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_5(struct S s, int i) {
+ printf("stdcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+// Test that stdcall support works correctly with the nullable pointer optimization.
+__declspec(dllexport) void __stdcall stdcall_fn_6(struct S* s) {
+ if (s) {
+ printf("stdcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+ } else {
+ printf("stdcall_fn_6(null)\n");
+ }
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __stdcall stdcall_fn_7(struct S2 s, int i) {
+ printf("stdcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+// Verify that we compute the correct amount of space in the argument list for a 5-byte struct.
+__declspec(dllexport) void __stdcall stdcall_fn_8(struct S3 s, struct S3 t) {
+ printf("stdcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+ s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+ t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+ );
+ fflush(stdout);
+}
+
+// test whether f64/double values are aligned on 4-byte or 8-byte boundaries.
+__declspec(dllexport) void __stdcall stdcall_fn_9(uint8_t x, double y) {
+ printf("stdcall_fn_9(%d, %.1f)\n", x, y);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_1(int i) {
+ printf("fastcall_fn_1(%d)\n", i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_2(uint8_t i, float f) {
+ printf("fastcall_fn_2(%d, %.1f)\n", i, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_3(double d) {
+ printf("fastcall_fn_3(%.1f)\n", d);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_4(uint8_t i, uint8_t j, float f) {
+ printf("fastcall_fn_4(%d, %d, %.1f)\n", i, j, f);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_5(struct S s, int i) {
+ printf("fastcall_fn_5(S { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_6(struct S* s) {
+ if (s) {
+ printf("fastcall_fn_6(S { x: %d, y: %d })\n", s->x, s->y);
+ } else {
+ printf("fastcall_fn_6(null)\n");
+ }
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_7(struct S2 s, int i) {
+ printf("fastcall_fn_7(S2 { x: %d, y: %d }, %d)\n", s.x, s.y, i);
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_8(struct S3 s, struct S3 t) {
+ printf("fastcall_fn_8(S3 { x: [%d, %d, %d, %d, %d] }, S3 { x: [%d, %d, %d, %d, %d] })\n",
+ s.x[0], s.x[1], s.x[2], s.x[3], s.x[4],
+ t.x[0], t.x[1], t.x[2], t.x[3], t.x[4]
+ );
+ fflush(stdout);
+}
+
+__declspec(dllexport) void __fastcall fastcall_fn_9(uint8_t x, double y) {
+ printf("fastcall_fn_9(%d, %.1f)\n", x, y);
+ fflush(stdout);
+}
--- /dev/null
+#![feature(raw_dylib)]
+
+#[repr(C)]
+#[derive(Clone)]
+struct S {
+ x: u8,
+ y: i32,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S2 {
+ x: i32,
+ y: u8,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+struct S3 {
+ x: [u8; 5],
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "stdcall" {
+ fn stdcall_fn_1(i: i32);
+ fn stdcall_fn_2(c: u8, f: f32);
+ fn stdcall_fn_3(d: f64);
+ fn stdcall_fn_4(i: u8, j: u8, f: f32);
+ fn stdcall_fn_5(a: S, b: i32);
+ fn stdcall_fn_6(a: Option<&S>);
+ fn stdcall_fn_7(a: S2, b: i32);
+ fn stdcall_fn_8(a: S3, b: S3);
+ fn stdcall_fn_9(x: u8, y: f64);
+}
+
+#[link(name = "extern", kind = "raw-dylib")]
+extern "fastcall" {
+ fn fastcall_fn_1(i: i32);
+ fn fastcall_fn_2(c: u8, f: f32);
+ fn fastcall_fn_3(d: f64);
+ fn fastcall_fn_4(i: u8, j: u8, f: f32);
+ fn fastcall_fn_5(a: S, b: i32);
+ fn fastcall_fn_6(a: Option<&S>);
+ fn fastcall_fn_7(a: S2, b: i32);
+ fn fastcall_fn_8(a: S3, b: S3);
+ fn fastcall_fn_9(x: u8, y: f64);
+}
+
+pub fn library_function() {
+ unsafe {
+ stdcall_fn_1(14);
+ stdcall_fn_2(16, 3.5);
+ stdcall_fn_3(3.5);
+ stdcall_fn_4(1, 2, 3.0);
+ stdcall_fn_5(S { x: 1, y: 2 }, 16);
+ stdcall_fn_6(Some(&S { x: 10, y: 12 }));
+ stdcall_fn_7(S2 { x: 15, y: 16 }, 3);
+ stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+ stdcall_fn_9(1, 3.0);
+
+ fastcall_fn_1(14);
+ fastcall_fn_2(16, 3.5);
+ fastcall_fn_3(3.5);
+ fastcall_fn_4(1, 2, 3.0);
+ fastcall_fn_5(S { x: 1, y: 2 }, 16);
+ fastcall_fn_6(Some(&S { x: 10, y: 12 }));
+ fastcall_fn_7(S2 { x: 15, y: 16 }, 3);
+ fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] });
+ fastcall_fn_9(1, 3.0);
+ }
+}
--- /dev/null
+stdcall_fn_1(14)
+stdcall_fn_2(16, 3.5)
+stdcall_fn_3(3.5)
+stdcall_fn_4(1, 2, 3.0)
+stdcall_fn_5(S { x: 1, y: 2 }, 16)
+stdcall_fn_6(S { x: 10, y: 12 })
+stdcall_fn_7(S2 { x: 15, y: 16 }, 3)
+stdcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+stdcall_fn_9(1, 3.0)
+fastcall_fn_1(14)
+fastcall_fn_2(16, 3.5)
+fastcall_fn_3(3.5)
+fastcall_fn_4(1, 2, 3.0)
+fastcall_fn_5(S { x: 1, y: 2 }, 16)
+fastcall_fn_6(S { x: 10, y: 12 })
+fastcall_fn_7(S2 { x: 15, y: 16 }, 3)
+fastcall_fn_8(S3 { x: [1, 2, 3, 4, 5] }, S3 { x: [6, 7, 8, 9, 10] })
+fastcall_fn_9(1, 3.0)
--- /dev/null
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+ $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+ $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
+ $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+ $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+ $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+ "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/output.txt output.txt
+else
+ $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
--- /dev/null
+extern crate raw_dylib_test;
+
+fn main() {
+ raw_dylib_test::library_function();
+}
--- /dev/null
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+ printf("extern_fn_1\n");
+ fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+ printf("extern_fn_2; didn't get the rename\n");
+ fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+ printf("extern_fn_with_long_name; got the rename\n");
+ fflush(stdout);
+}
--- /dev/null
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+ printf("extern_fn_3\n");
+ fflush(stdout);
+}
--- /dev/null
+#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+ fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+ fn extern_fn_3();
+}
+
+pub fn library_function() {
+ #[link(name = "extern_1", kind = "raw-dylib")]
+ extern { fn extern_fn_2(); }
+
+ unsafe {
+ extern_fn_1();
+ extern_fn_2();
+ extern_fn_3();
+ }
+}
--- /dev/null
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
+++ /dev/null
-# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
-
-# only-windows
-# only-msvc
-
--include ../../run-make-fulldeps/tools.mk
-
-all:
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
- $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
- $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
- $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
-
-ifdef RUSTC_BLESS_TEST
- cp "$(TMPDIR)"/output.txt output.txt
-else
- $(DIFF) output.txt "$(TMPDIR)"/output.txt
-endif
+++ /dev/null
-extern crate raw_dylib_test;
-
-fn main() {
- raw_dylib_test::library_function();
-}
+++ /dev/null
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_1() {
- printf("extern_fn_1\n");
- fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_2() {
- printf("extern_fn_2; didn't get the rename\n");
- fflush(stdout);
-}
-
-__declspec(dllexport) void extern_fn_with_long_name() {
- printf("extern_fn_with_long_name; got the rename\n");
- fflush(stdout);
-}
+++ /dev/null
-#include <stdio.h>
-
-__declspec(dllexport) void extern_fn_3() {
- printf("extern_fn_3\n");
- fflush(stdout);
-}
+++ /dev/null
-#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
-
-#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
-extern {
- fn extern_fn_1();
-}
-
-#[link(name = "extern_2", kind = "raw-dylib")]
-extern {
- fn extern_fn_3();
-}
-
-pub fn library_function() {
- #[link(name = "extern_1", kind = "raw-dylib")]
- extern { fn extern_fn_2(); }
-
- unsafe {
- extern_fn_1();
- extern_fn_2();
- extern_fn_3();
- }
-}
+++ /dev/null
-extern_fn_1
-extern_fn_2; didn't get the rename
-extern_fn_3
--- /dev/null
+#![feature(decl_macro)]
+
+pub macro addr_of($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_self($place:expr) {
+ &raw const $place
+}
+
+pub macro addr_of_crate($place:expr) {
+ &raw const $place
+}
+
+pub struct Foo;
+pub struct FooSelf;
+pub struct FooCrate;
+
+pub enum Bar { Foo, }
+pub enum BarSelf { Foo, }
+pub enum BarCrate { Foo, }
+
+pub fn foo() {}
+pub fn foo_self() {}
+pub fn foo_crate() {}
+
+pub type Type = i32;
+pub type TypeSelf = i32;
+pub type TypeCrate = i32;
+
+pub union Union {
+ a: i8,
+ b: i8,
+}
+pub union UnionSelf {
+ a: i8,
+ b: i8,
+}
+pub union UnionCrate {
+ a: i8,
+ b: i8,
+}
--- /dev/null
+// compile-flags: --document-private-items --document-private-items
+
+// @has duplicate_flags/struct.Private.html
+struct Private;
--- /dev/null
+// aux-build: reexports.rs
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
+pub use reexports::addr_of;
+// @has 'foo/macro.addr_of_crate.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_crate($place : expr) {'
+pub(crate) use reexports::addr_of_crate;
+// @has 'foo/macro.addr_of_self.html' '//*[@class="docblock type-decl"]' 'pub(crate) macro addr_of_self($place : expr) {'
+pub(self) use reexports::addr_of_self;
+
+// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @has 'foo/struct.FooCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooCrate;'
+pub(crate) use reexports::FooCrate;
+// @has 'foo/struct.FooSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) struct FooSelf;'
+pub(self) use reexports::FooSelf;
+
+// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @has 'foo/enum.BarCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarCrate {'
+pub(crate) use reexports::BarCrate;
+// @has 'foo/enum.BarSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) enum BarSelf {'
+pub(self) use reexports::BarSelf;
+
+// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+pub use reexports::foo;
+// @has 'foo/fn.foo_crate.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_crate()'
+pub(crate) use reexports::foo_crate;
+// @has 'foo/fn.foo_self.html' '//*[@class="rust fn"]' 'pub(crate) fn foo_self()'
+pub(self) use reexports::foo_self;
+
+// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
+pub use reexports::Type;
+// @has 'foo/type.TypeCrate.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeCrate ='
+pub(crate) use reexports::TypeCrate;
+// @has 'foo/type.TypeSelf.html' '//*[@class="rust typedef"]' 'pub(crate) type TypeSelf ='
+pub(self) use reexports::TypeSelf;
+
+// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @has 'foo/union.UnionCrate.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionCrate {'
+pub(crate) use reexports::UnionCrate;
+// @has 'foo/union.UnionSelf.html' '//*[@class="docblock type-decl"]' 'pub(crate) union UnionSelf {'
+pub(self) use reexports::UnionSelf;
+
+pub mod foo {
+ // @!has 'foo/foo/union.Union.html'
+ use crate::reexports::Union;
+}
--- /dev/null
+// aux-build: reexports.rs
+
+#![crate_name = "foo"]
+
+extern crate reexports;
+
+// @has 'foo/macro.addr_of.html' '//*[@class="docblock type-decl"]' 'pub macro addr_of($place : expr) {'
+pub use reexports::addr_of;
+// @!has 'foo/macro.addr_of_crate.html'
+pub(crate) use reexports::addr_of_crate;
+// @!has 'foo/macro.addr_of_self.html'
+pub(self) use reexports::addr_of_self;
+
+// @has 'foo/struct.Foo.html' '//*[@class="docblock type-decl"]' 'pub struct Foo;'
+pub use reexports::Foo;
+// @!has 'foo/struct.FooCrate.html'
+pub(crate) use reexports::FooCrate;
+// @!has 'foo/struct.FooSelf.html'
+pub(self) use reexports::FooSelf;
+
+// @has 'foo/enum.Bar.html' '//*[@class="docblock type-decl"]' 'pub enum Bar {'
+pub use reexports::Bar;
+// @!has 'foo/enum.BarCrate.html'
+pub(crate) use reexports::BarCrate;
+// @!has 'foo/enum.BarSelf.html'
+pub(self) use reexports::BarSelf;
+
+// @has 'foo/fn.foo.html' '//*[@class="rust fn"]' 'pub fn foo()'
+pub use reexports::foo;
+// @!has 'foo/fn.foo_crate.html'
+pub(crate) use reexports::foo_crate;
+// @!has 'foo/fn.foo_self.html'
+pub(self) use reexports::foo_self;
+
+// @has 'foo/type.Type.html' '//*[@class="rust typedef"]' 'pub type Type ='
+pub use reexports::Type;
+// @!has 'foo/type.TypeCrate.html'
+pub(crate) use reexports::TypeCrate;
+// @!has 'foo/type.TypeSelf.html'
+pub(self) use reexports::TypeSelf;
+
+// @has 'foo/union.Union.html' '//*[@class="docblock type-decl"]' 'pub union Union {'
+pub use reexports::Union;
+// @!has 'foo/union.UnionCrate.html'
+pub(crate) use reexports::UnionCrate;
+// @!has 'foo/union.UnionSelf.html'
+pub(self) use reexports::UnionSelf;
mod gravy;
pub fn main() {
- rustc_span::with_default_session_globals(|| parse());
+ rustc_span::create_default_session_globals_then(|| parse());
assert_eq!(gravy::foo(), 10);
}
}
fn main() {
- rustc_span::with_default_session_globals(|| run());
+ rustc_span::create_default_session_globals_then(|| run());
}
fn run() {
--- /dev/null
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:24:1
+ |
+LL | extern "ptx-kernel" fn ptx() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:26:1
+ |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:28:1
+ |
+LL | extern "wasm" fn wasm() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:33:1
+ |
+LL | extern "msp430-interrupt" fn msp430() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:35:1
+ |
+LL | extern "avr-interrupt" fn avr() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:37:1
+ |
+LL | extern "x86-interrupt" fn x86() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+ --> $DIR/unsupported.rs:39:1
+ |
+LL | extern "stdcall" fn stdcall() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+warning: use of calling convention not supported on this target
+ --> $DIR/unsupported.rs:44:1
+ |
+LL | extern "thiscall" fn thiscall() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = 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 #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
--- /dev/null
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:24:1
+ |
+LL | extern "ptx-kernel" fn ptx() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:26:1
+ |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:28:1
+ |
+LL | extern "wasm" fn wasm() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:30:1
+ |
+LL | extern "aapcs" fn aapcs() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:33:1
+ |
+LL | extern "msp430-interrupt" fn msp430() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:35:1
+ |
+LL | extern "avr-interrupt" fn avr() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0570`.
--- /dev/null
+// revisions: x64 i686 aarch64
+//
+// [x64] needs-llvm-components: x86
+// [x64]compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+// [i686] needs-llvm-components: x86
+// [i686]compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
+// [aarch64] needs-llvm-components: aarch64
+// [aarch64]compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
+#![no_core]
+#![feature(
+ no_core,
+ lang_items,
+ abi_ptx,
+ abi_msp430_interrupt,
+ abi_avr_interrupt,
+ abi_thiscall,
+ abi_amdgpu_kernel,
+ wasm_abi,
+ abi_x86_interrupt
+)]
+#[lang="sized"]
+trait Sized { }
+
+extern "ptx-kernel" fn ptx() {}
+//~^ ERROR is not a supported ABI
+extern "amdgpu-kernel" fn amdgpu() {}
+//~^ ERROR is not a supported ABI
+extern "wasm" fn wasm() {}
+//~^ ERROR is not a supported ABI
+extern "aapcs" fn aapcs() {}
+//[x64]~^ ERROR is not a supported ABI
+//[i686]~^^ ERROR is not a supported ABI
+extern "msp430-interrupt" fn msp430() {}
+//~^ ERROR is not a supported ABI
+extern "avr-interrupt" fn avr() {}
+//~^ ERROR is not a supported ABI
+extern "x86-interrupt" fn x86() {}
+//[aarch64]~^ ERROR is not a supported ABI
+extern "stdcall" fn stdcall() {}
+//[x64]~^ WARN use of calling convention not supported
+//[x64]~^^ WARN this was previously accepted
+//[aarch64]~^^^ WARN use of calling convention not supported
+//[aarch64]~^^^^ WARN this was previously accepted
+extern "thiscall" fn thiscall() {}
+//[x64]~^ WARN use of calling convention not supported
+//[x64]~^^ WARN this was previously accepted
+//[aarch64]~^^^ WARN use of calling convention not supported
+//[aarch64]~^^^^ WARN this was previously accepted
--- /dev/null
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:24:1
+ |
+LL | extern "ptx-kernel" fn ptx() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:26:1
+ |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:28:1
+ |
+LL | extern "wasm" fn wasm() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:30:1
+ |
+LL | extern "aapcs" fn aapcs() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:33:1
+ |
+LL | extern "msp430-interrupt" fn msp430() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+ --> $DIR/unsupported.rs:35:1
+ |
+LL | extern "avr-interrupt" fn avr() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+ --> $DIR/unsupported.rs:39:1
+ |
+LL | extern "stdcall" fn stdcall() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+warning: use of calling convention not supported on this target
+ --> $DIR/unsupported.rs:44:1
+ |
+LL | extern "thiscall" fn thiscall() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = 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 #00000 <https://github.com/rust-lang/rust/issues/00000>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
//~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
asm!("", in("ip") foo);
//~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
- asm!("", in("st(2)") foo);
- //~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands
- asm!("", in("mm0") foo);
- //~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands
asm!("", in("k0") foo);
//~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
asm!("", in("ah") foo);
//~^ ERROR invalid register `ah`: high byte registers cannot be used as an operand
+ asm!("", in("st(2)") foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("", in("mm0") foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ asm!("", out("st(2)") _);
+ asm!("", out("mm0") _);
+ asm!("{}", in(x87_reg) foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", in(mmx_reg) foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(x87_reg) _);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(mmx_reg) _);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+
// Explicit register conflicts
// (except in/lateout which don't conflict)
LL | asm!("", in("ip") foo);
| ^^^^^^^^^^^^
-error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm
+error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
+LL | asm!("", in("k0") foo);
+ | ^^^^^^^^^^^^
+
+error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
+ --> $DIR/bad-reg.rs:36:18
+ |
+LL | asm!("", in("ah") foo);
+ | ^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:39:18
+ |
LL | asm!("", in("st(2)") foo);
| ^^^^^^^^^^^^^^^
-error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm
- --> $DIR/bad-reg.rs:36:18
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:41:18
|
LL | asm!("", in("mm0") foo);
| ^^^^^^^^^^^^^
-error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:38:18
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:45:20
|
-LL | asm!("", in("k0") foo);
- | ^^^^^^^^^^^^
+LL | asm!("{}", in(x87_reg) foo);
+ | ^^^^^^^^^^^^^^^
-error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
- --> $DIR/bad-reg.rs:40:18
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:47:20
|
-LL | asm!("", in("ah") foo);
- | ^^^^^^^^^^^^
+LL | asm!("{}", in(mmx_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:49:20
+ |
+LL | asm!("{}", out(x87_reg) _);
+ | ^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:51:20
+ |
+LL | asm!("{}", out(mmx_reg) _);
+ | ^^^^^^^^^^^^^^
error: register `al` conflicts with register `ax`
- --> $DIR/bad-reg.rs:46:33
+ --> $DIR/bad-reg.rs:57:33
|
LL | asm!("", in("eax") foo, in("al") bar);
| ------------- ^^^^^^^^^^^^ register `al`
| register `ax`
error: register `ax` conflicts with register `ax`
- --> $DIR/bad-reg.rs:48:33
+ --> $DIR/bad-reg.rs:59:33
|
LL | asm!("", in("rax") foo, out("rax") bar);
| ------------- ^^^^^^^^^^^^^^ register `ax`
| register `ax`
|
help: use `lateout` instead of `out` to avoid conflict
- --> $DIR/bad-reg.rs:48:18
+ --> $DIR/bad-reg.rs:59:18
|
LL | asm!("", in("rax") foo, out("rax") bar);
| ^^^^^^^^^^^^^
error: register `ymm0` conflicts with register `xmm0`
- --> $DIR/bad-reg.rs:51:34
+ --> $DIR/bad-reg.rs:62:34
|
LL | asm!("", in("xmm0") foo, in("ymm0") bar);
| -------------- ^^^^^^^^^^^^^^ register `ymm0`
| register `xmm0`
error: register `ymm0` conflicts with register `xmm0`
- --> $DIR/bad-reg.rs:53:34
+ --> $DIR/bad-reg.rs:64:34
|
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
| -------------- ^^^^^^^^^^^^^^^ register `ymm0`
| register `xmm0`
|
help: use `lateout` instead of `out` to avoid conflict
- --> $DIR/bad-reg.rs:53:18
+ --> $DIR/bad-reg.rs:64:18
|
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
| ^^^^^^^^^^^^^^
-error: aborting due to 19 previous errors
+error: aborting due to 23 previous errors
macro_rules! pass_nonterminal {
($n:expr) => {
- #[repr(align($n))] //~ ERROR expected unsuffixed literal or identifier, found `n!()`
+ #[repr(align($n))]
+ //~^ ERROR expected unsuffixed literal or identifier, found `n!()`
+ //~| ERROR incorrect `repr(align)` attribute format
struct S;
};
}
|
= note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to previous error
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+ --> $DIR/nonterminal-expansion.rs:5:16
+ |
+LL | #[repr(align($n))]
+ | ^^^^^^^^^
+...
+LL | pass_nonterminal!(n!());
+ | ------------------------ in this macro invocation
+ |
+ = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0693`.
-error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
--> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5
|
LL | fn a(s: &S) {
LL | *s.pointer += 1;
| ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*s.pointer` which is behind a `&` reference
+error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference
--> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5
|
LL | fn c(s: & &mut S) {
-error[E0594]: cannot assign to `**t1` which is behind a `&` reference
+error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
LL | let t1 = t0;
-error[E0594]: cannot assign to `***p` which is behind a `&` reference
+error[E0594]: cannot assign to `***p`, which is behind a `&` reference
--> $DIR/borrowck-issue-14498.rs:16:5
|
LL | let p = &y;
-error[E0594]: cannot assign to `*item` which is behind a `&` reference
+error[E0594]: cannot assign to `*item`, which is behind a `&` reference
--> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9
|
LL | for item in &mut std::iter::empty::<&'static ()>() {
for v in Query.iter_mut() {
//~^ NOTE this iterator yields `&` references
*v -= 1;
- //~^ ERROR cannot assign to `*v` which is behind a `&` reference
+ //~^ ERROR cannot assign to `*v`, which is behind a `&` reference
//~| NOTE `v` is a `&` reference, so the data it refers to cannot be written
}
}
-error[E0594]: cannot assign to `*v` which is behind a `&` reference
+error[E0594]: cannot assign to `*v`, which is behind a `&` reference
--> $DIR/issue-83309-ice-immut-in-for-loop.rs:11:9
|
LL | for v in Query.iter_mut() {
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+
+ let mut mutvar = 42;
+ let r = &mutvar;
+ //~^ HELP consider changing this to be a mutable reference
+ *r = 0;
+ //~^ ERROR cannot assign to `*r`, which is behind a `&` reference
+ //~| NOTE `r` is a `&` reference, so the data it refers to cannot be written
}
LL | rofl.push(Vec::new());
| ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
-error: aborting due to previous error
+error[E0594]: cannot assign to `*r`, which is behind a `&` reference
+ --> $DIR/issue-85765.rs:12:5
+ |
+LL | let r = &mutvar;
+ | ------- help: consider changing this to be a mutable reference: `&mut mutvar`
+LL |
+LL | *r = 0;
+ | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0594, E0596.
+For more information about an error, try `rustc --explain E0594`.
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/mutability-errors.rs:9:5
|
LL | fn named_ref(x: &(i32,)) {
LL | *x = (1,);
| ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `x.0` which is behind a `&` reference
+error[E0594]: cannot assign to `x.0`, which is behind a `&` reference
--> $DIR/mutability-errors.rs:10:5
|
LL | fn named_ref(x: &(i32,)) {
LL | &mut f().0;
| ^^^^^^^^^^ cannot borrow as mutable
-error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
+error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer
--> $DIR/mutability-errors.rs:23:5
|
LL | unsafe fn named_ptr(x: *const (i32,)) {
LL | *x = (1,);
| ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
-error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
+error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer
--> $DIR/mutability-errors.rs:24:5
|
LL | unsafe fn named_ptr(x: *const (i32,)) {
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
extern "stdcall" {
fn printf(_: *const u8, ...); //~ ERROR: variadic function must have C or cdecl calling
error[E0045]: C-variadic function must have C or cdecl calling convention
- --> $DIR/variadic-ffi-1.rs:6:5
+ --> $DIR/variadic-ffi-1.rs:9:5
|
LL | fn printf(_: *const u8, ...);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
- --> $DIR/variadic-ffi-1.rs:17:9
+ --> $DIR/variadic-ffi-1.rs:20:9
|
LL | foo();
| ^^^-- supplied 0 arguments
| expected at least 2 arguments
|
note: function defined here
- --> $DIR/variadic-ffi-1.rs:10:8
+ --> $DIR/variadic-ffi-1.rs:13:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
- --> $DIR/variadic-ffi-1.rs:18:9
+ --> $DIR/variadic-ffi-1.rs:21:9
|
LL | foo(1);
| ^^^ - supplied 1 argument
| expected at least 2 arguments
|
note: function defined here
- --> $DIR/variadic-ffi-1.rs:10:8
+ --> $DIR/variadic-ffi-1.rs:13:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
error[E0308]: mismatched types
- --> $DIR/variadic-ffi-1.rs:20:56
+ --> $DIR/variadic-ffi-1.rs:23:56
|
LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
| ------------------------------------- ^^^ expected non-variadic fn, found variadic function
found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
error[E0308]: mismatched types
- --> $DIR/variadic-ffi-1.rs:21:54
+ --> $DIR/variadic-ffi-1.rs:24:54
|
LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
| ----------------------------------- ^^^ expected variadic fn, found non-variadic function
found fn item `extern "C" fn(_, _) {bar}`
error[E0617]: can't pass `f32` to variadic function
- --> $DIR/variadic-ffi-1.rs:23:19
+ --> $DIR/variadic-ffi-1.rs:26:19
|
LL | foo(1, 2, 3f32);
| ^^^^ help: cast the value to `c_double`: `3f32 as c_double`
error[E0617]: can't pass `bool` to variadic function
- --> $DIR/variadic-ffi-1.rs:24:19
+ --> $DIR/variadic-ffi-1.rs:27:19
|
LL | foo(1, 2, true);
| ^^^^ help: cast the value to `c_int`: `true as c_int`
error[E0617]: can't pass `i8` to variadic function
- --> $DIR/variadic-ffi-1.rs:25:19
+ --> $DIR/variadic-ffi-1.rs:28:19
|
LL | foo(1, 2, 1i8);
| ^^^ help: cast the value to `c_int`: `1i8 as c_int`
error[E0617]: can't pass `u8` to variadic function
- --> $DIR/variadic-ffi-1.rs:26:19
+ --> $DIR/variadic-ffi-1.rs:29:19
|
LL | foo(1, 2, 1u8);
| ^^^ help: cast the value to `c_uint`: `1u8 as c_uint`
error[E0617]: can't pass `i16` to variadic function
- --> $DIR/variadic-ffi-1.rs:27:19
+ --> $DIR/variadic-ffi-1.rs:30:19
|
LL | foo(1, 2, 1i16);
| ^^^^ help: cast the value to `c_int`: `1i16 as c_int`
error[E0617]: can't pass `u16` to variadic function
- --> $DIR/variadic-ffi-1.rs:28:19
+ --> $DIR/variadic-ffi-1.rs:31:19
|
LL | foo(1, 2, 1u16);
| ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint`
+++ /dev/null
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
- --> $DIR/cast-ptr-to-int-const.rs:10:9
- |
-LL | &Y as *const u32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
- |
- = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
- --> $DIR/cast-ptr-to-int-const.rs:17:5
- |
-LL | &0 as *const i32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
- |
- = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
- const Y: u32 = 0;
- // Cast in `const` without `unsafe` block
- const SAFE: usize = {
- &Y as *const u32 as usize
- //~^ ERROR cast of pointer to int is unsafe and requires unsafe
- };
-}
-
-// Cast in `const fn` without `unsafe` block
-const fn test() -> usize {
- &0 as *const i32 as usize
- //~^ ERROR cast of pointer to int is unsafe and requires unsafe
-}
+++ /dev/null
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
- --> $DIR/cast-ptr-to-int-const.rs:10:9
- |
-LL | &Y as *const u32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
- |
- = note: casting pointers to integers in constants
-
-error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
- --> $DIR/cast-ptr-to-int-const.rs:17:5
- |
-LL | &0 as *const i32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
- |
- = note: casting pointers to integers in constants
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-fn main() {
- const X: usize = unsafe {
- main as usize //~ ERROR casting pointers to integers in constants is unstable
- };
- const Y: u32 = 0;
- const Z: usize = unsafe {
- &Y as *const u32 as usize //~ ERROR is unstable
- };
-}
-
-const fn test() -> usize {
- &0 as *const i32 as usize //~ ERROR is unstable
-}
+++ /dev/null
-error[E0658]: casting pointers to integers in constants is unstable
- --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9
- |
-LL | main as usize
- | ^^^^^^^^^^^^^
- |
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constants is unstable
- --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9
- |
-LL | &Y as *const u32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error[E0658]: casting pointers to integers in constant functions is unstable
- --> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5
- |
-LL | &0 as *const i32 as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
let p = t.0.0;
- //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
- //~| NOTE: Capturing t[(0, 0)] -> ByValue
+ //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
println!("{} {:?}", t.1, p);
//~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
LL | | };
| |_____^
|
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
- --> $DIR/by_value.rs:24:17
- |
-LL | let p = t.0.0;
- | ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
--> $DIR/by_value.rs:24:17
|
LL | let p = t.0.0;
| ^^^^^
note: Capturing t[(1, 0)] -> ImmBorrow
- --> $DIR/by_value.rs:28:29
+ --> $DIR/by_value.rs:27:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^
LL | let p = t.0.0;
| ^^^^^
note: Min Capture t[(1, 0)] -> ImmBorrow
- --> $DIR/by_value.rs:28:29
+ --> $DIR/by_value.rs:27:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^
let mut y = (&x, "Y");
let z = (&mut y, "Z");
- // `x.0` is mutable but we access `x` via `z.0.0`, which is an immutable reference and
+ // `x.0` is mutable but we access `x` via `*z.0.0`, which is an immutable reference and
// therefore can't be mutated.
let mut c = || {
- //~^ ERROR: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
+ //~^ ERROR: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference
z.0.0.0 = format!("X1");
};
-error[E0596]: cannot borrow `z.0.0.0` as mutable, as it is behind a `&` reference
+error[E0596]: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference
--> $DIR/cant-mutate-imm-borrow.rs:13:17
|
LL | let mut c = || {
| ^^ cannot borrow as mutable
LL |
LL | z.0.0.0 = format!("X1");
- | ------- mutable borrow occurs due to use of `z.0.0.0` in closure
+ | ------- mutable borrow occurs due to use of `*z.0.0` in closure
error: aborting due to previous error
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
use std::thread;
/* Test Send Trait Migration */
-struct SendPointer (*mut i32);
+struct SendPointer(*mut i32);
unsafe impl Send for SendPointer {}
fn test_send_trait() {
let mut f = 10;
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || { let _ = &fptr; unsafe {
- //~^ ERROR: `Send` trait implementation
+ //~^ ERROR: `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
} });
}
/* Test Sync Trait Migration */
-struct CustomInt (*mut i32);
-struct SyncPointer (CustomInt);
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
unsafe impl Sync for SyncPointer {}
unsafe impl Send for CustomInt {}
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || { let _ = &fptr; unsafe {
- //~^ ERROR: `Sync`, `Send` trait implementation
+ //~^ ERROR: `Sync`, `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
} });
}
struct S(String);
struct T(i32);
-struct U(S,T);
+struct U(S, T);
impl Clone for U {
fn clone(&self) -> Self {
fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || { let _ = &f;
- //~^ ERROR: `Clone` trait implementation, and drop order
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
println!("{:?}", f_1.0);
};
c_clone();
}
+//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
fn main() {
test_send_trait();
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
use std::thread;
/* Test Send Trait Migration */
-struct SendPointer (*mut i32);
+struct SendPointer(*mut i32);
unsafe impl Send for SendPointer {}
fn test_send_trait() {
let mut f = 10;
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || unsafe {
- //~^ ERROR: `Send` trait implementation
+ //~^ ERROR: `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
});
}
/* Test Sync Trait Migration */
-struct CustomInt (*mut i32);
-struct SyncPointer (CustomInt);
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
unsafe impl Sync for SyncPointer {}
unsafe impl Send for CustomInt {}
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || unsafe {
- //~^ ERROR: `Sync`, `Send` trait implementation
+ //~^ ERROR: `Sync`, `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
});
}
struct S(String);
struct T(i32);
-struct U(S,T);
+struct U(S, T);
impl Clone for U {
fn clone(&self) -> Self {
fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || {
- //~^ ERROR: `Clone` trait implementation, and drop order
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
println!("{:?}", f_1.0);
};
c_clone();
}
+//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
fn main() {
test_send_trait();
-error: `Send` trait implementation will change in Rust 2021
- --> $DIR/auto_traits.rs:13:19
+error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
+ --> $DIR/auto_traits.rs:14:19
|
-LL | thread::spawn(move || unsafe {
- | ___________________^
-LL | |
-LL | |
-LL | | *fptr.0 = 20;
-LL | | });
- | |_____^
+LL | thread::spawn(move || unsafe {
+ | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+...
+LL | *fptr.0 = 20;
+ | ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
|
note: the lint level is defined here
--> $DIR/auto_traits.rs:2:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `fptr` to be fully captured
|
LL | thread::spawn(move || { let _ = &fptr; unsafe {
LL |
LL |
+LL |
+LL |
LL | *fptr.0 = 20;
-LL | } });
- |
+ ...
-error: `Sync`, `Send` trait implementation will change in Rust 2021
- --> $DIR/auto_traits.rs:30:19
+error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+ --> $DIR/auto_traits.rs:34:19
|
-LL | thread::spawn(move || unsafe {
- | ___________________^
-LL | |
-LL | |
-LL | | *fptr.0.0 = 20;
-LL | | });
- | |_____^
+LL | thread::spawn(move || unsafe {
+ | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+...
+LL | *fptr.0.0 = 20;
+ | --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `fptr` to be fully captured
LL | thread::spawn(move || { let _ = &fptr; unsafe {
LL |
LL |
+LL |
+LL |
LL | *fptr.0.0 = 20;
-LL | } });
- |
+ ...
-error: `Clone` trait implementation, and drop order will change in Rust 2021
- --> $DIR/auto_traits.rs:51:13
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+ --> $DIR/auto_traits.rs:58:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | | let f_1 = f.1;
-LL | | println!("{:?}", f_1.0);
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+...
+LL | let f_1 = f.1;
+ | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+...
+LL | }
+ | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
LL | let c = || { let _ = &f;
LL |
LL |
+LL |
+LL |
LL | let f_1 = f.1;
-LL | println!("{:?}", f_1.0);
-LL | };
- |
+ ...
error: aborting due to 3 previous errors
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test cases for types that implement a insignificant drop (stlib defined)
let t2 = (String::new(), String::new());
let c = || { let _ = (&t, &t1, &t2);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t2 = (String::new(), String::new());
let c = || { let _ = (&t, &t1);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
println!("{}", t1.1);
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Copy types get copied into the closure instead of move. Therefore we don't need to
// migrate then as their drop order isn't tied to the closure.
let t1 = (0i32, 0i32);
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn test5_only_drop_types_need_migration() {
struct S(i32, i32);
let s = S(0i32, 0i32);
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _s = s.0;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = move || { let _ = (&t1, &t);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{} {}", t1.1, t.1);
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
let t = (String::new(), String::new(), 0i32);
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn main() {
test1_all_need_migration();
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test cases for types that implement a insignificant drop (stlib defined)
let t2 = (String::new(), String::new());
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t2 = (String::new(), String::new());
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
println!("{}", t1.1);
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Copy types get copied into the closure instead of move. Therefore we don't need to
// migrate then as their drop order isn't tied to the closure.
let t1 = (0i32, 0i32);
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn test5_only_drop_types_need_migration() {
struct S(i32, i32);
let s = S(0i32, 0i32);
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _s = s.0;
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
let c = move || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{} {}", t1.1, t.1);
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
let t = (String::new(), String::new(), 0i32);
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn main() {
test1_all_need_migration();
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:15:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-... |
-LL | | let _t2 = t2.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL | let _t1 = t1.0;
+ | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+LL |
+LL | let _t2 = t2.0;
+ | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+ | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
|
note: the lint level is defined here
--> $DIR/insignificant_drop.rs:3:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
LL | let _t = t.0;
...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:35:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-... |
-LL | | let _t2 = t2;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:41:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL | let _t1 = t1.0;
+ | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | let _t1 = t1.0;
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:52:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | println!("{}", t1.1);
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:62:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | println!("{}", t1.1);
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:71:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | let _t1 = t1.0;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:83:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | let _t1 = t1.0;
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:90:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | let _s = s.0;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:104:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | let _s = s.0;
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:106:13
- |
-LL | let c = move || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | println!("{} {}", t1.1, t.1);
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:122:13
+ |
+LL | let c = move || {
+ | ^^^^^^^
+...
+LL | println!("{} {}", t1.1, t.1);
+ | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | |
+ | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
LL |
LL |
LL | println!("{} {}", t1.1, t.1);
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop.rs:122:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop.rs:142:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | };
- |
+LL |
+ ...
error: aborting due to 7 previous errors
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
-
#![feature(rustc_attrs)]
#![allow(unused)]
let t = (SigDrop {}, SigDrop {});
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Even if a type implements an insignificant drop, if it's
// elements have a significant drop then the overall type is
// move is used to force i32 to be copied instead of being a ref
let c = move || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
fn main() {
significant_drop_needs_migration();
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
-
#![feature(rustc_attrs)]
#![allow(unused)]
let t = (SigDrop {}, SigDrop {});
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Even if a type implements an insignificant drop, if it's
// elements have a significant drop then the overall type is
// move is used to force i32 to be copied instead of being a ref
let c = move || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
fn main() {
significant_drop_needs_migration();
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop_attr_migrations.rs:38:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop_attr_migrations.rs:37:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
note: the lint level is defined here
--> $DIR/insignificant_drop_attr_migrations.rs:3:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL |
LL |
LL | let _t = t.0;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/insignificant_drop_attr_migrations.rs:56:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/insignificant_drop_attr_migrations.rs:57:13
|
-LL | let c = move || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.1;
-LL | | };
- | |_____^
+LL | let c = move || {
+ | ^^^^^^^
+...
+LL | let _t = t.1;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.1;
-LL | };
- |
+LL |
+ ...
error: aborting due to 2 previous errors
// run-pass
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
#![feature(rustc_attrs)]
#![allow(unused)]
// run-pass
-#![warn(disjoint_capture_migration)]
+#![warn(rust_2021_incompatible_closure_captures)]
fn main() {
if let a = "" {
- //~^ WARNING: irrefutable `if let` pattern
+ //~^ WARNING: irrefutable `if let` pattern
drop(|_: ()| drop(a));
}
}
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test the two possible cases for automated migartion using rustfix
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn closure_doesnt_contain_block() {
let t = (Foo(0), Foo(0));
let c = || { let _ = &t; t.0 };
//~^ ERROR: drop order
+ //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn main() {
closure_contains_block();
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test the two possible cases for automated migartion using rustfix
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn closure_doesnt_contain_block() {
let t = (Foo(0), Foo(0));
let c = || t.0;
//~^ ERROR: drop order
+ //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
fn main() {
closure_contains_block();
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/migrations_rustfix.rs:19:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
note: the lint level is defined here
--> $DIR/migrations_rustfix.rs:2:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL |
LL |
LL | let _t = t.0;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/migrations_rustfix.rs:31:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/migrations_rustfix.rs:33:13
|
LL | let c = || t.0;
- | ^^^^^^
+ | ^^^---
+ | |
+ | in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
// ignore-wasm32-bare compiled with panic=abort by default
-
#![feature(fn_traits)]
#![feature(never_type)]
use std::panic;
-fn foo_diverges() -> ! { panic!() }
+fn foo_diverges() -> ! {
+ panic!()
+}
-fn assert_panics<F>(f: F) where F: FnOnce() {
+fn assert_panics<F>(f: F)
+where
+ F: FnOnce(),
+{
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || { let _ = &f;
- //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation
+ //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
+ //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
});
if let Ok(..) = result {
panic!("diverging function returned");
}
fn test_fn_ptr_panic<T>(mut t: T)
- where T: Fn() -> !
+where
+ T: Fn() -> !,
{
let as_fn = <T as Fn<()>>::call;
assert_panics(|| as_fn(&t, ()));
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
// ignore-wasm32-bare compiled with panic=abort by default
-
#![feature(fn_traits)]
#![feature(never_type)]
use std::panic;
-fn foo_diverges() -> ! { panic!() }
+fn foo_diverges() -> ! {
+ panic!()
+}
-fn assert_panics<F>(f: F) where F: FnOnce() {
+fn assert_panics<F>(f: F)
+where
+ F: FnOnce(),
+{
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || {
- //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation
+ //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+ //~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
+ //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
});
if let Ok(..) = result {
panic!("diverging function returned");
}
fn test_fn_ptr_panic<T>(mut t: T)
- where T: Fn() -> !
+where
+ T: Fn() -> !,
{
let as_fn = <T as Fn<()>>::call;
assert_panics(|| as_fn(&t, ()));
-error: `UnwindSafe`, `RefUnwindSafe` trait implementation will change in Rust 2021
- --> $DIR/mir_calls_to_shims.rs:15:38
+error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+ --> $DIR/mir_calls_to_shims.rs:20:38
|
-LL | let result = panic::catch_unwind(move || {
- | ______________________________________^
-LL | |
-LL | |
-LL | | f.0()
-LL | | });
- | |_____^
+LL | let result = panic::catch_unwind(move || {
+ | ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+...
+LL | f.0()
+ | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
|
note: the lint level is defined here
--> $DIR/mir_calls_to_shims.rs:3:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
LL | let result = panic::catch_unwind(move || { let _ = &f;
LL |
LL |
+LL |
+LL |
LL | f.0()
-LL | });
- |
+ ...
error: aborting due to previous error
--- /dev/null
+// run-rustfix
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+use std::thread;
+
+struct S(String);
+
+#[derive(Clone)]
+struct T(i32);
+
+struct U(S, T);
+
+impl Clone for U {
+ fn clone(&self) -> Self {
+ U(S(String::from("Hello World")), T(0))
+ }
+}
+
+fn test_multi_issues() {
+ let f1 = U(S(String::from("foo")), T(0));
+ let f2 = U(S(String::from("bar")), T(0));
+ let c = || { let _ = (&f1, &f2);
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
+ let _f_1 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f2.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+
+fn test_capturing_all_disjoint_fields_individually() {
+ let f1 = U(S(String::from("foo")), T(0));
+ let c = || { let _ = &f1;
+ //~^ ERROR: `Clone` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_1 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f1.1;
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+
+struct U1(S, T, S);
+
+impl Clone for U1 {
+ fn clone(&self) -> Self {
+ U1(S(String::from("foo")), T(0), S(String::from("bar")))
+ }
+}
+
+fn test_capturing_several_disjoint_fields_individually_1() {
+ let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+ let c = || { let _ = &f1;
+ //~^ ERROR: `Clone` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_0 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f1.2;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+
+fn test_capturing_several_disjoint_fields_individually_2() {
+ let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+ let c = || { let _ = &f1;
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_0 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_1 = f1.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+
+struct SendPointer(*mut i32);
+unsafe impl Send for SendPointer {}
+
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
+unsafe impl Sync for SyncPointer {}
+unsafe impl Send for CustomInt {}
+
+fn test_multi_traits_issues() {
+ let mut f1 = 10;
+ let f1 = CustomInt(&mut f1 as *mut i32);
+ let fptr1 = SyncPointer(f1);
+
+ let mut f2 = 10;
+ let fptr2 = SendPointer(&mut f2 as *mut i32);
+ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
+ //~^ ERROR: `Sync`, `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+ *fptr1.0.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+ *fptr2.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ } });
+}
+
+fn main() {
+ test_multi_issues();
+ test_capturing_all_disjoint_fields_individually();
+ test_capturing_several_disjoint_fields_individually_1();
+ test_capturing_several_disjoint_fields_individually_2();
+ test_multi_traits_issues();
+}
--- /dev/null
+// run-rustfix
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+use std::thread;
+
+struct S(String);
+
+#[derive(Clone)]
+struct T(i32);
+
+struct U(S, T);
+
+impl Clone for U {
+ fn clone(&self) -> Self {
+ U(S(String::from("Hello World")), T(0))
+ }
+}
+
+fn test_multi_issues() {
+ let f1 = U(S(String::from("foo")), T(0));
+ let f2 = U(S(String::from("bar")), T(0));
+ let c = || {
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
+ let _f_1 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f2.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+
+fn test_capturing_all_disjoint_fields_individually() {
+ let f1 = U(S(String::from("foo")), T(0));
+ let c = || {
+ //~^ ERROR: `Clone` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_1 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f1.1;
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+
+struct U1(S, T, S);
+
+impl Clone for U1 {
+ fn clone(&self) -> Self {
+ U1(S(String::from("foo")), T(0), S(String::from("bar")))
+ }
+}
+
+fn test_capturing_several_disjoint_fields_individually_1() {
+ let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+ let c = || {
+ //~^ ERROR: `Clone` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_0 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_2 = f1.2;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+
+fn test_capturing_several_disjoint_fields_individually_2() {
+ let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
+ let c = || {
+ //~^ ERROR: `Clone` trait implementation for closure and drop order
+ //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `f1` to be fully captured
+ let _f_0 = f1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ let _f_1 = f1.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+ };
+
+ let c_clone = c.clone();
+
+ c_clone();
+}
+//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+
+struct SendPointer(*mut i32);
+unsafe impl Send for SendPointer {}
+
+struct CustomInt(*mut i32);
+struct SyncPointer(CustomInt);
+unsafe impl Sync for SyncPointer {}
+unsafe impl Send for CustomInt {}
+
+fn test_multi_traits_issues() {
+ let mut f1 = 10;
+ let f1 = CustomInt(&mut f1 as *mut i32);
+ let fptr1 = SyncPointer(f1);
+
+ let mut f2 = 10;
+ let fptr2 = SendPointer(&mut f2 as *mut i32);
+ thread::spawn(move || unsafe {
+ //~^ ERROR: `Sync`, `Send` trait implementation for closure
+ //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+ *fptr1.0.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+ *fptr2.0 = 20;
+ //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ });
+}
+
+fn main() {
+ test_multi_issues();
+ test_capturing_all_disjoint_fields_individually();
+ test_capturing_several_disjoint_fields_individually_1();
+ test_capturing_several_disjoint_fields_individually_2();
+ test_multi_traits_issues();
+}
--- /dev/null
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+ --> $DIR/multi_diagnostics.rs:23:13
+ |
+LL | let c = || {
+ | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL | let _f_1 = f1.0;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL | let _f_2 = f2.1;
+ | ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+...
+LL | }
+ | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+ |
+note: the lint level is defined here
+ --> $DIR/multi_diagnostics.rs:2:9
+ |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1`, `f2` to be fully captured
+ |
+LL | let c = || { let _ = (&f1, &f2);
+LL |
+LL |
+LL |
+LL |
+LL | let _f_1 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
+ --> $DIR/multi_diagnostics.rs:42:13
+ |
+LL | let c = || {
+ | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL | let _f_1 = f1.0;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ |
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+ |
+LL | let c = || { let _ = &f1;
+LL |
+LL |
+LL |
+LL |
+LL | let _f_1 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
+ --> $DIR/multi_diagnostics.rs:67:13
+ |
+LL | let c = || {
+ | ^^
+ | |
+ | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+...
+LL | let _f_0 = f1.0;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL | let _f_2 = f1.2;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ |
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+ |
+LL | let c = || { let _ = &f1;
+LL |
+LL |
+LL |
+LL |
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
+ --> $DIR/multi_diagnostics.rs:86:13
+ |
+LL | let c = || {
+ | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+...
+LL | let _f_0 = f1.0;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+LL |
+LL | let _f_1 = f1.1;
+ | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+ | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+ |
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `f1` to be fully captured
+ |
+LL | let c = || { let _ = &f1;
+LL |
+LL |
+LL |
+LL |
+LL | let _f_0 = f1.0;
+ ...
+
+error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+ --> $DIR/multi_diagnostics.rs:119:19
+ |
+LL | thread::spawn(move || unsafe {
+ | ^^^^^^^^^^^^^^
+ | |
+ | in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ | in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+...
+LL | *fptr1.0.0 = 20;
+ | ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+LL |
+LL | *fptr2.0 = 20;
+ | -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ |
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
+ |
+LL | thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
+LL |
+LL |
+LL |
+LL |
+LL |
+ ...
+
+error: aborting due to 5 previous errors
+
// Set of test cases that don't need migrations
-#![deny(disjoint_capture_migration)]
-
+#![deny(rust_2021_incompatible_closure_captures)]
// Copy types as copied by the closure instead of being moved into the closure
// Therefore their drop order isn't tied to the closure and won't be requiring any
c();
}
-
struct Foo(i32);
impl Drop for Foo {
fn drop(&mut self) {
test3_only_copy_types_move_closure();
test4_insignificant_drop_non_drop_aggregate();
test5_significant_drop_non_drop_aggregate();
-
}
--- /dev/null
+// check-pass
+
+// Ensure that the old name for `rust_2021_incompatible_closure_captures` is still
+// accepted by the compiler
+
+#![allow(disjoint_capture_migration)]
+//~^ WARN lint `disjoint_capture_migration` has been renamed
+
+fn main() {}
--- /dev/null
+warning: lint `disjoint_capture_migration` has been renamed to `rust_2021_incompatible_closure_captures`
+ --> $DIR/old_name.rs:6:10
+ |
+LL | #![allow(disjoint_capture_migration)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rust_2021_incompatible_closure_captures`
+ |
+ = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+warning: 1 warning emitted
+
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
#[derive(Debug)]
struct Foo(i32);
let t = ConstainsDropField(Foo(10), Foo(20));
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t = &t.1;
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
struct S;
impl Drop for S {
- fn drop(&mut self) {
- }
+ fn drop(&mut self) {}
}
struct T(S, S);
let u = U(T(S, S), T(S, S));
let c = || { let _ = &u;
- //~^ ERROR: drop order
- //~| HELP: add a dummy let to cause `u` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `u` to be fully captured
let _x = u.0.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
let _x = u.0.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
let _x = u.1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+
fn main() {
test_precise_analysis_drop_paths_not_captured_by_move();
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
#[derive(Debug)]
struct Foo(i32);
let t = ConstainsDropField(Foo(10), Foo(20));
let c = || {
- //~^ ERROR: drop order
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t = &t.1;
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
struct S;
impl Drop for S {
- fn drop(&mut self) {
- }
+ fn drop(&mut self) {}
}
struct T(S, S);
let u = U(T(S, S), T(S, S));
let c = || {
- //~^ ERROR: drop order
- //~| HELP: add a dummy let to cause `u` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `u` to be fully captured
let _x = u.0.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
let _x = u.0.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
let _x = u.1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+
fn main() {
test_precise_analysis_drop_paths_not_captured_by_move();
-error: drop order will change in Rust 2021
- --> $DIR/precise.rs:19:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/precise.rs:20:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | let _t = &t.1;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
note: the lint level is defined here
--> $DIR/precise.rs:3:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL | let c = || { let _ = &t;
LL |
LL |
+LL |
LL | let _t = t.0;
-LL | let _t = &t.1;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/precise.rs:42:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/precise.rs:45:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | | let _x = u.0.0;
-LL | | let _x = u.0.1;
-LL | | let _x = u.1.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _x = u.0.0;
+ | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+LL |
+LL | let _x = u.0.1;
+ | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+LL |
+LL | let _x = u.1.0;
+ | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
+ | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
+ | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `u` to be fully captured
LL | let c = || { let _ = &u;
LL |
LL |
+LL |
LL | let _x = u.0.0;
-LL | let _x = u.0.1;
-LL | let _x = u.1.0;
+LL |
...
error: aborting due to 2 previous errors
// run-pass
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
#[derive(Debug)]
struct Foo(i32);
struct S;
impl Drop for S {
- fn drop(&mut self) {
- }
+ fn drop(&mut self) {}
}
struct T(S, S);
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test cases for types that implement a significant drop (user defined)
let t2 = (Foo(0), Foo(0));
let c = || { let _ = (&t, &t1, &t2);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t2 = (Foo(0), Foo(0));
let c = || { let _ = (&t, &t1);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2;
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0));
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
println!("{:?}", t1.1);
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// The root variable might not implement drop themselves but some path starting
// at the root variable might implement Drop.
let t = ConstainsDropField(Foo(0), Foo(0));
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
let t = (Foo(0), Foo(0), 0i32);
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Test migration analysis in case of Significant and Insignificant Drop aggregates.
fn test6_significant_insignificant_drop_aggregate_need_migration() {
let t = (Foo(0), String::new());
let c = || { let _ = &t;
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
let t1 = (Foo(0), Foo(0), Foo(0));
let c = move || { let _ = (&t1, &t);
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{:?} {:?}", t1.1, t.1);
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+
+
+fn test8_drop_order_and_blocks() {
+ {
+ let tuple =
+ (String::from("foo"), String::from("bar"));
+ {
+ let c = || { let _ = &tuple;
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `tuple` to be fully captured
+ tuple.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ };
+
+ c();
+ }
+ //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ }
+}
+
+fn test9_drop_order_and_nested_closures() {
+ let tuple =
+ (String::from("foo"), String::from("bar"));
+ let b = || {
+ let c = || { let _ = &tuple;
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `tuple` to be fully captured
+ tuple.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ };
+
+ c();
+ };
+ //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+
+ b();
+}
fn main() {
test1_all_need_migration();
test5_drop_non_drop_aggregate_need_migration();
test6_significant_insignificant_drop_aggregate_need_migration();
test7_move_closures_non_copy_types_might_need_migration();
+ test8_drop_order_and_blocks();
+ test9_drop_order_and_nested_closures();
}
// run-rustfix
-#![deny(disjoint_capture_migration)]
+#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
// Test cases for types that implement a significant drop (user defined)
let t2 = (Foo(0), Foo(0));
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t2 = (Foo(0), Foo(0));
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
let _t1 = t1.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
let _t2 = t2;
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0));
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
println!("{:?}", t1.1);
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// The root variable might not implement drop themselves but some path starting
// at the root variable might implement Drop.
let t = ConstainsDropField(Foo(0), Foo(0));
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
let t = (Foo(0), Foo(0), 0i32);
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
// Test migration analysis in case of Significant and Insignificant Drop aggregates.
fn test6_significant_insignificant_drop_aggregate_need_migration() {
let t = (Foo(0), String::new());
let c = || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
+ //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
let t1 = (Foo(0), Foo(0), Foo(0));
let c = move || {
- //~^ ERROR: drop order
- //~| NOTE: for more information, see
- //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{:?} {:?}", t1.1, t.1);
+ //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
};
c();
}
+//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+
+
+fn test8_drop_order_and_blocks() {
+ {
+ let tuple =
+ (String::from("foo"), String::from("bar"));
+ {
+ let c = || {
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `tuple` to be fully captured
+ tuple.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ };
+
+ c();
+ }
+ //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ }
+}
+
+fn test9_drop_order_and_nested_closures() {
+ let tuple =
+ (String::from("foo"), String::from("bar"));
+ let b = || {
+ let c = || {
+ //~^ ERROR: drop order
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `tuple` to be fully captured
+ tuple.0;
+ //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ };
+
+ c();
+ };
+ //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+
+ b();
+}
fn main() {
test1_all_need_migration();
test5_drop_non_drop_aggregate_need_migration();
test6_significant_insignificant_drop_aggregate_need_migration();
test7_move_closures_non_copy_types_might_need_migration();
+ test8_drop_order_and_blocks();
+ test9_drop_order_and_nested_closures();
}
-error: drop order will change in Rust 2021
+error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:25:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-... |
-LL | | let _t2 = t2.0;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL | let _t1 = t1.0;
+ | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+LL |
+LL | let _t2 = t2.0;
+ | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+ | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
|
note: the lint level is defined here
--> $DIR/significant_drop.rs:2:9
|
-LL | #![deny(disjoint_capture_migration)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
LL |
LL |
LL | let _t = t.0;
-LL | let _t1 = t1.0;
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:44:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-... |
-LL | | let _t2 = t2;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:50:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+LL |
+LL | let _t1 = t1.0;
+ | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | let _t1 = t1.0;
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:61:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | println!("{:?}", t1.1);
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:71:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | println!("{:?}", t1.1);
+LL |
...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:79:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:91:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:95:13
- |
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.0;
-LL | | };
- | |_____^
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:109:13
+ |
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.0;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.0;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:109:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:125:13
|
-LL | let c = || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | let _t = t.1;
-LL | | };
- | |_____^
+LL | let c = || {
+ | ^^
+...
+LL | let _t = t.1;
+ | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+...
+LL | }
+ | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
LL |
LL |
LL | let _t = t.1;
-LL | };
- |
+LL |
+ ...
-error: drop order will change in Rust 2021
- --> $DIR/significant_drop.rs:125:13
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:143:13
|
-LL | let c = move || {
- | _____________^
-LL | |
-LL | |
-LL | |
-LL | | println!("{:?} {:?}", t1.1, t.1);
-LL | | };
- | |_____^
+LL | let c = move || {
+ | ^^^^^^^
+...
+LL | println!("{:?} {:?}", t1.1, t.1);
+ | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | |
+ | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+...
+LL | }
+ | -
+ | |
+ | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+ | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
LL |
LL |
LL | println!("{:?} {:?}", t1.1, t.1);
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:163:21
+ |
+LL | let c = || {
+ | ^^
+...
+LL | tuple.0;
+ | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+...
+LL | }
+ | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ |
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `tuple` to be fully captured
+ |
+LL | let c = || { let _ = &tuple;
+LL |
+LL |
+LL |
+LL | tuple.0;
+LL |
+ ...
+
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/significant_drop.rs:181:17
+ |
+LL | let c = || {
+ | ^^
+...
+LL | tuple.0;
+ | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+...
LL | };
+ | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `tuple` to be fully captured
+ |
+LL | let c = || { let _ = &tuple;
+LL |
+LL |
+LL |
+LL | tuple.0;
+LL |
+ ...
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
--- /dev/null
+//run-pass
+#![deny(rust_2021_incompatible_closure_captures)]
+#![allow(unused_must_use)]
+
+fn filter_try_fold(
+ predicate: &mut impl FnMut() -> bool,
+) -> impl FnMut() -> bool + '_ {
+ move || predicate()
+}
+
+fn main() {
+ filter_try_fold(&mut || true);
+}
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
t.0.0 = "new S".into();
- //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> ByValue
+ //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
//~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
};
c();
//~| ERROR: Min Capture analysis includes:
let _t = t.0.0;
//~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
- //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
};
c();
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
let _t = t.0.0;
- //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
- //~| NOTE: Capturing t[(0, 0)] -> ByValue
+ //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
//~| NOTE: Min Capture t[(0, 0)] -> ByValue
};
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
let _t = b.0;
- //~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
- //~| NOTE: Capturing b[] -> ByValue
+ //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture b[] -> ByValue
};
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
println!("{}", b.0);
- //~^ NOTE: Capturing b[Deref,(0, 0)] -> ByValue
+ //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture b[] -> ByValue
};
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
println!("{}", t.1.0);
- //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
+ //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
//~| NOTE: Min Capture t[(1, 0)] -> ByValue
};
}
+struct Foo { x: i32 }
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_1() {
+ let mut foo = Foo { x: 0 } ;
+
+ let p_foo = &mut foo;
+ let box_p_foo = Box::new(p_foo);
+
+ let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| First Pass analysis includes:
+ //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ //~| Min Capture analysis includes:
+ //~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+}
+
+// Ensure that even in move closures, if the data is not owned by the root variable
+// then we don't truncate the derefs or a ByValue capture, rather do a reborrow
+fn box_mut_2() {
+ let foo = Foo { x: 0 } ;
+
+ let mut box_foo = Box::new(foo);
+ let p_foo = &mut box_foo;
+
+ let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| First Pass analysis includes:
+ //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ //~| Min Capture analysis includes:
+ //~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+}
+
fn main() {
simple_move_closure();
simple_ref();
struct_contains_ref_to_another_struct_2();
struct_contains_ref_to_another_struct_3();
truncate_box_derefs();
+ box_mut_2();
+ box_mut_1();
}
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
- --> $DIR/move_closure.rs:118:13
+ --> $DIR/move_closure.rs:117:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
- --> $DIR/move_closure.rs:135:13
+ --> $DIR/move_closure.rs:133:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
- --> $DIR/move_closure.rs:152:13
+ --> $DIR/move_closure.rs:150:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/move_closure.rs:172:13
+ |
+LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/move_closure.rs:189:13
+ |
+LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
error: First Pass analysis includes:
--> $DIR/move_closure.rs:15:5
|
LL | | };
| |_____^
|
-note: Capturing t[(0, 0),(0, 0)] -> ByValue
+note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
--> $DIR/move_closure.rs:18:9
|
LL | t.0.0 = "new S".into();
LL | | };
| |_____^
|
-note: Min Capture t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+note: Min Capture t[(0, 0),Deref] -> ImmBorrow
--> $DIR/move_closure.rs:80:18
|
LL | let _t = t.0.0;
LL | |
LL | |
LL | | let _t = t.0.0;
-... |
+LL | |
LL | |
LL | | };
| |_____^
|
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
- --> $DIR/move_closure.rs:102:18
- |
-LL | let _t = t.0.0;
- | ^^^^^
-note: Capturing t[(0, 0)] -> ByValue
+note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
--> $DIR/move_closure.rs:102:18
|
LL | let _t = t.0.0;
LL | |
LL | |
LL | | let _t = t.0.0;
-... |
+LL | |
LL | |
LL | | };
| |_____^
| ^^^^^
error: First Pass analysis includes:
- --> $DIR/move_closure.rs:121:5
+ --> $DIR/move_closure.rs:120:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = b.0;
-... |
+LL | |
LL | |
LL | | };
| |_____^
|
-note: Capturing b[Deref,(0, 0)] -> ByValue
- --> $DIR/move_closure.rs:124:18
- |
-LL | let _t = b.0;
- | ^^^
-note: Capturing b[] -> ByValue
- --> $DIR/move_closure.rs:124:18
+note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+ --> $DIR/move_closure.rs:123:18
|
LL | let _t = b.0;
| ^^^
error: Min Capture analysis includes:
- --> $DIR/move_closure.rs:121:5
+ --> $DIR/move_closure.rs:120:5
|
LL | / move || {
LL | |
LL | |
LL | | let _t = b.0;
-... |
+LL | |
LL | |
LL | | };
| |_____^
|
note: Min Capture b[] -> ByValue
- --> $DIR/move_closure.rs:124:18
+ --> $DIR/move_closure.rs:123:18
|
LL | let _t = b.0;
| ^^^
error: First Pass analysis includes:
- --> $DIR/move_closure.rs:138:5
+ --> $DIR/move_closure.rs:136:5
|
LL | / move || {
LL | |
LL | | };
| |_____^
|
-note: Capturing b[Deref,(0, 0)] -> ByValue
- --> $DIR/move_closure.rs:141:24
+note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+ --> $DIR/move_closure.rs:139:24
|
LL | println!("{}", b.0);
| ^^^
error: Min Capture analysis includes:
- --> $DIR/move_closure.rs:138:5
+ --> $DIR/move_closure.rs:136:5
|
LL | / move || {
LL | |
| |_____^
|
note: Min Capture b[] -> ByValue
- --> $DIR/move_closure.rs:141:24
+ --> $DIR/move_closure.rs:139:24
|
LL | println!("{}", b.0);
| ^^^
error: First Pass analysis includes:
- --> $DIR/move_closure.rs:155:5
+ --> $DIR/move_closure.rs:153:5
|
LL | / move || {
LL | |
LL | | };
| |_____^
|
-note: Capturing t[(1, 0),Deref,(0, 0)] -> ByValue
- --> $DIR/move_closure.rs:158:24
+note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
+ --> $DIR/move_closure.rs:156:24
|
LL | println!("{}", t.1.0);
| ^^^^^
error: Min Capture analysis includes:
- --> $DIR/move_closure.rs:155:5
+ --> $DIR/move_closure.rs:153:5
|
LL | / move || {
LL | |
| |_____^
|
note: Min Capture t[(1, 0)] -> ByValue
- --> $DIR/move_closure.rs:158:24
+ --> $DIR/move_closure.rs:156:24
|
LL | println!("{}", t.1.0);
| ^^^^^
-error: aborting due to 24 previous errors
+error: First Pass analysis includes:
+ --> $DIR/move_closure.rs:172:39
+ |
+LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ --> $DIR/move_closure.rs:172:47
+ |
+LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ | ^^^^^^^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/move_closure.rs:172:39
+ |
+LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ --> $DIR/move_closure.rs:172:47
+ |
+LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
+ | ^^^^^^^^^^^
+
+error: First Pass analysis includes:
+ --> $DIR/move_closure.rs:189:39
+ |
+LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: Capturing p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ --> $DIR/move_closure.rs:189:47
+ |
+LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ | ^^^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/move_closure.rs:189:39
+ |
+LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: Min Capture p_foo[Deref,Deref,(0, 0)] -> UniqueImmBorrow
+ --> $DIR/move_closure.rs:189:47
+ |
+LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10;
+ | ^^^^^^^
+
+error: aborting due to 30 previous errors
For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// edition:2021
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+#![allow(dead_code)]
+
+struct Int(i32);
+struct B<'a>(&'a i32);
+
+const I : Int = Int(0);
+const REF_I : &'static Int = &I;
+
+
+struct MyStruct<'a> {
+ a: &'static Int,
+ b: B<'a>,
+}
+
+fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+ let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ //~| ERROR: First Pass analysis includes:
+ //~| ERROR: Min Capture analysis includes:
+ //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
+ //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+ c
+}
+
+fn main() {
+ let t = 0;
+ let s = MyStruct { a: REF_I, b: B(&t) };
+ let _ = foo(&s);
+}
--- /dev/null
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/edge_case.rs:20:13
+ |
+LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+ --> $DIR/edge_case.rs:20:39
+ |
+LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ | ^^^^^^^^^^^^^^^
+ |
+note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
+ --> $DIR/edge_case.rs:20:48
+ |
+LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ | ^^^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/edge_case.rs:20:39
+ |
+LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ | ^^^^^^^^^^^^^^^
+ |
+note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+ --> $DIR/edge_case.rs:20:48
+ |
+LL | let c = #[rustc_capture_analysis] || drop(&m.a.0);
+ | ^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// edition:2021
+// run-pass
+
+#![allow(unused)]
+#![allow(dead_code)]
+
+struct Int(i32);
+struct B<'a>(&'a i32);
+
+const I : Int = Int(0);
+const REF_I : &'static Int = &I;
+
+struct MyStruct<'a> {
+ a: &'static Int,
+ b: B<'a>,
+}
+
+fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
+ let c = || drop(&m.a.0);
+ c
+}
+
+fn main() {
+ let t = 0;
+ let s = MyStruct { a: REF_I, b: B(&t) };
+ let _ = foo(&s);
+}
--- /dev/null
+// check-pass
+#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+struct Bar<const N: usize>(Foo<N, 3>);
+fn main() {}
+++ /dev/null
-error: constant expression depends on a generic parameter
- --> $DIR/complex-generic-default-expr.rs:6:34
- |
-LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
- | ^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
- --> $DIR/complex-generic-default-expr.rs:10:21
- |
-LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
- | ^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
error: generic parameters may not be used in const operations
- --> $DIR/complex-generic-default-expr.rs:6:47
+ --> $DIR/complex-generic-default-expr.rs:7:47
|
LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
| ^ cannot perform const operation using `N`
// revisions: full min
+//[full] check-pass
#![cfg_attr(full, feature(const_generics))]
#![feature(const_generics_defaults)]
#![allow(incomplete_features)]
struct Foo<const N: usize, const M: usize = { N + 1 }>;
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
fn main() {}
+++ /dev/null
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
- const OK: usize = unsafe { 0 as *const i32 as usize };
-
- const _ERROR: usize = unsafe { &0 as *const i32 as usize };
- //~^ ERROR [const_err]
- //~| NOTE cannot cast pointer to integer because it was not created by cast from integer
- //~| NOTE
- //~| NOTE `#[deny(const_err)]` on by default
- //~| WARN this was previously accepted by the compiler but is being phased out
- //~| NOTE see issue #71800
-}
+++ /dev/null
-error: any use of this value will cause an error
- --> $DIR/ptr_to_usize_cast.rs:6:36
- |
-LL | const _ERROR: usize = unsafe { &0 as *const i32 as usize };
- | -------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | cannot cast pointer to integer because it was not created by cast from integer
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
#![feature(const_panic)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
#![crate_type = "lib"]
const MSG: &str = "hello";
--- /dev/null
+#![feature(const_panic)]
+#![allow(non_fmt_panics)]
+#![crate_type = "lib"]
+
+#[track_caller]
+const fn a() -> u32 {
+ panic!("hey")
+}
+
+#[track_caller]
+const fn b() -> u32 {
+ a()
+}
+
+const fn c() -> u32 {
+ b()
+ //~^ ERROR evaluation of constant value failed
+ //~| NOTE the evaluated program panicked
+ //~| NOTE inside
+}
+
+const X: u32 = c();
+//~^ NOTE inside
--- /dev/null
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_panic_track_caller.rs:16:5
+ |
+LL | b()
+ | ^^^
+ | |
+ | the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:16:5
+ | inside `c` at $DIR/const_panic_track_caller.rs:16:5
+...
+LL | const X: u32 = c();
+ | --- inside `X` at $DIR/const_panic_track_caller.rs:22:16
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
fn main() {}
-// unconst and fine
-const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
-// unconst and bad, will thus error in miri
-const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
-//~| WARN this was previously accepted by the compiler but is being phased out
-// unconst and fine
+// fine
const Z: i32 = unsafe { *(&1 as *const i32) };
-// unconst and bad, will thus error in miri
+
+// bad, will thus error in miri
const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
//~| WARN this was previously accepted by the compiler but is being phased out
const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
error: any use of this value will cause an error
- --> $DIR/const_raw_ptr_ops2.rs:8:28
- |
-LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
- | ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
- | |
- | cannot cast pointer to integer because it was not created by cast from integer
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
- --> $DIR/const_raw_ptr_ops2.rs:13:26
+ --> $DIR/const_raw_ptr_ops2.rs:9:26
|
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
| -------------------------^^^^^^^^^^^^^^^^^^^---
| |
| unable to turn bytes into a pointer
|
+ = note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: any use of this value will cause an error
- --> $DIR/const_raw_ptr_ops2.rs:15:26
+ --> $DIR/const_raw_ptr_ops2.rs:11:26
|
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
| -------------------------^^^^^^^^^^^^^^^^^^^---
= 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 #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
+++ /dev/null
-fn main() {
- [(); { &loop { break } as *const _ as usize } ];
- //~^ ERROR casting pointers to integers in constants is unstable
-}
+++ /dev/null
-error[E0658]: casting pointers to integers in constants is unstable
- --> $DIR/issue-52442.rs:2:13
- |
-LL | [(); { &loop { break } as *const _ as usize } ];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
// bytes.
let _: [u8; 0] = [4; {
match &1 as *const i32 as usize {
- //~^ ERROR casting pointers to integers in constants
+ //~^ ERROR pointers cannot be cast to integers during const eval
0 => 42,
n => n,
}
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/match-test-ptr-null.rs:6:15
|
LL | match &1 as *const i32 as usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
-#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
+#![feature(const_raw_ptr_deref)]
fn main() {
let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
const unsafe extern "C" fn use_float() { 1.0 + 1.0; }
//~^ ERROR floating point arithmetic
const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
fn main() {}
= note: see issue #57241 <https://github.com/rust-lang/rust/issues/57241> for more information
= help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/const-extern-fn-min-const-fn.rs:9:48
|
LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
| ^^^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error: aborting due to 4 previous errors
const FOO: i32 = Some(42i32).unwrap();
-// This causes an error, but it is attributed to the `panic` *inside* `Option::unwrap` (maybe due
-// to `track_caller`?). A note points to the originating `const`.
-const BAR: i32 = Option::<i32>::None.unwrap(); //~ NOTE
+const BAR: i32 = Option::<i32>::None.unwrap();
+//~^ERROR: evaluation of constant value failed
fn main() {
println!("{}", FOO);
error[E0080]: evaluation of constant value failed
- --> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | None => panic!("called `Option::unwrap()` on a `None` value"),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:9:38
- | inside `Option::<i32>::unwrap` at $SRC_DIR/core/src/panic.rs:LL:COL
- |
- ::: $DIR/const-unwrap.rs:9:18
+ --> $DIR/const-unwrap.rs:7:18
|
LL | const BAR: i32 = Option::<i32>::None.unwrap();
- | ---------------------------- inside `BAR` at $DIR/const-unwrap.rs:9:18
- |
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38
error: aborting due to previous error
static X: usize = unsafe { core::ptr::null::<usize>() as usize };
-//~^ ERROR: casting pointers to integers in statics is unstable
+//~^ ERROR: pointers cannot be cast to integers during const eval
fn main() {
assert_eq!(X, 0);
-error[E0658]: casting pointers to integers in statics is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/issue-17458.rs:1:28
|
LL | static X: usize = unsafe { core::ptr::null::<usize>() as usize };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-#![feature(const_raw_ptr_to_usize_cast)]
-
-const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut ();
-pub const FOO: usize = unsafe { BAR as usize };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-fn main() {}
+++ /dev/null
-error: any use of this value will cause an error
- --> $DIR/issue-51559.rs:4:33
- |
-LL | pub const FOO: usize = unsafe { BAR as usize };
- | --------------------------------^^^^^^^^^^^^---
- | |
- | cannot cast pointer to integer because it was not created by cast from integer
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to previous error
-
fn main() {
- let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants
+ let _ = [0; (&0 as *const i32) as usize]; //~ ERROR pointers cannot be cast to integers during const eval
}
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
|
LL | let _ = [0; (&0 as *const i32) as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-#![feature(const_raw_ptr_to_usize_cast)]
-
-fn main() {
- [(); &(static |x| {}) as *const _ as usize];
- //~^ ERROR: closures cannot be static
- //~| ERROR: type annotations needed
- [(); &(static || {}) as *const _ as usize];
- //~^ ERROR: closures cannot be static
- //~| ERROR evaluation of constant value failed
-}
+++ /dev/null
-error[E0697]: closures cannot be static
- --> $DIR/issue-52432.rs:4:12
- |
-LL | [(); &(static |x| {}) as *const _ as usize];
- | ^^^^^^^^^^
-
-error[E0697]: closures cannot be static
- --> $DIR/issue-52432.rs:7:12
- |
-LL | [(); &(static || {}) as *const _ as usize];
- | ^^^^^^^^^
-
-error[E0282]: type annotations needed
- --> $DIR/issue-52432.rs:4:20
- |
-LL | [(); &(static |x| {}) as *const _ as usize];
- | ^ consider giving this closure parameter a type
-
-error[E0080]: evaluation of constant value failed
- --> $DIR/issue-52432.rs:7:10
- |
-LL | [(); &(static || {}) as *const _ as usize];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot cast pointer to integer because it was not created by cast from integer
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0080, E0282, E0697.
-For more information about an error, try `rustc --explain E0080`.
const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics
const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
-//~^ ERROR casting pointers to integers
+//~^ ERROR pointers cannot be cast to integers
const fn foo30_6() -> bool { let x = true; x }
const fn inc(x: &mut i32) { *x += 1 }
//~^ ERROR mutable references
|
= help: consider extracting the value of the `static` to a `const`, and referring to that
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/min_const_fn.rs:92:42
|
LL | const fn foo30(x: *const u32) -> usize { x as usize }
| ^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/min_const_fn.rs:94:63
|
LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/min_const_fn.rs:96:42
|
LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
| ^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-error[E0658]: casting pointers to integers in constant functions is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/min_const_fn.rs:98:63
|
LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/min_const_fn.rs:101:14
--> $DIR/tls.rs:12:25
|
LL | unsafe { let _val = A; }
- | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
+ | ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
error[E0080]: could not evaluate static initializer
--> $DIR/tls.rs:19:26
|
LL | unsafe { let _val = &A; }
- | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
+ | ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
warning: skipping const checks
|
--- /dev/null
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "foo", since = "1.0.0")]
+
+#[stable(feature = "foo", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foo", issue = "none")]
+pub fn foo() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "bar", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+pub fn bar() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "potato", since = "1.0.0")]
+pub struct Potato;
+
+impl Potato {
+ #[stable(feature = "salad", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_salad", issue = "none")]
+ pub fn salad(&self) -> &'static str { "mmmmmm" }
+ //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+ #[stable(feature = "roasted", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
+ pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+ //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+}
+
+#[stable(feature = "bar", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+pub extern "C" fn bar_c() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+#[stable(feature = "foo", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_foo", issue = "none")]
+pub extern "C" fn foo_c() {}
+//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+
+
+#[stable(feature = "foobar", since = "1.0.0")]
+#[rustc_const_unstable(feature = "foobar_const", issue = "none")]
+pub const fn foobar() {}
+
+#[stable(feature = "barfoo", since = "1.0.0")]
+#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
+pub const fn barfoo() {}
--- /dev/null
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:7:1
+ |
+LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
+ | -------------------------------------------------------------- attribute specified here
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:7:1
+ |
+LL | pub fn foo() {}
+ | ^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:12:1
+ |
+LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+ | ------------------------------------------------------------- attribute specified here
+LL | pub fn bar() {}
+ | ^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:12:1
+ |
+LL | pub fn bar() {}
+ | ^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:21:5
+ |
+LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")]
+ | ---------------------------------------------------------------- attribute specified here
+LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:21:5
+ |
+LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:26:5
+ |
+LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
+ | ------------------------------------------------------------------ attribute specified here
+LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:26:5
+ |
+LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:32:1
+ |
+LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
+ | ------------------------------------------------------------- attribute specified here
+LL | pub extern "C" fn bar_c() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:32:1
+ |
+LL | pub extern "C" fn bar_c() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ --> $DIR/rustc-const-stability-require-const.rs:37:1
+ |
+LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
+ | -------------------------------------------------------------- attribute specified here
+LL | pub extern "C" fn foo_c() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: make the function or method const
+ --> $DIR/rustc-const-stability-require-const.rs:37:1
+ |
+LL | pub extern "C" fn foo_c() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// build-pass
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(staged_api)]
+#![feature(const_trait_impl)]
+#![stable(feature = "foo", since = "1.0.0")]
+
+
+#[stable(feature = "potato", since = "1.27.0")]
+pub struct Data {
+ _data: u128
+}
+
+#[stable(feature = "potato", since = "1.27.0")]
+impl const Default for Data {
+ #[rustc_const_unstable(feature = "data_foo", issue = "none")]
+ fn default() -> Data {
+ Data { _data: 42 }
+ }
+}
+++ /dev/null
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:7:9
- |
-LL | 1.0 => {}
- | ^^^
- |
- = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:11:9
- |
-LL | 2.0 => {}
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:7:9
- |
-LL | 1.0 => {}
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: 3 warnings emitted
-
+++ /dev/null
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:7:9
- |
-LL | 1.0 => {}
- | ^^^
- |
- = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:11:9
- |
-LL | 2.0 => {}
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:7:9
- |
-LL | 1.0 => {}
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: floating-point types cannot be used in patterns
- --> $DIR/deduplicate-diagnostics-2.rs:11:9
- |
-LL | 2.0 => {}
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-warning: 4 warnings emitted
-
+++ /dev/null
-// build-pass
-// revisions: duplicate deduplicate
-//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes
-
-fn main() {
- match 0.0 {
- 1.0 => {} //~ WARNING floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted
- //~| WARNING floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted
- 2.0 => {} //~ WARNING floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted
- //[duplicate]~| WARNING floating-point types cannot be used in patterns
- //[duplicate]~| WARNING this was previously accepted
- _ => {}
- }
-}
error: use of deprecated function `deprecation_lint::deprecated_text`: text
- --> $DIR/deprecation-lint-3.rs:13:5
+ --> $DIR/deprecation-lint-3.rs:13:28
|
LL | macro_test_arg_nested!(deprecated_text);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/deprecation-lint-3.rs:4:9
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^
- = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
| ^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:21:9
+ --> $DIR/deprecation-lint.rs:21:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:23:9
+ --> $DIR/deprecation-lint.rs:23:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated function `deprecation_lint::deprecated_text`: text
--> $DIR/deprecation-lint.rs:25:9
| ^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:30:9
+ --> $DIR/deprecation-lint.rs:30:16
|
LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:32:9
+ --> $DIR/deprecation-lint.rs:32:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
--> $DIR/deprecation-lint.rs:34:17
| ^^^^^^^^^^^^^^^^^^^^
error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text
- --> $DIR/deprecation-lint.rs:40:17
+ --> $DIR/deprecation-lint.rs:40:23
|
LL | let _ = Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text
--> $DIR/deprecation-lint.rs:42:17
| ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text
- --> $DIR/deprecation-lint.rs:44:17
+ --> $DIR/deprecation-lint.rs:44:25
|
LL | let _ = nested::DeprecatedStruct {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text
- --> $DIR/deprecation-lint.rs:48:17
+ --> $DIR/deprecation-lint.rs:48:25
|
LL | let _ = nested::DeprecatedUnitStruct;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^
error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text
- --> $DIR/deprecation-lint.rs:50:17
+ --> $DIR/deprecation-lint.rs:50:31
|
LL | ... let _ = nested::Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
- --> $DIR/deprecation-lint.rs:52:17
+ --> $DIR/deprecation-lint.rs:52:25
|
LL | ... let _ = nested::DeprecatedTupleStruct (1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated function `deprecation_lint::deprecated_text`: text
--> $DIR/deprecation-lint.rs:59:25
| ^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:65:9
+ --> $DIR/deprecation-lint.rs:65:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:67:9
+ --> $DIR/deprecation-lint.rs:67:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:69:9
+ --> $DIR/deprecation-lint.rs:69:16
|
LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:71:9
+ --> $DIR/deprecation-lint.rs:71:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
--> $DIR/deprecation-lint.rs:81:10
| ^^^^^^^^^^^
error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text
- --> $DIR/deprecation-lint.rs:162:9
+ --> $DIR/deprecation-lint.rs:162:25
|
LL | deprecated_mod::deprecated();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^
error: use of deprecated function `this_crate::deprecated`: text
--> $DIR/deprecation-lint.rs:245:9
| ^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:250:9
+ --> $DIR/deprecation-lint.rs:250:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:252:9
+ --> $DIR/deprecation-lint.rs:252:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated function `this_crate::deprecated_text`: text
--> $DIR/deprecation-lint.rs:254:9
| ^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:259:9
+ --> $DIR/deprecation-lint.rs:259:16
|
LL | Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:261:9
+ --> $DIR/deprecation-lint.rs:261:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated function `this_crate::deprecated_future`: text
--> $DIR/deprecation-lint.rs:264:9
| ^^^^^^^^^^^^^^^^^^^^
error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
- --> $DIR/deprecation-lint.rs:274:17
+ --> $DIR/deprecation-lint.rs:274:23
|
LL | let _ = Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
--> $DIR/deprecation-lint.rs:276:17
| ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
- --> $DIR/deprecation-lint.rs:278:17
+ --> $DIR/deprecation-lint.rs:278:25
|
LL | let _ = nested::DeprecatedStruct {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
- --> $DIR/deprecation-lint.rs:283:17
+ --> $DIR/deprecation-lint.rs:283:25
|
LL | let _ = nested::DeprecatedUnitStruct;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^
error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
- --> $DIR/deprecation-lint.rs:285:17
+ --> $DIR/deprecation-lint.rs:285:31
|
LL | ... let _ = nested::Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
- --> $DIR/deprecation-lint.rs:287:17
+ --> $DIR/deprecation-lint.rs:287:25
|
LL | ... let _ = nested::DeprecatedTupleStruct (1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:292:9
+ --> $DIR/deprecation-lint.rs:292:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/deprecation-lint.rs:294:9
+ --> $DIR/deprecation-lint.rs:294:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:296:9
+ --> $DIR/deprecation-lint.rs:296:16
|
LL | Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/deprecation-lint.rs:298:9
+ --> $DIR/deprecation-lint.rs:298:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
--> $DIR/deprecation-lint.rs:316:13
fn replacement(&self) {}
}
+mod bar {
+ #[rustc_deprecated(
+ since = "1.0.0",
+ reason = "replaced by `replacement`",
+ suggestion = "replacement",
+ )]
+ #[stable(since = "1.0.0", feature = "test")]
+ pub fn deprecated() {}
+
+ pub fn replacement() {}
+}
+
fn main() {
let foo = Foo;
foo.replacement(); //~ ERROR use of deprecated
+
+ bar::replacement(); //~ ERROR use of deprecated
}
fn replacement(&self) {}
}
+mod bar {
+ #[rustc_deprecated(
+ since = "1.0.0",
+ reason = "replaced by `replacement`",
+ suggestion = "replacement",
+ )]
+ #[stable(since = "1.0.0", feature = "test")]
+ pub fn deprecated() {}
+
+ pub fn replacement() {}
+}
+
fn main() {
let foo = Foo;
foo.deprecated(); //~ ERROR use of deprecated
+
+ bar::deprecated(); //~ ERROR use of deprecated
}
-error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
- --> $DIR/suggestion.rs:27:9
+error: use of deprecated function `bar::deprecated`: replaced by `replacement`
+ --> $DIR/suggestion.rs:41:10
|
-LL | foo.deprecated();
- | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
+LL | bar::deprecated();
+ | ^^^^^^^^^^ help: replace the use of the deprecated function: `replacement`
|
note: the lint level is defined here
--> $DIR/suggestion.rs:7:9
LL | #![deny(deprecated)]
| ^^^^^^^^^^
-error: aborting due to previous error
+error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
+ --> $DIR/suggestion.rs:39:9
+ |
+LL | foo.deprecated();
+ | ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
+
+error: aborting due to 2 previous errors
let mut y = 0;
let x = (&y,);
*x.0 = 1;
- //~^ ERROR cannot assign to `*x.0` which is behind a `&` reference
+ //~^ ERROR cannot assign to `*x.0`, which is behind a `&` reference
}
LL | let _ = &mut w.x;
| ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable
-error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
+error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference
--> $DIR/issue-39544.rs:48:5
|
LL | *x.0 = 1;
fn main() {
let mut fancy = FancyNum{ num: 5 };
let fancy_ref = &(&mut fancy);
- fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num` which is behind a `&` reference
+ fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num`, which is behind a `&` reference
println!("{}", fancy_ref.num);
}
-error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
--> $DIR/E0389.rs:8:5
|
LL | let fancy_ref = &(&mut fancy);
// run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 fastcall isn't supported
+// only-i686
trait A {
extern "fastcall" fn test1(i: i32);
// run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 thiscall isn't supported
+// only-i686
#![feature(abi_thiscall)]
// run-pass
-// ignore-arm
-// ignore-aarch64
-// ignore-riscv64 vectorcall isn't supported
+// revisions: x64 x32
+// [x64]only-x86_64
+// [x32]only-i686
#![feature(abi_vectorcall)]
+// needs-llvm-components: avr
+// compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
// Test that the AVR interrupt ABI cannot be used when avr_interrupt
// feature gate is not used.
-extern "avr-interrupt" fn foo() {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+extern "avr-non-blocking-interrupt" fn fu() {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+extern "avr-interrupt" fn f() {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+trait T {
+ extern "avr-interrupt" fn m();
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+ extern "avr-non-blocking-interrupt" fn mu();
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+ extern "avr-interrupt" fn dm() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+ extern "avr-non-blocking-interrupt" fn dmu() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+}
+
+struct S;
+impl T for S {
+ extern "avr-interrupt" fn m() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+ extern "avr-non-blocking-interrupt" fn mu() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+}
-fn main() {
- foo();
+impl S {
+ extern "avr-interrupt" fn im() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+ extern "avr-non-blocking-interrupt" fn imu() {}
+ //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
}
+
+type TA = extern "avr-interrupt" fn();
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+type TAU = extern "avr-non-blocking-interrupt" fn();
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+
+extern "avr-interrupt" {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+extern "avr-non-blocking-interrupt" {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi-avr-interrupt.rs:4:8
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:11:8
|
-LL | extern "avr-interrupt" fn foo() {}
+LL | extern "avr-non-blocking-interrupt" fn fu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:13:8
+ |
+LL | extern "avr-interrupt" fn f() {}
| ^^^^^^^^^^^^^^^
|
= note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
= help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:17:12
+ |
+LL | extern "avr-interrupt" fn m();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:19:12
+ |
+LL | extern "avr-non-blocking-interrupt" fn mu();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:22:12
+ |
+LL | extern "avr-interrupt" fn dm() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:24:12
+ |
+LL | extern "avr-non-blocking-interrupt" fn dmu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:30:12
+ |
+LL | extern "avr-interrupt" fn m() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:32:12
+ |
+LL | extern "avr-non-blocking-interrupt" fn mu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:37:12
+ |
+LL | extern "avr-interrupt" fn im() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:39:12
+ |
+LL | extern "avr-non-blocking-interrupt" fn imu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:43:18
+ |
+LL | type TA = extern "avr-interrupt" fn();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:45:19
+ |
+LL | type TAU = extern "avr-non-blocking-interrupt" fn();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:48:8
+ |
+LL | extern "avr-interrupt" {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi-avr-interrupt.rs:50:8
+ |
+LL | extern "avr-non-blocking-interrupt" {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+ = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0658`.
-// Test that the MSP430 interrupt ABI cannot be used when msp430_interrupt
-// feature gate is not used.
+// needs-llvm-components: msp430
+// compile-flags: --target=msp430-none-elf --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
-// ignore-riscv64 msp430 is not supported
+extern "msp430-interrupt" fn f() {}
+//~^ ERROR msp430-interrupt ABI is experimental
-extern "msp430-interrupt" fn foo() {}
-//~^ ERROR msp430-interrupt ABI is experimental and subject to change
+trait T {
+ extern "msp430-interrupt" fn m();
+ //~^ ERROR msp430-interrupt ABI is experimental
-fn main() {
- foo();
+ extern "msp430-interrupt" fn dm() {}
+ //~^ ERROR msp430-interrupt ABI is experimental
}
+
+struct S;
+impl T for S {
+ extern "msp430-interrupt" fn m() {}
+ //~^ ERROR msp430-interrupt ABI is experimental
+}
+
+impl S {
+ extern "msp430-interrupt" fn im() {}
+ //~^ ERROR msp430-interrupt ABI is experimental
+}
+
+type TA = extern "msp430-interrupt" fn();
+//~^ ERROR msp430-interrupt ABI is experimental
+
+extern "msp430-interrupt" {}
+//~^ ERROR msp430-interrupt ABI is experimental
error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi-msp430-interrupt.rs:6:8
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:8:8
|
-LL | extern "msp430-interrupt" fn foo() {}
+LL | extern "msp430-interrupt" fn f() {}
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
= help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:12:12
+ |
+LL | extern "msp430-interrupt" fn m();
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:15:12
+ |
+LL | extern "msp430-interrupt" fn dm() {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:21:12
+ |
+LL | extern "msp430-interrupt" fn m() {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:26:12
+ |
+LL | extern "msp430-interrupt" fn im() {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:30:18
+ |
+LL | type TA = extern "msp430-interrupt" fn();
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error[E0658]: msp430-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-msp430-interrupt.rs:33:8
+ |
+LL | extern "msp430-interrupt" {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
+ = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// needs-llvm-components: x86
+// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+trait Tr {
+ extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
+ extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+struct S;
+
+// Methods in trait impl
+impl Tr for S {
+ extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+// Methods in inherent impl
+impl S {
+ extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+}
+
+type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+
+extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
--- /dev/null
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:8:8
+ |
+LL | extern "x86-interrupt" fn f7() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:10:12
+ |
+LL | extern "x86-interrupt" fn m7();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:11:12
+ |
+LL | extern "x86-interrupt" fn dm7() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:18:12
+ |
+LL | extern "x86-interrupt" fn m7() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:23:12
+ |
+LL | extern "x86-interrupt" fn im7() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:26:18
+ |
+LL | type A7 = extern "x86-interrupt" fn();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error[E0658]: x86-interrupt ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi-x86-interrupt.rs:28:8
+ |
+LL | extern "x86-interrupt" {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
+ = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
-// only-x86_64
// gate-test-intrinsics
// gate-test-platform_intrinsics
-// gate-test-abi_vectorcall
-// gate-test-abi_thiscall
-// gate-test-abi_ptx
-// gate-test-abi_x86_interrupt
-// gate-test-abi_amdgpu_kernel
// gate-test-abi_efiapi
+// compile-flags: --crate-type=rlib
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
// Functions
extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
//~^ ERROR intrinsic must be in
extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
//~^ ERROR intrinsic must be in
-extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
-extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
-extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
-extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
-extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
-extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change
-extern "wasm" fn f11() {} //~ ERROR wasm ABI is experimental and subject to change
// Methods in trait definition
trait Tr {
//~^ ERROR intrinsic must be in
extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
//~^ ERROR intrinsic must be in
- extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
- extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
- extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
- extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
- extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
- extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change
- extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change
- extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
- extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
- extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
- extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
- extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
- extern "amdgpu-kernel" fn dm9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change
- extern "wasm" fn dm11() {} //~ ERROR wasm ABI is experimental and subject to change
}
struct S;
//~^ ERROR intrinsic must be in
extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
//~^ ERROR intrinsic must be in
- extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
- extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
- extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
- extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
- extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
- extern "amdgpu-kernel" fn m9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change
- extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change
}
// Methods in inherent impl
//~^ ERROR intrinsic must be in
extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
//~^ ERROR intrinsic must be in
- extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
- extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
- extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
- extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
- extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
- extern "amdgpu-kernel" fn im9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change
- extern "wasm" fn im11() {} //~ ERROR wasm ABI is experimental and subject to change
}
// Function pointer types
type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
-type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
-type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
-type A6 = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental and subject to change
-type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
-type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
-type A9 = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change
type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change
-type A11 = extern "wasm" fn(); //~ ERROR wasm ABI is experimental and subject to change
// Foreign modules
extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
-extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
-extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
-extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
-extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
-extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
-extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change
extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change
-extern "wasm" {} //~ ERROR wasm ABI is experimental and subject to change
-
-fn main() {}
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:12:8
+ --> $DIR/feature-gate-abi.rs:13:8
|
LL | extern "rust-intrinsic" fn f1() {}
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:14:8
+ --> $DIR/feature-gate-abi.rs:15:8
|
LL | extern "platform-intrinsic" fn f2() {}
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:16:8
- |
-LL | extern "vectorcall" fn f3() {}
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
--> $DIR/feature-gate-abi.rs:17:8
|
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:18:8
- |
-LL | extern "msp430-interrupt" fn f5() {}
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:19:8
- |
-LL | extern "ptx-kernel" fn f6() {}
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:20:8
- |
-LL | extern "x86-interrupt" fn f7() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:21:8
- |
-LL | extern "thiscall" fn f8() {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:22:8
- |
-LL | extern "amdgpu-kernel" fn f9() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:23:8
+ --> $DIR/feature-gate-abi.rs:18:8
|
LL | extern "efiapi" fn f10() {}
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:24:8
- |
-LL | extern "wasm" fn f11() {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:28:12
+ --> $DIR/feature-gate-abi.rs:22:12
|
LL | extern "rust-intrinsic" fn m1();
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:30:12
+ --> $DIR/feature-gate-abi.rs:24:12
|
LL | extern "platform-intrinsic" fn m2();
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:32:12
- |
-LL | extern "vectorcall" fn m3();
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:33:12
+ --> $DIR/feature-gate-abi.rs:26:12
|
LL | extern "rust-call" fn m4(_: ());
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:34:12
- |
-LL | extern "msp430-interrupt" fn m5();
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:35:12
- |
-LL | extern "ptx-kernel" fn m6();
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:36:12
- |
-LL | extern "x86-interrupt" fn m7();
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:37:12
- |
-LL | extern "thiscall" fn m8();
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:38:12
- |
-LL | extern "amdgpu-kernel" fn m9();
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:39:12
+ --> $DIR/feature-gate-abi.rs:27:12
|
LL | extern "efiapi" fn m10();
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:40:12
- |
-LL | extern "wasm" fn m11() {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:42:12
- |
-LL | extern "vectorcall" fn dm3() {}
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:43:12
+ --> $DIR/feature-gate-abi.rs:29:12
|
LL | extern "rust-call" fn dm4(_: ()) {}
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:44:12
- |
-LL | extern "msp430-interrupt" fn dm5() {}
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:45:12
- |
-LL | extern "ptx-kernel" fn dm6() {}
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:46:12
- |
-LL | extern "x86-interrupt" fn dm7() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:47:12
- |
-LL | extern "thiscall" fn dm8() {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:48:12
- |
-LL | extern "amdgpu-kernel" fn dm9() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:49:12
+ --> $DIR/feature-gate-abi.rs:30:12
|
LL | extern "efiapi" fn dm10() {}
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:50:12
- |
-LL | extern "wasm" fn dm11() {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:57:12
+ --> $DIR/feature-gate-abi.rs:37:12
|
LL | extern "rust-intrinsic" fn m1() {}
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:59:12
+ --> $DIR/feature-gate-abi.rs:39:12
|
LL | extern "platform-intrinsic" fn m2() {}
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:61:12
- |
-LL | extern "vectorcall" fn m3() {}
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:62:12
+ --> $DIR/feature-gate-abi.rs:41:12
|
LL | extern "rust-call" fn m4(_: ()) {}
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:63:12
- |
-LL | extern "msp430-interrupt" fn m5() {}
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:64:12
- |
-LL | extern "ptx-kernel" fn m6() {}
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:65:12
- |
-LL | extern "x86-interrupt" fn m7() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:66:12
- |
-LL | extern "thiscall" fn m8() {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:67:12
- |
-LL | extern "amdgpu-kernel" fn m9() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:68:12
+ --> $DIR/feature-gate-abi.rs:42:12
|
LL | extern "efiapi" fn m10() {}
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:69:12
- |
-LL | extern "wasm" fn m11() {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:74:12
+ --> $DIR/feature-gate-abi.rs:47:12
|
LL | extern "rust-intrinsic" fn im1() {}
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:76:12
+ --> $DIR/feature-gate-abi.rs:49:12
|
LL | extern "platform-intrinsic" fn im2() {}
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:78:12
- |
-LL | extern "vectorcall" fn im3() {}
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:79:12
+ --> $DIR/feature-gate-abi.rs:51:12
|
LL | extern "rust-call" fn im4(_: ()) {}
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:80:12
- |
-LL | extern "msp430-interrupt" fn im5() {}
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:81:12
- |
-LL | extern "ptx-kernel" fn im6() {}
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:82:12
- |
-LL | extern "x86-interrupt" fn im7() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:83:12
- |
-LL | extern "thiscall" fn im8() {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:84:12
- |
-LL | extern "amdgpu-kernel" fn im9() {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:85:12
+ --> $DIR/feature-gate-abi.rs:52:12
|
LL | extern "efiapi" fn im10() {}
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:86:12
- |
-LL | extern "wasm" fn im11() {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:90:18
+ --> $DIR/feature-gate-abi.rs:56:18
|
LL | type A1 = extern "rust-intrinsic" fn();
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:91:18
+ --> $DIR/feature-gate-abi.rs:57:18
|
LL | type A2 = extern "platform-intrinsic" fn();
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:92:18
- |
-LL | type A3 = extern "vectorcall" fn();
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:93:18
+ --> $DIR/feature-gate-abi.rs:58:18
|
LL | type A4 = extern "rust-call" fn(_: ());
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:94:18
- |
-LL | type A5 = extern "msp430-interrupt" fn();
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:95:18
- |
-LL | type A6 = extern "ptx-kernel" fn();
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:96:18
- |
-LL | type A7 = extern "x86-interrupt" fn();
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:97:18
- |
-LL | type A8 = extern "thiscall" fn();
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:98:18
- |
-LL | type A9 = extern "amdgpu-kernel" fn();
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:99:19
+ --> $DIR/feature-gate-abi.rs:59:19
|
LL | type A10 = extern "efiapi" fn();
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:100:19
- |
-LL | type A11 = extern "wasm" fn();
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error[E0658]: intrinsics are subject to change
- --> $DIR/feature-gate-abi.rs:103:8
+ --> $DIR/feature-gate-abi.rs:62:8
|
LL | extern "rust-intrinsic" {}
| ^^^^^^^^^^^^^^^^
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
error[E0658]: platform intrinsics are experimental and possibly buggy
- --> $DIR/feature-gate-abi.rs:104:8
+ --> $DIR/feature-gate-abi.rs:63:8
|
LL | extern "platform-intrinsic" {}
| ^^^^^^^^^^^^^^^^^^^^
= note: see issue #27731 <https://github.com/rust-lang/rust/issues/27731> for more information
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
-error[E0658]: vectorcall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:105:8
- |
-LL | extern "vectorcall" {}
- | ^^^^^^^^^^^^
- |
- = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
-
error[E0658]: rust-call ABI is subject to change
- --> $DIR/feature-gate-abi.rs:106:8
+ --> $DIR/feature-gate-abi.rs:64:8
|
LL | extern "rust-call" {}
| ^^^^^^^^^^^
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:107:8
- |
-LL | extern "msp430-interrupt" {}
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #38487 <https://github.com/rust-lang/rust/issues/38487> for more information
- = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
-
-error[E0658]: PTX ABIs are experimental and subject to change
- --> $DIR/feature-gate-abi.rs:108:8
- |
-LL | extern "ptx-kernel" {}
- | ^^^^^^^^^^^^
- |
- = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
- = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
-
-error[E0658]: x86-interrupt ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:109:8
- |
-LL | extern "x86-interrupt" {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #40180 <https://github.com/rust-lang/rust/issues/40180> for more information
- = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
-
-error[E0658]: thiscall is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:110:8
- |
-LL | extern "thiscall" {}
- | ^^^^^^^^^^
- |
- = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
-
-error[E0658]: amdgpu-kernel ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:111:8
- |
-LL | extern "amdgpu-kernel" {}
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
- = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
-
error[E0658]: efiapi ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:112:8
+ --> $DIR/feature-gate-abi.rs:65:8
|
LL | extern "efiapi" {}
| ^^^^^^^^
= note: see issue #65815 <https://github.com/rust-lang/rust/issues/65815> for more information
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
-error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-abi.rs:113:8
- |
-LL | extern "wasm" {}
- | ^^^^^^
- |
- = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
- = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:28:32
+ --> $DIR/feature-gate-abi.rs:22:32
|
LL | extern "rust-intrinsic" fn m1();
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:30:36
+ --> $DIR/feature-gate-abi.rs:24:36
|
LL | extern "platform-intrinsic" fn m2();
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:12:33
+ --> $DIR/feature-gate-abi.rs:13:33
|
LL | extern "rust-intrinsic" fn f1() {}
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:14:37
+ --> $DIR/feature-gate-abi.rs:15:37
|
LL | extern "platform-intrinsic" fn f2() {}
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:57:37
+ --> $DIR/feature-gate-abi.rs:37:37
|
LL | extern "rust-intrinsic" fn m1() {}
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:59:41
+ --> $DIR/feature-gate-abi.rs:39:41
|
LL | extern "platform-intrinsic" fn m2() {}
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:74:38
+ --> $DIR/feature-gate-abi.rs:47:38
|
LL | extern "rust-intrinsic" fn im1() {}
| ^^
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
- --> $DIR/feature-gate-abi.rs:76:42
+ --> $DIR/feature-gate-abi.rs:49:42
|
LL | extern "platform-intrinsic" fn im2() {}
| ^^
-error: aborting due to 83 previous errors
+error: aborting due to 34 previous errors
For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// compile-flags: --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental
+//~^ ERROR is not a supported ABI
+
+trait T {
+ extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental
+ extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental
+ //~^ ERROR is not a supported ABI
+}
+
+struct S;
+impl T for S {
+ extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental
+ //~^ ERROR is not a supported ABI
+}
+
+impl S {
+ extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental
+ //~^ ERROR is not a supported ABI
+}
+
+type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental
+
+extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental
+//~^ ERROR is not a supported ABI
--- /dev/null
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8
+ |
+LL | extern "amdgpu-kernel" fn fu() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12
+ |
+LL | extern "amdgpu-kernel" fn mu();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12
+ |
+LL | extern "amdgpu-kernel" fn dmu() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12
+ |
+LL | extern "amdgpu-kernel" fn mu() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12
+ |
+LL | extern "amdgpu-kernel" fn imu() {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19
+ |
+LL | type TAU = extern "amdgpu-kernel" fn();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0658]: amdgpu-kernel ABI is experimental and subject to change
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8
+ |
+LL | extern "amdgpu-kernel" {}
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #51575 <https://github.com/rust-lang/rust/issues/51575> for more information
+ = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1
+ |
+LL | extern "amdgpu-kernel" {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1
+ |
+LL | extern "amdgpu-kernel" fn fu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5
+ |
+LL | extern "amdgpu-kernel" fn dmu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5
+ |
+LL | extern "amdgpu-kernel" fn mu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+ --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5
+ |
+LL | extern "amdgpu-kernel" fn imu() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0570, E0658.
+For more information about an error, try `rustc --explain E0570`.
--- /dev/null
+// needs-llvm-components: nvptx
+// compile-flags: --target=nvptx64-nvidia-cuda --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "ptx-kernel" fn fu() {} //~ ERROR PTX ABIs are experimental
+
+trait T {
+ extern "ptx-kernel" fn mu(); //~ ERROR PTX ABIs are experimental
+ extern "ptx-kernel" fn dmu() {} //~ ERROR PTX ABIs are experimental
+}
+
+struct S;
+impl T for S {
+ extern "ptx-kernel" fn mu() {} //~ ERROR PTX ABIs are experimental
+}
+
+impl S {
+ extern "ptx-kernel" fn imu() {} //~ ERROR PTX ABIs are experimental
+}
+
+type TAU = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental
+
+extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental
--- /dev/null
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:8:8
+ |
+LL | extern "ptx-kernel" fn fu() {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:11:12
+ |
+LL | extern "ptx-kernel" fn mu();
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:12:12
+ |
+LL | extern "ptx-kernel" fn dmu() {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:17:12
+ |
+LL | extern "ptx-kernel" fn mu() {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:21:12
+ |
+LL | extern "ptx-kernel" fn imu() {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:24:19
+ |
+LL | type TAU = extern "ptx-kernel" fn();
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error[E0658]: PTX ABIs are experimental and subject to change
+ --> $DIR/feature-gate-abi_ptx.rs:26:8
+ |
+LL | extern "ptx-kernel" {}
+ | ^^^^^^^^^^^^
+ |
+ = note: see issue #38788 <https://github.com/rust-lang/rust/issues/38788> for more information
+ = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
LL | let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
| ^^^^^^^^^^^^^^^^^
|
- = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
= help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
error[E0658]: usage of qualified paths in this context is experimental
LL | let _ = <Foo as A>::Assoc { br: 2 };
| ^^^^^^^^^^^^^^^^^
|
- = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
= help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
error[E0658]: usage of qualified paths in this context is experimental
LL | let <E>::V(..) = E::V(0);
| ^^^^^^
|
- = note: see issue #80080 <https://github.com/rust-lang/rust/issues/80080> for more information
+ = note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
= help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
error: aborting due to 3 previous errors
--- /dev/null
+// gate-test-abi_vectorcall
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+// Test that the "vectorcall-unwind" ABI is feature-gated, and cannot be used when
+// the `c_unwind` feature gate is not used.
+
+extern "vectorcall" fn f() {} //~ ERROR vectorcall is experimental
+
+trait T {
+ extern "vectorcall" fn m(); //~ ERROR vectorcall is experimental
+
+ extern "vectorcall" fn dm() {} //~ ERROR vectorcall is experimental
+}
+
+struct S;
+impl T for S {
+ extern "vectorcall" fn m() {} //~ ERROR vectorcall is experimental
+}
+
+impl S {
+ extern "vectorcall" fn im() {} //~ ERROR vectorcall is experimental
+}
+
+type TA = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental
+
+extern "vectorcall" {} //~ ERROR vectorcall is experimental
--- /dev/null
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:12:8
+ |
+LL | extern "vectorcall" fn f() {}
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:15:12
+ |
+LL | extern "vectorcall" fn m();
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:17:12
+ |
+LL | extern "vectorcall" fn dm() {}
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:22:12
+ |
+LL | extern "vectorcall" fn m() {}
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:26:12
+ |
+LL | extern "vectorcall" fn im() {}
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:29:18
+ |
+LL | type TA = extern "vectorcall" fn();
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error[E0658]: vectorcall is experimental and subject to change
+ --> $DIR/feature-gate-vectorcall.rs:31:8
+ |
+LL | extern "vectorcall" {}
+ | ^^^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
-extern "wasm" fn foo() {
- //~^ ERROR: wasm ABI is experimental and subject to change
+// needs-llvm-components: webassembly
+// compile-flags: --target=wasm32-unknown-unknown --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
+
+extern "wasm" fn fu() {} //~ ERROR wasm ABI is experimental
+
+trait T {
+ extern "wasm" fn mu(); //~ ERROR wasm ABI is experimental
+ extern "wasm" fn dmu() {} //~ ERROR wasm ABI is experimental
+}
+
+struct S;
+impl T for S {
+ extern "wasm" fn mu() {} //~ ERROR wasm ABI is experimental
}
-fn main() {
- foo();
+impl S {
+ extern "wasm" fn imu() {} //~ ERROR wasm ABI is experimental
}
+
+type TAU = extern "wasm" fn(); //~ ERROR wasm ABI is experimental
+
+extern "wasm" {} //~ ERROR wasm ABI is experimental
error[E0658]: wasm ABI is experimental and subject to change
- --> $DIR/feature-gate-wasm_abi.rs:1:8
+ --> $DIR/feature-gate-wasm_abi.rs:8:8
|
-LL | extern "wasm" fn foo() {
+LL | extern "wasm" fn fu() {}
| ^^^^^^
|
= note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
= help: add `#![feature(wasm_abi)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:11:12
+ |
+LL | extern "wasm" fn mu();
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:12:12
+ |
+LL | extern "wasm" fn dmu() {}
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:17:12
+ |
+LL | extern "wasm" fn mu() {}
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:21:12
+ |
+LL | extern "wasm" fn imu() {}
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:24:19
+ |
+LL | type TAU = extern "wasm" fn();
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error[E0658]: wasm ABI is experimental and subject to change
+ --> $DIR/feature-gate-wasm_abi.rs:26:8
+ |
+LL | extern "wasm" {}
+ | ^^^^^^
+ |
+ = note: see issue #83788 <https://github.com/rust-lang/rust/issues/83788> for more information
+ = help: add `#![feature(wasm_abi)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.
fn named_argument_takes_precedence_to_captured() {
let foo = "captured";
- let s = format!("{foo}", foo="named");
+ let s = format!("{foo}", foo = "named");
assert_eq!(&s, "named");
- let s = format!("{foo}-{foo}-{foo}", foo="named");
+ let s = format!("{foo}-{foo}-{foo}", foo = "named");
assert_eq!(&s, "named-named-named");
- let s = format!("{}-{bar}-{foo}", "positional", bar="named");
+ let s = format!("{}-{bar}-{foo}", "positional", bar = "named");
assert_eq!(&s, "positional-named-captured");
}
// RFC #2795 suggests that this may need to change so that captured arguments are formatted.
// For stability reasons this will need to part of an edition change.
- #[allow(non_fmt_panic)]
+ #[allow(non_fmt_panics)]
let msg = std::panic::catch_unwind(|| {
panic!("{foo}");
- }).unwrap_err();
+ })
+ .unwrap_err();
assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}"))
}
let foo = "captured";
let msg = std::panic::catch_unwind(|| {
- panic!("{}-{bar}-{foo}", "positional", bar="named");
- }).unwrap_err();
+ panic!("{}-{bar}-{foo}", "positional", bar = "named");
+ })
+ .unwrap_err();
assert_eq!(msg.downcast_ref::<String>(), Some(&"positional-named-captured".to_string()))
}
--> $DIR/generator-print-verbose-1.rs:35:9
|
LL | let _non_send_gen = make_non_send_generator();
- | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+ | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[70c9]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
LL | yield;
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
LL | };
= help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
- = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
- = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])`
- = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}`
- = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]`
+ = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[70c9]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+ = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), [])`
+ = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}`
+ = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}]`
error: aborting due to 2 previous errors
//~| ERROR range-to patterns with `...` are not allowed
if let ..5 = 0 {}
//~^ ERROR half-open range patterns are unstable
- if let 5.. = 0 {}
- //~^ ERROR half-open range patterns are unstable
if let 5..= = 0 {}
- //~^ ERROR half-open range patterns are unstable
- //~| ERROR inclusive range with no end
+ //~^ ERROR inclusive range with no end
if let 5... = 0 {}
- //~^ ERROR half-open range patterns are unstable
- //~| ERROR inclusive range with no end
+ //~^ ERROR inclusive range with no end
}
| ^^^ help: use `..=` instead
error[E0586]: inclusive range with no end
- --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
+ --> $DIR/feature-gate-half-open-range-patterns.rs:14:13
|
LL | if let 5..= = 0 {}
| ^^^ help: use `..` instead
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/feature-gate-half-open-range-patterns.rs:19:13
+ --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
|
LL | if let 5... = 0 {}
| ^^^ help: use `..` instead
= note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
= help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:14:12
- |
-LL | if let 5.. = 0 {}
- | ^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:16:12
- |
-LL | if let 5..= = 0 {}
- | ^^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:19:12
- |
-LL | if let 5... = 0 {}
- | ^^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error: aborting due to 9 previous errors
+error: aborting due to 6 previous errors
Some errors have detailed explanations: E0586, E0658.
For more information about an error, try `rustc --explain E0586`.
--- /dev/null
+// run-pass
+#![allow(incomplete_features)]
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+#![feature(inline_const)]
+
+fn main() {
+ let mut if_lettable = vec![];
+ let mut first_or = vec![];
+ let mut or_two = vec![];
+ let mut range_from = vec![];
+ let mut bottom = vec![];
+
+ for x in -9 + 1..=(9 - 2) {
+ if let -1..=0 | 2..3 | 4 = x {
+ if_lettable.push(x)
+ }
+ match x {
+ 1 | -3..0 => first_or.push(x),
+ y @ (0..5 | 6) => or_two.push(y),
+ y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ y @ -5.. => range_from.push(y),
+ y @ ..-7 => assert_eq!(y, -8),
+ y => bottom.push(y),
+ }
+ }
+ assert_eq!(if_lettable, [-1, 0, 2, 4]);
+ assert_eq!(first_or, [-3, -2, -1, 1]);
+ assert_eq!(or_two, [0, 2, 3, 4, 6]);
+ assert_eq!(range_from, [-5, -4, 7]);
+ assert_eq!(bottom, [-7, -6]);
+}
--- /dev/null
+fn main() {
+ let mut if_lettable = Vec::<i32>::new();
+ let mut first_or = Vec::<i32>::new();
+ let mut or_two = Vec::<i32>::new();
+ let mut range_from = Vec::<i32>::new();
+ let mut bottom = Vec::<i32>::new();
+ let mut errors_only = Vec::<i32>::new();
+
+ for x in -9 + 1..=(9 - 2) {
+ if let n @ 2..3|4 = x {
+ //~^ error: variable `n` is not bound in all patterns
+ //~| exclusive range pattern syntax is experimental
+ errors_only.push(x);
+ } else if let 2..3 | 4 = x {
+ //~^ exclusive range pattern syntax is experimental
+ if_lettable.push(x);
+ }
+ match x as i32 {
+ 0..5+1 => errors_only.push(x),
+ //~^ error: expected one of `=>`, `if`, or `|`, found `+`
+ 1 | -3..0 => first_or.push(x),
+ y @ (0..5 | 6) => or_two.push(y),
+ y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ y @ -5.. => range_from.push(y),
+ y @ ..-7 => assert_eq!(y, -8),
+ y => bottom.push(y),
+ }
+ }
+}
--- /dev/null
+error: expected one of `=>`, `if`, or `|`, found `+`
+ --> $DIR/range_pat_interactions1.rs:19:17
+ |
+LL | 0..5+1 => errors_only.push(x),
+ | ^ expected one of `=>`, `if`, or `|`
+
+error[E0408]: variable `n` is not bound in all patterns
+ --> $DIR/range_pat_interactions1.rs:10:25
+ |
+LL | if let n @ 2..3|4 = x {
+ | - ^ pattern doesn't bind `n`
+ | |
+ | variable not in all patterns
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions1.rs:10:20
+ |
+LL | if let n @ 2..3|4 = x {
+ | ^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions1.rs:14:23
+ |
+LL | } else if let 2..3 | 4 = x {
+ | ^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0408, E0658.
+For more information about an error, try `rustc --explain E0408`.
--- /dev/null
+fn main() {
+ let mut first_or = Vec::<i32>::new();
+ let mut or_two = Vec::<i32>::new();
+ let mut range_from = Vec::<i32>::new();
+ let mut bottom = Vec::<i32>::new();
+ let mut errors_only = Vec::<i32>::new();
+
+ for x in -9 + 1..=(9 - 2) {
+ match x as i32 {
+ 0..=(5+1) => errors_only.push(x),
+ //~^ error: inclusive range with no end
+ //~| error: expected one of `=>`, `if`, or `|`, found `(`
+ 1 | -3..0 => first_or.push(x),
+ y @ (0..5 | 6) => or_two.push(y),
+ y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ y @ -5.. => range_from.push(y),
+ y @ ..-7 => assert_eq!(y, -8),
+ y => bottom.push(y),
+ }
+ }
+}
--- /dev/null
+error[E0586]: inclusive range with no end
+ --> $DIR/range_pat_interactions2.rs:10:14
+ |
+LL | 0..=(5+1) => errors_only.push(x),
+ | ^^^ help: use `..` instead
+ |
+ = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: expected one of `=>`, `if`, or `|`, found `(`
+ --> $DIR/range_pat_interactions2.rs:10:17
+ |
+LL | 0..=(5+1) => errors_only.push(x),
+ | ^ expected one of `=>`, `if`, or `|`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
--- /dev/null
+fn main() {
+ let mut first_or = Vec::<i32>::new();
+ let mut or_two = Vec::<i32>::new();
+ let mut range_from = Vec::<i32>::new();
+ let mut bottom = Vec::<i32>::new();
+
+ for x in -9 + 1..=(9 - 2) {
+ match x as i32 {
+ 8.. => bottom.push(x),
+ 1 | -3..0 => first_or.push(x),
+ //~^ exclusive range pattern syntax is experimental
+ y @ (0..5 | 6) => or_two.push(y),
+ //~^ exclusive range pattern syntax is experimental
+ y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ //~^ inline-const is experimental
+ //~| exclusive range pattern syntax is experimental
+ y @ -5.. => range_from.push(y),
+ y @ ..-7 => assert_eq!(y, -8),
+ //~^ half-open range patterns are unstable
+ //~| exclusive range pattern syntax is experimental
+ y => bottom.push(y),
+ }
+ }
+}
--- /dev/null
+error[E0658]: half-open range patterns are unstable
+ --> $DIR/range_pat_interactions3.rs:18:17
+ |
+LL | y @ ..-7 => assert_eq!(y, -8),
+ | ^^^^
+ |
+ = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+ = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: inline-const is experimental
+ --> $DIR/range_pat_interactions3.rs:14:20
+ |
+LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ | ^^^^^
+ |
+ = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
+ = help: add `#![feature(inline_const)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions3.rs:10:17
+ |
+LL | 1 | -3..0 => first_or.push(x),
+ | ^^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions3.rs:12:18
+ |
+LL | y @ (0..5 | 6) => or_two.push(y),
+ | ^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions3.rs:14:17
+ |
+LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/range_pat_interactions3.rs:18:17
+ |
+LL | y @ ..-7 => assert_eq!(y, -8),
+ | ^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+ let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+ let [a, b, c, rest @ ..] = xs;
+ // Consider the following example:
+ assert!(a == 13 && b == 1 && c == 5 && rest.len() == 5);
+
+ // What if we wanted to pull this apart without individually binding a, b, and c?
+ let [first_three @ ..3, rest @ 2..] = xs;
+ //~^ pattern requires 2 elements but array has 8
+ // This is somewhat unintuitive and makes slice patterns exceedingly verbose.
+ // We want to stabilize half-open RangeFrom (`X..`) patterns
+ // but without banning us from using them for a more efficient slice pattern syntax.
+}
--- /dev/null
+error[E0527]: pattern requires 2 elements but array has 8
+ --> $DIR/slice_pattern_syntax_problem0.rs:11:9
+ |
+LL | let [first_three @ ..3, rest @ 2..] = xs;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0527`.
--- /dev/null
+// Instead of allowing the previous case, maintain the feature gate for slice patterns for now.
+fn main() {
+ let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+ let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ //~^ `X..` patterns in slices are experimental
+ //~| half-open range patterns are unstable
+ //~| exclusive range pattern syntax is experimental
+ //~| exclusive range pattern syntax is experimental
+}
--- /dev/null
+error[E0658]: half-open range patterns are unstable
+ --> $DIR/slice_pattern_syntax_problem1.rs:4:23
+ |
+LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ | ^^^
+ |
+ = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+ = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: `X..` patterns in slices are experimental
+ --> $DIR/slice_pattern_syntax_problem1.rs:4:10
+ |
+LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ | ^^^^^^^
+ |
+ = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+ = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/slice_pattern_syntax_problem1.rs:4:23
+ |
+LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ | ^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0658]: exclusive range pattern syntax is experimental
+ --> $DIR/slice_pattern_syntax_problem1.rs:4:32
+ |
+LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ | ^^^^
+ |
+ = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+ = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// run-pass
+
+fn main() {
+ let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+ if let [3..=14, ..] = xs {
+ /* this variant must pass for now, unfortunately.
+ * This test is included here to help inform a future plan for these.
+ */
+ };
+}
/*
Expansions:
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
-1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "foo", proc_macro: false }
+1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo")
SyntaxContexts:
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
--- /dev/null
+#![feature(core_intrinsics)]
+#![feature(const_intrinsic_raw_eq)]
+#![deny(const_err)]
+
+const BAD_RAW_EQ_CALL: bool = unsafe {
+ std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
+//~^ ERROR evaluation of constant value failed
+};
+
+pub fn main() {
+}
--- /dev/null
+error[E0080]: evaluation of constant value failed
+ --> $DIR/intrinsic-raw_eq-const-padding.rs:6:5
+ |
+LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading 4 bytes of memory starting at alloc2, but 1 byte is uninitialized starting at alloc2+0x1, and this operation requires initialized memory
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
--- /dev/null
+// run-pass
+
+#![feature(core_intrinsics)]
+#![feature(const_intrinsic_raw_eq)]
+#![deny(const_err)]
+
+pub fn main() {
+ use std::intrinsics::raw_eq;
+
+ const RAW_EQ_I32_TRUE: bool = unsafe { raw_eq(&42_i32, &42) };
+ assert!(RAW_EQ_I32_TRUE);
+
+ const RAW_EQ_I32_FALSE: bool = unsafe { raw_eq(&4_i32, &2) };
+ assert!(!RAW_EQ_I32_FALSE);
+
+ const RAW_EQ_CHAR_TRUE: bool = unsafe { raw_eq(&'a', &'a') };
+ assert!(RAW_EQ_CHAR_TRUE);
+
+ const RAW_EQ_CHAR_FALSE: bool = unsafe { raw_eq(&'a', &'A') };
+ assert!(!RAW_EQ_CHAR_FALSE);
+
+ const RAW_EQ_ARRAY_TRUE: bool = unsafe { raw_eq(&[13_u8, 42], &[13, 42]) };
+ assert!(RAW_EQ_ARRAY_TRUE);
+
+ const RAW_EQ_ARRAY_FALSE: bool = unsafe { raw_eq(&[13_u8, 42], &[42, 13]) };
+ assert!(!RAW_EQ_ARRAY_FALSE);
+}
fn main() {
const X: u32 = 1;
- const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+ const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
println!("{}", Y);
}
-error[E0658]: casting pointers to integers in constants is unstable
+error: pointers cannot be cast to integers during const eval.
--> $DIR/issue-18294.rs:3:31
|
LL | const Y: usize = unsafe { &X as *const u32 as usize };
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
- = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
match x {
5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING this was previously accepted by the compiler but is being
5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
//~| WARNING hard error
-5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
//~| WARNING hard error
1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
//~| ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
- //~| ERROR floating-point types cannot be used in patterns
//~| ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
//~| WARNING hard error
- //~| WARNING hard error
..71.0 => {}
//~^ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
//~| WARNING this was previously accepted by the compiler
..=72.0 => {}
//~^ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
//~| WARNING this was previously accepted by the compiler
71.0.. => {}
//~^ ERROR floating-point types cannot be used in patterns
- //~| ERROR floating-point types cannot be used in patterns
- //~| WARNING hard error
//~| WARNING this was previously accepted by the compiler
_ => {},
};
// Same for tuples
match (x, 5) {
(3.14, 1) => {}, //~ ERROR floating-point types cannot be used
- //~| ERROR floating-point types cannot be used
- //~| WARNING hard error
//~| WARNING hard error
_ => {},
}
struct Foo { x: f32 };
match (Foo { x }) {
Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
- //~| ERROR floating-point types cannot be used
- //~| WARNING hard error
//~| WARNING hard error
_ => {},
}
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:15:9
+ --> $DIR/issue-41255.rs:13:9
|
LL | 5.0f32 => {},
| ^^^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:19:10
+ --> $DIR/issue-41255.rs:15:10
|
LL | -5.0 => {},
| ^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:23:9
+ --> $DIR/issue-41255.rs:17:9
|
LL | 1.0 .. 33.0 => {},
| ^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:23:16
+ --> $DIR/issue-41255.rs:17:16
|
LL | 1.0 .. 33.0 => {},
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:31:9
+ --> $DIR/issue-41255.rs:21:9
|
LL | 39.0 ..= 70.0 => {},
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:31:18
+ --> $DIR/issue-41255.rs:21:18
|
LL | 39.0 ..= 70.0 => {},
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:40:11
+ --> $DIR/issue-41255.rs:26:11
|
LL | ..71.0 => {}
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:45:12
+ --> $DIR/issue-41255.rs:29:12
|
LL | ..=72.0 => {}
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:50:9
+ --> $DIR/issue-41255.rs:32:9
|
LL | 71.0.. => {}
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:60:10
+ --> $DIR/issue-41255.rs:40:10
|
LL | (3.14, 1) => {},
| ^^^^
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:69:18
+ --> $DIR/issue-41255.rs:47:18
|
LL | Foo { x: 2.0 } => {},
| ^^^
= 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:11:9
- |
-LL | 5.0 => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:15:9
- |
-LL | 5.0f32 => {},
- | ^^^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:19:10
- |
-LL | -5.0 => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:23:9
- |
-LL | 1.0 .. 33.0 => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:23:16
- |
-LL | 1.0 .. 33.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:31:9
- |
-LL | 39.0 ..= 70.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:31:18
- |
-LL | 39.0 ..= 70.0 => {},
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:40:11
- |
-LL | ..71.0 => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:45:12
- |
-LL | ..=72.0 => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:50:9
- |
-LL | 71.0.. => {}
- | ^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:60:10
- |
-LL | (3.14, 1) => {},
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:69:18
- |
-LL | Foo { x: 2.0 } => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 24 previous errors
+error: aborting due to 12 previous errors
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
- --> $DIR/issue-47412.rs:21:11
+ --> $DIR/issue-47412.rs:20:11
|
LL | match *ptr {}
| ^^^^ dereference of raw pointer
union Union { unit: (), void: Void }
let u = Union { unit: () };
match u.void {}
- //[mir]~^ ERROR access to union field is unsafe
- // FIXME(thir-unsafeck): AccessToUnionField unimplemented
+ //~^ ERROR access to union field is unsafe
}
fn raw_ptr_deref() {
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/issue-47412.rs:14:11
+ |
+LL | match u.void {}
+ | ^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
- --> $DIR/issue-47412.rs:21:11
+ --> $DIR/issue-47412.rs:20:11
|
LL | match *ptr {}
| ^^^^ dereference of raw pointer
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0133`.
fn main() {
let ref my_ref @ _ = 0;
- *my_ref = 0; //~ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+ *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
}
-error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
--> $DIR/issue-51244.rs:3:5
|
LL | let ref my_ref @ _ = 0;
//~^ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut 16
*foo = 32;
- //~^ ERROR cannot assign to `*foo` which is behind a `&` reference
+ //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
//~^ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut i32
*bar = 64;
- //~^ ERROR cannot assign to `*bar` which is behind a `&` reference
+ //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
-error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-51515.rs:5:5
|
LL | let foo = &16;
LL | *foo = 32;
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
--> $DIR/issue-51515.rs:10:5
|
LL | let bar = foo;
let x = NAN;
match x {
NAN => {}, //~ ERROR floating-point types cannot be used
- //~^ WARN this was previously accepted by the compiler but is being phased out
- //~| ERROR floating-point types cannot be used in patterns
//~| WARN this was previously accepted by the compiler but is being phased out
_ => {},
};
match [x, 1.0] {
[NAN, _] => {}, //~ ERROR floating-point types cannot be used
- //~| ERROR floating-point types cannot be used
- //~| WARN this was previously accepted by the compiler but is being phased out
//~| WARN this was previously accepted by the compiler but is being phased out
_ => {},
};
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-6804.rs:19:10
+ --> $DIR/issue-6804.rs:17:10
|
LL | [NAN, _] => {},
| ^^^
= 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-6804.rs:11:9
- |
-LL | NAN => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-6804.rs:19:10
- |
-LL | [NAN, _] => {},
- | ^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
--> $DIR/issue-73886.rs:4:13
|
LL | let _ = 7u32 as Option<_>;
- | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+ | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+ |
+ = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
--- /dev/null
+// Regression test for the ICE described in issue #86238.
+
+#![feature(lang_items)]
+#![feature(no_core)]
+
+#![no_core]
+fn main() {
+ let one = || {};
+ one()
+ //~^ ERROR: failed to find an overloaded call trait for closure call
+ //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined
+}
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
--- /dev/null
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/issue-86238.rs:9:5
+ |
+LL | one()
+ | ^^^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have associated `call`/`call_mut`/`call_once` functions
+
+error: aborting due to previous error
+
--- /dev/null
+// compile-flags: -A known_tool::foo
+// check-pass
+
+#![feature(register_tool)]
+#![register_tool(known_tool)]
+
+fn main() {}
--- /dev/null
+// compile-flags: -A unknown_tool::foo
+// error-pattern: unknown lint tool: `unknown_tool`
+
+fn main() {}
--- /dev/null
+error[E0602]: unknown lint tool: `unknown_tool`
+ |
+ = note: requested on the command line with `-A unknown_tool::foo`
+
+error[E0602]: unknown lint tool: `unknown_tool`
+ |
+ = note: requested on the command line with `-A unknown_tool::foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0602`.
--- /dev/null
+// compile-flags: --cap-lints warn --force-warns rust-2021-compatibility -Zunstable-options
+// check-pass
+#![allow(ellipsis_inclusive_range_patterns)]
+
+pub fn f() -> bool {
+ let x = 123;
+ match x {
+ 0...100 => true,
+ //~^ WARN range patterns are deprecated
+ //~| WARN this is accepted in the current edition
+ _ => false,
+ }
+}
+
+fn main() {}
--- /dev/null
+warning: `...` range patterns are deprecated
+ --> $DIR/force-warn-cap-lints-warn.rs:8:10
+ |
+LL | 0...100 => true,
+ | ^^^ help: use `..=` for an inclusive range
+ |
+ = note: `--force-warns ellipsis-inclusive-range-patterns` implied by `--force-warns rust-2021-compatibility`
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
--- /dev/null
+// compile-flags: --cap-lints allow --force-warns bare_trait_objects -Zunstable-options
+// check-pass
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this is accepted in the current edition
+
+fn main() {}
--- /dev/null
+warning: trait objects without an explicit `dyn` are deprecated
+ --> $DIR/force-warns-cap-lints-allow.rs:6:25
+ |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+ | ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+ |
+ = note: requested on the command line with `--force-warns bare-trait-objects`
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
--- /dev/null
+// Regression test for #86600, where an instance of the
+// `illegal_floating_point_literal_pattern` lint was issued twice.
+
+// check-pass
+
+fn main() {
+ let x = 42.0;
+
+ match x {
+ 5.0 => {}
+ //~^ WARNING: floating-point types cannot be used in patterns
+ //~| WARNING: this was previously accepted by the compiler
+ _ => {}
+ }
+}
--- /dev/null
+warning: floating-point types cannot be used in patterns
+ --> $DIR/issue-86600-lint-twice.rs:10:9
+ |
+LL | 5.0 => {}
+ | ^^^
+ |
+ = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: 1 warning emitted
+
| ^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:29:9
+ --> $DIR/lint-stability-deprecated.rs:29:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:31:9
+ --> $DIR/lint-stability-deprecated.rs:31:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated function `lint_stability::deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:33:9
| ^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:38:9
+ --> $DIR/lint-stability-deprecated.rs:38:16
|
LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:40:9
+ --> $DIR/lint-stability-deprecated.rs:40:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated function `lint_stability::deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:42:9
| ^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
- --> $DIR/lint-stability-deprecated.rs:47:9
+ --> $DIR/lint-stability-deprecated.rs:47:16
|
LL | ... Trait::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
- --> $DIR/lint-stability-deprecated.rs:49:9
+ --> $DIR/lint-stability-deprecated.rs:49:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:51:9
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- --> $DIR/lint-stability-deprecated.rs:56:9
+ --> $DIR/lint-stability-deprecated.rs:56:16
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- --> $DIR/lint-stability-deprecated.rs:58:9
+ --> $DIR/lint-stability-deprecated.rs:58:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text
--> $DIR/lint-stability-deprecated.rs:108:17
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text
- --> $DIR/lint-stability-deprecated.rs:123:17
+ --> $DIR/lint-stability-deprecated.rs:123:23
|
LL | let _ = Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text
- --> $DIR/lint-stability-deprecated.rs:124:17
+ --> $DIR/lint-stability-deprecated.rs:124:23
|
LL | let _ = Enum::DeprecatedUnstableVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text
--> $DIR/lint-stability-deprecated.rs:128:17
| ^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:145:9
+ --> $DIR/lint-stability-deprecated.rs:145:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:147:9
+ --> $DIR/lint-stability-deprecated.rs:147:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:149:9
+ --> $DIR/lint-stability-deprecated.rs:149:16
|
LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:151:9
+ --> $DIR/lint-stability-deprecated.rs:151:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
- --> $DIR/lint-stability-deprecated.rs:153:9
+ --> $DIR/lint-stability-deprecated.rs:153:16
|
LL | ... Trait::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
- --> $DIR/lint-stability-deprecated.rs:155:9
+ --> $DIR/lint-stability-deprecated.rs:155:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- --> $DIR/lint-stability-deprecated.rs:157:9
+ --> $DIR/lint-stability-deprecated.rs:157:16
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- --> $DIR/lint-stability-deprecated.rs:159:9
+ --> $DIR/lint-stability-deprecated.rs:159:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text
--> $DIR/lint-stability-deprecated.rs:187:10
| ^^^^^^^^^^^^^^^
warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:208:9
+ --> $DIR/lint-stability-deprecated.rs:208:23
|
LL | unstable_mod::deprecated();
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^
warning: use of deprecated function `this_crate::deprecated`: text
--> $DIR/lint-stability-deprecated.rs:330:9
| ^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:335:9
+ --> $DIR/lint-stability-deprecated.rs:335:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:337:9
+ --> $DIR/lint-stability-deprecated.rs:337:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated function `this_crate::deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:339:9
| ^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:344:9
+ --> $DIR/lint-stability-deprecated.rs:344:16
|
LL | Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:346:9
+ --> $DIR/lint-stability-deprecated.rs:346:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated struct `this_crate::DeprecatedStruct`: text
--> $DIR/lint-stability-deprecated.rs:384:17
| ^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
- --> $DIR/lint-stability-deprecated.rs:395:17
+ --> $DIR/lint-stability-deprecated.rs:395:23
|
LL | let _ = Enum::DeprecatedVariant;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
--> $DIR/lint-stability-deprecated.rs:399:17
| ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:406:9
+ --> $DIR/lint-stability-deprecated.rs:406:16
|
LL | Trait::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
- --> $DIR/lint-stability-deprecated.rs:408:9
+ --> $DIR/lint-stability-deprecated.rs:408:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:410:9
+ --> $DIR/lint-stability-deprecated.rs:410:16
|
LL | Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- --> $DIR/lint-stability-deprecated.rs:412:9
+ --> $DIR/lint-stability-deprecated.rs:412:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
--> $DIR/lint-stability-deprecated.rs:439:9
error: use of deprecated function `lint_stability::deprecated_text`: text
- --> $DIR/lint-stability3.rs:13:5
+ --> $DIR/lint-stability3.rs:13:28
|
LL | macro_test_arg_nested!(deprecated_text);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-stability3.rs:4:9
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^
- = note: this error originates in the macro `macro_test_arg_nested` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
--- /dev/null
+// Checks that undocumented private macros will not generate `missing_docs`
+// lints, but public ones will.
+//
+// This is a regression test for issue #57569
+#![deny(missing_docs)]
+#![feature(decl_macro)]
+//! Empty documentation.
+
+macro new_style_private_macro {
+ () => ()
+}
+
+pub(crate) macro new_style_crate_macro {
+ () => ()
+}
+
+macro_rules! old_style_private_macro {
+ () => ()
+}
+
+mod submodule {
+ pub macro new_style_macro_in_private_module {
+ () => ()
+ }
+
+ macro_rules! old_style_mod_private_macro {
+ () => ()
+ }
+
+ #[macro_export]
+ macro_rules! exported_to_top_level {
+ //~^ ERROR missing documentation for macro
+ () => ()
+ }
+}
+
+pub macro top_level_pub_macro {
+ //~^ ERROR missing documentation for macro
+ () => ()
+}
+
+/// Empty documentation.
+pub fn main() {}
--- /dev/null
+error: missing documentation for macro
+ --> $DIR/missing-doc-private-macro.rs:31:5
+ |
+LL | macro_rules! exported_to_top_level {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/missing-doc-private-macro.rs:5:9
+ |
+LL | #![deny(missing_docs)]
+ | ^^^^^^^^^^^^
+
+error: missing documentation for macro
+ --> $DIR/missing-doc-private-macro.rs:37:1
+ |
+LL | pub macro top_level_pub_macro {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
warning: Linking globals named 'foo': symbol multiply defined!
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o":
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o":
error: aborting due to previous error; 1 warning emitted
// error-pattern:panicked at 'test-assert-owned'
// ignore-emscripten no processes
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
fn main() {
assert!(false, "test-assert-owned".to_string());
// revisions: std core
// ignore-wasm32-bare compiled with panic=abort by default
-
#![cfg_attr(core, no_std)]
-#[cfg(std)] use std::fmt;
-#[cfg(core)] use core::fmt;
+#[cfg(core)]
+use core::fmt;
+#[cfg(std)]
+use std::fmt;
// an easy mistake in the implementation of 'assert!'
// would cause this to say "explicit panic"
//
// (Example: Issue #48042)
#[test]
-#[allow(non_fmt_panic)]
+#[allow(non_fmt_panics)]
fn to_format_or_not_to_format() {
// ("{}" is the easiest string to test because if this gets
// sent to format_args!, it'll simply fail to compile.
// format!("{}",); // see check-fail
// format_args!("{}",); // see check-fail
- if falsum() { panic!("{}",); }
+ if falsum() {
+ panic!("{}",);
+ }
// print!("{}",); // see check-fail
// println!("{}",); // see check-fail
// unimplemented!("{}",); // see check-fail
- if falsum() { unreachable!("{}",); }
+ if falsum() {
+ unreachable!("{}",);
+ }
// write!(&mut stdout, "{}",); // see check-fail
// writeln!(&mut stdout, "{}",); // see check-fail
// run-rustfix
// aux-build:or-pattern.rs
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
#![allow(unused_macros)]
#[macro_use]
// run-rustfix
// aux-build:or-pattern.rs
-#![deny(or_patterns_back_compat)]
+#![deny(rust_2021_incompatible_or_patterns)]
#![allow(unused_macros)]
#[macro_use]
note: the lint level is defined here
--> $DIR/macro-or-patterns-back-compat.rs:4:9
|
-LL | #![deny(or_patterns_back_compat)]
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(rust_2021_incompatible_or_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
-error[E0594]: cannot assign to `self.how_hungry` which is behind a `&` reference
+error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference
--> $DIR/mutable-class-fields-2.rs:9:5
|
LL | pub fn eat(&self) {
-error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference
--> $DIR/issue-47388.rs:8:5
|
LL | let fancy_ref = &(&mut fancy);
fn main() {
let ref my_ref @ _ = 0;
*my_ref = 0;
- //~^ ERROR cannot assign to `*my_ref` which is behind a `&` reference [E0594]
+ //~^ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
}
-error[E0594]: cannot assign to `*my_ref` which is behind a `&` reference
+error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
--> $DIR/issue-51244.rs:3:5
|
LL | let ref my_ref @ _ = 0;
fn f(x: &i32) {
let g = &x;
- *x = 0; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+ *x = 0; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| ERROR cannot assign to `*x` because it is borrowed
g;
}
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-57989.rs:5:5
|
LL | fn f(x: &i32) {
LL | panic!("here's a brace: {");
| ^
|
- = note: `#[warn(non_fmt_panic)]` on by default
+ = note: `#[warn(non_fmt_panics)]` on by default
= note: this message is not used as a format string, but will be in Rust 2021
help: add a "{}" format string to use the message literally
|
#![allow(unused_assignments)]
#![allow(unused_variables)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
// run-fail
// error-pattern:wooooo
// error-pattern:panicked at 'Box<dyn Any>'
// ignore-emscripten no processes
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
fn main() {
panic!(Box::new(612_i64));
// ignore-emscripten no processes
#![feature(box_syntax)]
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
fn main() {
panic!(box 413 as Box<dyn std::any::Any + Send>);
--- /dev/null
+const pub () {}
+//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`
+pub fn main() {}
--- /dev/null
+error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
+ --> $DIR/issue-86895.rs:1:7
+ |
+LL | const pub () {}
+ | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe`
+
+error: aborting due to previous error
+
--- /dev/null
+// Test that the parser detects `&dyn mut`, offers a help message, and
+// recovers.
+
+fn main() {
+ let r: &dyn mut Trait;
+ //~^ ERROR: `mut` must precede `dyn`
+ //~| HELP: place `mut` before `dyn`
+ //~| ERROR: cannot find trait `Trait` in this scope [E0405]
+}
--- /dev/null
+error: `mut` must precede `dyn`
+ --> $DIR/recover-ref-dyn-mut.rs:5:12
+ |
+LL | let r: &dyn mut Trait;
+ | ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn`
+
+error[E0405]: cannot find trait `Trait` in this scope
+ --> $DIR/recover-ref-dyn-mut.rs:5:21
+ |
+LL | let r: &dyn mut Trait;
+ | ^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
_x1 = U; //~ ERROR cannot assign twice to immutable variable
let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also
let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also
- *_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference
- *_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference
+ *_x0 = U; //~ ERROR cannot assign to `*_x0`, which is behind a `&` reference
+ *_x2 = U; //~ ERROR cannot assign to `*_x2`, which is behind a `&` reference
drop(tup.1); //~ ERROR use of moved value: `tup.1`
let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1`
let (.., ref mut _x3) = tup;
LL | *_x0 = U;
| -------- immutable borrow later used here
-error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
+error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:26:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
LL | *_x0 = U;
| ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
+error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:27:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
Expansions:
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "produce_it", proc_macro: false }
+2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "meta_macro::print_def_site", proc_macro: true }
-5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "$crate::dummy", proc_macro: true }
+4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
SyntaxContexts:
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
Expansions:
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "outer", proc_macro: false }
+2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro { kind: Bang, name: "inner", proc_macro: false }
-5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro { kind: Bang, name: "print_bang", proc_macro: true }
+4: parent: ExpnId(2), call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
+5: parent: ExpnId(4), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
SyntaxContexts:
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
- | ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
+ | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:46:21
|
LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream {
- | ------------------------------------------------------------ in this expansion of procedural macro `#[derive(ErrorFromDerive)]`
+ | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]`
...
LL | Variant(OtherMissingType)
| ^^^^^^^^^^^^^^^^ not found in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:29:9
|
LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream {
- | ---------------------------------------------------------------- in this expansion of procedural macro `other_error_from_bang!`
+ | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!`
LL | custom_quote::custom_quote! {
LL | my_ident
| ^^^^^^^^ not found in this scope
| expected due to this
...
LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream {
- | ---------------------------------------------------------- in this expansion of procedural macro `error_from_bang!`
+ | ---------------------------------------------------------- in this expansion of `error_from_bang!`
|
::: $DIR/span-from-proc-macro.rs:15:5
|
#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer
//~| `limit` must be a non-negative integer
+ //~| ERROR `limit` must be a non-negative integer
+ //~| `limit` must be a non-negative integer
fn main() {}
| |
| `limit` must be a non-negative integer
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+ --> $DIR/empty.rs:3:1
+ |
+LL | #![recursion_limit = ""]
+ | ^^^^^^^^^^^^^^^^^^^^^--^
+ | |
+ | `limit` must be a non-negative integer
+
+error: aborting due to 2 previous errors
#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer
//~| not a valid integer
-
+ //~| ERROR `limit` must be a non-negative integer
+ //~| not a valid integer
fn main() {}
| |
| not a valid integer
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+ --> $DIR/invalid_digit.rs:3:1
+ |
+LL | #![recursion_limit = "-100"]
+ | ^^^^^^^^^^^^^^^^^^^^^------^
+ | |
+ | not a valid integer
+
+error: aborting due to 2 previous errors
#![recursion_limit = "999999999999999999999999"]
//~^ ERROR `limit` must be a non-negative integer
//~| `limit` is too large
+//~| ERROR `limit` must be a non-negative integer
+//~| `limit` is too large
fn main() {}
| |
| `limit` is too large
-error: aborting due to previous error
+error: `limit` must be a non-negative integer
+ --> $DIR/overflow.rs:3:1
+ |
+LL | #![recursion_limit = "999999999999999999999999"]
+ | ^^^^^^^^^^^^^^^^^^^^^--------------------------^
+ | |
+ | `limit` is too large
+
+error: aborting due to 2 previous errors
--- /dev/null
+// Regression test for various ICEs inspired by
+// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734
+
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
+#[repr(packed())]
+//~^ ERROR: incorrect `repr(packed)` attribute format
+struct S1;
+
+#[repr(align)]
+//~^ ERROR: invalid `repr(align)` attribute
+struct S2;
+
+#[repr(align(2, 4))]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S3;
+
+#[repr(align())]
+//~^ ERROR: incorrect `repr(align)` attribute format
+struct S4;
+
+#[repr(i8())]
+//~^ ERROR: invalid representation hint
+enum E1 { A, B }
+
+#[repr(u32(42))]
+//~^ ERROR: invalid representation hint
+enum E2 { A, B }
+
+#[repr(i64 = 2)]
+//~^ ERROR: invalid representation hint
+enum E3 { A, B }
+
+fn main() {}
--- /dev/null
+error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
+ --> $DIR/issue-83921-ice.rs:6:8
+ |
+LL | #[repr(packed())]
+ | ^^^^^^^^
+
+error[E0589]: invalid `repr(align)` attribute: `align` needs an argument
+ --> $DIR/issue-83921-ice.rs:10:8
+ |
+LL | #[repr(align)]
+ | ^^^^^ help: supply an argument here: `align(...)`
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+ --> $DIR/issue-83921-ice.rs:14:8
+ |
+LL | #[repr(align(2, 4))]
+ | ^^^^^^^^^^^
+
+error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
+ --> $DIR/issue-83921-ice.rs:18:8
+ |
+LL | #[repr(align())]
+ | ^^^^^^^
+
+error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list
+ --> $DIR/issue-83921-ice.rs:22:8
+ |
+LL | #[repr(i8())]
+ | ^^^^
+
+error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list
+ --> $DIR/issue-83921-ice.rs:26:8
+ |
+LL | #[repr(u32(42))]
+ | ^^^^^^^
+
+error[E0552]: invalid representation hint: `i64` does not take a value
+ --> $DIR/issue-83921-ice.rs:30:8
+ |
+LL | #[repr(i64 = 2)]
+ | ^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0552, E0589, E0693.
+For more information about an error, try `rustc --explain E0552`.
--- /dev/null
+error[E0565]: meta item in `repr` must be an identifier
+ --> $DIR/issue-83921-pretty.rs:10:8
+ |
+LL | #[repr("C")]
+ | ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0565`.
--- /dev/null
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+#[repr("C")]
+struct A {
+}
+
+fn main() { loop { } }
--- /dev/null
+// Regression test for #83921. A `delay_span_bug()` call was issued, but the
+// error was never reported because the pass responsible for detecting and
+// reporting the error does not run in certain modes of pretty-printing.
+
+// Make sure the error is reported if we do not just pretty-print:
+// revisions: pretty normal
+// [pretty]compile-flags: -Zunpretty=everybody_loops
+// [pretty]check-pass
+
+#[repr("C")]
+//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565]
+struct A {}
+
+fn main() {}
match x {
f32::INFINITY => { }
//~^ WARNING floating-point types cannot be used in patterns
- //~| WARNING will become a hard error in a future release
- //~| WARNING floating-point types cannot be used in patterns
//~| WARNING this was previously accepted by the compiler but is being phased out
_ => { }
}
= 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-warning: floating-point types cannot be used in patterns
- --> $DIR/match-forbidden-without-eq.rs:18:9
- |
-LL | f32::INFINITY => { }
- | ^^^^^^^^^^^^^
- |
- = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error; 1 warning emitted
pub fn main() {
let Wrap(x) = &Wrap(3);
- *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
if let Some(x) = &Some(3) {
- *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
} else {
panic!();
}
while let Some(x) = &Some(3) {
- *x += 1; //~ ERROR cannot assign to `*x` which is behind a `&` reference
+ *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference
break;
}
}
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:9:5
|
LL | *x += 1;
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:13:9
|
LL | *x += 1;
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*x` which is behind a `&` reference
+error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/enum.rs:19:9
|
LL | *x += 1;
fn main() {
match &&Some(5i32) {
Some(n) => {
- *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
match &mut &Some(5i32) {
Some(n) => {
- *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
match &&mut Some(5i32) {
Some(n) => {
- *n += 1; //~ ERROR cannot assign to `*n` which is behind a `&` reference
+ *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference
let _ = n;
}
None => {},
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:7:13
|
LL | *n += 1;
| ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:15:13
|
LL | *n += 1;
| ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*n` which is behind a `&` reference
+error[E0594]: cannot assign to `*n`, which is behind a `&` reference
--> $DIR/explicit-mut.rs:23:13
|
LL | *n += 1;
trait Tracked {
#[track_caller]
- fn handle(&self) {
+ fn track_caller_trait_method(&self, line: u32, col: u32) {
let location = std::panic::Location::caller();
assert_eq!(location.file(), file!());
- // we only call this via trait object, so the def site should *always* be returned
- assert_eq!(location.line(), line!() - 4);
- assert_eq!(location.column(), 5);
+ // The trait method definition is annotated with `#[track_caller]`,
+ // so caller location information will work through a method
+ // call on a trait object
+ assert_eq!(location.line(), line, "Bad line");
+ assert_eq!(location.column(), col, "Bad col");
}
+
+ fn track_caller_not_on_trait_method(&self);
+
+ #[track_caller]
+ fn track_caller_through_self(self: Box<Self>, line: u32, col: u32);
}
-impl Tracked for () {}
-impl Tracked for u8 {}
+impl Tracked for () {
+ // We have `#[track_caller]` on the implementation of the method,
+ // but not on the definition of the method in the trait. Therefore,
+ // caller location information will *not* work through a method call
+ // on a trait object. Instead, we will get the location of this method
+ #[track_caller]
+ fn track_caller_not_on_trait_method(&self) {
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ assert_eq!(location.line(), line!() - 3);
+ assert_eq!(location.column(), 5);
+ }
+
+ // We don't have a `#[track_caller]` attribute, but
+ // `#[track_caller]` is present on the trait definition,
+ // so we'll still get location information
+ fn track_caller_through_self(self: Box<Self>, line: u32, col: u32) {
+ let location = std::panic::Location::caller();
+ assert_eq!(location.file(), file!());
+ // The trait method definition is annotated with `#[track_caller]`,
+ // so caller location information will work through a method
+ // call on a trait object
+ assert_eq!(location.line(), line, "Bad line");
+ assert_eq!(location.column(), col, "Bad col");
+ }
+}
fn main() {
- let tracked: &dyn Tracked = &5u8;
- tracked.handle();
+ let tracked: &dyn Tracked = &();
+ // The column is the start of 'track_caller_trait_method'
+ tracked.track_caller_trait_method(line!(), 13);
const TRACKED: &dyn Tracked = &();
- TRACKED.handle();
+ // The column is the start of 'track_caller_trait_method'
+ TRACKED.track_caller_trait_method(line!(), 13);
+ TRACKED.track_caller_not_on_trait_method();
+
+ // The column is the start of `track_caller_through_self`
+ let boxed: Box<dyn Tracked> = Box::new(());
+ boxed.track_caller_through_self(line!(), 11);
}
--- /dev/null
+// only-x86_64-pc-windows-msvc
+// compile-flags: --crate-type lib --emit link
+#![allow(incomplete_features)]
+#![feature(raw_dylib)]
+#[link(name = "foo", kind = "raw-dylib")]
+extern "stdcall" {
+ fn f(x: i32);
+ //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+}
+
+pub fn lib_main() {
+ unsafe { f(42); }
+}
--- /dev/null
+error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
+ --> $DIR/unsupported-abi.rs:7:5
+ |
+LL | fn f(x: i32);
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
// run-rustfix
// edition:2018
// check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
#![allow(dead_code)]
#![allow(unused_imports)]
// run-rustfix
// edition:2018
// check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
#![allow(dead_code)]
#![allow(unused_imports)]
note: the lint level is defined here
--> $DIR/future-prelude-collision-imported.rs:4:9
|
-LL | #![warn(future_prelude_collision)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
// edition:2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
#![allow(dead_code)]
#![allow(unused_imports)]
// edition:2018
// check-pass
#![allow(unused)]
-#![deny(future_prelude_collision)]
+#![deny(rust_2021_prelude_collisions)]
struct S;
impl S {
- fn try_into(self) -> S { S }
+ fn try_into(self) -> S {
+ S
+ }
+}
+
+struct X;
+
+trait Hey {
+ fn from_iter(_: i32) -> Self;
+}
+
+impl Hey for X {
+ fn from_iter(_: i32) -> Self {
+ X
+ }
+}
+
+struct Y<T>(T);
+
+impl Hey for Y<i32> {
+ fn from_iter(_: i32) -> Self {
+ Y(0)
+ }
+}
+
+struct Z<T>(T);
+
+impl Hey for Z<i32> {
+ fn from_iter(_: i32) -> Self {
+ Z(0)
+ }
+}
+
+impl std::iter::FromIterator<u32> for Z<u32> {
+ fn from_iter<T: IntoIterator<Item = u32>>(_: T) -> Self {
+ todo!()
+ }
}
-// See https://github.com/rust-lang/rust/issues/86633
fn main() {
+ // See https://github.com/rust-lang/rust/issues/86633
let s = S;
let s2 = s.try_into();
+
+ // Check that we do not issue suggestions for types that do not implement `FromIter`.
+ //
+ // See https://github.com/rust-lang/rust/issues/86902
+ X::from_iter(1);
+ Y::from_iter(1);
+ Y::<i32>::from_iter(1);
+ Z::<i32>::from_iter(1);
}
// run-rustfix
// edition:2018
// check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait TryIntoU32 {
fn try_into(self) -> Result<u32, ()>;
// run-rustfix
// edition:2018
// check-pass
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait TryIntoU32 {
fn try_into(self) -> Result<u32, ()>;
note: the lint level is defined here
--> $DIR/future-prelude-collision.rs:4:9
|
-LL | #![warn(future_prelude_collision)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
// check-pass
// run-rustfix
// edition 2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait MyTrait<A> {
fn from_iter(x: Option<A>);
// check-pass
// run-rustfix
// edition 2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait MyTrait<A> {
fn from_iter(x: Option<A>);
note: the lint level is defined here
--> $DIR/generic-type-collision.rs:4:9
|
-LL | #![warn(future_prelude_collision)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
// run-rustfix
// edition:2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait TryIntoU32 {
fn try_into(&self) -> Result<u32, ()>;
// run-rustfix
// edition:2018
-#![warn(future_prelude_collision)]
+#![warn(rust_2021_prelude_collisions)]
trait TryIntoU32 {
fn try_into(&self) -> Result<u32, ()>;
note: the lint level is defined here
--> $DIR/inherent-dyn-collision.rs:8:9
|
-LL | #![warn(future_prelude_collision)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
//
// check-pass
-#![deny(future_prelude_collision)]
+#![deny(rust_2021_prelude_collisions)]
pub struct MySeq {}
// run-rustfix
// compile-flags: -Z unstable-options --edition 2018
-#![warn(reserved_prefix)]
+#![warn(rust_2021_prefixes_incompatible_syntax)]
macro_rules! m2 {
($a:tt $b:tt) => {};
fn main() {
m2!(z "hey");
- //~^ WARNING prefix `z` is unknown [reserved_prefix]
+ //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m2!(prefix "hey");
- //~^ WARNING prefix `prefix` is unknown [reserved_prefix]
+ //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m3!(hey #123);
- //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+ //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m3!(hey #hey);
- //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+ //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
}
quote! {
#name = #kind #value
- //~^ WARNING prefix `kind` is unknown [reserved_prefix]
+ //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
}
// run-rustfix
// compile-flags: -Z unstable-options --edition 2018
-#![warn(reserved_prefix)]
+#![warn(rust_2021_prefixes_incompatible_syntax)]
macro_rules! m2 {
($a:tt $b:tt) => {};
fn main() {
m2!(z"hey");
- //~^ WARNING prefix `z` is unknown [reserved_prefix]
+ //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m2!(prefix"hey");
- //~^ WARNING prefix `prefix` is unknown [reserved_prefix]
+ //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m3!(hey#123);
- //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+ //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
m3!(hey#hey);
- //~^ WARNING prefix `hey` is unknown [reserved_prefix]
+ //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
}
quote! {
#name = #kind#value
- //~^ WARNING prefix `kind` is unknown [reserved_prefix]
+ //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax]
//~| WARNING hard error in Rust 2021
}
note: the lint level is defined here
--> $DIR/reserved-prefixes-migration.rs:5:9
|
-LL | #![warn(reserved_prefix)]
- | ^^^^^^^^^^^^^^^
+LL | #![warn(rust_2021_prefixes_incompatible_syntax)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
-error: lifetime parameter `'b` only used once
- --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
+error: lifetime parameter `'a` only used once
+ --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
|
LL | fn a(x: &'a u32, y: &'b u32) {
- | ^^-
- | |
- | this lifetime is only used here
- | help: elide the single-use lifetime
+ | ^^-
+ | |
+ | this lifetime is only used here
+ | help: elide the single-use lifetime
|
note: the lint level is defined here
--> $DIR/one-use-in-fn-argument-in-band.rs:4:9
LL | #![deny(single_use_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^
-error: lifetime parameter `'a` only used once
- --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
+error: lifetime parameter `'b` only used once
+ --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
|
LL | fn a(x: &'a u32, y: &'b u32) {
- | ^^-
- | |
- | this lifetime is only used here
- | help: elide the single-use lifetime
+ | ^^-
+ | |
+ | this lifetime is only used here
+ | help: elide the single-use lifetime
error: aborting due to 2 previous errors
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[b09c]::Id::This) }, (I,)), [])`
--> $DIR/repeated_projection_type.rs:19:1
|
LL | / impl<I, V: Id<This = (I,)>> X for V {
--> $DIR/generics-default-stability.rs:83:12
|
LL | let _: Struct4<isize> = Struct4 { field: 1 };
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated struct `unstable_generic_param::Struct4`: test
--> $DIR/generics-default-stability.rs:88:12
--> $DIR/generics-default-stability.rs:89:12
|
LL | let _: Struct4<usize> = STRUCT4;
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated struct `unstable_generic_param::Struct4`: test
--> $DIR/generics-default-stability.rs:90:29
--> $DIR/generics-default-stability.rs:90:12
|
LL | let _: Struct4<isize> = Struct4 { field: 0 };
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated struct `unstable_generic_param::Struct5`: test
--> $DIR/generics-default-stability.rs:96:29
--> $DIR/generics-default-stability.rs:96:12
|
LL | let _: Struct5<isize> = Struct5 { field: 1 };
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated struct `unstable_generic_param::Struct5`: test
--> $DIR/generics-default-stability.rs:101:12
--> $DIR/generics-default-stability.rs:102:12
|
LL | let _: Struct5<usize> = STRUCT5;
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated struct `unstable_generic_param::Struct5`: test
--> $DIR/generics-default-stability.rs:104:29
--> $DIR/generics-default-stability.rs:104:12
|
LL | let _: Struct5<isize> = Struct5 { field: 0 };
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
--> $DIR/generics-default-stability.rs:159:28
--> $DIR/generics-default-stability.rs:159:12
|
LL | let _: Alias4<isize> = Alias4::Some(1);
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
--> $DIR/generics-default-stability.rs:163:12
--> $DIR/generics-default-stability.rs:164:12
|
LL | let _: Alias4<usize> = ALIAS4;
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias4`: test
--> $DIR/generics-default-stability.rs:165:28
--> $DIR/generics-default-stability.rs:165:12
|
LL | let _: Alias4<isize> = Alias4::Some(0);
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
--> $DIR/generics-default-stability.rs:170:28
--> $DIR/generics-default-stability.rs:170:12
|
LL | let _: Alias5<isize> = Alias5::Some(1);
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
--> $DIR/generics-default-stability.rs:174:12
--> $DIR/generics-default-stability.rs:175:12
|
LL | let _: Alias5<usize> = ALIAS5;
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated type alias `unstable_generic_param::Alias5`: test
--> $DIR/generics-default-stability.rs:177:28
--> $DIR/generics-default-stability.rs:177:12
|
LL | let _: Alias5<isize> = Alias5::Some(0);
- | ^^^^^^^^^^^^^
+ | ^^^^^^
warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
- --> $DIR/generics-default-stability.rs:231:27
+ --> $DIR/generics-default-stability.rs:231:34
|
LL | let _: Enum4<isize> = Enum4::Some(1);
- | ^^^^^^^^^^^
+ | ^^^^
warning: use of deprecated enum `unstable_generic_param::Enum4`: test
--> $DIR/generics-default-stability.rs:231:12
|
LL | let _: Enum4<isize> = Enum4::Some(1);
- | ^^^^^^^^^^^^
+ | ^^^^^
warning: use of deprecated enum `unstable_generic_param::Enum4`: test
--> $DIR/generics-default-stability.rs:235:12
--> $DIR/generics-default-stability.rs:236:12
|
LL | let _: Enum4<usize> = ENUM4;
- | ^^^^^^^^^^^^
+ | ^^^^^
warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
- --> $DIR/generics-default-stability.rs:237:27
+ --> $DIR/generics-default-stability.rs:237:34
|
LL | let _: Enum4<isize> = Enum4::Some(0);
- | ^^^^^^^^^^^
+ | ^^^^
warning: use of deprecated enum `unstable_generic_param::Enum4`: test
--> $DIR/generics-default-stability.rs:237:12
|
LL | let _: Enum4<isize> = Enum4::Some(0);
- | ^^^^^^^^^^^^
+ | ^^^^^
warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
- --> $DIR/generics-default-stability.rs:242:27
+ --> $DIR/generics-default-stability.rs:242:34
|
LL | let _: Enum5<isize> = Enum5::Some(1);
- | ^^^^^^^^^^^
+ | ^^^^
warning: use of deprecated enum `unstable_generic_param::Enum5`: test
--> $DIR/generics-default-stability.rs:242:12
|
LL | let _: Enum5<isize> = Enum5::Some(1);
- | ^^^^^^^^^^^^
+ | ^^^^^
warning: use of deprecated enum `unstable_generic_param::Enum5`: test
--> $DIR/generics-default-stability.rs:246:12
--> $DIR/generics-default-stability.rs:247:12
|
LL | let _: Enum5<usize> = ENUM5;
- | ^^^^^^^^^^^^
+ | ^^^^^
warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
- --> $DIR/generics-default-stability.rs:249:27
+ --> $DIR/generics-default-stability.rs:249:34
|
LL | let _: Enum5<isize> = Enum5::Some(0);
- | ^^^^^^^^^^^
+ | ^^^^
warning: use of deprecated enum `unstable_generic_param::Enum5`: test
--> $DIR/generics-default-stability.rs:249:12
|
LL | let _: Enum5<isize> = Enum5::Some(0);
- | ^^^^^^^^^^^^
+ | ^^^^^
error[E0658]: use of unstable library feature 'unstable_default'
--> $DIR/generics-default-stability.rs:35:20
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
--> $DIR/issue-68049-1.rs:7:9
|
LL | self.0 += 1;
-error[E0594]: cannot assign to `*input` which is behind a `&` reference
+error[E0594]: cannot assign to `*input`, which is behind a `&` reference
--> $DIR/issue-68049-2.rs:9:7
|
LL | fn example(&self, input: &i32); // should suggest here
LL | *input = self.0;
| ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
--> $DIR/issue-68049-2.rs:17:5
|
LL | fn example(&self, input: &i32); // should suggest here
-error[E0594]: cannot assign to `t.v` which is behind a `&` reference
+error[E0594]: cannot assign to `t.v`, which is behind a `&` reference
--> $DIR/suggest-mut-method-for-loop.rs:14:9
|
LL | for mut t in buzz.values() {
-error[E0594]: cannot assign to `self.0` which is behind a `&` reference
+error[E0594]: cannot assign to `self.0`, which is behind a `&` reference
--> $DIR/suggest-ref-mut.rs:7:9
|
LL | fn zap(&self) {
LL | self.0 = 32;
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/suggest-ref-mut.rs:16:5
|
LL | let ref foo = 16;
LL | *foo = 32;
| ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
--> $DIR/suggest-ref-mut.rs:21:9
|
LL | if let Some(ref bar) = Some(16) {
LL | *bar = 32;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
-error[E0594]: cannot assign to `*quo` which is behind a `&` reference
+error[E0594]: cannot assign to `*quo`, which is behind a `&` reference
--> $DIR/suggest-ref-mut.rs:25:22
|
LL | ref quo => { *quo = 32; },
--- /dev/null
+// Regression test for #87051, where a double semicolon was erroneously
+// suggested after a `?` operator.
+
+fn main() -> Result<(), ()> {
+ a(|| {
+ b()
+ //~^ ERROR: mismatched types [E0308]
+ //~| NOTE: expected `()`, found `i32`
+ //~| HELP: consider using a semicolon here
+ })?;
+
+ // Here, we do want to suggest a semicolon:
+ let x = Ok(42);
+ if true {
+ //~^ NOTE: expected this to be `()`
+ x?
+ //~^ ERROR: mismatched types [E0308]
+ //~| NOTE: expected `()`, found integer
+ //~| HELP: consider using a semicolon here
+ }
+ //~^ HELP: consider using a semicolon here
+
+ Ok(())
+}
+
+fn a<F>(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) }
+fn b() -> i32 { 42 }
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9
+ |
+LL | b()
+ | ^^^- help: consider using a semicolon here: `;`
+ | |
+ | expected `()`, found `i32`
+
+error[E0308]: mismatched types
+ --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9
+ |
+LL | / if true {
+LL | |
+LL | | x?
+ | | ^^ expected `()`, found integer
+LL | |
+LL | |
+LL | |
+LL | | }
+ | |_____- expected this to be `()`
+ |
+help: consider using a semicolon here
+ |
+LL | x?;
+ | ^
+help: consider using a semicolon here
+ |
+LL | };
+ | ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
-error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
+error: symbol-name(_ZN5basic4main17hd75b915511563828E)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(basic::main::h6c535bbea2051f85)
+error: demangling(basic::main::hd75b915511563828)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
//[legacy]~^ ERROR symbol-name(_ZN5basic4main
//[legacy]~| ERROR demangling(basic::main
//[legacy]~| ERROR demangling-alt(basic::main)
- //[v0]~^^^^ ERROR symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
- //[v0]~| ERROR demangling(basic[17891616a171812d]::main)
+ //[v0]~^^^^ ERROR symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
+ //[v0]~| ERROR demangling(basic[de7d5b6b69c71f37]::main)
//[v0]~| ERROR demangling-alt(basic::main)
#[rustc_def_path]
//[legacy]~^ ERROR def-path(main)
-error: symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
+error: symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(basic[17891616a171812d]::main)
+error: demangling(basic[de7d5b6b69c71f37]::main)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
pub struct Unsigned<const F: u8>;
#[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
+//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
//~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
impl Unsigned<11> {}
pub struct Signed<const F: i16>;
#[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
+//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
//~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
impl Signed<-152> {}
pub struct Bool<const F: bool>;
#[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
+//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
//~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
impl Bool<true> {}
pub struct Char<const F: char>;
#[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
-//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
+//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
+//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
//~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
impl Char<'∂'> {}
-error: symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
--> $DIR/const-generics-demangling.rs:7:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
--> $DIR/const-generics-demangling.rs:7:1
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
+error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
--> $DIR/const-generics-demangling.rs:15:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
--> $DIR/const-generics-demangling.rs:15:1
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
+error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
--> $DIR/const-generics-demangling.rs:23:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
--> $DIR/const-generics-demangling.rs:23:1
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
+error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
--> $DIR/const-generics-demangling.rs:31:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
+error: demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
--> $DIR/const-generics-demangling.rs:31:1
|
LL | #[rustc_symbol_name]
//[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar
//[legacy]~| ERROR demangling(impl1::foo::Foo::bar
//[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar)
- //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
- //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
+ //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
+ //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
//[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::bar)
#[rustc_def_path]
//[legacy]~^ ERROR def-path(foo::Foo::bar)
//[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
//[legacy]~| ERROR demangling(impl1::bar::<impl impl1::foo::Foo>::baz
//[legacy]~| ERROR demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
- //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
- //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
+ //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
+ //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
//[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::baz)
#[rustc_def_path]
//[legacy]~^ ERROR def-path(bar::<impl foo::Foo>::baz)
//[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
//[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
//[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
- //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
- //[v0]~| ERROR demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
+ //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+ //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
//[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
#[rustc_def_path]
//[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
+error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
--> $DIR/impl1.rs:14:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
+error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
--> $DIR/impl1.rs:14:9
|
LL | #[rustc_symbol_name]
LL | #[rustc_def_path]
| ^^^^^^^^^^^^^^^^^
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
+error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
--> $DIR/impl1.rs:32:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
+error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
--> $DIR/impl1.rs:32:9
|
LL | #[rustc_symbol_name]
LL | #[rustc_def_path]
| ^^^^^^^^^^^^^^^^^
-error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
--> $DIR/impl1.rs:62:13
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
--> $DIR/impl1.rs:62:13
|
LL | #[rustc_symbol_name]
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h18eaa05e22e59176E)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h18eaa05e22e59176)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
//[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
//[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo
//[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
- //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
- //[v0]~| ERROR demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
+ //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+ //[v0]~| ERROR demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
//[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
pub(crate) fn foo() {
for _ in 0..0 {
-error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+error: symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
+error: demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
//[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next
//[legacy]~| ERROR demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next
//[legacy]~| ERROR demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
- //[v0]~^^^^ ERROR symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
- //[v0]~| ERROR demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
+ //[v0]~^^^^ ERROR symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+ //[v0]~| ERROR demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
//[v0]~| ERROR demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
fn next(&mut self) -> Option<Self::Item> {
self.find(|_| true)
-error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+error: symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
--> $DIR/issue-75326.rs:41:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
+error: demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
--> $DIR/issue-75326.rs:41:5
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3f8b57f879016e18]::Bar>::method)
--> $DIR/trait-objects.rs:16:5
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Foo>::method)
--> $DIR/trait-objects.rs:28:5
|
LL | #[rustc_symbol_name]
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Baz>::method)
--> $DIR/trait-objects.rs:40:5
|
LL | #[rustc_symbol_name]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
use std::mem::{size_of, size_of_val, align_of, align_of_val};
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(path_statements)]
#![allow(dead_code)]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(unused_imports)]
// aux-build:union.rs
--- /dev/null
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+ |
+LL | let a = &mut u.x.0;
+ | ---------- mutable borrow occurs here (via `u.x.0`)
+LL | let b = &u.y;
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+ --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+ |
+LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+ | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL | let a = u.x.0;
+ | ----- value moved here
+LL | let b = u.y;
+ | ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+ |
+LL | let a = &mut (u.x.0).0;
+ | -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL | let b = &u.y;
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+ --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+ |
+LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+ | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL | let a = (u.x.0).0;
+ | --------- value moved here
+LL | let b = u.y;
+ | ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+ |
+LL | let a = &mut *u.y;
+ | --- mutable borrow occurs here (via `u.y`)
+LL | let b = &u.x;
+ | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![feature(untagged_unions)]
#![allow(unused)]
+++ /dev/null
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
- --> $DIR/union-borrow-move-parent-sibling.rs:53:13
- |
-LL | let a = &mut u.x.0;
- | ---------- mutable borrow occurs here (via `u.x.0`)
-LL | let b = &u.y;
- | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
-LL | use_borrow(a);
- | - mutable borrow later used here
- |
- = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
-
-error[E0382]: use of moved value: `u`
- --> $DIR/union-borrow-move-parent-sibling.rs:60:13
- |
-LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
- | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL | let a = u.x.0;
- | ----- value moved here
-LL | let b = u.y;
- | ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
- --> $DIR/union-borrow-move-parent-sibling.rs:66:13
- |
-LL | let a = &mut (u.x.0).0;
- | -------------- mutable borrow occurs here (via `u.x.0.0`)
-LL | let b = &u.y;
- | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
-LL | use_borrow(a);
- | - mutable borrow later used here
- |
- = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
-
-error[E0382]: use of moved value: `u`
- --> $DIR/union-borrow-move-parent-sibling.rs:73:13
- |
-LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
- | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
-LL | let a = (u.x.0).0;
- | --------- value moved here
-LL | let b = u.y;
- | ^^^ value used here after move
-
-error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
- --> $DIR/union-borrow-move-parent-sibling.rs:79:13
- |
-LL | let a = &mut *u.y;
- | --- mutable borrow occurs here (via `u.y`)
-LL | let b = &u.x;
- | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
-LL | use_borrow(a);
- | - mutable borrow later used here
- |
- = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0382, E0502.
-For more information about an error, try `rustc --explain E0382`.
--- /dev/null
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:56:13
+ |
+LL | let a = &mut u.x.0;
+ | ---------- mutable borrow occurs here (via `u.x.0`)
+LL | let b = &u.y;
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
+
+error[E0382]: use of moved value: `u`
+ --> $DIR/union-borrow-move-parent-sibling.rs:63:13
+ |
+LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+ | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL | let a = u.x.0;
+ | ----- value moved here
+LL | let b = u.y;
+ | ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:69:13
+ |
+LL | let a = &mut (u.x.0).0;
+ | -------------- mutable borrow occurs here (via `u.x.0.0`)
+LL | let b = &u.y;
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
+
+error[E0382]: use of moved value: `u`
+ --> $DIR/union-borrow-move-parent-sibling.rs:76:13
+ |
+LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
+ | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
+LL | let a = (u.x.0).0;
+ | --------- value moved here
+LL | let b = u.y;
+ | ^^^ value used here after move
+
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`)
+ --> $DIR/union-borrow-move-parent-sibling.rs:82:13
+ |
+LL | let a = &mut *u.y;
+ | --- mutable borrow occurs here (via `u.y`)
+LL | let b = &u.x;
+ | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here
+LL | use_borrow(a);
+ | - mutable borrow later used here
+ |
+ = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0382, E0502.
+For more information about an error, try `rustc --explain E0382`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: u64,
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
type Field1 = (i32, u32);
type Field2 = f32;
// build-pass (FIXME(62277): could be check-pass?)
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![feature(const_fn_union)]
union U {
--- /dev/null
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:17:14
+ |
+LL | unsafe { u.f.0 = Vec::new() };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:19:19
+ |
+LL | unsafe { &mut u.f.0 };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:21:14
+ |
+LL | unsafe { u.f.0.push(0) };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:25:14
+ |
+LL | unsafe { u.f.0.0 = Vec::new() };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:27:19
+ |
+LL | unsafe { &mut u.f.0.0 };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:29:14
+ |
+LL | unsafe { u.f.0.0.push(0) };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
//! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
//! of union fields.
#![feature(untagged_unions)]
+++ /dev/null
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:14:14
- |
-LL | unsafe { u.f.0 = Vec::new() };
- | ^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:16:19
- |
-LL | unsafe { &mut u.f.0 };
- | ^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:18:14
- |
-LL | unsafe { u.f.0.push(0) };
- | ^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:22:14
- |
-LL | unsafe { u.f.0.0 = Vec::new() };
- | ^^^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:24:19
- |
-LL | unsafe { &mut u.f.0.0 };
- | ^^^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: not automatically applying `DerefMut` on `ManuallyDrop` union field
- --> $DIR/union-deref.rs:26:14
- |
-LL | unsafe { u.f.0.0.push(0) };
- | ^^^^^
- |
- = help: writing to this reference calls the destructor for the old value
- = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
-
-error: aborting due to 6 previous errors
-
--- /dev/null
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:17:14
+ |
+LL | unsafe { u.f.0 = Vec::new() };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:19:19
+ |
+LL | unsafe { &mut u.f.0 };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:21:14
+ |
+LL | unsafe { u.f.0.push(0) };
+ | ^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:25:14
+ |
+LL | unsafe { u.f.0.0 = Vec::new() };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:27:19
+ |
+LL | unsafe { &mut u.f.0.0 };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: not automatically applying `DerefMut` on `ManuallyDrop` union field
+ --> $DIR/union-deref.rs:29:14
+ |
+LL | unsafe { u.f.0.0.push(0) };
+ | ^^^^^
+ |
+ = help: writing to this reference calls the destructor for the old value
+ = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+ --> $DIR/union-derive-clone.rs:6:10
+ |
+LL | #[derive(Clone)]
+ | ^^^^^ the trait `Copy` is not implemented for `U1`
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+ | ---- required by this bound in `AssertParamIsCopy`
+ |
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+ --> $DIR/union-derive-clone.rs:38:15
+ |
+LL | union U5<T> {
+ | -----------
+ | |
+ | method `clone` not found for this
+ | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+ | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL | let w = u.clone();
+ | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `CloneNoCopy: Copy`
+ which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
use std::mem::ManuallyDrop;
#[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied
+++ /dev/null
-error[E0277]: the trait bound `U1: Copy` is not satisfied
- --> $DIR/union-derive-clone.rs:3:10
- |
-LL | #[derive(Clone)]
- | ^^^^^ the trait `Copy` is not implemented for `U1`
- |
- ::: $SRC_DIR/core/src/clone.rs:LL:COL
- |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
- | ---- required by this bound in `AssertParamIsCopy`
- |
- = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
- --> $DIR/union-derive-clone.rs:35:15
- |
-LL | union U5<T> {
- | -----------
- | |
- | method `clone` not found for this
- | doesn't satisfy `U5<CloneNoCopy>: Clone`
-...
-LL | struct CloneNoCopy;
- | ------------------- doesn't satisfy `CloneNoCopy: Copy`
-...
-LL | let w = u.clone();
- | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
- |
- = note: the following trait bounds were not satisfied:
- `CloneNoCopy: Copy`
- which is required by `U5<CloneNoCopy>: Clone`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0599.
-For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+ --> $DIR/union-derive-clone.rs:6:10
+ |
+LL | #[derive(Clone)]
+ | ^^^^^ the trait `Copy` is not implemented for `U1`
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+ | ---- required by this bound in `AssertParamIsCopy`
+ |
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
+ --> $DIR/union-derive-clone.rs:38:15
+ |
+LL | union U5<T> {
+ | -----------
+ | |
+ | method `clone` not found for this
+ | doesn't satisfy `U5<CloneNoCopy>: Clone`
+...
+LL | struct CloneNoCopy;
+ | ------------------- doesn't satisfy `CloneNoCopy: Copy`
+...
+LL | let w = u.clone();
+ | ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `CloneNoCopy: Copy`
+ which is required by `U5<CloneNoCopy>: Clone`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+ --> $DIR/union-derive-eq.rs:16:5
+ |
+LL | a: PartialEqNotEq,
+ | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+ |
+ ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+ | -- required by this bound in `AssertParamIsEq`
+ |
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#[derive(Eq)] // OK
union U1 {
a: u8,
+++ /dev/null
-error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
- --> $DIR/union-derive-eq.rs:13:5
- |
-LL | a: PartialEqNotEq,
- | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
- |
- ::: $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
- | -- required by this bound in `AssertParamIsEq`
- |
- = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
+ --> $DIR/union-derive-eq.rs:16:5
+ |
+LL | a: PartialEqNotEq,
+ | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
+ |
+ ::: $SRC_DIR/core/src/cmp.rs:LL:COL
+ |
+LL | pub struct AssertParamIsEq<T: Eq + ?Sized> {
+ | -- required by this bound in `AssertParamIsEq`
+ |
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
#![allow(unused_variables)]
--- /dev/null
+warning: unnecessary `unsafe` block
+ --> $DIR/union-drop.rs:27:9
+ |
+LL | unsafe { CHECK += 1; }
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+ --> $DIR/union-drop.rs:33:9
+ |
+LL | unsafe { CHECK += 1; }
+ | ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+ --> $DIR/union-drop.rs:40:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+warning: 3 warnings emitted
+
--- /dev/null
+error: field is never read: `c`
+ --> $DIR/union-fields-1.rs:9:5
+ |
+LL | c: u8,
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/union-fields-1.rs:4:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: field is never read: `a`
+ --> $DIR/union-fields-1.rs:12:5
+ |
+LL | a: u8,
+ | ^^^^^
+
+error: field is never read: `a`
+ --> $DIR/union-fields-1.rs:16:20
+ |
+LL | union NoDropLike { a: u8 }
+ | ^^^^^
+
+error: field is never read: `c`
+ --> $DIR/union-fields-1.rs:21:5
+ |
+LL | c: u8,
+ | ^^^^^
+
+error: aborting due to 4 previous errors
+
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![deny(dead_code)]
union U1 {
+++ /dev/null
-error: field is never read: `c`
- --> $DIR/union-fields-1.rs:6:5
- |
-LL | c: u8,
- | ^^^^^
- |
-note: the lint level is defined here
- --> $DIR/union-fields-1.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: field is never read: `a`
- --> $DIR/union-fields-1.rs:9:5
- |
-LL | a: u8,
- | ^^^^^
-
-error: field is never read: `a`
- --> $DIR/union-fields-1.rs:13:20
- |
-LL | union NoDropLike { a: u8 }
- | ^^^^^
-
-error: field is never read: `c`
- --> $DIR/union-fields-1.rs:18:5
- |
-LL | c: u8,
- | ^^^^^
-
-error: aborting due to 4 previous errors
-
--- /dev/null
+error: field is never read: `c`
+ --> $DIR/union-fields-1.rs:9:5
+ |
+LL | c: u8,
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/union-fields-1.rs:4:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: field is never read: `a`
+ --> $DIR/union-fields-1.rs:12:5
+ |
+LL | a: u8,
+ | ^^^^^
+
+error: field is never read: `a`
+ --> $DIR/union-fields-1.rs:16:20
+ |
+LL | union NoDropLike { a: u8 }
+ | ^^^^^
+
+error: field is never read: `c`
+ --> $DIR/union-fields-1.rs:21:5
+ |
+LL | c: u8,
+ | ^^^^^
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:10:13
+ |
+LL | let u = U {};
+ | ^
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:12:13
+ |
+LL | let u = U { a: 0, b: 1 };
+ | ^
+
+error[E0560]: union `U` has no field named `c`
+ --> $DIR/union-fields-2.rs:13:29
+ |
+LL | let u = U { a: 0, b: 1, c: 2 };
+ | ^ `U` does not have this field
+ |
+ = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:13:13
+ |
+LL | let u = U { a: 0, b: 1, c: 2 };
+ | ^
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:15:13
+ |
+LL | let u = U { ..u };
+ | ^
+
+error[E0436]: functional record update syntax requires a struct
+ --> $DIR/union-fields-2.rs:15:19
+ |
+LL | let u = U { ..u };
+ | ^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:18:9
+ |
+LL | let U {} = u;
+ | ^^^^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:20:9
+ |
+LL | let U { a, b } = u;
+ | ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:21:9
+ |
+LL | let U { a, b, c } = u;
+ | ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+ --> $DIR/union-fields-2.rs:21:19
+ |
+LL | let U { a, b, c } = u;
+ | ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:23:9
+ |
+LL | let U { .. } = u;
+ | ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+ --> $DIR/union-fields-2.rs:23:9
+ |
+LL | let U { .. } = u;
+ | ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+ --> $DIR/union-fields-2.rs:25:9
+ |
+LL | let U { a, .. } = u;
+ | ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
union U {
a: u8,
b: u16,
+++ /dev/null
-error: union expressions should have exactly one field
- --> $DIR/union-fields-2.rs:7:13
- |
-LL | let u = U {};
- | ^
-
-error: union expressions should have exactly one field
- --> $DIR/union-fields-2.rs:9:13
- |
-LL | let u = U { a: 0, b: 1 };
- | ^
-
-error[E0560]: union `U` has no field named `c`
- --> $DIR/union-fields-2.rs:10:29
- |
-LL | let u = U { a: 0, b: 1, c: 2 };
- | ^ `U` does not have this field
- |
- = note: available fields are: `a`, `b`
-
-error: union expressions should have exactly one field
- --> $DIR/union-fields-2.rs:10:13
- |
-LL | let u = U { a: 0, b: 1, c: 2 };
- | ^
-
-error: union expressions should have exactly one field
- --> $DIR/union-fields-2.rs:12:13
- |
-LL | let u = U { ..u };
- | ^
-
-error[E0436]: functional record update syntax requires a struct
- --> $DIR/union-fields-2.rs:12:19
- |
-LL | let u = U { ..u };
- | ^
-
-error: union patterns should have exactly one field
- --> $DIR/union-fields-2.rs:15:9
- |
-LL | let U {} = u;
- | ^^^^
-
-error: union patterns should have exactly one field
- --> $DIR/union-fields-2.rs:17:9
- |
-LL | let U { a, b } = u;
- | ^^^^^^^^^^
-
-error: union patterns should have exactly one field
- --> $DIR/union-fields-2.rs:18:9
- |
-LL | let U { a, b, c } = u;
- | ^^^^^^^^^^^^^
-
-error[E0026]: union `U` does not have a field named `c`
- --> $DIR/union-fields-2.rs:18:19
- |
-LL | let U { a, b, c } = u;
- | ^ union `U` does not have this field
-
-error: union patterns should have exactly one field
- --> $DIR/union-fields-2.rs:20:9
- |
-LL | let U { .. } = u;
- | ^^^^^^^^
-
-error: `..` cannot be used in union patterns
- --> $DIR/union-fields-2.rs:20:9
- |
-LL | let U { .. } = u;
- | ^^^^^^^^
-
-error: `..` cannot be used in union patterns
- --> $DIR/union-fields-2.rs:22:9
- |
-LL | let U { a, .. } = u;
- | ^^^^^^^^^^^
-
-error: aborting due to 13 previous errors
-
-Some errors have detailed explanations: E0026, E0436, E0560.
-For more information about an error, try `rustc --explain E0026`.
--- /dev/null
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:10:13
+ |
+LL | let u = U {};
+ | ^
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:12:13
+ |
+LL | let u = U { a: 0, b: 1 };
+ | ^
+
+error[E0560]: union `U` has no field named `c`
+ --> $DIR/union-fields-2.rs:13:29
+ |
+LL | let u = U { a: 0, b: 1, c: 2 };
+ | ^ `U` does not have this field
+ |
+ = note: available fields are: `a`, `b`
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:13:13
+ |
+LL | let u = U { a: 0, b: 1, c: 2 };
+ | ^
+
+error: union expressions should have exactly one field
+ --> $DIR/union-fields-2.rs:15:13
+ |
+LL | let u = U { ..u };
+ | ^
+
+error[E0436]: functional record update syntax requires a struct
+ --> $DIR/union-fields-2.rs:15:19
+ |
+LL | let u = U { ..u };
+ | ^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:18:9
+ |
+LL | let U {} = u;
+ | ^^^^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:20:9
+ |
+LL | let U { a, b } = u;
+ | ^^^^^^^^^^
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:21:9
+ |
+LL | let U { a, b, c } = u;
+ | ^^^^^^^^^^^^^
+
+error[E0026]: union `U` does not have a field named `c`
+ --> $DIR/union-fields-2.rs:21:19
+ |
+LL | let U { a, b, c } = u;
+ | ^ union `U` does not have this field
+
+error: union patterns should have exactly one field
+ --> $DIR/union-fields-2.rs:23:9
+ |
+LL | let U { .. } = u;
+ | ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+ --> $DIR/union-fields-2.rs:23:9
+ |
+LL | let U { .. } = u;
+ | ^^^^^^^^
+
+error: `..` cannot be used in union patterns
+ --> $DIR/union-fields-2.rs:25:9
+ |
+LL | let U { a, .. } = u;
+ | ^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0026, E0436, E0560.
+For more information about an error, try `rustc --explain E0026`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
use std::mem::ManuallyDrop;
--- /dev/null
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+ --> $DIR/union-generic.rs:11:13
+ |
+LL | union U<T: Copy> {
+ | ---------------- required by `U`
+...
+LL | let u = U { a: Rc::new(0u32) };
+ | ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+ --> $DIR/union-generic.rs:13:13
+ |
+LL | union U<T: Copy> {
+ | ---------------- required by `U`
+...
+LL | let u = U::<Rc<u32>> { a: Default::default() };
+ | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
use std::rc::Rc;
union U<T: Copy> {
+++ /dev/null
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
- --> $DIR/union-generic.rs:8:13
- |
-LL | union U<T: Copy> {
- | ---------------- required by `U`
-...
-LL | let u = U { a: Rc::new(0u32) };
- | ^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
- --> $DIR/union-generic.rs:10:13
- |
-LL | union U<T: Copy> {
- | ---------------- required by `U`
-...
-LL | let u = U::<Rc<u32>> { a: Default::default() };
- | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+ --> $DIR/union-generic.rs:11:13
+ |
+LL | union U<T: Copy> {
+ | ---------------- required by `U`
+...
+LL | let u = U { a: Rc::new(0u32) };
+ | ^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
+ --> $DIR/union-generic.rs:13:13
+ |
+LL | union U<T: Copy> {
+ | ---------------- required by `U`
+...
+LL | let u = U::<Rc<u32>> { a: Default::default() };
+ | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: u8,
--- /dev/null
+error: field is never read: `b`
+ --> $DIR/union-lint-dead-code.rs:8:5
+ |
+LL | b: bool,
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/union-lint-dead-code.rs:4:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![deny(dead_code)]
union Foo {
+++ /dev/null
-error: field is never read: `b`
- --> $DIR/union-lint-dead-code.rs:5:5
- |
-LL | b: bool,
- | ^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/union-lint-dead-code.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: aborting due to previous error
-
--- /dev/null
+error: field is never read: `b`
+ --> $DIR/union-lint-dead-code.rs:8:5
+ |
+LL | b: bool,
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/union-lint-dead-code.rs:4:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(unused_variables)]
macro_rules! duplicate {
-#![allow(dead_code)]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![allow(dead_code)]
use std::mem::needs_drop;
use std::mem::ManuallyDrop;
--- /dev/null
+error[E0382]: use of moved value: `x`
+ --> $DIR/union-move.rs:29:18
+ |
+LL | fn test1(x: U1) {
+ | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL | move_out(x.f1_nocopy);
+ | ----------- value moved here
+LL | move_out(x.f2_nocopy);
+ | ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/union-move.rs:45:18
+ |
+LL | fn test3(x: U1) {
+ | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL | move_out(x.f2_nocopy);
+ | ----------- value moved here
+LL | move_out(x.f3_copy);
+ | ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+ --> $DIR/union-move.rs:52:18
+ |
+LL | move_out(x.f1_nocopy);
+ | ^^^^^^^^^^^
+ | |
+ | cannot move out of here
+ | move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
//! Test the behavior of moving out of non-`Copy` union fields.
//! Avoid types that `Drop`, we want to focus on moving.
#![feature(untagged_unions)]
+++ /dev/null
-error[E0382]: use of moved value: `x`
- --> $DIR/union-move.rs:26:18
- |
-LL | fn test1(x: U1) {
- | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL | move_out(x.f1_nocopy);
- | ----------- value moved here
-LL | move_out(x.f2_nocopy);
- | ^^^^^^^^^^^ value used here after move
-
-error[E0382]: use of moved value: `x`
- --> $DIR/union-move.rs:42:18
- |
-LL | fn test3(x: U1) {
- | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
-...
-LL | move_out(x.f2_nocopy);
- | ----------- value moved here
-LL | move_out(x.f3_copy);
- | ^^^^^^^^^ value used here after move
-
-error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
- --> $DIR/union-move.rs:49:18
- |
-LL | move_out(x.f1_nocopy);
- | ^^^^^^^^^^^
- | |
- | cannot move out of here
- | move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0382, E0509.
-For more information about an error, try `rustc --explain E0382`.
--- /dev/null
+error[E0382]: use of moved value: `x`
+ --> $DIR/union-move.rs:29:18
+ |
+LL | fn test1(x: U1) {
+ | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL | move_out(x.f1_nocopy);
+ | ----------- value moved here
+LL | move_out(x.f2_nocopy);
+ | ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+ --> $DIR/union-move.rs:45:18
+ |
+LL | fn test3(x: U1) {
+ | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL | move_out(x.f2_nocopy);
+ | ----------- value moved here
+LL | move_out(x.f3_copy);
+ | ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+ --> $DIR/union-move.rs:52:18
+ |
+LL | move_out(x.f1_nocopy);
+ | ^^^^^^^^^^^
+ | |
+ | cannot move out of here
+ | move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
#[repr(C)]
#[derive(Copy, Clone)]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
#![allow(non_snake_case)]
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
#![allow(illegal_floating_point_literal_pattern)]
--- /dev/null
+error[E0560]: union `U` has no field named `principle`
+ --> $DIR/union-suggest-field.rs:13:17
+ |
+LL | let u = U { principle: 0 };
+ | ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+ --> $DIR/union-suggest-field.rs:17:15
+ |
+LL | let w = u.principial;
+ | ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+ --> $DIR/union-suggest-field.rs:21:15
+ |
+LL | let y = u.calculate;
+ | ^^^^^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | let y = u.calculate();
+ | ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
union U {
principal: u8,
}
+++ /dev/null
-error[E0560]: union `U` has no field named `principle`
- --> $DIR/union-suggest-field.rs:10:17
- |
-LL | let u = U { principle: 0 };
- | ^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0609]: no field `principial` on type `U`
- --> $DIR/union-suggest-field.rs:14:15
- |
-LL | let w = u.principial;
- | ^^^^^^^^^^ help: a field with a similar name exists: `principal`
-
-error[E0615]: attempted to take value of method `calculate` on type `U`
- --> $DIR/union-suggest-field.rs:18:15
- |
-LL | let y = u.calculate;
- | ^^^^^^^^^ method, not a field
- |
-help: use parentheses to call the method
- |
-LL | let y = u.calculate();
- | ^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0560, E0609, E0615.
-For more information about an error, try `rustc --explain E0560`.
--- /dev/null
+error[E0560]: union `U` has no field named `principle`
+ --> $DIR/union-suggest-field.rs:13:17
+ |
+LL | let u = U { principle: 0 };
+ | ^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0609]: no field `principial` on type `U`
+ --> $DIR/union-suggest-field.rs:17:15
+ |
+LL | let w = u.principial;
+ | ^^^^^^^^^^ help: a field with a similar name exists: `principal`
+
+error[E0615]: attempted to take value of method `calculate` on type `U`
+ --> $DIR/union-suggest-field.rs:21:15
+ |
+LL | let y = u.calculate;
+ | ^^^^^^^^^ method, not a field
+ |
+help: use parentheses to call the method
+ |
+LL | let y = u.calculate();
+ | ^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0560, E0609, E0615.
+For more information about an error, try `rustc --explain E0560`.
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::fmt;
// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: (u8, u8),
--- /dev/null
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:34:5
+ |
+LL | *(u.p) = 13;
+ | ^^^^^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:39:5
+ |
+LL | u.a = (RefCell::new(0), 1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+ |
+ = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:40:5
+ |
+LL | u.a.0 = RefCell::new(0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
+ |
+ = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:47:6
+ |
+LL | *u3.a = T::default();
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:53:6
+ |
+LL | *u3.a = T::default();
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:61:13
+ |
+LL | let a = u1.a;
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:64:14
+ |
+LL | let U1 { a } = u1;
+ | ^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:65:20
+ |
+LL | if let U1 { a: 12 } = u1 {}
+ | ^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:70:6
+ |
+LL | *u2.a = String::from("new");
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:74:6
+ |
+LL | *u3.a = 1;
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:78:6
+ |
+LL | *u3.a = String::from("new");
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
use std::cell::RefCell;
}
fn assign_noncopy_union_field(mut u: URefCell) {
- u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping
- u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping
+ // FIXME(thir-unsafeck)
+ u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping
+ u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping
u.a.1 = 1; // OK
}
+++ /dev/null
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:31:5
- |
-LL | *(u.p) = 13;
- | ^^^^^^^^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:35:5
- |
-LL | u.a = (RefCell::new(0), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
- |
- = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:36:5
- |
-LL | u.a.0 = RefCell::new(0);
- | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
- |
- = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:43:6
- |
-LL | *u3.a = T::default();
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:49:6
- |
-LL | *u3.a = T::default();
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:57:13
- |
-LL | let a = u1.a;
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:60:14
- |
-LL | let U1 { a } = u1;
- | ^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:61:20
- |
-LL | if let U1 { a: 12 } = u1 {}
- | ^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:66:6
- |
-LL | *u2.a = String::from("new");
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:70:6
- |
-LL | *u3.a = 1;
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/union-unsafe.rs:74:6
- |
-LL | *u3.a = String::from("new");
- | ^^^^ access to union field
- |
- = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-
-error: aborting due to 11 previous errors
-
-For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:34:6
+ |
+LL | *(u.p) = 13;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:47:6
+ |
+LL | *u3.a = T::default();
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:53:6
+ |
+LL | *u3.a = T::default();
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:61:13
+ |
+LL | let a = u1.a;
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:64:14
+ |
+LL | let U1 { a } = u1;
+ | ^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:65:20
+ |
+LL | if let U1 { a: 12 } = u1 {}
+ | ^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:70:6
+ |
+LL | *u2.a = String::from("new");
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:74:6
+ |
+LL | *u3.a = 1;
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-unsafe.rs:78:6
+ |
+LL | *u3.a = String::from("new");
+ | ^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/union-unsized.rs:7:8
+ |
+LL | a: str,
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | a: &str,
+ | ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | a: Box<str>,
+ | ^^^^ ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/union-unsized.rs:15:8
+ |
+LL | b: str,
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | b: &str,
+ | ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | b: Box<str>,
+ | ^^^^ ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![feature(untagged_unions)]
union U {
+++ /dev/null
-error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/union-unsized.rs:4:8
- |
-LL | a: str,
- | ^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `str`
- = note: no field of a union may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | a: &str,
- | ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | a: Box<str>,
- | ^^^^ ^
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/union-unsized.rs:12:8
- |
-LL | b: str,
- | ^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `str`
- = note: no field of a union may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | b: &str,
- | ^
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | b: Box<str>,
- | ^^^^ ^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/union-unsized.rs:7:8
+ |
+LL | a: str,
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | a: &str,
+ | ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | a: Box<str>,
+ | ^^^^ ^
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/union-unsized.rs:15:8
+ |
+LL | b: str,
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `str`
+ = note: no field of a union may have a dynamically sized type
+ = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+ |
+LL | b: &str,
+ | ^
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+ |
+LL | b: Box<str>,
+ | ^^^^ ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:11:5
+ |
+LL | a: String,
+ | ^^^^^^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:11:5
+ |
+LL | a: String,
+ | ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:19:5
+ |
+LL | a: S,
+ | ^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:19:5
+ |
+LL | a: S,
+ | ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:24:5
+ |
+LL | a: T,
+ | ^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:24:5
+ |
+LL | a: T,
+ | ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
-#![feature(untagged_unions)]
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
#![allow(dead_code)]
union U {
+++ /dev/null
-error[E0740]: unions may not contain fields that need dropping
- --> $DIR/union-with-drop-fields.rs:9:5
- |
-LL | a: String,
- | ^^^^^^^^^
- |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
- --> $DIR/union-with-drop-fields.rs:9:5
- |
-LL | a: String,
- | ^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
- --> $DIR/union-with-drop-fields.rs:17:5
- |
-LL | a: S,
- | ^^^^
- |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
- --> $DIR/union-with-drop-fields.rs:17:5
- |
-LL | a: S,
- | ^^^^
-
-error[E0740]: unions may not contain fields that need dropping
- --> $DIR/union-with-drop-fields.rs:22:5
- |
-LL | a: T,
- | ^^^^
- |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
- --> $DIR/union-with-drop-fields.rs:22:5
- |
-LL | a: T,
- | ^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
--- /dev/null
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:11:5
+ |
+LL | a: String,
+ | ^^^^^^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:11:5
+ |
+LL | a: String,
+ | ^^^^^^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:19:5
+ |
+LL | a: S,
+ | ^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:19:5
+ |
+LL | a: S,
+ | ^^^^
+
+error[E0740]: unions may not contain fields that need dropping
+ --> $DIR/union-with-drop-fields.rs:24:5
+ |
+LL | a: T,
+ | ^^^^
+ |
+note: `std::mem::ManuallyDrop` can be used to wrap the type
+ --> $DIR/union-with-drop-fields.rs:24:5
+ |
+LL | a: T,
+ | ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0740`.
--- /dev/null
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:13:13
+ |
+LL | let a = foo.bar;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:14:13
+ |
+LL | let b = foo.baz;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(unused_variables)]
+
+union Foo {
+ bar: i8,
+ baz: u8,
+}
+
+fn main() {
+ let foo = Foo { bar: 5 };
+ let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block
+ let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block
+}
--- /dev/null
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:13:13
+ |
+LL | let a = foo.bar;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:14:13
+ |
+LL | let b = foo.baz;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+warning: unnecessary `unsafe` block
+ --> $DIR/union.rs:61:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+ --> $DIR/union.rs:66:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
--- /dev/null
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(untagged_unions)]
+
+union Foo {
+ bar: i8,
+ zst: (),
+ pizza: Pizza,
+}
+
+struct Pizza {
+ topping: Option<PizzaTopping>
+}
+
+#[allow(dead_code)]
+enum PizzaTopping {
+ Cheese,
+ Pineapple,
+}
+
+struct FooHolder {
+ inner_foo: Foo
+}
+
+fn do_nothing(_x: &mut Foo) {}
+
+pub fn main() {
+ let mut foo = Foo { bar: 5 };
+ do_nothing(&mut foo);
+ foo.bar = 6;
+ unsafe { foo.bar += 1; }
+ assert_eq!(unsafe { foo.bar }, 7);
+ unsafe {
+ let Foo { bar: inner } = foo;
+ assert_eq!(inner, 7);
+ }
+ let foo = if let true = true { foo } else { foo };
+
+ unsafe {
+ match foo {
+ Foo { bar: _a } => {},
+ }
+ }
+ unsafe {
+ match foo {
+ Foo {
+ pizza: Pizza {
+ topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None
+ }
+ } => {},
+ }
+ }
+ // binding to wildcard is okay
+ match foo {
+ Foo { bar: _ } => {},
+ }
+ let Foo { bar: _ } = foo;
+ // MIR unsafeck incorrectly thinks that it is safe to do these
+ unsafe { //[mir]~ WARNING
+ match foo {
+ Foo { zst: () } => {},
+ }
+ }
+ unsafe { //[mir]~ WARNING
+ match foo {
+ Foo { pizza: Pizza { .. } } => {},
+ }
+ }
+ let foo = Foo { bar: 5 };
+ let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo };
+
+ let (_foo2, _random) = (foo, 42);
+
+ let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } };
+ foo_holder.inner_foo.bar = 4;
+ assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4);
+ drop(foo_holder);
+}
--- /dev/null
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+pub struct Foo { a: bool }
+
+pub union Bar {
+ a: Foo,
+ b: u32,
+}
+pub fn baz(mut bar: Bar) {
+ unsafe {
+ { bar.a }.a = true;
+ }
+}
+
+fn main() {}
--- /dev/null
+warning: unnecessary `unsafe` block
+ --> $DIR/union_destructure.rs:35:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+ --> $DIR/union_destructure.rs:41:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
--- /dev/null
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+#[allow(dead_code)]
+struct Pie {
+ slices: u8,
+ size: u8,
+}
+
+union Foo {
+ #[allow(dead_code)]
+ bar: i8,
+ baz: Pie
+}
+
+fn main() {
+ let u = Foo { bar: 5 };
+ let (Some(Foo { bar: _ }) | None) = Some(u);
+ let u = Foo { bar: 6 };
+ let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u);
+ unsafe {
+ let u = Foo { bar: 7 };
+ let (Foo { bar } | Foo { bar }) = u;
+ assert_eq!(bar, 7)
+ }
+ let u = Foo { bar: 8 };
+ match Some(u) {
+ Some(Foo { bar: _ }) => 3,
+ None => 4,
+ };
+
+ let u = Foo { bar: 9 };
+ unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+ match u {
+ Foo { baz: Pie { .. } } => {},
+ };
+ }
+ let u = Foo { bar: 10 };
+ unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+ match u {
+ Foo { baz: Pie { slices: _, size: _ } } => {},
+ };
+ }
+
+ let u = Foo { bar: 11 };
+ match u {
+ Foo { baz: _ } => {},
+ };
+}
--- /dev/null
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union X { a: i8 }
+
+fn main() {
+ let x = X { a: 5 };
+ match x {
+ X { a: _ | _ } => {},
+ }
+}
-// ignore-arm stdcall isn't supported
-// ignore-aarch64 stdcall isn't supported
-// ignore-riscv64 stdcall isn't supported
+// gate-test-c_unwind
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
// Test that the "stdcall-unwind" ABI is feature-gated, and cannot be used when
// the `c_unwind` feature gate is not used.
-extern "stdcall-unwind" fn f() {}
-//~^ ERROR stdcall-unwind ABI is experimental and subject to change [E0658]
+extern "stdcall-unwind" fn fu() {} //~ ERROR stdcall-unwind ABI is experimental
-fn main() {
- f();
+trait T {
+ extern "stdcall-unwind" fn mu(); //~ ERROR stdcall-unwind ABI is experimental
+ extern "stdcall-unwind" fn dmu() {} //~ ERROR stdcall-unwind ABI is experimental
}
+
+struct S;
+impl T for S {
+ extern "stdcall-unwind" fn mu() {} //~ ERROR stdcall-unwind ABI is experimental
+}
+
+impl S {
+ extern "stdcall-unwind" fn imu() {} //~ ERROR stdcall-unwind ABI is experimental
+}
+
+type TAU = extern "stdcall-unwind" fn(); //~ ERROR stdcall-unwind ABI is experimental
+
+extern "stdcall-unwind" {} //~ ERROR stdcall-unwind ABI is experimental
error[E0658]: stdcall-unwind ABI is experimental and subject to change
- --> $DIR/feature-gate-stdcall-unwind.rs:8:8
+ --> $DIR/feature-gate-stdcall-unwind.rs:12:8
|
-LL | extern "stdcall-unwind" fn f() {}
+LL | extern "stdcall-unwind" fn fu() {}
| ^^^^^^^^^^^^^^^^
|
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:15:12
+ |
+LL | extern "stdcall-unwind" fn mu();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:16:12
+ |
+LL | extern "stdcall-unwind" fn dmu() {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:21:12
+ |
+LL | extern "stdcall-unwind" fn mu() {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:25:12
+ |
+LL | extern "stdcall-unwind" fn imu() {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:28:19
+ |
+LL | type TAU = extern "stdcall-unwind" fn();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: stdcall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-stdcall-unwind.rs:30:8
+ |
+LL | extern "stdcall-unwind" {}
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.
-// ignore-arm thiscall isn't supported
-// ignore-aarch64 thiscall isn't supported
-// ignore-riscv64 thiscall isn't supported
+// gate-test-abi_thiscall
+// gate-test-c_unwind
+// needs-llvm-components: x86
+// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib
+#![no_core]
+#![feature(no_core, lang_items)]
+#[lang="sized"]
+trait Sized { }
// Test that the "thiscall-unwind" ABI is feature-gated, and cannot be used when
// the `c_unwind` feature gate is not used.
-extern "thiscall-unwind" fn f() {}
-//~^ ERROR thiscall-unwind ABI is experimental and subject to change [E0658]
+extern "thiscall-unwind" fn fu() {} //~ ERROR thiscall-unwind ABI is experimental
+extern "thiscall" fn f() {} //~ ERROR thiscall is experimental
-fn main() {
- f();
+trait T {
+ extern "thiscall" fn m(); //~ ERROR thiscall is experimental
+ extern "thiscall-unwind" fn mu(); //~ ERROR thiscall-unwind ABI is experimental
+
+ extern "thiscall" fn dm() {} //~ ERROR thiscall is experimental
+ extern "thiscall-unwind" fn dmu() {} //~ ERROR thiscall-unwind ABI is experimental
+}
+
+struct S;
+impl T for S {
+ extern "thiscall" fn m() {} //~ ERROR thiscall is experimental
+ extern "thiscall-unwind" fn mu() {} //~ ERROR thiscall-unwind ABI is experimental
}
+
+impl S {
+ extern "thiscall" fn im() {} //~ ERROR thiscall is experimental
+ extern "thiscall-unwind" fn imu() {} //~ ERROR thiscall-unwind ABI is experimental
+}
+
+type TA = extern "thiscall" fn(); //~ ERROR thiscall is experimental
+type TAU = extern "thiscall-unwind" fn(); //~ ERROR thiscall-unwind ABI is experimental
+
+extern "thiscall" {} //~ ERROR thiscall is experimental
+extern "thiscall-unwind" {} //~ ERROR thiscall-unwind ABI is experimental
error[E0658]: thiscall-unwind ABI is experimental and subject to change
- --> $DIR/feature-gate-thiscall-unwind.rs:8:8
+ --> $DIR/feature-gate-thiscall-unwind.rs:13:8
|
-LL | extern "thiscall-unwind" fn f() {}
+LL | extern "thiscall-unwind" fn fu() {}
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:14:8
+ |
+LL | extern "thiscall" fn f() {}
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:17:12
+ |
+LL | extern "thiscall" fn m();
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:18:12
+ |
+LL | extern "thiscall-unwind" fn mu();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:20:12
+ |
+LL | extern "thiscall" fn dm() {}
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:21:12
+ |
+LL | extern "thiscall-unwind" fn dmu() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:26:12
+ |
+LL | extern "thiscall" fn m() {}
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:27:12
+ |
+LL | extern "thiscall-unwind" fn mu() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:31:12
+ |
+LL | extern "thiscall" fn im() {}
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:32:12
+ |
+LL | extern "thiscall-unwind" fn imu() {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:35:18
+ |
+LL | type TA = extern "thiscall" fn();
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:36:19
+ |
+LL | type TAU = extern "thiscall-unwind" fn();
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error[E0658]: thiscall is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:38:8
+ |
+LL | extern "thiscall" {}
+ | ^^^^^^^^^^
+ |
+ = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable
+
+error[E0658]: thiscall-unwind ABI is experimental and subject to change
+ --> $DIR/feature-gate-thiscall-unwind.rs:39:8
+ |
+LL | extern "thiscall-unwind" {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
+ = help: add `#![feature(c_unwind)]` to the crate attributes to enable
+
+error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0658`.
* Previously deprecated [`str_to_string`] and [`string_to_string`] have been un-deprecated
as `restriction` lints [#6333](https://github.com/rust-lang/rust-clippy/pull/6333)
-* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panic`
+* Deprecate `panic_params` lint. This is now available in rustc as `non_fmt_panics`
[#6351](https://github.com/rust-lang/rust-clippy/pull/6351)
* Move [`map_err_ignore`] to `restriction`
[#6416](https://github.com/rust-lang/rust-clippy/pull/6416)
use rustc_span::{sym, FileName, Pos};
use std::io;
use std::ops::Range;
+use std::thread;
use url::Url;
declare_clippy_lint! {
}
fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
- fn has_needless_main(code: &str, edition: Edition) -> bool {
+ fn has_needless_main(code: String, edition: Edition) -> bool {
rustc_driver::catch_fatal_errors(|| {
- rustc_span::with_session_globals(edition, || {
- let filename = FileName::anon_source_code(code);
+ rustc_span::create_session_globals_then(edition, || {
+ let filename = FileName::anon_source_code(&code);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
.unwrap_or_default()
}
- if has_needless_main(text, edition) {
+ // Because of the global session, we need to create a new session in a different thread with
+ // the edition we need.
+ let text = text.to_owned();
+ if thread::spawn(move || has_needless_main(text, edition)).join().expect("thread::spawn failed") {
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
}
}
ls.register_renamed("clippy::unused_label", "unused_labels");
ls.register_renamed("clippy::drop_bounds", "drop_bounds");
ls.register_renamed("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr");
- ls.register_renamed("clippy::panic_params", "non_fmt_panic");
+ ls.register_renamed("clippy::panic_params", "non_fmt_panics");
ls.register_renamed("clippy::unknown_clippy_lints", "unknown_lints");
}
use rustc_span::hygiene::MacroKind;
if expr.span.from_expansion() {
let data = expr.span.ctxt().outer_expn_data();
- matches!(
- data.kind,
- ExpnKind::Macro {
- kind: MacroKind::Attr,
- name: _,
- proc_macro: _
- }
- )
+ matches!(data.kind, ExpnKind::Macro(MacroKind::Attr, _))
} else {
false
}
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
if expr.span.from_expansion() {
if let Some(callee) = expr.span.source_callee() {
- if let ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: symbol,
- proc_macro: _,
- } = callee.kind
- {
+ if let ExpnKind::Macro(MacroKind::Bang, symbol) = callee.kind {
if let ExprKind::Binary(ref cmp, left, _) = expr.kind {
let op = cmp.node;
if op.is_comparison() && cx.typeck_results().expr_ty(left).is_unit() {
let data = span.ctxt().outer_expn_data();
let new_span = data.call_site;
- if let ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: mac_name,
- proc_macro: _,
- } = data.kind
- {
+ if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
if mac_name.as_str() == name {
return Some(new_span);
}
let data = span.ctxt().outer_expn_data();
let new_span = data.call_site;
- if let ExpnKind::Macro {
- kind: MacroKind::Bang,
- name: mac_name,
- proc_macro: _,
- } = data.kind
- {
+ if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
if mac_name.as_str() == name {
return Some(new_span);
}
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::infer::InferCtxtExt;
use crate::{match_def_path, must_use_attr};
}
/// Checks whether a type implements a trait.
+/// The function returns false in case the type contains an inference variable.
/// See also `get_trait_def_id`.
pub fn implements_trait<'tcx>(
cx: &LateContext<'tcx>,
trait_id: DefId,
ty_params: &[GenericArg<'tcx>],
) -> bool {
- // Do not check on infer_types to avoid panic in evaluate_obligation.
- if ty.has_infer_types() {
- return false;
- }
+ // Clippy shouldn't have infer types
+ assert!(!ty.needs_infer());
+
let ty = cx.tcx.erase_regions(ty);
if ty.has_escaping_bound_vars() {
return false;
}
let ty_params = cx.tcx.mk_substs(ty_params.iter());
- cx.tcx
- .type_implements_trait((trait_id, ty, ty_params, cx.param_env))
+ cx.tcx.infer_ctxt().enter(|infcx|
+ infcx.type_implements_trait(trait_id, ty, ty_params, cx.param_env)
.must_apply_modulo_regions()
+ )
}
/// Checks whether this type implements `Drop`.
-#![allow(non_fmt_panic)]
+#![allow(non_fmt_panics)]
macro_rules! assert_const {
($len:expr) => {
LL | #[warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
-error: lint `clippy::panic_params` has been renamed to `non_fmt_panic`
+error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
--> $DIR/deprecated.rs:11:8
|
LL | #[warn(clippy::panic_params)]
- | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panic`
+ | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
--> $DIR/deprecated.rs:12:8
let rust_type_regexes = vec![
"^(alloc::([a-z_]+::)+)String$",
- "^&str$",
- "^&\\[.+\\]$",
+ "^&(mut )?str$",
+ "^&(mut )?\\[.+\\]$",
"^(std::ffi::([a-z_]+::)+)OsString$",
"^(alloc::([a-z_]+::)+)Vec<.+>$",
"^(alloc::([a-z_]+::)+)VecDeque<.+>$",
fn main() {
rustc_driver::init_env_logger("RUST_LOG");
let (format, dst) = parse_args();
- let result = rustc_span::with_default_session_globals(move || main_with_result(format, &dst));
+ let result =
+ rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
if let Err(e) = result {
panic!("{}", e.to_string());
}
return Err("lint name should end with comma");
}
let name = &name[..name.len() - 1];
- if !name.chars().all(|ch| ch.is_uppercase() || ch == '_') || name.is_empty() {
+ if !name.chars().all(|ch| ch.is_uppercase() || ch.is_ascii_digit() || ch == '_')
+ || name.is_empty()
+ {
return Err("lint name did not have expected format");
}
Ok(name.to_lowercase().to_string())
-Subproject commit 15e81a94b1aff99f7c38151d6976757ee0ed0097
+Subproject commit b06130762ed75f52da7c22979c61c597ced667c6
-Subproject commit 1fa82adfdca502a13f4dd952f9a50574870f5b7b
+Subproject commit e5c1c8cf2fcfae3e15c8bcf5256e84cad3bd3436
return Err(ErrorKind::VersionMismatch);
}
- rustc_span::with_session_globals(self.config.edition().into(), || {
+ rustc_span::create_session_if_not_set_then(self.config.edition().into(), |_| {
if self.config.disable_all_formatting() {
// When the input is from stdin, echo back the input.
if let Input::Text(ref buf) = input {
"libloading",
"log",
"mach",
+ "memchr",
"object",
"regalloc",
"region",
// A few of those error codes can't be tested but all the others can and *should* be tested!
const EXEMPTED_FROM_TEST: &[&str] = &[
"E0227", "E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0464", "E0465", "E0476",
- "E0482", "E0514", "E0519", "E0523", "E0554", "E0570", "E0640", "E0717", "E0729",
+ "E0482", "E0514", "E0519", "E0523", "E0554", "E0640", "E0717", "E0729",
];
// Some error codes don't have any tests apparently...