os: windows-latest-xl
- name: dist-x86_64-msvc
env:
- RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
+ RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.lto=thin"
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
os: windows-latest-xl
[submodule "src/llvm-project"]
path = src/llvm-project
url = https://github.com/rust-lang/llvm-project.git
- branch = rustc/15.0-2022-08-09
+ branch = rustc/15.0-2022-12-07
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
url = https://github.com/rust-embedded/book.git
"directories",
"rustc-build-sysroot",
"rustc-workspace-hack",
- "rustc_tools_util",
+ "rustc_tools_util 0.2.1",
"rustc_version",
"serde",
"serde_json",
[[package]]
name = "clippy"
-version = "0.1.67"
+version = "0.1.68"
dependencies = [
"clippy_lints",
"clippy_utils",
"regex",
"rustc-semver",
"rustc-workspace-hack",
- "rustc_tools_util",
+ "rustc_tools_util 0.3.0",
"semver",
"serde",
"syn",
[[package]]
name = "clippy_lints"
-version = "0.1.67"
+version = "0.1.68"
dependencies = [
"cargo_metadata 0.14.0",
"clippy_utils",
[[package]]
name = "clippy_utils"
-version = "0.1.67"
+version = "0.1.68"
dependencies = [
"arrayvec",
"if_chain",
[[package]]
name = "compiler_builtins"
-version = "0.1.84"
+version = "0.1.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
dependencies = [
"cc",
"rustc-std-workspace-core",
[[package]]
name = "crossbeam-deque"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch",
[[package]]
name = "crossbeam-epoch"
-version = "0.9.6"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
+ "autocfg",
"cfg-if 1.0.0",
"crossbeam-utils",
- "lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.8"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if 1.0.0",
- "lazy_static",
]
[[package]]
[[package]]
name = "declare_clippy_lint"
-version = "0.1.67"
+version = "0.1.68"
dependencies = [
"itertools",
"quote",
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
"rustc_hir",
"rustc_index",
"rustc_infer",
+ "rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
name = "rustc_parse_format"
version = "0.0.0"
dependencies = [
+ "rustc_data_structures",
"rustc_lexer",
]
"rustc_feature",
"rustc_fs_util",
"rustc_hir",
+ "rustc_index",
"rustc_lint_defs",
"rustc_macros",
"rustc_serialize",
"rustc_span",
"rustc_target",
"smallvec",
+ "termize",
"tracing",
"winapi",
]
"rustc_span",
"rustc_target",
"tracing",
+ "twox-hash",
]
[[package]]
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
+[[package]]
+name = "rustc_tools_util"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
+
[[package]]
name = "rustc_trait_selection"
version = "0.0.0"
[[package]]
name = "rustix"
-version = "0.36.3"
+version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b1fbb4dfc4eb1d390c02df47760bb19a84bb80b301ecc947ab5406394d8223e"
+checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
dependencies = [
"bitflags",
"errno",
"tracing-subscriber",
]
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if 0.1.10",
+ "rand 0.8.5",
+ "static_assertions",
+]
+
[[package]]
name = "type-map"
version = "0.4.0"
+Version 1.66.0 (2022-12-15)
+==========================
+
+Language
+--------
+- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
+ ```rust
+ #[repr(u8)]
+ enum Foo {
+ A(u8) = 0,
+ B(i8) = 1,
+ C(bool) = 42,
+ }
+ ```
+- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
+- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
+- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
+ This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
+- [Allow `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
+- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
+- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+ This is a soundness fix which may break code that was erroneously relying on this behavior.
+
+Compiler
+--------
+- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
+ - Refer to Rust's [platform support page][platform-support-doc] for more
+ information on Rust's tiered platform support.
+- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
+
+Libraries
+---------
+- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
+
+Stabilized APIs
+---------------
+
+- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
+- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
+- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
+- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
+- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
+- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
+- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
+- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
+- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
+- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
+- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
+
+
+Rustdoc
+-------
+
+- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
+
+Cargo
+-----
+
+- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
+- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
+
+See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
+
+Compatibility Notes
+-------------------
+
+- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
+- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
+- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
+- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
+- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
+- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+ This is a soundness fix which may break code that was erroneously relying on this behavior.
+- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
+- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
+- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
+
Version 1.65.0 (2022-11-03)
==========================
#![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))]
-use std::convert::{TryFrom, TryInto};
use std::fmt;
#[cfg(feature = "nightly")]
use std::iter::Step;
pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
let dl = cx.data_layout();
- for candidate in [I8, I16, I32, I64, I128] {
- if wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes() {
- return Some(candidate);
- }
- }
- None
+ [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
+ wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
+ })
}
/// Find the largest integer with the given alignment or less.
use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd};
use core::cmp::{self, Ordering};
-use core::convert::TryFrom;
use core::fmt::{self, Write};
use core::marker::PhantomData;
use core::mem;
use std::alloc::Layout;
use std::cell::{Cell, RefCell};
use std::cmp;
-use std::marker::{PhantomData, Send};
+use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::ptr::{self, NonNull};
use std::slice;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use std::convert::TryFrom;
use std::fmt;
use std::mem;
use thin_vec::{thin_vec, ThinVec};
/// A literal in a meta item.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MetaItemLit {
- /// The original literal token as written in source code.
- pub token_lit: token::Lit,
+ /// The original literal as written in the source code.
+ pub symbol: Symbol,
+ /// The original suffix as written in the source code.
+ pub suffix: Option<Symbol>,
/// The "semantic" representation of the literal lowered from the original tokens.
/// Strings are unescaped, hexadecimal forms are eliminated, etc.
pub kind: LitKind,
/// Similar to `MetaItemLit`, but restricted to string literals.
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct StrLit {
- /// The original literal token as written in source code.
- pub style: StrStyle,
+ /// The original literal as written in source code.
pub symbol: Symbol,
+ /// The original suffix as written in source code.
pub suffix: Option<Symbol>,
- pub span: Span,
- /// The unescaped "semantic" representation of the literal lowered from the original token.
+ /// The semantic (unescaped) representation of the literal.
pub symbol_unescaped: Symbol,
+ pub style: StrStyle,
+ pub span: Span,
}
impl StrLit {
/// A string literal (`"foo"`). The symbol is unescaped, and so may differ
/// from the original token's symbol.
Str(Symbol, StrStyle),
- /// A byte string (`b"foo"`).
- ByteStr(Lrc<[u8]>),
+ /// A byte string (`b"foo"`). Not stored as a symbol because it might be
+ /// non-utf8, and symbols only allow utf8 strings.
+ ByteStr(Lrc<[u8]>, StrStyle),
/// A byte char (`b'f'`).
Byte(u8),
/// A character literal (`'a'`).
/// Returns `true` if this literal is byte literal string.
pub fn is_bytestr(&self) -> bool {
- matches!(self, LitKind::ByteStr(_))
+ matches!(self, LitKind::ByteStr(..))
}
/// Returns `true` if this is a numeric literal.
Unloaded,
}
-#[derive(Copy, Clone, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
pub struct ModSpans {
/// `inner_span` covers the body of the module; for a file module, its the whole file.
/// For an inline module, its the span inside the `{ ... }`, not including the curly braces.
pub inject_use_span: Span,
}
-impl Default for ModSpans {
- fn default() -> ModSpans {
- ModSpans { inner_span: Default::default(), inject_use_span: Default::default() }
- }
-}
-
/// Foreign module declaration.
///
/// E.g., `extern { .. }` or `extern "C" { .. }`.
static_assert_size!(ItemKind, 112);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
- static_assert_size!(MetaItemLit, 48);
+ static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 88);
static_assert_size!(Path, 24);
//! Functions dealing with attributes and meta items.
-use crate::ast;
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
-use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID};
+use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter, Token};
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
use crate::util::comments;
+use crate::util::literal::escape_string_symbol;
use rustc_data_structures::sync::WorkerLocal;
use rustc_index::bit_set::GrowableBitSet;
use rustc_span::symbol::{sym, Ident, Symbol};
}
}
-/* Constructors */
-
-pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem {
- mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span)
-}
-
-pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem {
- let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span };
- let span = ident.span.to(lit_span);
- MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span }
-}
-
pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
#[cfg(debug_assertions)]
val: Symbol,
span: Span,
) -> Attribute {
- let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit();
+ let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
let expr = P(Expr {
id: DUMMY_NODE_ID,
kind: ExprKind::Lit(lit),
//! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.
use std::fmt::{self, Debug, Display};
-use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::{slice, vec};
if let NtExpr(expr) | NtLiteral(expr) = &**nt
&& let ast::ExprKind::Lit(token_lit) = expr.kind =>
{
- Some(token_lit.clone())
+ Some(token_lit)
}
_ => None,
}
}
}
-impl iter::FromIterator<TokenTree> for TokenStream {
+impl FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
}
//! Code related to parsing literals.
-use crate::ast::{self, LitKind, MetaItemLit};
+use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
use crate::token::{self, Token};
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use std::ascii;
+use std::{ascii, fmt, str};
+
+// Escapes a string, represented as a symbol. Reuses the original symbol,
+// avoiding interning, if no changes are required.
+pub fn escape_string_symbol(symbol: Symbol) -> Symbol {
+ let s = symbol.as_str();
+ let escaped = s.escape_default().to_string();
+ if s == escaped { symbol } else { Symbol::intern(&escaped) }
+}
+
+// Escapes a char.
+pub fn escape_char_symbol(ch: char) -> Symbol {
+ let s: String = ch.escape_default().map(Into::<char>::into).collect();
+ Symbol::intern(&s)
+}
+
+// Escapes a byte string.
+pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol {
+ let s = bytes.escape_ascii().to_string();
+ Symbol::intern(&s)
+}
#[derive(Debug)]
pub enum LitError {
}
});
error?;
- LitKind::ByteStr(buf.into())
+ LitKind::ByteStr(buf.into(), StrStyle::Cooked)
}
- token::ByteStrRaw(_) => {
+ token::ByteStrRaw(n) => {
let s = symbol.as_str();
let bytes = if s.contains('\r') {
let mut buf = Vec::with_capacity(s.len());
symbol.to_string().into_bytes()
};
- LitKind::ByteStr(bytes.into())
+ LitKind::ByteStr(bytes.into(), StrStyle::Raw(n))
}
token::Err => LitKind::Err,
})
}
+}
- /// Attempts to recover a token from semantic literal.
- /// This function is used when the original token doesn't exist (e.g. the literal is created
- /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
- pub fn to_token_lit(&self) -> token::Lit {
- let (kind, symbol, suffix) = match *self {
- LitKind::Str(symbol, ast::StrStyle::Cooked) => {
- // Don't re-intern unless the escaped string is different.
- let s = symbol.as_str();
- let escaped = s.escape_default().to_string();
- let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) };
- (token::Str, symbol, None)
- }
- LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
- LitKind::ByteStr(ref bytes) => {
- let string = bytes.escape_ascii().to_string();
- (token::ByteStr, Symbol::intern(&string), None)
+impl fmt::Display for LitKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ LitKind::Byte(b) => {
+ let b: String = ascii::escape_default(b).map(Into::<char>::into).collect();
+ write!(f, "b'{}'", b)?;
}
- LitKind::Byte(byte) => {
- let string: String = ascii::escape_default(byte).map(Into::<char>::into).collect();
- (token::Byte, Symbol::intern(&string), None)
+ LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?,
+ LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?,
+ LitKind::Str(sym, StrStyle::Raw(n)) => write!(
+ f,
+ "r{delim}\"{string}\"{delim}",
+ delim = "#".repeat(n as usize),
+ string = sym
+ )?,
+ LitKind::ByteStr(ref bytes, StrStyle::Cooked) => {
+ write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))?
}
- LitKind::Char(ch) => {
- let string: String = ch.escape_default().map(Into::<char>::into).collect();
- (token::Char, Symbol::intern(&string), None)
+ LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => {
+ // Unwrap because raw byte string literals can only contain ASCII.
+ let symbol = str::from_utf8(bytes).unwrap();
+ write!(
+ f,
+ "br{delim}\"{string}\"{delim}",
+ delim = "#".repeat(n as usize),
+ string = symbol
+ )?;
}
LitKind::Int(n, ty) => {
- let suffix = match ty {
- ast::LitIntType::Unsigned(ty) => Some(ty.name()),
- ast::LitIntType::Signed(ty) => Some(ty.name()),
- ast::LitIntType::Unsuffixed => None,
- };
- (token::Integer, sym::integer(n), suffix)
+ write!(f, "{}", n)?;
+ match ty {
+ ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?,
+ ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?,
+ ast::LitIntType::Unsuffixed => {}
+ }
}
LitKind::Float(symbol, ty) => {
- let suffix = match ty {
- ast::LitFloatType::Suffixed(ty) => Some(ty.name()),
- ast::LitFloatType::Unsuffixed => None,
- };
- (token::Float, symbol, suffix)
+ write!(f, "{}", symbol)?;
+ match ty {
+ ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?,
+ ast::LitFloatType::Unsuffixed => {}
+ }
}
- LitKind::Bool(value) => {
- let symbol = if value { kw::True } else { kw::False };
- (token::Bool, symbol, None)
+ LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?,
+ LitKind::Err => {
+ // This only shows up in places like `-Zunpretty=hir` output, so we
+ // don't bother to produce something useful.
+ write!(f, "<bad-literal>")?;
}
- // This only shows up in places like `-Zunpretty=hir` output, so we
- // don't bother to produce something useful.
- LitKind::Err => (token::Err, Symbol::intern("<bad-literal>"), None),
- };
+ }
- token::Lit::new(kind, symbol, suffix)
+ Ok(())
}
}
impl MetaItemLit {
- /// Converts token literal into a meta item literal.
+ /// Converts a token literal into a meta item literal.
pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> {
- Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span })
+ Ok(MetaItemLit {
+ symbol: token_lit.symbol,
+ suffix: token_lit.suffix,
+ kind: LitKind::from_token_lit(token_lit)?,
+ span,
+ })
+ }
+
+ /// Cheaply converts a meta item literal into a token literal.
+ pub fn as_token_lit(&self) -> token::Lit {
+ let kind = match self.kind {
+ LitKind::Bool(_) => token::Bool,
+ LitKind::Str(_, ast::StrStyle::Cooked) => token::Str,
+ LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n),
+ LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr,
+ LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n),
+ LitKind::Byte(_) => token::Byte,
+ LitKind::Char(_) => token::Char,
+ LitKind::Int(..) => token::Integer,
+ LitKind::Float(..) => token::Float,
+ LitKind::Err => token::Err,
+ };
+
+ token::Lit::new(kind, self.symbol, self.suffix)
}
/// Converts an arbitrary token into meta item literal.
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
ensure_sufficient_stack(|| {
+ match &e.kind {
+ // Paranthesis expression does not have a HirId and is handled specially.
+ ExprKind::Paren(ex) => {
+ let mut ex = self.lower_expr_mut(ex);
+ // Include parens in span, but only if it is a super-span.
+ if e.span.contains(ex.span) {
+ ex.span = self.lower_span(e.span);
+ }
+ // Merge attributes into the inner expression.
+ if !e.attrs.is_empty() {
+ let old_attrs =
+ self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
+ self.attrs.insert(
+ ex.hir_id.local_id,
+ &*self.arena.alloc_from_iter(
+ e.attrs
+ .iter()
+ .map(|a| self.lower_attr(a))
+ .chain(old_attrs.iter().cloned()),
+ ),
+ );
+ }
+ return ex;
+ }
+ // Desugar `ExprForLoop`
+ // from: `[opt_ident]: for <pat> in <head> <body>`
+ //
+ // This also needs special handling because the HirId of the returned `hir::Expr` will not
+ // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
+ ExprKind::ForLoop(pat, head, body, opt_label) => {
+ return self.lower_expr_for(e, pat, head, body, *opt_label);
+ }
+ _ => (),
+ }
+
+ let hir_id = self.lower_node_id(e.id);
+ self.lower_attrs(hir_id, &e.attrs);
+
let kind = match &e.kind {
ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
if let [inner] = &args[..] && e.attrs.len() == 1 {
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
- let hir_id = self.lower_node_id(e.id);
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
} else {
self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
}
ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan(
self.lower_span(e.span),
- LitKind::ByteStr(bytes.clone()),
+ LitKind::ByteStr(bytes.clone(), StrStyle::Cooked),
)),
ExprKind::Cast(expr, ty) => {
let expr = self.lower_expr(expr);
),
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
*capture_clause,
- None,
+ hir_id,
*closure_node_id,
None,
e.span,
binder,
*capture_clause,
e.id,
+ hir_id,
*closure_id,
fn_decl,
body,
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
ExprKind::Err => hir::ExprKind::Err,
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
- ExprKind::Paren(ex) => {
- let mut ex = self.lower_expr_mut(ex);
- // Include parens in span, but only if it is a super-span.
- if e.span.contains(ex.span) {
- ex.span = self.lower_span(e.span);
- }
- // Merge attributes into the inner expression.
- if !e.attrs.is_empty() {
- let old_attrs =
- self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
- self.attrs.insert(
- ex.hir_id.local_id,
- &*self.arena.alloc_from_iter(
- e.attrs
- .iter()
- .map(|a| self.lower_attr(a))
- .chain(old_attrs.iter().cloned()),
- ),
- );
- }
- return ex;
- }
- // Desugar `ExprForLoop`
- // from: `[opt_ident]: for <pat> in <head> <body>`
- ExprKind::ForLoop(pat, head, body, opt_label) => {
- return self.lower_expr_for(e, pat, head, body, *opt_label);
- }
+ ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
+
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
};
- let hir_id = self.lower_node_id(e.id);
- self.lower_attrs(hir_id, &e.attrs);
hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
})
}
let lhs = self.lower_cond(lhs);
let rhs = self.lower_cond(rhs);
- self.arena.alloc(self.expr(
- cond.span,
- hir::ExprKind::Binary(op, lhs, rhs),
- AttrVec::new(),
- ))
+ self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
}
ExprKind::Let(..) => self.lower_expr(cond),
_ => {
let cond = self.lower_expr(cond);
let reason = DesugaringKind::CondTemporary;
let span_block = self.mark_span_with_reason(reason, cond.span, None);
- self.expr_drop_temps(span_block, cond, AttrVec::new())
+ self.expr_drop_temps(span_block, cond)
}
}
}
) -> hir::ExprKind<'hir> {
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
let then = self.lower_block_expr(body);
- let expr_break = self.expr_break(span, AttrVec::new());
+ let expr_break = self.expr_break(span);
let stmt_break = self.stmt_expr(span, expr_break);
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
- let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
+ let else_expr = self.arena.alloc(self.expr_block(else_blk));
let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
- let if_expr = self.expr(span, if_kind, AttrVec::new());
+ let if_expr = self.expr(span, if_kind);
let block = self.block_expr(self.arena.alloc(if_expr));
let span = self.lower_span(span.with_hi(cond.span.hi()));
let opt_label = self.lower_label(opt_label);
expr: &'hir hir::Expr<'hir>,
overall_span: Span,
) -> &'hir hir::Expr<'hir> {
- let constructor = self.arena.alloc(self.expr_lang_item_path(
- method_span,
- lang_item,
- AttrVec::new(),
- None,
- ));
+ let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None));
self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
}
pub(super) fn make_async_expr(
&mut self,
capture_clause: CaptureBy,
- outer_hir_id: Option<hir::HirId>,
+ outer_hir_id: hir::HirId,
closure_node_id: NodeId,
ret_ty: Option<hir::FnRetTy<'hir>>,
span: Span,
hir::ExprKind::Closure(c)
};
- let track_caller = outer_hir_id
- .and_then(|id| self.attrs.get(&id.local_id))
+ let track_caller = self
+ .attrs
+ .get(&outer_hir_id.local_id)
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
let hir_id = self.lower_node_id(closure_node_id);
// E0700 in src/test/ui/self/self_lifetime-async.rs
// `future::identity_future`:
- let identity_future = self.expr_lang_item_path(
- unstable_span,
- hir::LangItem::IdentityFuture,
- AttrVec::new(),
- None,
- );
+ let identity_future =
+ self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
// `future::identity_future(generator)`:
hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
let break_x = self.with_loop_scope(loop_node_id, move |this| {
let expr_break =
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
- this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
+ this.arena.alloc(this.expr(gen_future_span, expr_break))
});
self.arm(ready_pat, break_x)
};
let yield_expr = self.expr(
span,
hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
- AttrVec::new(),
);
let yield_expr = self.arena.alloc(yield_expr);
if let Some(task_context_hid) = self.task_context {
let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
- let assign = self.expr(
- span,
- hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
- AttrVec::new(),
- );
+ let assign =
+ self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));
self.stmt_expr(span, assign)
} else {
// Use of `await` outside of an async context. Return `yield_expr` so that we can
binder: &ClosureBinder,
capture_clause: CaptureBy,
closure_id: NodeId,
+ closure_hir_id: hir::HirId,
inner_closure_id: NodeId,
decl: &FnDecl,
body: &Expr,
let async_body = this.make_async_expr(
capture_clause,
- // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
- // can be applied on async closures as well.
- None,
+ closure_hir_id,
inner_closure_id,
async_ret_ty,
body.span,
hir::AsyncGeneratorKind::Closure,
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
);
- this.expr(fn_decl_span, async_body, AttrVec::new())
+ this.expr(fn_decl_span, async_body)
});
body_id
});
let ident = self.expr_ident(lhs.span, ident, binding);
let assign =
hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
- let expr = self.expr(lhs.span, assign, AttrVec::new());
+ let expr = self.expr(lhs.span, assign);
assignments.push(self.stmt_expr(lhs.span, expr));
pat
}
let e2 = self.lower_expr_mut(e2);
let fn_path =
hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
- let fn_expr =
- self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
+ let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
}
// `None => break`
let none_arm = {
- let break_expr =
- self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
+ let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span));
let pat = self.pat_none(for_span);
self.arm(pat, break_expr)
};
let some_arm = {
let some_pat = self.pat_some(pat_span, pat);
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
- let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
+ let body_expr = self.arena.alloc(self.expr_block(body_block));
self.arm(some_pat, body_expr)
};
// surrounding scope of the `match` since the `match` is not a terminating scope.
//
// Also, add the attributes to the outer returned expr node.
- self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone())
+ let expr = self.expr_drop_temps_mut(for_span, match_expr);
+ self.lower_attrs(expr.hir_id, &e.attrs);
+ expr
}
/// Desugar `ExprKind::Try` from: `<expr>?` into:
let continue_arm = {
let val_ident = Ident::with_dummy_span(sym::val);
let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
- let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
- span,
- val_ident,
- val_pat_nid,
- attrs.clone(),
- ));
+ let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
+ self.lower_attrs(val_expr.hir_id, &attrs);
let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
self.arm(continue_pat, val_expr)
};
hir::Destination { label: None, target_id },
Some(from_residual_expr),
),
- attrs,
))
} else {
- self.arena.alloc(self.expr(
- try_span,
- hir::ExprKind::Ret(Some(from_residual_expr)),
- attrs,
- ))
+ self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
};
+ self.lower_attrs(ret_expr.hir_id, &attrs);
let break_pat = self.pat_cf_break(try_span, residual_local);
self.arm(break_pat, ret_expr)
&mut self,
span: Span,
expr: &'hir hir::Expr<'hir>,
- attrs: AttrVec,
) -> &'hir hir::Expr<'hir> {
- self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
+ self.arena.alloc(self.expr_drop_temps_mut(span, expr))
}
pub(super) fn expr_drop_temps_mut(
&mut self,
span: Span,
expr: &'hir hir::Expr<'hir>,
- attrs: AttrVec,
) -> hir::Expr<'hir> {
- self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
+ self.expr(span, hir::ExprKind::DropTemps(expr))
}
fn expr_match(
arms: &'hir [hir::Arm<'hir>],
source: hir::MatchSource,
) -> hir::Expr<'hir> {
- self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
+ self.expr(span, hir::ExprKind::Match(arg, arms, source))
}
- fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
+ fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> {
let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
- self.expr(span, expr_break, attrs)
+ self.expr(span, expr_break)
}
- fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
- let expr_break = self.expr_break(span, attrs);
+ fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
+ let expr_break = self.expr_break(span);
self.arena.alloc(expr_break)
}
fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
- self.expr(
- span,
- hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
- AttrVec::new(),
- )
+ self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e))
}
fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
- self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
+ self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
}
fn expr_call_mut(
e: &'hir hir::Expr<'hir>,
args: &'hir [hir::Expr<'hir>],
) -> hir::Expr<'hir> {
- self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
+ self.expr(span, hir::ExprKind::Call(e, args))
}
fn expr_call(
args: &'hir [hir::Expr<'hir>],
hir_id: Option<hir::HirId>,
) -> hir::Expr<'hir> {
- let path =
- self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
+ let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id));
self.expr_call_mut(span, path, args)
}
&mut self,
span: Span,
lang_item: hir::LangItem,
- attrs: AttrVec,
hir_id: Option<hir::HirId>,
) -> hir::Expr<'hir> {
self.expr(
span,
hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
- attrs,
)
}
}
pub(super) fn expr_ident_mut(
- &mut self,
- sp: Span,
- ident: Ident,
- binding: hir::HirId,
- ) -> hir::Expr<'hir> {
- self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
- }
-
- fn expr_ident_with_attrs(
&mut self,
span: Span,
ident: Ident,
binding: hir::HirId,
- attrs: AttrVec,
) -> hir::Expr<'hir> {
let hir_id = self.next_id();
let res = Res::Local(binding);
}),
));
- self.expr(span, expr_path, attrs)
+ self.expr(span, expr_path)
}
fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
}),
None,
),
- AttrVec::new(),
)
}
fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
let blk = self.block_all(span, &[], None);
- let expr = self.expr_block(blk, AttrVec::new());
+ let expr = self.expr_block(blk);
self.arena.alloc(expr)
}
- pub(super) fn expr_block(
- &mut self,
- b: &'hir hir::Block<'hir>,
- attrs: AttrVec,
- ) -> hir::Expr<'hir> {
- self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
+ pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> {
+ self.expr(b.span, hir::ExprKind::Block(b, None))
}
- pub(super) fn expr(
- &mut self,
- span: Span,
- kind: hir::ExprKind<'hir>,
- attrs: AttrVec,
- ) -> hir::Expr<'hir> {
+ pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
let hir_id = self.next_id();
- self.lower_attrs(hir_id, &attrs);
hir::Expr { hir_id, kind, span: self.lower_span(span) }
}
/// Construct `ExprKind::Err` for the given `span`.
pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
- self.expr(span, hir::ExprKind::Err, AttrVec::new())
+ self.expr(span, hir::ExprKind::Err)
}
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
let async_expr = this.make_async_expr(
CaptureBy::Value,
- Some(fn_id),
+ fn_id,
closure_id,
None,
body.span,
// Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span =
this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
- let user_body = this.expr_drop_temps(
- desugared_span,
- this.arena.alloc(user_body),
- AttrVec::new(),
- );
+ let user_body =
+ this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
// As noted above, create the final block like
//
Some(user_body),
);
- this.expr_block(body, AttrVec::new())
+ this.expr_block(body)
},
);
- (
- this.arena.alloc_from_iter(parameters),
- this.expr(body.span, async_expr, AttrVec::new()),
- )
+ (this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
})
}
},
/// Impl trait in type aliases.
TypeAliasesOpaqueTy,
+ /// `impl Trait` is unstably accepted in this position.
+ FeatureGated(ImplTraitPosition, Symbol),
/// `impl Trait` is not accepted in this position.
Disallowed(ImplTraitPosition),
}
}
// Drop AST to free memory
- std::mem::drop(ast_index);
- sess.time("drop_ast", || std::mem::drop(krate));
+ drop(ast_index);
+ sess.time("drop_ast", || drop(krate));
// Discard hygiene data, which isn't required after lowering to HIR.
if !sess.opts.unstable_opts.keep_hygiene_data {
lit
} else {
MetaItemLit {
- token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None),
+ symbol: kw::Empty,
+ suffix: None,
kind: LitKind::Err,
span: DUMMY_SP,
}
}
path
}
- ImplTraitContext::Disallowed(
- position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
- ) => {
+ ImplTraitContext::FeatureGated(position, feature) => {
self.tcx
.sess
.create_feature_err(
MisplacedImplTrait {
span: t.span,
- position: DiagnosticArgFromDisplay(&position),
+ position: DiagnosticArgFromDisplay(position),
},
- sym::return_position_impl_trait_in_trait,
+ *feature,
)
.emit();
hir::TyKind::Err
ImplTraitContext::Disallowed(position) => {
self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
- position: DiagnosticArgFromDisplay(&position),
+ position: DiagnosticArgFromDisplay(position),
});
hir::TyKind::Err
}
} else {
match &decl.output {
FnRetTy::Ty(ty) => {
- let mut context = if kind.return_impl_trait_allowed(self.tcx) {
+ let context = if kind.return_impl_trait_allowed(self.tcx) {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: matches!(kind, FnDeclKind::Trait),
}
} else {
- ImplTraitContext::Disallowed(match kind {
+ let position = match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")
}
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
- })
+ };
+ match kind {
+ FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
+ position,
+ sym::return_position_impl_trait_in_trait,
+ ),
+ _ => ImplTraitContext::Disallowed(position),
+ }
};
- hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
+ hir::FnRetTy::Return(self.lower_ty(ty, &context))
}
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
}
output,
span,
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
- ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+ ImplTraitContext::FeatureGated(
+ ImplTraitPosition::TraitReturn,
+ sym::return_position_impl_trait_in_trait,
+ )
} else {
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
/// has no attributes and is not targeted by a `break`.
fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
let block = self.lower_block(b, false);
- self.expr_block(block, AttrVec::new())
+ self.expr_block(block)
}
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
use rustc_hir as hir;
use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::GenericArg;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
// fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
// ```
- FnRetTy::Ty(ty)
- if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
- && self.tcx.features().impl_trait_in_fn_trait_return =>
- {
- self.lower_ty(&ty, itctx)
+ FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
+ if self.tcx.features().impl_trait_in_fn_trait_return {
+ self.lower_ty(&ty, itctx)
+ } else {
+ self.lower_ty(
+ &ty,
+ &ImplTraitContext::FeatureGated(
+ ImplTraitPosition::FnTraitReturn,
+ sym::impl_trait_in_fn_trait_return,
+ ),
+ )
+ }
}
FnRetTy::Ty(ty) => {
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
/// What is the context that prevents using `~const`?
enum DisallowTildeConstContext<'a> {
TraitObject,
- ImplTrait,
Fn(FnKind<'a>),
}
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
- if outer.is_some() {
- self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
- } else {
- f(self);
- }
+ f(self);
self.outer_impl_trait = old;
}
let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
match reason {
DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
- DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
};
{
let spans = vec![f1_span, f2_span];
sess.struct_span_err(
- spans.clone(),
+ spans,
&format!(
"features `{}` and `{}` are incompatible, using them at the same time \
is not allowed",
}
fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
- self.print_token_literal(lit.token_lit, lit.span)
+ self.print_token_literal(lit.as_token_lit(), lit.span)
}
fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
use rustc_ast::ptr::P;
+use rustc_ast::token;
+use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast::util::parser::{self, AssocOp, Fixity};
use rustc_ast::{self as ast, BlockCheckMode};
self.print_token_literal(*token_lit, expr.span);
}
ast::ExprKind::IncludedBytes(bytes) => {
- let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+ let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
self.print_token_literal(lit, expr.span)
}
ast::ExprKind::Cast(expr, ty) => {
allowed_through_unstable_modules = true;
}
// attributes with data
- else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
- let meta = meta.as_ref().unwrap();
+ else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta {
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
handle_errors(
// Merge the const-unstable info into the stability info
if promotable {
- if let Some((ref mut stab, _)) = const_stab {
- stab.promotable = promotable;
- } else {
- sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
+ match &mut const_stab {
+ Some((stab, _)) => stab.promotable = promotable,
+ _ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }),
}
}
if allowed_through_unstable_modules {
- if let Some((
- Stability {
- level: StabilityLevel::Stable { ref mut allowed_through_unstable_modules, .. },
- ..
- },
- _,
- )) = stab
- {
- *allowed_through_unstable_modules = true;
- } else {
- sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+ match &mut stab {
+ Some((
+ Stability {
+ level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
+ ..
+ },
+ _,
+ )) => *allowed_through_unstable_modules = true,
+ _ => {
+ sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
+ }
}
}
features: Option<&Features>,
eval: &mut impl FnMut(Condition) -> bool,
) -> bool {
- match cfg.kind {
- ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
+ match &cfg.kind {
+ ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
try_gate_cfg(sym::version, cfg.span, sess, features);
let (min_version, span) = match &mis[..] {
[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
rustc_version >= min_version
}
}
- ast::MetaItemKind::List(ref mis) => {
+ ast::MetaItemKind::List(mis) => {
for mi in mis.iter() {
if !mi.is_meta_item() {
handle_errors(
sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
true
}
- MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+ MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
handle_errors(
sess,
lit.span,
});
}
} else if let Some(meta_item) = item.meta_item() {
- 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;
- sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
- span: item.span(),
- repr_arg: &name,
- cause: IncorrectReprFormatGenericCause::from_lit_kind(
- item.span(),
- &value.kind,
- &name,
- ),
- });
- } else if matches!(
- meta_item.name_or_empty(),
- sym::C | sym::simd | sym::transparent
- ) || int_type_of_word(meta_item.name_or_empty()).is_some()
- {
- recognised = true;
- sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
- span: meta_item.span,
- name: meta_item.name_or_empty().to_ident_string(),
- });
+ match &meta_item.kind {
+ MetaItemKind::NameValue(value) => {
+ 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;
+ sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
+ span: item.span(),
+ repr_arg: &name,
+ cause: IncorrectReprFormatGenericCause::from_lit_kind(
+ item.span(),
+ &value.kind,
+ &name,
+ ),
+ });
+ } else if matches!(
+ meta_item.name_or_empty(),
+ sym::C | sym::simd | sym::transparent
+ ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+ {
+ recognised = true;
+ sess.emit_err(session_diagnostics::InvalidReprHintNoValue {
+ span: meta_item.span,
+ name: meta_item.name_or_empty().to_ident_string(),
+ });
+ }
}
- } else if let MetaItemKind::List(_) = meta_item.kind {
- if meta_item.has_name(sym::align) {
- recognised = true;
- sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
- span: meta_item.span,
- });
- } else if meta_item.has_name(sym::packed) {
- recognised = true;
- sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
- span: meta_item.span,
- });
- } else if matches!(
- meta_item.name_or_empty(),
- sym::C | sym::simd | sym::transparent
- ) || int_type_of_word(meta_item.name_or_empty()).is_some()
- {
- recognised = true;
- sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
- span: meta_item.span,
- name: meta_item.name_or_empty().to_ident_string(),
- });
+ MetaItemKind::List(_) => {
+ if meta_item.has_name(sym::align) {
+ recognised = true;
+ sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
+ span: meta_item.span,
+ });
+ } else if meta_item.has_name(sym::packed) {
+ recognised = true;
+ sess.emit_err(
+ session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
+ span: meta_item.span,
+ },
+ );
+ } else if matches!(
+ meta_item.name_or_empty(),
+ sym::C | sym::simd | sym::transparent
+ ) || int_type_of_word(meta_item.name_or_empty()).is_some()
+ {
+ recognised = true;
+ sess.emit_err(session_diagnostics::InvalidReprHintNoParen {
+ span: meta_item.span,
+ name: meta_item.name_or_empty().to_ident_string(),
+ });
+ }
}
+ _ => (),
}
}
if !recognised {
rvalue: &mir::Rvalue<'tcx>,
location: mir::Location,
) {
- if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
+ if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue {
if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
debug!("ignoring_borrow of {:?}", borrowed_place);
return;
region,
reserve_location: location,
activation_location: TwoPhaseActivation::NotTwoPhase,
- borrowed_place: *borrowed_place,
+ borrowed_place,
assigned_place: *assigned_place,
};
let (idx, _) = self.location_map.insert_full(location, borrow);
}
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
- if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
+ if let &mir::Rvalue::Ref(region, kind, place) = rvalue {
// double-check that we already registered a BorrowData for this
let borrow_data = &self.location_map[&location];
assert_eq!(borrow_data.reserve_location, location);
assert_eq!(borrow_data.kind, kind);
assert_eq!(borrow_data.region, region.to_region_vid());
- assert_eq!(borrow_data.borrowed_place, *place);
+ assert_eq!(borrow_data.borrowed_place, place);
}
self.super_rvalue(rvalue, location)
stmt: &mir::Statement<'tcx>,
location: Location,
) {
- match stmt.kind {
- mir::StatementKind::Assign(box (lhs, ref rhs)) => {
- if let mir::Rvalue::Ref(_, _, place) = *rhs {
+ match &stmt.kind {
+ mir::StatementKind::Assign(box (lhs, rhs)) => {
+ if let mir::Rvalue::Ref(_, _, place) = rhs {
if place.ignore_borrow(
self.tcx,
self.body,
// Make sure there are no remaining borrows for variables
// that are assigned over.
- self.kill_borrows_on_place(trans, lhs);
+ self.kill_borrows_on_place(trans, *lhs);
}
mir::StatementKind::StorageDead(local) => {
// Make sure there are no remaining borrows for locals that
// are gone out of scope.
- self.kill_borrows_on_place(trans, Place::from(local));
+ self.kill_borrows_on_place(trans, Place::from(*local));
}
mir::StatementKind::FakeRead(..)
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new(&infcx);
type_op_prove_predicate_with_cause(&ocx, key, cause);
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
}
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new(&infcx);
// FIXME(lqd): Unify and de-duplicate the following with the actual
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new(&infcx);
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
}
DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
);
let note_msg = match opt_name {
- Some(ref name) => format!("`{}`", name),
+ Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg) {
.map_bound(|p| p.predicates),
None,
),
- ty::Opaque(did, substs) => {
- find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*def_id), Some(*substs))
}
ty::Closure(_, substs) => match substs.as_closure().kind() {
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider cloning the value if the performance cost is acceptable",
- ".clone()".to_string(),
+ ".clone()",
Applicability::MachineApplicable,
);
}
// then just use the normal error. The closure isn't escaping
// and `move` will not help here.
(
- Some(ref name),
+ Some(name),
BorrowExplanation::MustBeValidFor {
category:
category @ (ConstraintCategory::Return(_)
&format!("`{}`", name),
),
(
- ref name,
+ name,
BorrowExplanation::MustBeValidFor {
category: ConstraintCategory::Assignment,
from_closure: false,
span,
..
},
- ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
+ ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
location,
&name,
// and it'll make sense.
let location = borrow.reserve_location;
debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
- if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) =
+ if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
&self.body[location.block].statements.get(location.statement_index)
{
debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
// Check if our `target` was captured by a closure.
if let Rvalue::Aggregate(
box AggregateKind::Closure(def_id, substs),
- ref operands,
- ) = *rvalue
+ operands,
+ ) = rvalue
{
for operand in operands {
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure =
- self.annotate_fn_sig(def_id, substs.as_closure().sig());
+ self.annotate_fn_sig(*def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \
} else if self.was_captured_by_trait_object(borrow) {
LaterUseKind::TraitCapture
} else if location.statement_index == block.statements.len() {
- if let TerminatorKind::Call { ref func, from_hir_call: true, .. } =
- block.terminator().kind
+ if let TerminatorKind::Call { func, from_hir_call: true, .. } =
+ &block.terminator().kind
{
// Just point to the function, to reduce the chance of overlapping spans.
let function_span = match func {
// will only ever have one item at any given time, but by using a vector, we can pop from
// it which simplifies the termination logic.
let mut queue = vec![location];
- let mut target = if let Some(&Statement {
- kind: StatementKind::Assign(box (ref place, _)),
- ..
- }) = stmt
- {
- if let Some(local) = place.as_local() {
- local
+ let mut target =
+ if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
+ if let Some(local) = place.as_local() {
+ local
+ } else {
+ return false;
+ }
} else {
return false;
- }
- } else {
- return false;
- };
+ };
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
while let Some(current_location) = queue.pop() {
if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind {
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
match from {
- Operand::Copy(ref place) | Operand::Move(ref place)
+ Operand::Copy(place) | Operand::Move(place)
if target == place.local_or_deref_local() =>
{
target = into.local_or_deref_local()
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() {
- Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
+ Some(Operand::Copy(place) | Operand::Move(place))
if target == place.local_or_deref_local() =>
{
place.local_or_deref_local().unwrap()
if !is_terminator {
continue;
} else if let Some(Terminator {
- kind: TerminatorKind::Call { ref func, from_hir_call: false, .. },
+ kind: TerminatorKind::Call { func, from_hir_call: false, .. },
..
- }) = bbd.terminator
+ }) = &bbd.terminator
{
if let Some(source) =
BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
};
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
- if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
- match **kind {
- AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
- debug!("move_spans: def_id={:?} places={:?}", def_id, places);
- if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
- self.closure_span(def_id, moved_place, places)
- {
- return ClosureUse {
- generator_kind,
- args_span,
- capture_kind_span,
- path_span,
- };
- }
- }
- _ => {}
+ if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
+ && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
+ {
+ debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+ if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+ self.closure_span(def_id, moved_place, places)
+ {
+ return ClosureUse {
+ generator_kind,
+ args_span,
+ capture_kind_span,
+ path_span,
+ };
}
}
// StatementKind::FakeRead only contains a def_id if they are introduced as a result
// of pattern matching within a closure.
- if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
+ if let StatementKind::FakeRead(box (cause, place)) = stmt.kind {
match cause {
FakeReadCause::ForMatchedPlace(Some(closure_def_id))
| FakeReadCause::ForLet(Some(closure_def_id)) => {
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
- let places = &[Operand::Move(*place)];
+ let places = &[Operand::Move(place)];
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
self.closure_span(closure_def_id, moved_place, places)
{
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
let target = match self.body[location.block].statements.get(location.statement_index) {
- Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => {
+ Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
if let Some(local) = place.as_local() {
local
} else {
}
for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
- if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
- stmt.kind
- {
+ if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
let (&def_id, is_generator) = match kind {
box AggregateKind::Closure(def_id, _) => (def_id, false),
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
- // Check whether the source is accessible
- if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
- self_arg.span
- } else {
- fn_call_span
- },
+ self_arg.span,
"calling this operator moves the left-hand side",
);
}
}
- CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
+ CallKind::Normal { self_arg, desugaring, method_did } => {
let self_arg = self_arg.unwrap();
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
),
);
}
+ let tcx = self.infcx.tcx;
// Avoid pointing to the same function in multiple different
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+ let func = tcx.def_path_str(method_did);
err.span_note(
self_arg.span,
- &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
+ &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}")
);
}
+ let parent_did = tcx.parent(method_did);
+ let parent_self_ty = (tcx.def_kind(parent_did)
+ == rustc_hir::def::DefKind::Impl)
+ .then_some(parent_did)
+ .and_then(|did| match tcx.type_of(did).kind() {
+ ty::Adt(def, ..) => Some(def.did()),
+ _ => None,
+ });
+ let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
+ matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
+ });
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.span_label(
var_span,
use rustc_mir_dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
use crate::prefixes::PrefixSet;
match_span: Span,
statement_span: Span,
) {
- debug!("append_binding_error(match_place={:?}, match_span={:?})", match_place, match_span);
+ debug!(?match_place, ?match_span, "append_binding_error");
let from_simple_let = match_place.is_none();
let match_place = match_place.unwrap_or(move_from);
if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge
&& match_span == *span
{
- debug!("appending local({:?}) to list", bind_to);
+ debug!("appending local({bind_to:?}) to list");
if !binds_to.is_empty() {
binds_to.push(bind_to);
}
} = ge
{
if match_span == *span && mpi == *other_mpi {
- debug!("appending local({:?}) to list", bind_to);
+ debug!("appending local({bind_to:?}) to list");
binds_to.push(bind_to);
return;
}
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diagnostic, span: Span) {
match error {
GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
- if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
- err.span_suggestion(
- span,
- "consider borrowing here",
- format!("&{snippet}"),
- Applicability::Unspecified,
- );
- }
-
+ self.add_borrow_suggestions(err, span);
if binds_to.is_empty() {
let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
let place_desc = match self.describe_place(move_from.as_ref()) {
}
}
+ fn add_borrow_suggestions(&self, err: &mut Diagnostic, span: Span) {
+ match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+ Ok(snippet) if snippet.starts_with('*') => {
+ err.span_suggestion_verbose(
+ span.with_hi(span.lo() + BytePos(1)),
+ "consider removing the dereference here",
+ String::new(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ err.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ "consider borrowing here",
+ "&".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+
fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) {
- let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+ let mut suggestions: Vec<(Span, String, String)> = Vec::new();
for local in binds_to {
let bind_to = &self.body.local_decls[*local];
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { pat_span, .. },
)))) = bind_to.local_info
{
- if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+ let Ok(pat_snippet) =
+ self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
+ let Some(stripped) = pat_snippet.strip_prefix('&') else {
+ suggestions.push((
+ bind_to.source_info.span.shrink_to_lo(),
+ "consider borrowing the pattern binding".to_string(),
+ "ref ".to_string(),
+ ));
+ continue;
+ };
+ let inner_pat_snippet = stripped.trim_start();
+ let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut")
+ && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
{
- if let Some(stripped) = pat_snippet.strip_prefix('&') {
- let pat_snippet = stripped.trim_start();
- let (suggestion, to_remove) = if pat_snippet.starts_with("mut")
- && pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace)
- {
- (pat_snippet["mut".len()..].trim_start(), "&mut")
- } else {
- (pat_snippet, "&")
- };
- suggestions.push((pat_span, to_remove, suggestion.to_owned()));
- }
- }
+ let inner_pat_snippet = inner_pat_snippet["mut".len()..].trim_start();
+ let pat_span = pat_span.with_hi(
+ pat_span.lo()
+ + BytePos((pat_snippet.len() - inner_pat_snippet.len()) as u32),
+ );
+ (pat_span, String::new(), "mutable borrow")
+ } else {
+ let pat_span = pat_span.with_hi(
+ pat_span.lo()
+ + BytePos(
+ (pat_snippet.len() - inner_pat_snippet.trim_start().len()) as u32,
+ ),
+ );
+ (pat_span, String::new(), "borrow")
+ };
+ suggestions.push((
+ pat_span,
+ format!("consider removing the {to_remove}"),
+ suggestion.to_string(),
+ ));
}
}
suggestions.sort_unstable_by_key(|&(span, _, _)| span);
suggestions.dedup_by_key(|&mut (span, _, _)| span);
- for (span, to_remove, suggestion) in suggestions {
- err.span_suggestion(
- span,
- &format!("consider removing the `{to_remove}`"),
- suggestion,
- Applicability::MachineApplicable,
- );
+ for (span, msg, suggestion) in suggestions {
+ err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable);
}
}
if binds_to.len() > 1 {
err.note(
- "move occurs because these variables have types that \
- don't implement the `Copy` trait",
+ "move occurs because these variables have types that don't implement the `Copy` \
+ trait",
);
}
}
PlaceRef {
local,
projection:
- &[
- ref proj_base @ ..,
+ [
+ proj_base @ ..,
ProjectionElem::Deref,
ProjectionElem::Field(field, _),
ProjectionElem::Deref,
if let Some(span) = get_mut_span_in_struct_field(
self.infcx.tcx,
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
- field,
+ *field,
) {
err.span_suggestion_verbose(
span,
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
- if let ty::Opaque(def_id, _) = *output_ty.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
output_ty = self.infcx.tcx.type_of(def_id)
};
}
}
hir::ExprKind::Block(blk, _) => {
- if let Some(ref expr) = blk.expr {
+ if let Some(expr) = blk.expr {
// only when the block is a closure
if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref,
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
- if let Some(ref value) = value {
+ if let Some(value) = &value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
}
self.consume_operand(location, op);
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
- ref src,
- ref dst,
- ref count,
+ src,
+ dst,
+ count,
})) => {
self.consume_operand(location, src);
self.consume_operand(location, dst);
self.check_activations(location);
match &terminator.kind {
- TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+ TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(location, discr);
}
TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
}
TerminatorKind::DropAndReplace {
place: drop_place,
- value: ref new_value,
+ value: new_value,
target: _,
unwind: _,
} => {
self.consume_operand(location, new_value);
}
TerminatorKind::Call {
- ref func,
- ref args,
+ func,
+ args,
destination,
target: _,
cleanup: _,
}
self.mutate_place(location, *destination, Deep);
}
- TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+ TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
self.consume_operand(location, cond);
use rustc_middle::mir::AssertKind;
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
self.consume_operand(location, len);
self.consume_operand(location, index);
}
}
- TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
+ TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => {
self.consume_operand(location, value);
// Invalidate all borrows of local places
}
TerminatorKind::InlineAsm {
template: _,
- ref operands,
+ operands,
options: _,
line_spans: _,
destination: _,
cleanup: _,
} => {
for op in operands {
- match *op {
- InlineAsmOperand::In { reg: _, ref value } => {
+ match op {
+ InlineAsmOperand::In { reg: _, value } => {
self.consume_operand(location, value);
}
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
- if let Some(place) = place {
+ if let &Some(place) = place {
self.mutate_place(location, place, Shallow(None));
}
}
- InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+ InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
self.consume_operand(location, in_value);
- if let Some(out_place) = out_place {
+ if let &Some(out_place) = out_place {
self.mutate_place(location, out_place, Shallow(None));
}
}
// Simulates consumption of an rvalue
fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
- match *rvalue {
- Rvalue::Ref(_ /*rgn*/, bk, place) => {
+ match rvalue {
+ &Rvalue::Ref(_ /*rgn*/, bk, place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
}
- Rvalue::AddressOf(mutability, place) => {
+ &Rvalue::AddressOf(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
Deep,
Rvalue::ThreadLocalRef(_) => {}
- Rvalue::Use(ref operand)
- | Rvalue::Repeat(ref operand, _)
- | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
- | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
- self.consume_operand(location, operand)
- }
- Rvalue::CopyForDeref(ref place) => {
- let op = &Operand::Copy(*place);
+ Rvalue::Use(operand)
+ | Rvalue::Repeat(operand, _)
+ | Rvalue::UnaryOp(_ /*un_op*/, operand)
+ | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
+
+ &Rvalue::CopyForDeref(place) => {
+ let op = &Operand::Copy(place);
self.consume_operand(location, op);
}
- Rvalue::Len(place) | Rvalue::Discriminant(place) => {
- let af = match *rvalue {
+ &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
+ let af = match rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
);
}
- Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
- | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+ Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+ | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, operand1);
self.consume_operand(location, operand2);
}
Rvalue::NullaryOp(_op, _ty) => {}
- Rvalue::Aggregate(_, ref operands) => {
+ Rvalue::Aggregate(_, operands) => {
for operand in operands {
self.consume_operand(location, operand);
}
self.check_activations(location, span, flow_state);
match &stmt.kind {
- StatementKind::Assign(box (lhs, ref rhs)) => {
+ StatementKind::Assign(box (lhs, rhs)) => {
self.consume_rvalue(location, (rhs, span), flow_state);
self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
}
- StatementKind::FakeRead(box (_, ref place)) => {
+ StatementKind::FakeRead(box (_, place)) => {
// Read for match doesn't access any memory and is used to
// assert that a place is safe and live. So we don't have to
// do any checks here.
flow_state,
);
}
- StatementKind::Intrinsic(box ref kind) => match kind {
+ StatementKind::Intrinsic(box kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
span,
self.check_activations(loc, span, flow_state);
- match term.kind {
- TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+ match &term.kind {
+ TerminatorKind::SwitchInt { discr, targets: _ } => {
self.consume_operand(loc, (discr, span), flow_state);
}
TerminatorKind::Drop { place, target: _, unwind: _ } => {
self.access_place(
loc,
- (place, span),
+ (*place, span),
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
flow_state,
}
TerminatorKind::DropAndReplace {
place: drop_place,
- value: ref new_value,
+ value: new_value,
target: _,
unwind: _,
} => {
- self.mutate_place(loc, (drop_place, span), Deep, flow_state);
+ self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
self.consume_operand(loc, (new_value, span), flow_state);
}
TerminatorKind::Call {
- ref func,
- ref args,
+ func,
+ args,
destination,
target: _,
cleanup: _,
for arg in args {
self.consume_operand(loc, (arg, span), flow_state);
}
- self.mutate_place(loc, (destination, span), Deep, flow_state);
+ self.mutate_place(loc, (*destination, span), Deep, flow_state);
}
- TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+ TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
self.consume_operand(loc, (cond, span), flow_state);
use rustc_middle::mir::AssertKind;
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
self.consume_operand(loc, (len, span), flow_state);
self.consume_operand(loc, (index, span), flow_state);
}
}
- TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => {
+ TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
self.consume_operand(loc, (value, span), flow_state);
- self.mutate_place(loc, (resume_arg, span), Deep, flow_state);
+ self.mutate_place(loc, (*resume_arg, span), Deep, flow_state);
}
TerminatorKind::InlineAsm {
template: _,
- ref operands,
+ operands,
options: _,
line_spans: _,
destination: _,
cleanup: _,
} => {
for op in operands {
- match *op {
- InlineAsmOperand::In { reg: _, ref value } => {
+ match op {
+ InlineAsmOperand::In { reg: _, value } => {
self.consume_operand(loc, (value, span), flow_state);
}
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
if let Some(place) = place {
- self.mutate_place(loc, (place, span), Shallow(None), flow_state);
+ self.mutate_place(loc, (*place, span), Shallow(None), flow_state);
}
}
- InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+ InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
self.consume_operand(loc, (in_value, span), flow_state);
- if let Some(out_place) = out_place {
+ if let &Some(out_place) = out_place {
self.mutate_place(
loc,
(out_place, span),
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
- match *rvalue {
- Rvalue::Ref(_ /*rgn*/, bk, place) => {
+ match rvalue {
+ &Rvalue::Ref(_ /*rgn*/, bk, place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
);
}
- Rvalue::AddressOf(mutability, place) => {
+ &Rvalue::AddressOf(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
Deep,
Rvalue::ThreadLocalRef(_) => {}
- Rvalue::Use(ref operand)
- | Rvalue::Repeat(ref operand, _)
- | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
- | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
+ Rvalue::Use(operand)
+ | Rvalue::Repeat(operand, _)
+ | Rvalue::UnaryOp(_ /*un_op*/, operand)
+ | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
self.consume_operand(location, (operand, span), flow_state)
}
- Rvalue::CopyForDeref(place) => {
+
+ &Rvalue::CopyForDeref(place) => {
self.access_place(
location,
(place, span),
);
}
- Rvalue::Len(place) | Rvalue::Discriminant(place) => {
+ &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
let af = match *rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
);
}
- Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
- | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+ Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+ | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, (operand1, span), flow_state);
self.consume_operand(location, (operand2, span), flow_state);
}
// nullary ops take no dynamic input; no borrowck effect.
}
- Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
+ Rvalue::Aggregate(aggregate_kind, operands) => {
// We need to report back the list of mutable upvars that were
// moved into the closure and subsequently used by the closure,
// in order to populate our used_mut set.
// Otherwise, we need to find the minimum remaining choice, if
// any, and take that.
debug!("choice_regions remaining are {:#?}", choice_regions);
- let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
- let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
- let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
- match (r1_outlives_r2, r2_outlives_r1) {
- (true, true) => Some(r1.min(r2)),
- (true, false) => Some(r2),
- (false, true) => Some(r1),
- (false, false) => None,
- }
+ let Some(&min_choice) = choice_regions.iter().find(|&r1| {
+ choice_regions.iter().all(|&r2| {
+ self.universal_region_relations.outlives(r2, *r1)
+ })
+ }) else {
+ debug!("no choice region outlived by all others");
+ return false;
};
- let mut min_choice = choice_regions[0];
- for &other_option in &choice_regions[1..] {
- debug!(?min_choice, ?other_option,);
- match min(min_choice, other_option) {
- Some(m) => min_choice = m,
- None => {
- debug!(?min_choice, ?other_option, "incomparable; no min choice",);
- return false;
- }
- }
- }
let min_choice_scc = self.constraint_sccs.scc(min_choice);
debug!(?min_choice, ?min_choice_scc);
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
let tcx = self.tcx();
debug!("stmt kind: {:?}", stmt.kind);
- match stmt.kind {
- StatementKind::Assign(box (ref place, ref rv)) => {
+ match &stmt.kind {
+ StatementKind::Assign(box (place, rv)) => {
// Assignments to temporaries are not "interesting";
// they are not caused by the user, but rather artifacts
// of lowering. Assignments to other sorts of places *are* interesting
);
}
}
- StatementKind::AscribeUserType(box (ref place, ref projection), variance) => {
+ StatementKind::AscribeUserType(box (place, projection), variance) => {
let place_ty = place.ty(body, tcx).ty;
if let Err(terr) = self.relate_type_and_user_type(
place_ty,
- variance,
+ *variance,
projection,
Locations::All(stmt.source_info.span),
ConstraintCategory::TypeAnnotation,
);
}
}
- StatementKind::Intrinsic(box ref kind) => match kind {
+ StatementKind::Intrinsic(box kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
stmt.source_info.span,
) {
let tcx = self.tcx();
debug!("terminator kind: {:?}", term.kind);
- match term.kind {
+ match &term.kind {
TerminatorKind::Goto { .. }
| TerminatorKind::Resume
| TerminatorKind::Abort
// no checks needed for these
}
- TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => {
+ TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
let place_ty = place.ty(body, tcx).ty;
let rv_ty = value.ty(body, tcx);
);
}
}
- TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+ TerminatorKind::SwitchInt { discr, .. } => {
self.check_operand(discr, term_location);
- let discr_ty = discr.ty(body, tcx);
- if let Err(terr) = self.sub_types(
- discr_ty,
- switch_ty,
- term_location.to_locations(),
- ConstraintCategory::Assignment,
- ) {
- span_mirbug!(
- self,
- term,
- "bad SwitchInt ({:?} on {:?}): {:?}",
- switch_ty,
- discr_ty,
- terr
- );
- }
+ let switch_ty = discr.ty(body, tcx);
if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
}
// FIXME: check the values
}
- TerminatorKind::Call {
- ref func,
- ref args,
- ref destination,
- from_hir_call,
- target,
- ..
- } => {
+ TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
self.check_operand(func, term_location);
for arg in args {
self.check_operand(arg, term_location);
ConstraintCategory::Boring,
);
let sig = self.normalize(sig, term_location);
- self.check_call_dest(body, term, &sig, *destination, target, term_location);
+ self.check_call_dest(body, term, &sig, *destination, *target, term_location);
// The ordinary liveness rules will ensure that all
// regions in the type of the callee are live here. We
.add_element(region_vid, term_location);
}
- self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
+ self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
}
- TerminatorKind::Assert { ref cond, ref msg, .. } => {
+ TerminatorKind::Assert { cond, msg, .. } => {
self.check_operand(cond, term_location);
let cond_ty = cond.ty(body, tcx);
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
}
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
if len.ty(body, tcx) != tcx.types.usize {
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
}
}
}
}
- TerminatorKind::Yield { ref value, .. } => {
+ TerminatorKind::Yield { value, .. } => {
self.check_operand(value, term_location);
let value_ty = value.ty(body, tcx);
substs: SubstsRef<'tcx>,
location: Location,
) -> ty::InstantiatedPredicates<'tcx> {
- if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+ if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
constraint_conversion::ConstraintConversion::new(
self.infcx,
self.borrowck_context.universal_regions,
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
let fr_substs = match defining_ty {
- DefiningTy::Closure(_, ref substs)
- | DefiningTy::Generator(_, ref substs, _)
- | DefiningTy::InlineConst(_, ref substs) => {
+ DefiningTy::Closure(_, substs)
+ | DefiningTy::Generator(_, substs, _)
+ | DefiningTy::InlineConst(_, substs) => {
// In the case of closures, we rely on the fact that
// the first N elements in the ClosureSubsts are
// inherited from the `typeck_root_def_id`.
check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler);
let orig_item = item.clone();
- let not_function = || {
- ecx.sess
- .parse_sess
- .span_diagnostic
- .span_err(item.span(), "alloc_error_handler must be a function");
- vec![orig_item.clone()]
- };
// Allow using `#[alloc_error_handler]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, sig_span) = match &item {
- Annotatable::Item(item) => match item.kind {
- ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)),
- _ => return not_function(),
- },
- Annotatable::Stmt(stmt) => match &stmt.kind {
- StmtKind::Item(item_) => match item_.kind {
- ItemKind::Fn(ref fn_kind) => {
- (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
- }
- _ => return not_function(),
- },
- _ => return not_function(),
- },
- _ => return not_function(),
- };
+ let (item, is_stmt, sig_span) =
+ if let Annotatable::Item(item) = &item
+ && let ItemKind::Fn(fn_kind) = &item.kind
+ {
+ (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ } else if let Annotatable::Stmt(stmt) = &item
+ && let StmtKind::Item(item) = &stmt.kind
+ && let ItemKind::Fn(fn_kind) = &item.kind
+ {
+ (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
+ } else {
+ ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
+ return vec![orig_item];
+ };
// Generate a bunch of new items using the AllocFnFactory
let span = ecx.with_def_site_ctxt(item.span);
///
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
- match (*expr).kind {
- ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+ match &mut expr.kind {
+ ExprKind::AddrOf(_, mutability, local_expr) => {
self.with_is_consumed_management(
matches!(mutability, Mutability::Mut),
|this| this.manage_cond_expr(local_expr)
);
}
- ExprKind::Array(ref mut local_exprs) => {
+ ExprKind::Array(local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+ ExprKind::Binary(op, lhs, rhs) => {
self.with_is_consumed_management(
matches!(
op.node,
}
);
}
- ExprKind::Call(_, ref mut local_exprs) => {
+ ExprKind::Call(_, local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Cast(ref mut local_expr, _) => {
+ ExprKind::Cast(local_expr, _) => {
self.manage_cond_expr(local_expr);
}
- ExprKind::Index(ref mut prefix, ref mut suffix) => {
+ ExprKind::Index(prefix, suffix) => {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
- ExprKind::MethodCall(ref mut call) => {
- for arg in call.args.iter_mut() {
+ ExprKind::MethodCall(call) => {
+ for arg in &mut call.args {
self.manage_cond_expr(arg);
}
}
- ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => {
+ ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
let path_ident = path_segment.ident;
self.manage_initial_capture(expr, path_ident);
}
- ExprKind::Paren(ref mut local_expr) => {
+ ExprKind::Paren(local_expr) => {
self.manage_cond_expr(local_expr);
}
- ExprKind::Range(ref mut prefix, ref mut suffix, _) => {
- if let Some(ref mut elem) = prefix {
+ ExprKind::Range(prefix, suffix, _) => {
+ if let Some(elem) = prefix {
self.manage_cond_expr(elem);
}
- if let Some(ref mut elem) = suffix {
+ if let Some(elem) = suffix {
self.manage_cond_expr(elem);
}
}
- ExprKind::Repeat(ref mut local_expr, ref mut elem) => {
+ ExprKind::Repeat(local_expr, elem) => {
self.manage_cond_expr(local_expr);
self.manage_cond_expr(&mut elem.value);
}
- ExprKind::Struct(ref mut elem) => {
+ ExprKind::Struct(elem) => {
for field in &mut elem.fields {
self.manage_cond_expr(&mut field.expr);
}
- if let StructRest::Base(ref mut local_expr) = elem.rest {
+ if let StructRest::Base(local_expr) = &mut elem.rest {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Tup(ref mut local_exprs) => {
+ ExprKind::Tup(local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Unary(un_op, ref mut local_expr) => {
+ ExprKind::Unary(un_op, local_expr) => {
self.with_is_consumed_management(
matches!(un_op, UnOp::Neg | UnOp::Not),
|this| this.manage_cond_expr(local_expr)
use rustc_session::errors::report_lit_error;
use rustc_span::symbol::Symbol;
-use std::string::String;
-
pub fn expand_concat(
cx: &mut base::ExtCtxt<'_>,
sp: rustc_span::Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'static> {
- let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+ let Some(es) = base::get_exprs_from_tts(cx, tts) else {
return DummyResult::any(sp);
};
let mut accumulator = String::new();
for e in es {
match e.kind {
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
- Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => {
+ Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => {
accumulator.push_str(s.as_str());
}
Ok(ast::LitKind::Char(c)) => {
Ok(ast::LitKind::Int(_, _)) => {
cx.span_err(span, "numeric literal is not a `u8`");
}
- Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(),
+ Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
Err(err) => {
report_lit_error(&cx.sess.parse_sess, err, token_lit, span);
}
)) if val <= u8::MAX.into() => Some(val as u8),
Ok(ast::LitKind::Byte(val)) => Some(val),
- Ok(ast::LitKind::ByteStr(_)) => {
+ Ok(ast::LitKind::ByteStr(..)) => {
if !*has_errors {
cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
.note("byte strings are treated as arrays of bytes")
sp: rustc_span::Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'static> {
- let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+ let Some(es) = base::get_exprs_from_tts(cx, tts) else {
return DummyResult::any(sp);
};
let mut accumulator = Vec::new();
let mut missing_literals = vec![];
let mut has_errors = false;
for e in es {
- match e.kind {
- ast::ExprKind::Array(ref exprs) => {
+ match &e.kind {
+ ast::ExprKind::Array(exprs) => {
for expr in exprs {
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
}
}
}
- ast::ExprKind::Repeat(ref expr, ref count) => {
+ ast::ExprKind::Repeat(expr, count) => {
if let ast::ExprKind::Lit(token_lit) = count.value.kind
&& let Ok(ast::LitKind::Int(count_val, _)) =
ast::LitKind::from_token_lit(token_lit)
cx.span_err(count.value.span, "repeat count is not a positive number");
}
}
- ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
+ &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
Ok(ast::LitKind::Byte(val)) => {
accumulator.push(val);
}
- Ok(ast::LitKind::ByteStr(ref bytes)) => {
+ Ok(ast::LitKind::ByteStr(ref bytes, _)) => {
accumulator.extend_from_slice(&bytes);
}
_ => {
has_errors = true;
}
},
- ast::ExprKind::IncludedBytes(ref bytes) => {
+ ast::ExprKind::IncludedBytes(bytes) => {
accumulator.extend_from_slice(bytes);
}
ast::ExprKind::Err => {
}
}
if !missing_literals.is_empty() {
- let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal");
+ let mut err = cx.struct_span_err(missing_literals, "expected a byte literal");
err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
err.emit();
return base::MacEager::expr(DummyResult::raw_expr(sp, true));
use crate::cfg_eval::cfg_eval;
use rustc_ast as ast;
-use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
}
fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
- let help_msg = match lit.token_lit.kind {
- token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => {
- format!("try using `#[derive({})]`", lit.token_lit.symbol)
+ let help_msg = match lit.kind {
+ ast::LitKind::Str(_, ast::StrStyle::Cooked)
+ if rustc_lexer::is_ident(lit.symbol.as_str()) =>
+ {
+ format!("try using `#[derive({})]`", lit.symbol)
}
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
};
let bounds;
let substructure;
let is_simple;
- match *item {
- Annotatable::Item(ref annitem) => match annitem.kind {
- ItemKind::Struct(_, Generics { ref params, .. })
- | ItemKind::Enum(_, Generics { ref params, .. }) => {
+ match item {
+ Annotatable::Item(annitem) => match &annitem.kind {
+ ItemKind::Struct(_, Generics { params, .. })
+ | ItemKind::Enum(_, Generics { params, .. }) => {
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
if has_derive_copy
};
let vdata;
- match *substr.fields {
- Struct(vdata_, ref af) => {
+ match substr.fields {
+ Struct(vdata_, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident]);
all_fields = af;
- vdata = vdata_;
+ vdata = *vdata_;
}
- EnumMatching(.., variant, ref af) => {
+ EnumMatching(.., variant, af) => {
ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]);
all_fields = af;
vdata = &variant.data;
let blkarg = Ident::new(sym::_d, trait_span);
let blkdecoder = cx.expr_ident(trait_span, blkarg);
- let expr = match *substr.fields {
- StaticStruct(_, ref summary) => {
- let nfields = match *summary {
- Unnamed(ref fields, _) => fields.len(),
- Named(ref fields) => fields.len(),
+ let expr = match substr.fields {
+ StaticStruct(_, summary) => {
+ let nfields = match summary {
+ Unnamed(fields, _) => fields.len(),
+ Named(fields) => fields.len(),
};
let fn_read_struct_field_path: Vec<_> =
cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]);
],
)
}
- StaticEnum(_, ref fields) => {
+ StaticEnum(_, fields) => {
let variant = Ident::new(sym::i, trait_span);
let mut arms = Vec::with_capacity(fields.len() + 1);
where
F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>,
{
- match *fields {
- Unnamed(ref fields, is_tuple) => {
+ match fields {
+ Unnamed(fields, is_tuple) => {
let path_expr = cx.expr_path(outer_pat_path);
- if !is_tuple {
+ if !*is_tuple {
path_expr
} else {
let fields = fields
cx.expr_call(trait_span, path_expr, fields)
}
}
- Named(ref fields) => {
+ Named(fields) => {
// use the field's span to get nicer error messages.
let fields = fields
.iter()
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
let expr = match summary {
- Unnamed(ref fields, is_tuple) => {
- if !is_tuple {
- cx.expr_ident(trait_span, substr.type_ident)
- } else {
- let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
- cx.expr_call_ident(trait_span, substr.type_ident, exprs)
- }
+ Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
+ Unnamed(fields, true) => {
+ let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
+ cx.expr_call_ident(trait_span, substr.type_ident, exprs)
}
- Named(ref fields) => {
+ Named(fields) => {
let default_fields = fields
.iter()
.map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
],
));
- match *substr.fields {
- Struct(_, ref fields) => {
+ match substr.fields {
+ Struct(_, fields) => {
let fn_emit_struct_field_path =
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
let mut stmts = Vec::new();
BlockOrExpr::new_expr(expr)
}
- EnumMatching(idx, _, variant, ref fields) => {
+ EnumMatching(idx, _, variant, fields) => {
// We're not generating an AST that the borrow checker is expecting,
// so we need to generate a unique local variable to take the
// mutable loan out on, otherwise we get conflicts which don't
vec![
blkencoder,
name,
- cx.expr_usize(trait_span, idx),
+ cx.expr_usize(trait_span, *idx),
cx.expr_usize(trait_span, fields.len()),
blk,
],
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
fn visit_ty(&mut self, ty: &'a ast::Ty) {
- if let ast::TyKind::Path(_, ref path) = ty.kind {
- if let Some(segment) = path.segments.first() {
- if self.ty_param_names.contains(&segment.ident.name) {
- self.type_params.push(TypeParameter {
- bound_generic_params: self.bound_generic_params_stack.clone(),
- ty: P(ty.clone()),
- });
- }
- }
+ if let ast::TyKind::Path(_, path) = &ty.kind
+ && let Some(segment) = path.segments.first()
+ && self.ty_param_names.contains(&segment.ident.name)
+ {
+ self.type_params.push(TypeParameter {
+ bound_generic_params: self.bound_generic_params_stack.clone(),
+ ty: P(ty.clone()),
+ });
}
visit::walk_ty(self, ty)
push: &mut dyn FnMut(Annotatable),
from_scratch: bool,
) {
- match *item {
- Annotatable::Item(ref item) => {
+ match item {
+ Annotatable::Item(item) => {
let is_packed = item.attrs.iter().any(|attr| {
for r in attr::find_repr_attrs(&cx.sess, attr) {
if let attr::ReprPacked(_) = r {
}
false
});
- let has_no_type_params = match item.kind {
- ast::ItemKind::Struct(_, ref generics)
- | ast::ItemKind::Enum(_, ref generics)
- | ast::ItemKind::Union(_, ref generics) => !generics
+ let has_no_type_params = match &item.kind {
+ ast::ItemKind::Struct(_, generics)
+ | ast::ItemKind::Enum(_, generics)
+ | ast::ItemKind::Union(_, generics) => !generics
.params
.iter()
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
let copy_fields =
is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
- let newitem = match item.kind {
- ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def(
+ let newitem = match &item.kind {
+ ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
cx,
&struct_def,
item.ident,
from_scratch,
copy_fields,
),
- ast::ItemKind::Enum(ref enum_def, ref generics) => {
+ ast::ItemKind::Enum(enum_def, generics) => {
// We ignore `is_packed` here, because `repr(packed)`
// enums cause an error later on.
//
// downstream in blatantly illegal code, so it is fine.
self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch)
}
- ast::ItemKind::Union(ref struct_def, ref generics) => {
+ ast::ItemKind::Union(struct_def, generics) => {
if self.supports_unions {
self.expand_struct_def(
cx,
for field_ty_param in field_ty_params {
// if we have already handled this type, skip it
- if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind {
- if p.segments.len() == 1
- && ty_param_names.contains(&p.segments[0].ident.name)
- {
- continue;
- };
+ if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
+ && let [sole_segment] = &*p.segments
+ && ty_param_names.contains(&sole_segment.ident.name)
+ {
+ continue;
}
let mut bounds: Vec<_> = self
.additional_bounds
self_ty: Ident,
generics: &Generics,
) -> ast::Path {
- match *self {
+ match self {
Self_ => {
let params: Vec<_> = generics
.params
cx.path_all(span, false, vec![self_ty], params)
}
- Path(ref p) => p.to_path(cx, span, self_ty, generics),
+ Path(p) => p.to_path(cx, span, self_ty, generics),
Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
}
let params = self
.bounds
.iter()
- .map(|t| {
- let (name, ref bounds) = *t;
- mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
- })
+ .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics))
.collect();
Generics {
structural_path: generic::ty::Path,
push: &mut dyn FnMut(Annotatable),
) {
- let Annotatable::Item(ref item) = *item else {
+ let Annotatable::Item(item) = item else {
unreachable!();
};
- let generics = match item.kind {
- ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics,
+ let generics = match &item.kind {
+ ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
// Do not inject `impl Structural for Union`. (`PartialEq` does not
// support unions, so we will see error downstream.)
ItemKind::Union(..) => return,
sp: Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'cx> {
- let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
- Some(ref exprs) if exprs.is_empty() => {
+ let mut exprs = match get_exprs_from_tts(cx, tts) {
+ Some(exprs) if exprs.is_empty() => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::any(sp);
}
parse::Piece::String(s) => {
unfinished_literal.push_str(s);
}
- parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => {
+ parse::Piece::NextArgument(box parse::Argument { position, position_span, format }) => {
if !unfinished_literal.is_empty() {
template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
unfinished_literal.clear();
impl<'a> Substitution<'a> {
pub fn as_str(&self) -> &str {
- match *self {
- Substitution::Format(ref fmt) => fmt.span,
+ match self {
+ Substitution::Format(fmt) => fmt.span,
Substitution::Escape(_) => "%%",
}
}
pub fn position(&self) -> Option<InnerSpan> {
- match *self {
- Substitution::Format(ref fmt) => Some(fmt.position),
- Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
+ match self {
+ Substitution::Format(fmt) => Some(fmt.position),
+ &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
}
}
pub fn set_position(&mut self, start: usize, end: usize) {
match self {
- Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
- Substitution::Escape(ref mut pos) => *pos = (start, end),
+ Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end),
+ Substitution::Escape(pos) => *pos = (start, end),
}
}
/// This ignores cases where the substitution does not have an exact equivalent, or where
/// the substitution would be unnecessary.
pub fn translate(&self) -> Result<String, Option<String>> {
- match *self {
- Substitution::Format(ref fmt) => fmt.translate(),
+ match self {
+ Substitution::Format(fmt) => fmt.translate(),
Substitution::Escape(_) => Err(None),
}
}
}
pub fn position(&self) -> Option<InnerSpan> {
- match self {
- Substitution::Ordinal(_, pos)
- | Substitution::Name(_, pos)
- | Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)),
- }
+ let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+ Some(InnerSpan::new(pos.0, pos.1))
}
pub fn set_position(&mut self, start: usize, end: usize) {
- match self {
- Substitution::Ordinal(_, ref mut pos)
- | Substitution::Name(_, ref mut pos)
- | Substitution::Escape(ref mut pos) => *pos = (start, end),
- }
+ let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self;
+ *pos = (start, end);
}
pub fn translate(&self) -> Result<String, Option<String>> {
- match *self {
+ match self {
Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Escape(_) => Err(None),
check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
let orig_item = item.clone();
- let not_static = || {
- ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
- vec![orig_item.clone()]
- };
// Allow using `#[global_allocator]` on an item statement
// FIXME - if we get deref patterns, use them to reduce duplication here
- let (item, is_stmt, ty_span) = match &item {
- Annotatable::Item(item) => match item.kind {
- ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)),
- _ => return not_static(),
- },
- Annotatable::Stmt(stmt) => match &stmt.kind {
- StmtKind::Item(item_) => match item_.kind {
- ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)),
- _ => return not_static(),
- },
- _ => return not_static(),
- },
- _ => return not_static(),
- };
+ let (item, is_stmt, ty_span) =
+ if let Annotatable::Item(item) = &item
+ && let ItemKind::Static(ty, ..) = &item.kind
+ {
+ (item, false, ecx.with_def_site_ctxt(ty.span))
+ } else if let Annotatable::Stmt(stmt) = &item
+ && let StmtKind::Item(item) = &stmt.kind
+ && let ItemKind::Static(ty, ..) = &item.kind
+ {
+ (item, true, ecx.with_def_site_ctxt(ty.span))
+ } else {
+ ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
+ return vec![orig_item];
+ };
// Generate a bunch of new items using the AllocFnFactory
let span = ecx.with_def_site_ctxt(item.span);
cx.attr_nested_word(sym::cfg, sym::test, attr_sp),
// #[rustc_test_marker = "test_case_sort_key"]
cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp),
- ]
- .into(),
+ ],
// const $ident: test::TestDescAndFn =
ast::ItemKind::Const(
ast::Defaultness::Final,
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
let sd = &cx.sess.parse_sess.span_diagnostic;
- if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
- if let ast::Unsafe::Yes(span) = sig.header.unsafety {
- sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
- .span_label(span, "`unsafe` because of this")
- .emit();
- return false;
- }
- if let ast::Async::Yes { span, .. } = sig.header.asyncness {
- sd.struct_span_err(i.span, "async functions cannot be used for tests")
- .span_label(span, "`async` because of this")
- .emit();
- return false;
- }
-
- // If the termination trait is active, the compiler will check that the output
- // type implements the `Termination` trait as `libtest` enforces that.
- let has_output = match sig.decl.output {
- ast::FnRetTy::Default(..) => false,
- ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false,
- _ => true,
- };
-
- if !sig.decl.inputs.is_empty() {
- sd.span_err(i.span, "functions used as tests can not have any arguments");
- return false;
- }
+ match &i.kind {
+ ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
+ if let ast::Unsafe::Yes(span) = sig.header.unsafety {
+ sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
+ .span_label(span, "`unsafe` because of this")
+ .emit();
+ return false;
+ }
+ if let ast::Async::Yes { span, .. } = sig.header.asyncness {
+ sd.struct_span_err(i.span, "async functions cannot be used for tests")
+ .span_label(span, "`async` because of this")
+ .emit();
+ return false;
+ }
- match (has_output, has_should_panic_attr) {
- (true, true) => {
- sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
- false
+ // If the termination trait is active, the compiler will check that the output
+ // type implements the `Termination` trait as `libtest` enforces that.
+ let has_output = match &sig.decl.output {
+ ast::FnRetTy::Default(..) => false,
+ ast::FnRetTy::Ty(t) if t.kind.is_unit() => false,
+ _ => true,
+ };
+
+ if !sig.decl.inputs.is_empty() {
+ sd.span_err(i.span, "functions used as tests can not have any arguments");
+ return false;
}
- (true, false) => {
- if !generics.params.is_empty() {
- sd.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+
+ match (has_output, has_should_panic_attr) {
+ (true, true) => {
+ sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
false
- } else {
- true
}
+ (true, false) => {
+ if !generics.params.is_empty() {
+ sd.span_err(
+ i.span,
+ "functions used as tests must have signature fn() -> ()",
+ );
+ false
+ } else {
+ true
+ }
+ }
+ (false, _) => true,
}
- (false, _) => true,
}
- } else {
- // should be unreachable because `is_test_fn_item` should catch all non-fn items
- false
+ _ => {
+ // should be unreachable because `is_test_fn_item` should catch all non-fn items
+ debug_assert!(false);
+ false
+ }
}
}
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
- let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
+ let has_sig = match &i.kind {
// N.B., inadequate check, but we're running
// well before resolve, can't get too deep.
- sig.decl.inputs.len() == 1
- } else {
- false
+ ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1,
+ _ => false,
};
if !has_sig {
// We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things
- if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind {
- let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans;
+ if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) =
+ item.kind
+ {
let prev_tests = mem::take(&mut self.tests);
noop_visit_item_kind(&mut item.kind, self);
self.add_test_cases(item.id, span, prev_tests);
folder: target
prepare_script:
- . $HOME/.cargo/env
- - git config --global user.email "user@example.com"
- - git config --global user.name "User"
- ./y.rs prepare
test_script:
- . $HOME/.cargo/env
- name: Rustfmt
run: |
cargo fmt --check
+ rustfmt --check build_system/mod.rs
build:
runs-on: ${{ matrix.os }}
fail-fast: false
matrix:
include:
- - os: ubuntu-latest
+ - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest
- os: ubuntu-latest
env:
TARGET_TRIPLE: aarch64-unknown-linux-gnu
+ # s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default
+ - os: ubuntu-latest
+ env:
+ TARGET_TRIPLE: s390x-unknown-linux-gnu
steps:
- uses: actions/checkout@v3
- name: Cache cargo installed crates
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: target
+ path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Install MinGW toolchain and wine
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user
- - name: Prepare dependencies
+ - name: Install s390x toolchain and qemu
+ if: matrix.env.TARGET_TRIPLE == 's390x-unknown-linux-gnu'
run: |
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- ./y.rs prepare
+ sudo apt-get update
+ sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
+
+ - name: Prepare dependencies
+ run: ./y.rs prepare
- name: Build without unstable features
env:
./y.rs test
- name: Package prebuilt cg_clif
- run: tar cvfJ cg_clif.tar.xz build
+ run: tar cvfJ cg_clif.tar.xz dist
- name: Upload prebuilt cg_clif
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
- name: Upload prebuilt cg_clif (cross compile)
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz
- uses: actions/checkout@v3
- name: Cache cargo installed crates
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
- name: Cache cargo registry and index
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/.cargo/registry
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: target
+ path: build/cg_clif
key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Set MinGW as the default toolchain
- name: Prepare dependencies
run: |
- git config --global user.email "user@example.com"
- git config --global user.name "User"
git config --global core.autocrlf false
rustc y.rs -o y.exe -g
./y.exe prepare
# Enable extra checks
$Env:CG_CLIF_ENABLE_VERIFIER=1
-
+
# WIP Disable some tests
-
+
# This fails due to some weird argument handling by hyperfine, not an actual regression
# more of a build system issue
(Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt
-
- # This fails with a different output than expected
+
+ # This fails with a different output than expected
(Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt
./y.exe test
- name: Package prebuilt cg_clif
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
- run: tar cvf cg_clif.tar build
+ run: tar cvf cg_clif.tar dist
- name: Upload prebuilt cg_clif
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar
- uses: actions/checkout@v3
- name: Cache cargo installed crates
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ubuntu-latest-cargo-installed-crates
- uses: actions/checkout@v3
- name: Cache cargo installed crates
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: target
+ path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
- uses: actions/checkout@v3
- name: Cache cargo installed crates
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
- path: target
+ path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
/build_sysroot/sysroot_src
/build_sysroot/compiler-builtins
/build_sysroot/rustc_version
+/dist
/rust
/download
"rust-analyzer.imports.granularity.enforce": true,
"rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.prefix": "crate",
- "rust-analyzer.cargo.features": ["unstable-features"],
+ "rust-analyzer.cargo.features": ["unstable-features", "__check_build_system_using_ra"],
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
- //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
{
- "roots": [
- "./example/mini_core.rs",
- "./example/mini_core_hello_world.rs",
- "./example/mod_bench.rs"
- ],
"crates": [
{
"root_module": "./example/mini_core.rs",
]
},
{
- "roots": ["./example/std_example.rs"],
+ "sysroot_src": "./build_sysroot/sysroot_src/library",
"crates": [
{
"root_module": "./example/std_example.rs",
- "edition": "2018",
- "deps": [{ "crate": 1, "name": "std" }],
- "cfg": [],
- },
- {
- "root_module": "./build_sysroot/sysroot_src/library/std/src/lib.rs",
- "edition": "2018",
- "deps": [],
- "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",
+ "edition": "2015",
"deps": [],
"cfg": [],
},
[[package]]
name = "anyhow"
-version = "1.0.60"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "arrayvec"
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "byteorder"
[[package]]
name = "cranelift-bforest"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
+checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
+checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
dependencies = [
"arrayvec",
"bumpalo",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
+ "cranelift-egraph",
"cranelift-entity",
"cranelift-isle",
"gimli",
[[package]]
name = "cranelift-codegen-meta"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
+checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
+checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
+
+[[package]]
+name = "cranelift-egraph"
+version = "0.90.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
+dependencies = [
+ "cranelift-entity",
+ "fxhash",
+ "hashbrown",
+ "indexmap",
+ "log",
+ "smallvec",
+]
[[package]]
name = "cranelift-entity"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
+checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
[[package]]
name = "cranelift-frontend"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
+checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
dependencies = [
"cranelift-codegen",
"log",
[[package]]
name = "cranelift-isle"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
+checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
[[package]]
name = "cranelift-jit"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
+checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
dependencies = [
"anyhow",
"cranelift-codegen",
"log",
"region",
"target-lexicon",
+ "wasmtime-jit-icache-coherence",
"windows-sys",
]
[[package]]
name = "cranelift-module"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
+checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "cranelift-native"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
+checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
dependencies = [
"cranelift-codegen",
"libc",
[[package]]
name = "cranelift-object"
-version = "0.88.1"
+version = "0.90.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
+checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
dependencies = [
"anyhow",
"cranelift-codegen",
"cfg-if",
]
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
[[package]]
name = "fxhash"
version = "0.2.1"
[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
+ "fallible-iterator",
"indexmap",
+ "stable_deref_trait",
]
[[package]]
[[package]]
name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
[[package]]
name = "libc"
-version = "0.2.127"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
[[package]]
name = "once_cell"
-version = "1.13.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "regalloc2"
-version = "0.3.2"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779"
+checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
dependencies = [
"fxhash",
"log",
[[package]]
name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "target-lexicon"
-version = "0.12.4"
+version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d"
[[package]]
name = "version_check"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+[[package]]
+name = "wasmtime-jit-icache-coherence"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "windows-sys",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
version = "0.1.0"
edition = "2021"
+[[bin]]
+# This is used just to teach rust-analyzer how to check the build system. required-features is used
+# to disable it for regular builds.
+name = "y"
+path = "./y.rs"
+required-features = ["__check_build_system_using_ra"]
+
[lib]
crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.88.1"
-cranelift-module = "0.88.1"
-cranelift-native = "0.88.1"
-cranelift-jit = { version = "0.88.1", optional = true }
-cranelift-object = "0.88.1"
+cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.90.1"
+cranelift-module = "0.90.1"
+cranelift-native = "0.90.1"
+cranelift-jit = { version = "0.90.1", optional = true }
+cranelift-object = "0.90.1"
target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
unstable-features = ["jit", "inline_asm"]
jit = ["cranelift-jit", "libloading"]
inline_asm = []
+__check_build_system_using_ra = []
[package.metadata.rust-analyzer]
rustc_private = true
In the directory with your project (where you can do the usual `cargo build`), run:
```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
[[package]]
name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"compiler_builtins",
"gimli",
"core",
]
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
[[package]]
name = "cc"
-version = "1.0.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
+version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
[[package]]
name = "compiler_builtins"
-version = "0.1.82"
+version = "0.1.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
+checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "gimli"
-version = "0.25.0"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
[[package]]
name = "libc"
-version = "0.2.135"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
- "autocfg",
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
[[package]]
name = "object"
-version = "0.26.2"
+version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"compiler_builtins",
"memchr",
version = "0.0.0"
dependencies = [
"alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
"compiler_builtins",
"core",
"libc",
version = "0.0.0"
dependencies = [
"alloc",
- "cfg-if 0.1.10",
+ "cfg-if",
"compiler_builtins",
"core",
"libc",
dependencies = [
"addr2line",
"alloc",
- "cfg-if 1.0.0",
+ "cfg-if",
"compiler_builtins",
"core",
"dlmalloc",
name = "std_detect"
version = "0.1.5"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"compiler_builtins",
"libc",
"rustc-std-workspace-alloc",
name = "test"
version = "0.0.0"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
"core",
"getopts",
"libc",
version = "0.0.0"
dependencies = [
"cc",
- "cfg-if 0.1.10",
+ "cfg-if",
"compiler_builtins",
"core",
"libc",
-use std::env;
use std::path::Path;
use super::build_sysroot;
use super::config;
-use super::prepare;
-use super::utils::{cargo_command, spawn_and_wait};
+use super::path::Dirs;
+use super::prepare::GitRepo;
+use super::utils::{spawn_and_wait, CargoProject, Compiler};
use super::SysrootKind;
+pub(crate) static ABI_CAFE_REPO: GitRepo =
+ GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
+
pub(crate) fn run(
channel: &str,
sysroot_kind: SysrootKind,
- target_dir: &Path,
+ dirs: &Dirs,
cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
eprintln!("Building sysroot for abi-cafe");
build_sysroot::build_sysroot(
+ dirs,
channel,
sysroot_kind,
- target_dir,
cg_clif_dylib,
host_triple,
target_triple,
);
eprintln!("Running abi-cafe");
- let abi_cafe_path = prepare::ABI_CAFE.source_dir();
- env::set_current_dir(abi_cafe_path.clone()).unwrap();
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
- let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+ let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
cmd.arg("--");
cmd.arg("--pairs");
cmd.args(pairs);
cmd.arg("--add-rustc-codegen-backend");
cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+ cmd.current_dir(ABI_CAFE.source_dir(dirs));
spawn_and_wait(cmd);
}
use std::env;
use std::path::PathBuf;
+use super::path::{Dirs, RelPath};
use super::rustc_info::get_file_name;
-use super::utils::{cargo_command, is_ci};
+use super::utils::{is_ci, CargoProject, Compiler};
+
+static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
pub(crate) fn build_backend(
+ dirs: &Dirs,
channel: &str,
host_triple: &str,
use_unstable_features: bool,
) -> PathBuf {
- let source_dir = std::env::current_dir().unwrap();
- let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
+ let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
eprintln!("[BUILD] rustc_codegen_cranelift");
super::utils::spawn_and_wait(cmd);
- source_dir
- .join("target")
+ CG_CLIF
+ .target_dir(dirs)
.join(host_triple)
.join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
use std::process::{self, Command};
+use super::path::{Dirs, RelPath};
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
+use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::SysrootKind;
+static DIST_DIR: RelPath = RelPath::DIST;
+static BIN_DIR: RelPath = RelPath::DIST.join("bin");
+static LIB_DIR: RelPath = RelPath::DIST.join("lib");
+static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
+
pub(crate) fn build_sysroot(
+ dirs: &Dirs,
channel: &str,
sysroot_kind: SysrootKind,
- target_dir: &Path,
cg_clif_dylib_src: &Path,
host_triple: &str,
target_triple: &str,
) {
eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
- 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();
+ DIST_DIR.ensure_fresh(dirs);
+ BIN_DIR.ensure_exists(dirs);
+ LIB_DIR.ensure_exists(dirs);
// Copy the backend
- let cg_clif_dylib_path = 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(get_file_name("rustc_codegen_cranelift", "dylib"));
+ let cg_clif_dylib_path = if cfg!(windows) {
+ // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
+ // binaries.
+ BIN_DIR
+ } else {
+ LIB_DIR
+ }
+ .to_path(dirs)
+ .join(get_file_name("rustc_codegen_cranelift", "dylib"));
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers
- for wrapper in ["rustc-clif", "cargo-clif"] {
+ for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
let wrapper_name = get_wrapper_file_name(wrapper, "bin");
let mut build_cargo_wrapper_cmd = Command::new("rustc");
build_cargo_wrapper_cmd
- .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs")))
+ .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
.arg("-o")
- .arg(target_dir.join(wrapper_name))
+ .arg(DIST_DIR.to_path(dirs).join(wrapper_name))
.arg("-g");
spawn_and_wait(build_cargo_wrapper_cmd);
}
let default_sysroot = super::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");
+ let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
+ let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
fs::create_dir_all(&host_rustlib_lib).unwrap();
fs::create_dir_all(&target_rustlib_lib).unwrap();
}
}
SysrootKind::Clif => {
- build_clif_sysroot_for_triple(
- channel,
- target_dir,
- host_triple,
- &cg_clif_dylib_path,
- None,
- );
+ build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, 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
+ let linker = match target_triple {
+ "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
+ "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
+ _ => None,
};
build_clif_sysroot_for_triple(
+ dirs,
channel,
- target_dir,
target_triple,
&cg_clif_dylib_path,
linker,
let file = file.unwrap().path();
let filename = file.file_name().unwrap().to_str().unwrap();
if filename.contains("std-") && !filename.contains(".rlib") {
- try_hard_link(&file, target_dir.join("lib").join(file.file_name().unwrap()));
+ try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
}
}
}
}
}
+// FIXME move to download/ or dist/
+pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
+pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
+static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
+
fn build_clif_sysroot_for_triple(
+ dirs: &Dirs,
channel: &str,
- target_dir: &Path,
triple: &str,
cg_clif_dylib_path: &Path,
linker: Option<&str>,
) {
- match fs::read_to_string(Path::new("build_sysroot").join("rustc_version")) {
+ match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
Err(e) => {
eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
eprintln!("Hint: Try `./y.rs prepare` to patch the sysroot source");
}
}
- let build_dir = Path::new("build_sysroot").join("target").join(triple).join(channel);
+ let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
if !super::config::get_bool("keep_sysroot") {
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster
}
// Build sysroot
- let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
- rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
+ rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
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);
+ let mut compiler = Compiler::with_triple(triple.to_owned());
+ compiler.rustflags = rustflags;
+ let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
+ if channel == "release" {
+ build_cmd.arg("--release");
+ }
build_cmd.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()
- {
+ for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
let entry = entry.unwrap();
if let Some(ext) = entry.path().extension() {
if ext == "rmeta" || ext == "d" || ext == "dSYM" || ext == "clif" {
};
try_hard_link(
entry.path(),
- target_dir.join("lib").join("rustlib").join(triple).join("lib").join(entry.file_name()),
+ RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
);
}
}
mod build_backend;
mod build_sysroot;
mod config;
+mod path;
mod prepare;
mod rustc_info;
mod tests;
mod utils;
+const USAGE: &str = r#"The build system of cg_clif.
+
+USAGE:
+ ./y.rs prepare [--out-dir DIR]
+ ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+ ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+
+OPTIONS:
+ --sysroot none|clif|llvm
+ Which sysroot libraries to use:
+ `none` will not include any standard library in the sysroot.
+ `clif` will build the standard library using Cranelift.
+ `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
+
+ --out-dir DIR
+ Specify the directory in which the download, build and dist directories are stored.
+ By default this is the working directory.
+
+ --no-unstable-features
+ fSome features are not yet ready for production usage. This option will disable these
+ features. This includes the JIT mode and inline assembly support.
+"#;
+
fn usage() {
- eprintln!("Usage:");
- eprintln!(" ./y.rs prepare");
- eprintln!(
- " ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
- );
- eprintln!(
- " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]"
- );
+ eprintln!("{USAGE}");
}
macro_rules! arg_error {
#[derive(PartialEq, Debug)]
enum Command {
+ Prepare,
Build,
Test,
}
pub 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");
if is_ci() {
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
let mut args = env::args().skip(1);
let command = match args.next().as_deref() {
- Some("prepare") => {
- if args.next().is_some() {
- arg_error!("./y.rs prepare doesn't expect arguments");
- }
- prepare::prepare();
- process::exit(0);
- }
+ Some("prepare") => Command::Prepare,
Some("build") => Command::Build,
Some("test") => Command::Test,
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
}
};
- let mut target_dir = PathBuf::from("build");
+ let mut out_dir = PathBuf::from(".");
let mut channel = "release";
let mut sysroot_kind = SysrootKind::Clif;
let mut use_unstable_features = true;
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");
+ "--out-dir" => {
+ out_dir = PathBuf::from(args.next().unwrap_or_else(|| {
+ arg_error!("--out-dir requires argument");
}))
}
"--debug" => channel = "debug",
arg => arg_error!("Unexpected argument {}", arg),
}
}
- target_dir = std::env::current_dir().unwrap().join(target_dir);
let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
host_triple
host_triple.clone()
};
- let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
+ // FIXME allow changing the location of these dirs using cli arguments
+ let current_dir = std::env::current_dir().unwrap();
+ out_dir = current_dir.join(out_dir);
+ let dirs = path::Dirs {
+ source_dir: current_dir.clone(),
+ download_dir: out_dir.join("download"),
+ build_dir: out_dir.join("build"),
+ dist_dir: out_dir.join("dist"),
+ };
+
+ path::RelPath::BUILD.ensure_exists(&dirs);
+
+ {
+ // Make sure we always explicitly specify the target dir
+ let target =
+ path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs);
+ env::set_var("CARGO_TARGET_DIR", &target);
+ let _ = std::fs::remove_file(&target);
+ std::fs::File::create(target).unwrap();
+ }
+
+ if command == Command::Prepare {
+ prepare::prepare(&dirs);
+ process::exit(0);
+ }
+
+ let cg_clif_dylib =
+ build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
match command {
+ Command::Prepare => {
+ // Handled above
+ }
Command::Test => {
tests::run_tests(
+ &dirs,
channel,
sysroot_kind,
- &target_dir,
&cg_clif_dylib,
&host_triple,
&target_triple,
abi_cafe::run(
channel,
sysroot_kind,
- &target_dir,
+ &dirs,
&cg_clif_dylib,
&host_triple,
&target_triple,
}
Command::Build => {
build_sysroot::build_sysroot(
+ &dirs,
channel,
sysroot_kind,
- &target_dir,
&cg_clif_dylib,
&host_triple,
&target_triple,
--- /dev/null
+use std::fs;
+use std::path::PathBuf;
+
+#[derive(Debug, Clone)]
+pub(crate) struct Dirs {
+ pub(crate) source_dir: PathBuf,
+ pub(crate) download_dir: PathBuf,
+ pub(crate) build_dir: PathBuf,
+ pub(crate) dist_dir: PathBuf,
+}
+
+#[doc(hidden)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum PathBase {
+ Source,
+ Download,
+ Build,
+ Dist,
+}
+
+impl PathBase {
+ fn to_path(self, dirs: &Dirs) -> PathBuf {
+ match self {
+ PathBase::Source => dirs.source_dir.clone(),
+ PathBase::Download => dirs.download_dir.clone(),
+ PathBase::Build => dirs.build_dir.clone(),
+ PathBase::Dist => dirs.dist_dir.clone(),
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum RelPath {
+ Base(PathBase),
+ Join(&'static RelPath, &'static str),
+}
+
+impl RelPath {
+ pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source);
+ pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download);
+ pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build);
+ pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
+
+ pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
+ pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
+ pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
+
+ pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
+ RelPath::Join(self, suffix)
+ }
+
+ pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf {
+ match self {
+ RelPath::Base(base) => base.to_path(dirs),
+ RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix),
+ }
+ }
+
+ pub(crate) fn ensure_exists(&self, dirs: &Dirs) {
+ fs::create_dir_all(self.to_path(dirs)).unwrap();
+ }
+
+ pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
+ let path = self.to_path(dirs);
+ if path.exists() {
+ fs::remove_dir_all(&path).unwrap();
+ }
+ fs::create_dir_all(path).unwrap();
+ }
+}
-use std::env;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
+use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
+use super::path::{Dirs, RelPath};
use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
-
-pub(crate) const ABI_CAFE: GitRepo =
- GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
-
-pub(crate) const RAND: GitRepo =
- GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
-
-pub(crate) const REGEX: GitRepo =
- GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
-
-pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
- "rust-lang",
- "portable-simd",
- "d5cd4a8112d958bd3a252327e0d069a6363249bd",
- "portable-simd",
-);
-
-pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
- "ebobby",
- "simple-raytracer",
- "804a7a21b9e673a482797aa289a18ed480e4d813",
- "<none>",
-);
-
-pub(crate) fn prepare() {
- if Path::new("download").exists() {
- std::fs::remove_dir_all(Path::new("download")).unwrap();
+use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
+
+pub(crate) fn prepare(dirs: &Dirs) {
+ if RelPath::DOWNLOAD.to_path(dirs).exists() {
+ std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
}
- std::fs::create_dir_all(Path::new("download")).unwrap();
+ std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
- prepare_sysroot();
+ prepare_sysroot(dirs);
// FIXME maybe install this only locally?
eprintln!("[INSTALL] hyperfine");
- Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
+ Command::new("cargo")
+ .arg("install")
+ .arg("hyperfine")
+ .env_remove("CARGO_TARGET_DIR")
+ .spawn()
+ .unwrap()
+ .wait()
+ .unwrap();
- ABI_CAFE.fetch();
- RAND.fetch();
- REGEX.fetch();
- PORTABLE_SIMD.fetch();
- SIMPLE_RAYTRACER.fetch();
+ super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
+ super::tests::RAND_REPO.fetch(dirs);
+ super::tests::REGEX_REPO.fetch(dirs);
+ super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
+ super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
eprintln!("[LLVM BUILD] simple-raytracer");
- let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
+ let host_compiler = Compiler::host();
+ let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
spawn_and_wait(build_cmd);
fs::copy(
- SIMPLE_RAYTRACER
- .source_dir()
- .join("target")
+ super::tests::SIMPLE_RAYTRACER
+ .target_dir(dirs)
+ .join(&host_compiler.triple)
.join("debug")
.join(get_file_name("main", "bin")),
- SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
+ RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
)
.unwrap();
}
-fn prepare_sysroot() {
+fn prepare_sysroot(dirs: &Dirs) {
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");
+ let sysroot_src = 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();
+ sysroot_src.ensure_fresh(dirs);
+ fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
eprintln!("[COPY] sysroot src");
- copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
+ copy_dir_recursively(
+ &sysroot_src_orig.join("library"),
+ &sysroot_src.to_path(dirs).join("library"),
+ );
let rustc_version = get_rustc_version();
- fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap();
+ fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &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);
-
- init_git_repo(&sysroot_src);
+ init_git_repo(&sysroot_src.to_path(dirs));
- apply_patches("sysroot", &sysroot_src);
+ apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
}
pub(crate) struct GitRepo {
}
impl GitRepo {
- const fn github(
+ pub(crate) const fn github(
user: &'static str,
repo: &'static str,
rev: &'static str,
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
}
- pub(crate) fn source_dir(&self) -> PathBuf {
+ pub(crate) const fn source_dir(&self) -> RelPath {
match self.url {
- GitRepoUrl::Github { user: _, repo } => {
- std::env::current_dir().unwrap().join("download").join(repo)
- }
+ GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo),
}
}
- fn fetch(&self) {
+ fn fetch(&self, dirs: &Dirs) {
match self.url {
GitRepoUrl::Github { user, repo } => {
- clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+ clone_repo_shallow_github(
+ dirs,
+ &self.source_dir().to_path(dirs),
+ user,
+ repo,
+ self.rev,
+ );
}
}
- apply_patches(self.patch_name, &self.source_dir());
+ apply_patches(dirs, self.patch_name, &self.source_dir().to_path(dirs));
}
}
spawn_and_wait(checkout_cmd);
}
-fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo: &str, rev: &str) {
if cfg!(windows) {
// Older windows doesn't have tar or curl by default. Fall back to using git.
clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
return;
}
- let downloads_dir = std::env::current_dir().unwrap().join("download");
-
let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
- let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
- let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
+ let archive_file = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}.tar.gz", rev));
+ let archive_dir = RelPath::DOWNLOAD.to_path(dirs).join(format!("{}-{}", repo, rev));
eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
// Unpack tar archive
let mut unpack_cmd = Command::new("tar");
- unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
+ unpack_cmd.arg("xf").arg(&archive_file).current_dir(RelPath::DOWNLOAD.to_path(dirs));
spawn_and_wait(unpack_cmd);
// Rename unpacked dir to the expected name
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(repo_dir);
+ git_commit_cmd
+ .arg("-c")
+ .arg("user.name=Dummy")
+ .arg("-c")
+ .arg("user.email=dummy@example.com")
+ .arg("commit")
+ .arg("-m")
+ .arg("Initial commit")
+ .arg("-q")
+ .current_dir(repo_dir);
spawn_and_wait(git_commit_cmd);
}
-fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
- let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
+fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> {
+ let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs))
.unwrap()
.map(|entry| entry.unwrap().path())
.filter(|path| path.extension() == Some(OsStr::new("patch")))
patches
}
-fn apply_patches(crate_name: &str, target_dir: &Path) {
+fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
if crate_name == "<none>" {
return;
}
- for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+ for patch in get_patches(dirs, crate_name) {
eprintln!(
"[PATCH] {:?} <- {:?}",
target_dir.file_name().unwrap(),
patch.file_name().unwrap()
);
let mut apply_patch_cmd = Command::new("git");
- apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
+ apply_patch_cmd
+ .arg("-c")
+ .arg("user.name=Dummy")
+ .arg("-c")
+ .arg("user.email=dummy@example.com")
+ .arg("am")
+ .arg(patch)
+ .arg("-q")
+ .current_dir(target_dir);
spawn_and_wait(apply_patch_cmd);
}
}
.to_owned()
}
+pub(crate) fn get_cargo_path() -> PathBuf {
+ let cargo_path = Command::new("rustup")
+ .stderr(Stdio::inherit())
+ .args(&["which", "cargo"])
+ .output()
+ .unwrap()
+ .stdout;
+ Path::new(String::from_utf8(cargo_path).unwrap().trim()).to_owned()
+}
+
pub(crate) fn get_rustc_path() -> PathBuf {
let rustc_path = Command::new("rustup")
.stderr(Stdio::inherit())
Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
}
+pub(crate) fn get_rustdoc_path() -> PathBuf {
+ let rustc_path = Command::new("rustup")
+ .stderr(Stdio::inherit())
+ .args(&["which", "rustdoc"])
+ .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())
use super::build_sysroot;
use super::config;
-use super::prepare;
-use super::rustc_info::get_wrapper_file_name;
-use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
-use build_system::SysrootKind;
+use super::path::{Dirs, RelPath};
+use super::prepare::GitRepo;
+use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
+use super::utils::{
+ hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
+};
+use super::SysrootKind;
use std::env;
use std::ffi::OsStr;
use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::Path;
use std::process::Command;
+static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
+
struct TestCase {
config: &'static str,
func: &'static dyn Fn(&TestRunner),
"--crate-type",
"lib,dylib",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
}),
TestCase::new("build.example", &|runner| {
"--crate-type",
"lib",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
}),
TestCase::new("jit.mini_core_hello_world", &|runner| {
"--cfg",
"jit",
"--target",
- &runner.host_triple,
+ &runner.target_compiler.triple,
]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd);
"--cfg",
"jit",
"--target",
- &runner.host_triple,
+ &runner.target_compiler.triple,
]);
jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
spawn_and_wait(jit_cmd);
"bin",
"-g",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
}),
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
}),
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("issue_91827_extern_types", []);
}),
"--crate-type",
"lib",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
}),
TestCase::new("aot.alloc_example", &|runner| {
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("alloc_example", []);
}),
"-Cprefer-dynamic",
"example/std_example.rs",
"--target",
- &runner.host_triple,
+ &runner.target_compiler.triple,
]);
eprintln!("[JIT-lazy] std_example");
"-Cprefer-dynamic",
"example/std_example.rs",
"--target",
- &runner.host_triple,
+ &runner.target_compiler.triple,
]);
}),
TestCase::new("aot.std_example", &|runner| {
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("std_example", ["arg"]);
}),
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("dst_field_align", []);
}),
"bin",
"-Cpanic=abort",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("subslice-patterns-const-eval", []);
}),
"bin",
"-Cpanic=abort",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("track-caller-attribute", []);
}),
"bin",
"-Cpanic=abort",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("float-minmax-pass", []);
}),
"--crate-type",
"bin",
"--target",
- &runner.target_triple,
+ &runner.target_compiler.triple,
]);
runner.run_out_command("mod_bench", []);
}),
+ TestCase::new("aot.issue-72793", &|runner| {
+ runner.run_rustc([
+ "example/issue-72793.rs",
+ "--crate-type",
+ "bin",
+ "--target",
+ &runner.target_compiler.triple,
+ ]);
+ runner.run_out_command("issue-72793", []);
+ }),
];
+pub(crate) static RAND_REPO: GitRepo =
+ GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
+
+pub(crate) static REGEX_REPO: GitRepo =
+ GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex");
+
+pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
+ "rust-lang",
+ "portable-simd",
+ "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+ "portable-simd",
+);
+
+static PORTABLE_SIMD: CargoProject =
+ CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
+
+pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
+ "ebobby",
+ "simple-raytracer",
+ "804a7a21b9e673a482797aa289a18ed480e4d813",
+ "<none>",
+);
+
+pub(crate) static SIMPLE_RAYTRACER: CargoProject =
+ CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
+
+static LIBCORE_TESTS: CargoProject =
+ CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
+
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("test.rust-random/rand", &|runner| {
- runner.in_dir(prepare::RAND.source_dir(), |runner| {
- runner.run_cargo("clean", []);
-
- if runner.host_triple == runner.target_triple {
- eprintln!("[TEST] rust-random/rand");
- runner.run_cargo("test", ["--workspace"]);
- } else {
- eprintln!("[AOT] rust-random/rand");
- runner.run_cargo("build", ["--workspace", "--tests"]);
- }
- });
+ spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+ if runner.is_native {
+ eprintln!("[TEST] rust-random/rand");
+ let mut test_cmd = RAND.test(&runner.target_compiler, &runner.dirs);
+ test_cmd.arg("--workspace");
+ spawn_and_wait(test_cmd);
+ } else {
+ eprintln!("[AOT] rust-random/rand");
+ let mut build_cmd = RAND.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.arg("--workspace").arg("--tests");
+ spawn_and_wait(build_cmd);
+ }
}),
TestCase::new("bench.simple-raytracer", &|runner| {
- runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
- let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
-
- if runner.host_triple == runner.target_triple {
- eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
- let prepare = runner.cargo_command("clean", []);
-
- let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
-
- let cargo_clif = runner
- .root_dir
- .clone()
- .join("build")
- .join(get_wrapper_file_name("cargo-clif", "bin"));
- let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
-
- let bench_compile =
- hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
-
- spawn_and_wait(bench_compile);
-
- eprintln!("[BENCH RUN] ebobby/simple-raytracer");
- fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
- .unwrap();
-
- let bench_run = hyperfine_command(
- 0,
- run_runs,
- None,
- Command::new("./raytracer_cg_llvm"),
- Command::new("./raytracer_cg_clif"),
- );
- spawn_and_wait(bench_run);
- } else {
- runner.run_cargo("clean", []);
- eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
- eprintln!("[COMPILE] ebobby/simple-raytracer");
- runner.run_cargo("build", []);
- eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
- }
- });
+ let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
+
+ if runner.is_native {
+ eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+ let cargo_clif = RelPath::DIST
+ .to_path(&runner.dirs)
+ .join(get_wrapper_file_name("cargo-clif", "bin"));
+ let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
+ let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
+
+ let clean_cmd = format!(
+ "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+ let llvm_build_cmd = format!(
+ "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+ let clif_build_cmd = format!(
+ "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
+ cargo_clif = cargo_clif.display(),
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+
+ let bench_compile =
+ hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
+
+ spawn_and_wait(bench_compile);
+
+ eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+ fs::copy(
+ target_dir.join("debug").join("main"),
+ RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
+ )
+ .unwrap();
+
+ let mut bench_run =
+ hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
+ bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
+ spawn_and_wait(bench_run);
+ } else {
+ spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
+ eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
+ eprintln!("[COMPILE] ebobby/simple-raytracer");
+ spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
+ eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
+ }
}),
TestCase::new("test.libcore", &|runner| {
- runner.in_dir(
- std::env::current_dir()
- .unwrap()
- .join("build_sysroot")
- .join("sysroot_src")
- .join("library")
- .join("core")
- .join("tests"),
- |runner| {
- runner.run_cargo("clean", []);
-
- if runner.host_triple == runner.target_triple {
- runner.run_cargo("test", []);
- } else {
- eprintln!("Cross-Compiling: Not running tests");
- runner.run_cargo("build", ["--tests"]);
- }
- },
- );
+ spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+ if runner.is_native {
+ spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
+ } else {
+ eprintln!("Cross-Compiling: Not running tests");
+ let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.arg("--tests");
+ spawn_and_wait(build_cmd);
+ }
}),
TestCase::new("test.regex-shootout-regex-dna", &|runner| {
- runner.in_dir(prepare::REGEX.source_dir(), |runner| {
- runner.run_cargo("clean", []);
-
- // newer aho_corasick versions throw a deprecation warning
- let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
- let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
- build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
- spawn_and_wait(build_cmd);
-
- if runner.host_triple == runner.target_triple {
- let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
- run_cmd.env("RUSTFLAGS", lint_rust_flags);
-
- let input =
- fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap();
- let expected_path = PathBuf::from("examples/regexdna-output.txt");
- let expected = fs::read_to_string(&expected_path).unwrap();
-
- let output = spawn_and_wait_with_input(run_cmd, input);
- // Make sure `[codegen mono items] start` doesn't poison the diff
- let output = output
- .lines()
- .filter(|line| !line.contains("codegen mono items"))
- .chain(Some("")) // This just adds the trailing newline
- .collect::<Vec<&str>>()
- .join("\r\n");
-
- let output_matches = expected.lines().eq(output.lines());
- if !output_matches {
- let res_path = PathBuf::from("res.txt");
- fs::write(&res_path, &output).unwrap();
-
- if cfg!(windows) {
- println!("Output files don't match!");
- println!("Expected Output:\n{}", expected);
- println!("Actual Output:\n{}", output);
- } else {
- let mut diff = Command::new("diff");
- diff.arg("-u");
- diff.arg(res_path);
- diff.arg(expected_path);
- spawn_and_wait(diff);
- }
-
- std::process::exit(1);
+ spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
+
+ // newer aho_corasick versions throw a deprecation warning
+ let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+ let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.arg("--example").arg("shootout-regex-dna");
+ build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+ spawn_and_wait(build_cmd);
+
+ if runner.is_native {
+ let mut run_cmd = REGEX.run(&runner.target_compiler, &runner.dirs);
+ run_cmd.arg("--example").arg("shootout-regex-dna");
+ run_cmd.env("RUSTFLAGS", lint_rust_flags);
+
+ let input = fs::read_to_string(
+ REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
+ )
+ .unwrap();
+ let expected_path =
+ REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
+ let expected = fs::read_to_string(&expected_path).unwrap();
+
+ let output = spawn_and_wait_with_input(run_cmd, input);
+ // Make sure `[codegen mono items] start` doesn't poison the diff
+ let output = output
+ .lines()
+ .filter(|line| !line.contains("codegen mono items"))
+ .chain(Some("")) // This just adds the trailing newline
+ .collect::<Vec<&str>>()
+ .join("\r\n");
+
+ let output_matches = expected.lines().eq(output.lines());
+ if !output_matches {
+ let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
+ fs::write(&res_path, &output).unwrap();
+
+ if cfg!(windows) {
+ println!("Output files don't match!");
+ println!("Expected Output:\n{}", expected);
+ println!("Actual Output:\n{}", output);
+ } else {
+ let mut diff = Command::new("diff");
+ diff.arg("-u");
+ diff.arg(res_path);
+ diff.arg(expected_path);
+ spawn_and_wait(diff);
}
+
+ std::process::exit(1);
}
- });
+ }
}),
TestCase::new("test.regex", &|runner| {
- runner.in_dir(prepare::REGEX.source_dir(), |runner| {
- runner.run_cargo("clean", []);
-
- // newer aho_corasick versions throw a deprecation warning
- let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
-
- if runner.host_triple == runner.target_triple {
- let mut run_cmd = runner.cargo_command(
- "test",
- [
- "--tests",
- "--",
- "--exclude-should-panic",
- "--test-threads",
- "1",
- "-Zunstable-options",
- "-q",
- ],
- );
- run_cmd.env("RUSTFLAGS", lint_rust_flags);
- spawn_and_wait(run_cmd);
- } else {
- eprintln!("Cross-Compiling: Not running tests");
- let mut build_cmd =
- runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
- build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
- spawn_and_wait(build_cmd);
- }
- });
+ spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
+
+ // newer aho_corasick versions throw a deprecation warning
+ let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
+
+ if runner.is_native {
+ let mut run_cmd = REGEX.test(&runner.target_compiler, &runner.dirs);
+ run_cmd.args([
+ "--tests",
+ "--",
+ "--exclude-should-panic",
+ "--test-threads",
+ "1",
+ "-Zunstable-options",
+ "-q",
+ ]);
+ run_cmd.env("RUSTFLAGS", lint_rust_flags);
+ spawn_and_wait(run_cmd);
+ } else {
+ eprintln!("Cross-Compiling: Not running tests");
+ let mut build_cmd = REGEX.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.arg("--tests");
+ build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
+ spawn_and_wait(build_cmd);
+ }
}),
TestCase::new("test.portable-simd", &|runner| {
- runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
- runner.run_cargo("clean", []);
- runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
+ spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
- if runner.host_triple == runner.target_triple {
- runner.run_cargo("test", ["-q"]);
- }
- });
+ let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
+ build_cmd.arg("--all-targets");
+ spawn_and_wait(build_cmd);
+
+ if runner.is_native {
+ let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
+ test_cmd.arg("-q");
+ spawn_and_wait(test_cmd);
+ }
}),
];
pub(crate) fn run_tests(
+ dirs: &Dirs,
channel: &str,
sysroot_kind: SysrootKind,
- target_dir: &Path,
cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
) {
- let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string());
+ let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
if config::get_bool("testsuite.no_sysroot") {
build_sysroot::build_sysroot(
+ dirs,
channel,
SysrootKind::None,
- &target_dir,
cg_clif_dylib,
&host_triple,
&target_triple,
);
- let _ = fs::remove_dir_all(Path::new("target").join("out"));
+ BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
runner.run_testsuite(NO_SYSROOT_SUITE);
} else {
eprintln!("[SKIP] no_sysroot tests");
if run_base_sysroot || run_extended_sysroot {
build_sysroot::build_sysroot(
+ dirs,
channel,
sysroot_kind,
- &target_dir,
cg_clif_dylib,
&host_triple,
&target_triple,
}
struct TestRunner {
- root_dir: PathBuf,
- out_dir: PathBuf,
+ is_native: bool,
jit_supported: bool,
- rust_flags: String,
- run_wrapper: Vec<String>,
- host_triple: String,
- target_triple: String,
+ dirs: Dirs,
+ host_compiler: Compiler,
+ target_compiler: Compiler,
}
impl TestRunner {
- pub fn new(host_triple: String, target_triple: String) -> Self {
- let root_dir = env::current_dir().unwrap();
-
- let mut out_dir = root_dir.clone();
- out_dir.push("target");
- out_dir.push("out");
-
+ pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
let is_native = host_triple == target_triple;
let jit_supported =
target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
- let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
- let mut run_wrapper = Vec::new();
+ let rustc_clif =
+ RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
+ let rustdoc_clif =
+ RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
+
+ let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
+ let mut runner = vec![];
if !is_native {
match target_triple.as_str() {
"aarch64-unknown-linux-gnu" => {
// We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
- rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags);
- run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"];
+ rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
+ runner = vec![
+ "qemu-aarch64".to_owned(),
+ "-L".to_owned(),
+ "/usr/aarch64-linux-gnu".to_owned(),
+ ];
+ }
+ "s390x-unknown-linux-gnu" => {
+ // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
+ rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
+ runner = vec![
+ "qemu-s390x".to_owned(),
+ "-L".to_owned(),
+ "/usr/s390x-linux-gnu".to_owned(),
+ ];
}
"x86_64-pc-windows-gnu" => {
// We are cross-compiling for Windows. Run tests in wine.
- run_wrapper = vec!["wine"];
+ runner = vec!["wine".to_owned()];
}
_ => {
println!("Unknown non-native platform");
}
// FIXME fix `#[linkage = "extern_weak"]` without this
- if host_triple.contains("darwin") {
- rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags);
+ if target_triple.contains("darwin") {
+ rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
}
- Self {
- root_dir,
- out_dir,
- jit_supported,
- rust_flags,
- run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(),
- host_triple,
- target_triple,
- }
+ let host_compiler = Compiler {
+ cargo: get_cargo_path(),
+ rustc: rustc_clif.clone(),
+ rustdoc: rustdoc_clif.clone(),
+ rustflags: String::new(),
+ rustdocflags: String::new(),
+ triple: host_triple,
+ runner: vec![],
+ };
+
+ let target_compiler = Compiler {
+ cargo: get_cargo_path(),
+ rustc: rustc_clif,
+ rustdoc: rustdoc_clif,
+ rustflags: rustflags.clone(),
+ rustdocflags: rustflags,
+ triple: target_triple,
+ runner,
+ };
+
+ Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
}
pub fn run_testsuite(&self, tests: &[TestCase]) {
}
}
- fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
- let current = env::current_dir().unwrap();
-
- env::set_current_dir(new).unwrap();
- callback(self);
- env::set_current_dir(current).unwrap();
- }
-
+ #[must_use]
fn rustc_command<I, S>(&self, args: I) -> Command
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
- let mut rustc_clif = self.root_dir.clone();
- rustc_clif.push("build");
- rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin"));
-
- let mut cmd = Command::new(rustc_clif);
- cmd.args(self.rust_flags.split_whitespace());
+ let mut cmd = Command::new(&self.target_compiler.rustc);
+ cmd.args(self.target_compiler.rustflags.split_whitespace());
cmd.arg("-L");
- cmd.arg(format!("crate={}", self.out_dir.display()));
+ cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("--out-dir");
- cmd.arg(format!("{}", self.out_dir.display()));
+ cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("-Cdebuginfo=2");
cmd.args(args);
cmd
let mut full_cmd = vec![];
// Prepend the RUN_WRAPPER's
- if !self.run_wrapper.is_empty() {
- full_cmd.extend(self.run_wrapper.iter().cloned());
+ if !self.target_compiler.runner.is_empty() {
+ full_cmd.extend(self.target_compiler.runner.iter().cloned());
}
- full_cmd.push({
- let mut out_path = self.out_dir.clone();
- out_path.push(name);
- out_path.to_str().unwrap().to_string()
- });
+ full_cmd.push(
+ BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
+ );
for arg in args.into_iter() {
full_cmd.push(arg.to_string());
spawn_and_wait(cmd);
}
-
- fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
- where
- I: IntoIterator<Item = &'a str>,
- {
- let mut cargo_clif = self.root_dir.clone();
- cargo_clif.push("build");
- cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
-
- let mut cmd = cargo_command(
- cargo_clif,
- subcommand,
- if subcommand == "clean" { None } else { Some(&self.target_triple) },
- Path::new("."),
- );
- cmd.args(args);
- cmd.env("RUSTFLAGS", &self.rust_flags);
- cmd
- }
-
- fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
- where
- I: IntoIterator<Item = &'a str>,
- {
- spawn_and_wait(self.cargo_command(subcommand, args));
- }
}
use std::env;
use std::fs;
use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
-pub(crate) fn cargo_command(
- cargo: impl AsRef<Path>,
- subcommand: &str,
- triple: Option<&str>,
- source_dir: &Path,
-) -> Command {
- let mut cmd = Command::new(cargo.as_ref());
- cmd.arg(subcommand)
- .arg("--manifest-path")
- .arg(source_dir.join("Cargo.toml"))
- .arg("--target-dir")
- .arg(source_dir.join("target"));
+use super::path::{Dirs, RelPath};
+use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
+
+pub(crate) struct Compiler {
+ pub(crate) cargo: PathBuf,
+ pub(crate) rustc: PathBuf,
+ pub(crate) rustdoc: PathBuf,
+ pub(crate) rustflags: String,
+ pub(crate) rustdocflags: String,
+ pub(crate) triple: String,
+ pub(crate) runner: Vec<String>,
+}
+
+impl Compiler {
+ pub(crate) fn host() -> Compiler {
+ Compiler {
+ cargo: get_cargo_path(),
+ rustc: get_rustc_path(),
+ rustdoc: get_rustdoc_path(),
+ rustflags: String::new(),
+ rustdocflags: String::new(),
+ triple: get_host_triple(),
+ runner: vec![],
+ }
+ }
+
+ pub(crate) fn with_triple(triple: String) -> Compiler {
+ Compiler {
+ cargo: get_cargo_path(),
+ rustc: get_rustc_path(),
+ rustdoc: get_rustdoc_path(),
+ rustflags: String::new(),
+ rustdocflags: String::new(),
+ triple,
+ runner: vec![],
+ }
+ }
+}
+
+pub(crate) struct CargoProject {
+ source: &'static RelPath,
+ target: &'static str,
+}
+
+impl CargoProject {
+ pub(crate) const fn new(path: &'static RelPath, target: &'static str) -> CargoProject {
+ CargoProject { source: path, target }
+ }
+
+ pub(crate) fn source_dir(&self, dirs: &Dirs) -> PathBuf {
+ self.source.to_path(dirs)
+ }
+
+ pub(crate) fn manifest_path(&self, dirs: &Dirs) -> PathBuf {
+ self.source_dir(dirs).join("Cargo.toml")
+ }
+
+ pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf {
+ RelPath::BUILD.join(self.target).to_path(dirs)
+ }
- if let Some(triple) = triple {
- cmd.arg("--target").arg(triple);
+ fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
+ let mut cmd = Command::new(cargo);
+
+ cmd.arg(command)
+ .arg("--manifest-path")
+ .arg(self.manifest_path(dirs))
+ .arg("--target-dir")
+ .arg(self.target_dir(dirs));
+
+ cmd
+ }
+
+ fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
+ let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
+
+ cmd.arg("--target").arg(&compiler.triple);
+
+ cmd.env("RUSTC", &compiler.rustc);
+ cmd.env("RUSTDOC", &compiler.rustdoc);
+ cmd.env("RUSTFLAGS", &compiler.rustflags);
+ cmd.env("RUSTDOCFLAGS", &compiler.rustdocflags);
+ if !compiler.runner.is_empty() {
+ cmd.env(
+ format!("CARGO_TARGET_{}_RUNNER", compiler.triple.to_uppercase().replace('-', "_")),
+ compiler.runner.join(" "),
+ );
+ }
+
+ cmd
}
- cmd
+ #[must_use]
+ pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
+ let mut cmd = Command::new(cargo.as_ref());
+
+ cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
+
+ cmd
+ }
+
+ #[must_use]
+ pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
+ self.base_cmd("clean", cargo, dirs)
+ }
+
+ #[must_use]
+ pub(crate) fn build(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+ self.build_cmd("build", compiler, dirs)
+ }
+
+ #[must_use]
+ pub(crate) fn test(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+ self.build_cmd("test", compiler, dirs)
+ }
+
+ #[must_use]
+ pub(crate) fn run(&self, compiler: &Compiler, dirs: &Dirs) -> Command {
+ self.build_cmd("run", compiler, dirs)
+ }
}
+#[must_use]
pub(crate) fn hyperfine_command(
warmup: u64,
runs: u64,
- prepare: Option<Command>,
- a: Command,
- b: Command,
+ prepare: Option<&str>,
+ a: &str,
+ b: &str,
) -> Command {
let mut bench = Command::new("hyperfine");
}
if let Some(prepare) = prepare {
- bench.arg("--prepare").arg(format!("{:?}", prepare));
+ bench.arg("--prepare").arg(prepare);
}
- bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+ bench.arg(a).arg(b);
bench
}
set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
-rm -rf target/ build/ perf.data{,.old} y.bin
+rm -rf target/ build/ dist/ perf.data{,.old} y.bin
rm -rf download/
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
aot.track-caller-attribute
aot.float-minmax-pass
aot.mod_bench
+aot.issue-72793
testsuite.extended_sysroot
test.rust-random/rand
In the directory with your project (where you can do the usual `cargo build`), run:
```bash
-$ $cg_clif_dir/build/cargo-clif build
+$ $cg_clif_dir/dist/cargo-clif build
```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
> You should prefer using the Cargo method.
```bash
-$ $cg_clif_dir/build/rustc-clif my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif my_crate.rs
```
## Jit mode
> The jit mode will probably need cargo integration to make this possible.
```bash
-$ $cg_clif_dir/build/cargo-clif jit
+$ $cg_clif_dir/dist/cargo-clif jit
```
or
```bash
-$ $cg_clif_dir/build/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
+$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
```
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
first called.
```bash
-$ $cg_clif_dir/build/cargo-clif lazy-jit
+$ $cg_clif_dir/dist/cargo-clif lazy-jit
```
## Shell
```bash
function jit_naked() {
- echo "$@" | $cg_clif_dir/build/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
+ echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic
}
function jit() {
--- /dev/null
+// Adapted from rustc ui test suite (ui/type-alias-impl-trait/issue-72793.rs)
+
+#![feature(type_alias_impl_trait)]
+
+trait T { type Item; }
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+ type Item = &'a ();
+}
+
+fn filter_positive<'a>() -> Alias<'a> {
+ &S
+}
+
+fn with_positive(fun: impl Fn(Alias<'_>)) {
+ fun(filter_positive());
+}
+
+fn main() {
+ with_positive(|_| ());
+}
#[lang = "destruct"]
pub trait Destruct {}
+#[lang = "tuple_trait"]
+pub trait Tuple {}
+
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "fn_once"]
#[rustc_paren_sugar]
-pub trait FnOnce<Args> {
+pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
#[lang = "fn_mut"]
#[rustc_paren_sugar]
-pub trait FnMut<Args>: FnOnce<Args> {
+pub trait FnMut<Args: Tuple>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
assert_eq!(slice_ptr as usize % 4, 0);
- //return;
-
unsafe {
printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
let cmp_eq = _mm_cmpeq_epi8(y, y);
let cmp_lt = _mm_cmplt_epi8(y, y);
+ let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
+ assert_eq!((zero0, zero1), (0, 0));
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]);
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
[toolchain]
-channel = "nightly-2022-10-23"
+channel = "nightly-2022-12-13"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
+ignore = ["y.rs"]
+
# Matches rustfmt.toml of rustc
version = "Two"
use_small_heuristics = "Max"
#![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc
pushd $(dirname "$0")/../
-RUSTC="$(pwd)/build/rustc-clif"
+RUSTC="$(pwd)/dist/rustc-clif"
popd
PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/
--- /dev/null
+use std::env;
+use std::ffi::OsString;
+#[cfg(unix)]
+use std::os::unix::process::CommandExt;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+ let sysroot = PathBuf::from(env::current_exe().unwrap().parent().unwrap());
+
+ let cg_clif_dylib_path = sysroot.join(if cfg!(windows) { "bin" } else { "lib" }).join(
+ env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
+ );
+
+ let mut args = std::env::args_os().skip(1).collect::<Vec<_>>();
+ args.push(OsString::from("-Cpanic=abort"));
+ args.push(OsString::from("-Zpanic-abort-tests"));
+ let mut codegen_backend_arg = OsString::from("-Zcodegen-backend=");
+ codegen_backend_arg.push(cg_clif_dylib_path);
+ args.push(codegen_backend_arg);
+ if !args.contains(&OsString::from("--sysroot")) {
+ args.push(OsString::from("--sysroot"));
+ args.push(OsString::from(sysroot.to_str().unwrap()));
+ }
+
+ // Ensure that the right toolchain is used
+ env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+
+ #[cfg(unix)]
+ Command::new("rustdoc").args(args).exec();
+
+ #[cfg(not(unix))]
+ std::process::exit(
+ Command::new("rustdoc").args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
+ );
+}
[dev-dependencies]
rand = "0.7"
rand_xorshift = "0.2"
-diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
-index 8431aa7b818..a3ff7e68ce5 100644
---- a/src/tools/compiletest/src/runtest.rs
-+++ b/src/tools/compiletest/src/runtest.rs
-@@ -3489,12 +3489,7 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
- let compiler_src_dir = base_dir.join("compiler");
- normalize_path(&compiler_src_dir, "$(echo '$COMPILER_DIR')");
-
-- if let Some(virtual_rust_source_base_dir) =
-- option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from)
-- {
-- normalize_path(&virtual_rust_source_base_dir.join("library"), "$(echo '$SRC_DIR')");
-- normalize_path(&virtual_rust_source_base_dir.join("compiler"), "$(echo '$COMPILER_DIR')");
-- }
-+ normalize_path(&Path::new("$(cd ../build_sysroot/sysroot_src/library; pwd)"), "$(echo '$SRC_DIR')");
-
- // Paths into the build directory
- let test_build_dir = &self.config.build_base;
EOF
cat > config.toml <<EOF
ninja = false
[build]
-rustc = "$(pwd)/../build/rustc-clif"
+rustc = "$(pwd)/../dist/rustc-clif"
cargo = "$(rustup which cargo)"
full-bootstrap = true
local-rebuild = true
# FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
+export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
+
# Allow the testsuite to use llvm tools
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
done
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
+git checkout -- src/test/ui/proc-macro/pretty-print-hack/
# missing features
# ================
# requires compiling with -Cpanic=unwind
rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
+rm -r src/test/run-make/test-benches
# vendor intrinsics
rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
rm -r src/test/run-make/emit-named-files # requires full --emit support
rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
+rm -r src/test/run-make/repr128-dwarf # debuginfo test
+rm src/test/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
# optimization tests
# ==================
rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
rm src/test/ui/consts/issue-33537.rs # same
+rm src/test/ui/layout/valid_range_oob.rs # different ICE message
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
# ============================================================
-rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/
+rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/
rm -r src/test/run-make/unstable-flag-required # same
rm -r src/test/run-make/rustdoc-* # same
rm -r src/test/run-make/issue-88756-default-output # same
rm -r src/test/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
+rm -r src/test/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
# genuine bugs
# ============
-rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
-
rm src/test/incremental/spike-neg1.rs # errors out for some reason
rm src/test/incremental/spike-neg2.rs # same
rm src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
+rm src/test/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
+
# bugs in the test suite
# ======================
rm src/test/ui/backtrace.rs # TODO warning
rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
# not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
rm -r src/test/run-make/native-link-modifier-bundle
+rm src/test/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm src/test/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
pub(crate) fn get_function_sig<'tcx>(
tcx: TyCtxt<'tcx>,
- triple: &target_lexicon::Triple,
+ default_call_conv: CallConv,
inst: Instance<'tcx>,
) -> Signature {
assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi(
tcx,
- CallConv::triple_default(triple),
+ default_call_conv,
&RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
)
}
inst: Instance<'tcx>,
) -> FuncId {
let name = tcx.symbol_name(inst).name;
- let sig = get_function_sig(tcx, module.isa().triple(), inst);
+ let sig = get_function_sig(tcx, module.target_config().default_call_conv, inst);
match module.declare_function(name, Linkage::Import, &sig) {
Ok(func_id) => func_id,
Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
destination: Place<'tcx>,
target: Option<BasicBlock>,
) {
- let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
- let fn_sig =
- fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
+ let func = codegen_operand(fx, func);
+ let fn_sig = func.layout().ty.fn_sig(fx.tcx);
let ret_place = codegen_place(fx, destination);
// Handle special calls like intrinsics and empty drop glue.
- let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
- let instance = ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
- .unwrap()
- .unwrap()
- .polymorphize(fx.tcx);
+ let instance = if let ty::FnDef(def_id, substs) = *func.layout().ty.kind() {
+ let instance =
+ ty::Instance::expect_resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+ .polymorphize(fx.tcx);
if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
crate::intrinsics::codegen_llvm_intrinsic_call(
None
};
- let extra_args = &args[fn_sig.inputs().len()..];
+ let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
let extra_args = fx
.tcx
.mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
let fn_abi = if let Some(instance) = instance {
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} else {
- RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args)
};
- let is_cold = if fn_sig.abi == Abi::RustCold {
+ let is_cold = if fn_sig.abi() == Abi::RustCold {
true
} else {
instance
}
// Unpack arguments tuple for closures
- let mut args = if fn_sig.abi == Abi::RustCall {
+ let mut args = if fn_sig.abi() == Abi::RustCall {
assert_eq!(args.len(), 2, "rust-call abi requires two arguments");
let self_arg = codegen_call_argument_operand(fx, &args[0]);
let pack_arg = codegen_call_argument_operand(fx, &args[1]);
fx.add_comment(nop_inst, "indirect call");
}
- let func = codegen_operand(fx, func).load_scalar(fx);
+ let func = func.load_scalar(fx);
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = fx.bcx.import_signature(sig);
};
// FIXME find a cleaner way to support varargs
- if fn_sig.c_variadic {
- if !matches!(fn_sig.abi, Abi::C { .. }) {
+ if fn_sig.c_variadic() {
+ if !matches!(fn_sig.abi(), Abi::C { .. }) {
fx.tcx.sess.span_fatal(
source_info.span,
- &format!("Variadic call for non-C abi {:?}", fn_sig.abi),
+ &format!("Variadic call for non-C abi {:?}", fn_sig.abi()),
);
}
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
};
let sig = Signature {
- call_conv: CallConv::triple_default(module.isa().triple()),
+ call_conv: module.target_config().default_call_conv,
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
returns: output.into_iter().map(AbiParam::new).collect(),
};
}
let sig = Signature {
- call_conv: CallConv::triple_default(module.isa().triple()),
+ call_conv: module.target_config().default_call_conv,
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
returns: vec![],
};
// Declare function
let symbol_name = tcx.symbol_name(instance).name.to_string();
- let sig = get_function_sig(tcx, module.isa().triple(), instance);
+ let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
// Make the FunctionBuilder
}
}
- TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
- let discr = codegen_operand(fx, discr).load_scalar(fx);
+ TerminatorKind::SwitchInt { discr, targets } => {
+ let discr = codegen_operand(fx, discr);
+ let switch_ty = discr.layout().ty;
+ let discr = discr.load_scalar(fx);
let use_bool_opt = switch_ty.kind() == fx.tcx.types.bool.kind()
|| (targets.iter().count() == 1 && targets.iter().next().unwrap().0 == 0);
_ => unreachable!("{:?}", targets),
};
- let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
let (discr, is_inverted) =
crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
let test_zero = if is_inverted { !test_zero } else { test_zero };
- let discr = crate::optimize::peephole::maybe_unwrap_bint(&mut fx.bcx, discr);
if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
&fx.bcx, discr, test_zero,
) {
UnOp::Not => match layout.ty.kind() {
ty::Bool => {
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
- CValue::by_val(fx.bcx.ins().bint(types::I8, res), layout)
+ CValue::by_val(res, layout)
}
ty::Uint(_) | ty::Int(_) => {
CValue::by_val(fx.bcx.ins().bnot(val), layout)
_ => unreachable!("un op Not for {:?}", layout.ty),
},
UnOp::Neg => match layout.ty.kind() {
- ty::Int(IntTy::I128) => {
- // FIXME remove this case once ineg.i128 works
- let zero =
- CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
- crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
- }
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
_ => unreachable!("un op Neg for {:?}", layout.ty),
}
let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
- let zero = fx.bcx.ins().iconst(to_ty, 0);
+ let zero = type_zero_value(&mut fx.bcx, to_ty);
fx.bcx.ins().select(is_not_nan, val, zero)
} else if from_ty.is_float() && to_ty.is_float() {
// float -> float
}
}
} else {
- let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
+ let rhs = rhs as i64; // Truncates on purpose in case rhs is actually an unsigned value
fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
}
}
+pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
+ if ty == types::I128 {
+ let zero = bcx.ins().iconst(types::I64, 0);
+ bcx.ins().iconcat(zero, zero)
+ } else {
+ bcx.ins().iconst(ty, 0)
+ }
+}
+
pub(crate) fn type_min_max_value(
bcx: &mut FunctionBuilder<'_>,
ty: Type,
}
pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
- //println!("todo {:?}", self.todo);
define_all_allocs(tcx, module, &mut self);
- //println!("done {:?}", self.done);
self.done.clear();
}
}
def_id: DefId,
definition: bool,
) -> DataId {
- let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
- let linkage = if definition {
- crate::linkage::get_static_linkage(tcx, def_id)
- } else if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
- || rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
- {
- Linkage::Preemptible
- } else {
- Linkage::Import
- };
+ let attrs = tcx.codegen_fn_attrs(def_id);
let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
let symbol_name = tcx.symbol_name(instance).name;
};
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
- let attrs = tcx.codegen_fn_attrs(def_id);
+ if let Some(import_linkage) = attrs.import_linkage {
+ assert!(!definition);
- let data_id = match module.declare_data(
- &*symbol_name,
- linkage,
- is_mutable,
- attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
- ) {
- Ok(data_id) => data_id,
- Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
- "attempt to declare `{symbol_name}` as static, but it was already declared as function"
- )),
- Err(err) => Err::<_, _>(err).unwrap(),
- };
+ let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
+ || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
+ {
+ Linkage::Preemptible
+ } else {
+ Linkage::Import
+ };
+
+ let data_id = match module.declare_data(
+ &*symbol_name,
+ linkage,
+ is_mutable,
+ attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+ ) {
+ Ok(data_id) => data_id,
+ Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+ "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+ )),
+ Err(err) => Err::<_, _>(err).unwrap(),
+ };
- if rlinkage.is_some() {
// Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
// Declare an internal global `extern_with_linkage_foo` which
// is initialized with the address of `foo`. If `foo` is
Err(ModuleError::DuplicateDefinition(_)) => {}
res => res.unwrap(),
}
- ref_data_id
- } else {
- data_id
+
+ return ref_data_id;
}
+
+ let linkage = if definition {
+ crate::linkage::get_static_linkage(tcx, def_id)
+ } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
+ || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
+ {
+ Linkage::Preemptible
+ } else {
+ Linkage::Import
+ };
+
+ let data_id = match module.declare_data(
+ &*symbol_name,
+ linkage,
+ is_mutable,
+ attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL),
+ ) {
+ Ok(data_id) => data_id,
+ Err(ModuleError::IncompatibleDeclaration(_)) => tcx.sess.fatal(&format!(
+ "attempt to declare `{symbol_name}` as static, but it was already declared as function"
+ )),
+ Err(err) => Err::<_, _>(err).unwrap(),
+ };
+
+ data_id
}
fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
(data_id, alloc, None)
}
TodoItem::Static(def_id) => {
- //println!("static {:?}", def_id);
-
let section_name = tcx.codegen_fn_attrs(def_id).link_section;
let alloc = tcx.eval_static_initializer(def_id).unwrap();
}
};
- //("data_id {}", data_id);
if cx.done.contains(&data_id) {
continue;
}
}
pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) {
- let unwind_info = if let Some(unwind_info) = context.create_unwind_info(isa).unwrap() {
+ let unwind_info = if let Some(unwind_info) =
+ context.compiled_code().unwrap().create_unwind_info(isa).unwrap()
+ {
unwind_info
} else {
return;
//! Handling of enum discriminants
//!
-//! Adapted from <https://github.com/rust-lang/rust/blob/d760df5aea483aae041c9a241e7acacf48f75035/src/librustc_codegen_ssa/mir/place.rs>
+//! Adapted from <https://github.com/rust-lang/rust/blob/31c0645b9d2539f47eecb096142474b29dc542f7/compiler/rustc_codegen_ssa/src/mir/place.rs>
+//! (<https://github.com/rust-lang/rust/pull/104535>)
use rustc_target::abi::{Int, TagEncoding, Variants};
} => {
if variant_index != untagged_variant {
let niche = place.place_field(fx, mir::Field::new(tag_field));
+ let niche_type = fx.clif_type(niche.layout().ty).unwrap();
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
- let niche_value = ty::ScalarInt::try_from_uint(
- u128::from(niche_value).wrapping_add(niche_start),
- niche.layout().size,
- )
- .unwrap();
- let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
+ let niche_value = (niche_value as u128).wrapping_add(niche_start);
+ let niche_value = match niche_type {
+ types::I128 => {
+ let lsb = fx.bcx.ins().iconst(types::I64, niche_value as u64 as i64);
+ let msb =
+ fx.bcx.ins().iconst(types::I64, (niche_value >> 64) as u64 as i64);
+ fx.bcx.ins().iconcat(lsb, msb)
+ }
+ ty => fx.bcx.ins().iconst(ty, niche_value as i64),
+ };
+ let niche_llval = CValue::by_val(niche_value, niche.layout());
niche.write_cvalue(fx, niche_llval);
}
}
}
};
+ let cast_to_size = dest_layout.layout.size();
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
// Read the tag/niche-encoded discriminant from memory.
dest.write_cvalue(fx, res);
}
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
- // Rebase from niche values to discriminants, and check
- // whether the result is in range for the niche variants.
-
- // We first compute the "relative discriminant" (wrt `niche_variants`),
- // that is, if `n = niche_variants.end() - niche_variants.start()`,
- // we remap `niche_start..=niche_start + n` (which may wrap around)
- // to (non-wrap-around) `0..=n`, to be able to check whether the
- // discriminant corresponds to a niche variant with one comparison.
- // We also can't go directly to the (variant index) discriminant
- // and check that it is in the range `niche_variants`, because
- // that might not fit in the same type, on top of needing an extra
- // comparison (see also the comment on `let niche_discr`).
- let relative_discr = if niche_start == 0 {
- tag
+ let tag_size = tag_scalar.size(fx);
+ let max_unsigned = tag_size.unsigned_int_max();
+ let max_signed = tag_size.signed_int_max() as u128;
+ let min_signed = max_signed + 1;
+ let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+ let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned;
+ let range = tag_scalar.valid_range(fx);
+
+ let sle = |lhs: u128, rhs: u128| -> bool {
+ // Signed and unsigned comparisons give the same results,
+ // except that in signed comparisons an integer with the
+ // sign bit set is less than one with the sign bit clear.
+ // Toggle the sign bit to do a signed comparison.
+ (lhs ^ min_signed) <= (rhs ^ min_signed)
+ };
+
+ // We have a subrange `niche_start..=niche_end` inside `range`.
+ // If the value of the tag is inside this subrange, it's a
+ // "niche value", an increment of the discriminant. Otherwise it
+ // indicates the untagged variant.
+ // A general algorithm to extract the discriminant from the tag
+ // is:
+ // relative_tag = tag - niche_start
+ // is_niche = relative_tag <= (ule) relative_max
+ // discr = if is_niche {
+ // cast(relative_tag) + niche_variants.start()
+ // } else {
+ // untagged_variant
+ // }
+ // However, we will likely be able to emit simpler code.
+
+ // Find the least and greatest values in `range`, considered
+ // both as signed and unsigned.
+ let (low_unsigned, high_unsigned) =
+ if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) };
+ let (low_signed, high_signed) = if sle(range.start, range.end) {
+ (range.start, range.end)
} else {
+ (min_signed, max_signed)
+ };
+
+ let niches_ule = niche_start <= niche_end;
+ let niches_sle = sle(niche_start, niche_end);
+ let cast_smaller = cast_to_size <= tag_size;
+
+ // In the algorithm above, we can change
+ // cast(relative_tag) + niche_variants.start()
+ // into
+ // cast(tag + (niche_variants.start() - niche_start))
+ // if either the casted type is no larger than the original
+ // type, or if the niche values are contiguous (in either the
+ // signed or unsigned sense).
+ let can_incr = cast_smaller || niches_ule || niches_sle;
+
+ let data_for_boundary_niche = || -> Option<(IntCC, u128)> {
+ if !can_incr {
+ None
+ } else if niche_start == low_unsigned {
+ Some((IntCC::UnsignedLessThanOrEqual, niche_end))
+ } else if niche_end == high_unsigned {
+ Some((IntCC::UnsignedGreaterThanOrEqual, niche_start))
+ } else if niche_start == low_signed {
+ Some((IntCC::SignedLessThanOrEqual, niche_end))
+ } else if niche_end == high_signed {
+ Some((IntCC::SignedGreaterThanOrEqual, niche_start))
+ } else {
+ None
+ }
+ };
+
+ let (is_niche, tagged_discr, delta) = if relative_max == 0 {
+ // Best case scenario: only one tagged variant. This will
+ // likely become just a comparison and a jump.
+ // The algorithm is:
+ // is_niche = tag == niche_start
+ // discr = if is_niche {
+ // niche_start
+ // } else {
+ // untagged_variant
+ // }
+ let is_niche = codegen_icmp_imm(fx, IntCC::Equal, tag, niche_start as i128);
+ let tagged_discr =
+ fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64);
+ (is_niche, tagged_discr, 0)
+ } else if let Some((predicate, constant)) = data_for_boundary_niche() {
+ // The niche values are either the lowest or the highest in
+ // `range`. We can avoid the first subtraction in the
+ // algorithm.
+ // The algorithm is now this:
+ // is_niche = tag <= niche_end
+ // discr = if is_niche {
+ // cast(tag + (niche_variants.start() - niche_start))
+ // } else {
+ // untagged_variant
+ // }
+ // (the first line may instead be tag >= niche_start,
+ // and may be a signed or unsigned comparison)
+ // The arithmetic must be done before the cast, so we can
+ // have the correct wrapping behavior. See issue #104519 for
+ // the consequences of getting this wrong.
+ let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128);
+ let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start);
+ let incr_tag = if delta == 0 {
+ tag
+ } else {
+ let delta = match fx.bcx.func.dfg.value_type(tag) {
+ types::I128 => {
+ let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+ let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+ fx.bcx.ins().iconcat(lsb, msb)
+ }
+ ty => fx.bcx.ins().iconst(ty, delta as i64),
+ };
+ fx.bcx.ins().iadd(tag, delta)
+ };
+
+ let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule);
+
+ (is_niche, cast_tag, 0)
+ } else {
+ // The special cases don't apply, so we'll have to go with
+ // the general algorithm.
let niche_start = match fx.bcx.func.dfg.value_type(tag) {
types::I128 => {
let lsb = fx.bcx.ins().iconst(types::I64, niche_start as u64 as i64);
}
ty => fx.bcx.ins().iconst(ty, niche_start as i64),
};
- fx.bcx.ins().isub(tag, niche_start)
- };
- let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
- let is_niche = {
- codegen_icmp_imm(
+ let relative_discr = fx.bcx.ins().isub(tag, niche_start);
+ let cast_tag = clif_intcast(fx, relative_discr, cast_to, false);
+ let is_niche = crate::common::codegen_icmp_imm(
fx,
IntCC::UnsignedLessThanOrEqual,
relative_discr,
i128::from(relative_max),
- )
+ );
+ (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
};
- // NOTE(eddyb) this addition needs to be performed on the final
- // type, in case the niche itself can't represent all variant
- // indices (e.g. `u8` niche with more than `256` variants,
- // but enough uninhabited variants so that the remaining variants
- // fit in the niche).
- // In other words, `niche_variants.end - niche_variants.start`
- // is representable in the niche, but `niche_variants.end`
- // might not be, in extreme cases.
- let niche_discr = {
- let relative_discr = if relative_max == 0 {
- // HACK(eddyb) since we have only one niche, we know which
- // one it is, and we can avoid having a dynamic value here.
- fx.bcx.ins().iconst(cast_to, 0)
- } else {
- clif_intcast(fx, relative_discr, cast_to, false)
+ let tagged_discr = if delta == 0 {
+ tagged_discr
+ } else {
+ let delta = match cast_to {
+ types::I128 => {
+ let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64);
+ let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64);
+ fx.bcx.ins().iconcat(lsb, msb)
+ }
+ ty => fx.bcx.ins().iconst(ty, delta as i64),
};
- fx.bcx.ins().iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
+ fx.bcx.ins().iadd(tagged_discr, delta)
};
- let untagged_variant =
- fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()));
- let discr = fx.bcx.ins().select(is_niche, niche_discr, untagged_variant);
+ let untagged_variant = if cast_to == types::I128 {
+ let zero = fx.bcx.ins().iconst(types::I64, 0);
+ let untagged_variant =
+ fx.bcx.ins().iconst(types::I64, i64::from(untagged_variant.as_u32()));
+ fx.bcx.ins().iconcat(untagged_variant, zero)
+ } else {
+ fx.bcx.ins().iconst(cast_to, i64::from(untagged_variant.as_u32()))
+ };
+ let discr = fx.bcx.ins().select(is_niche, tagged_discr, untagged_variant);
let res = CValue::by_val(discr, dest_layout);
dest.write_cvalue(fx, res);
}
tcx.sess.abort_if_errors();
- jit_module.finalize_definitions();
+ jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) };
println!(
let backend_config = lazy_jit_state.backend_config.clone();
let name = tcx.symbol_name(instance).name;
- let sig = crate::abi::get_function_sig(tcx, jit_module.isa().triple(), instance);
+ let sig = crate::abi::get_function_sig(
+ tcx,
+ jit_module.target_config().default_call_conv,
+ instance,
+ );
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
let current_ptr = jit_module.read_got_entry(func_id);
});
assert!(cx.global_asm.is_empty());
- jit_module.finalize_definitions();
+ jit_module.finalize_definitions().unwrap();
unsafe { cx.unwind_context.register_jit(&jit_module) };
jit_module.get_finalized_function(func_id)
})
let pointer_type = module.target_config().pointer_type();
let name = tcx.symbol_name(inst).name;
- let sig = crate::abi::get_function_sig(tcx, module.isa().triple(), inst);
+ let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
let instance_ptr = Box::into_raw(Box::new(inst));
MonoItem::Fn(instance) => {
let name = tcx.symbol_name(instance).name;
let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
- let sig = get_function_sig(tcx, module.isa().triple(), instance);
+ let sig =
+ get_function_sig(tcx, module.target_config().default_call_conv, instance);
let linkage = crate::linkage::get_clif_linkage(
mono_item,
linkage,
pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: &str,
- _substs: SubstsRef<'tcx>,
+ substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>,
target: Option<BasicBlock>,
) {
- match intrinsic {
- "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
- // Spin loop hint
- }
+ if intrinsic.starts_with("llvm.aarch64") {
+ return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
+ fx, intrinsic, substs, args, ret, target,
+ );
+ }
+ if intrinsic.starts_with("llvm.x86") {
+ return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
+ }
- // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
- "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+ match intrinsic {
+ _ if intrinsic.starts_with("llvm.ctlz.v") => {
intrinsic_args!(fx, args => (a); intrinsic);
- let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
- let lane_ty = fx.clif_type(lane_ty).unwrap();
- assert!(lane_count <= 32);
-
- let mut res = fx.bcx.ins().iconst(types::I32, 0);
-
- for lane in (0..lane_count).rev() {
- let a_lane = a.value_lane(fx, lane).load_scalar(fx);
-
- // cast float to int
- let a_lane = match lane_ty {
- types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
- types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
- _ => a_lane,
- };
-
- // extract sign bit of an int
- let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
-
- // shift sign bit into result
- let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
- res = fx.bcx.ins().ishl_imm(res, 1);
- res = fx.bcx.ins().bor(res, a_lane_sign);
- }
-
- let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
- ret.write_cvalue(fx, res);
- }
- "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
- let (x, y, kind) = match args {
- [x, y, kind] => (x, y, kind),
- _ => bug!("wrong number of args for intrinsic {intrinsic}"),
- };
- let x = codegen_operand(fx, x);
- let y = codegen_operand(fx, y);
- let kind = crate::constant::mir_operand_get_const_val(fx, kind)
- .expect("llvm.x86.sse2.cmp.* kind not const");
-
- let flt_cc = match kind
- .try_to_bits(Size::from_bytes(1))
- .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
- {
- 0 => FloatCC::Equal,
- 1 => FloatCC::LessThan,
- 2 => FloatCC::LessThanOrEqual,
- 7 => FloatCC::Ordered,
- 3 => FloatCC::Unordered,
- 4 => FloatCC::NotEqual,
- 5 => FloatCC::UnorderedOrGreaterThanOrEqual,
- 6 => FloatCC::UnorderedOrGreaterThan,
- kind => unreachable!("kind {:?}", kind),
- };
-
- simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
- let res_lane = match lane_ty.kind() {
- ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
- _ => unreachable!("{:?}", lane_ty),
- };
- bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().clz(lane)
});
}
- "llvm.x86.sse2.psrli.d" => {
- let (a, imm8) = match args {
- [a, imm8] => (a, imm8),
- _ => bug!("wrong number of args for intrinsic {intrinsic}"),
- };
- let a = codegen_operand(fx, a);
- let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
- .expect("llvm.x86.sse2.psrli.d imm8 not const");
- simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
- .try_to_bits(Size::from_bytes(4))
- .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
- {
- imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
- _ => fx.bcx.ins().iconst(types::I32, 0),
- });
- }
- "llvm.x86.sse2.pslli.d" => {
- let (a, imm8) = match args {
- [a, imm8] => (a, imm8),
- _ => bug!("wrong number of args for intrinsic {intrinsic}"),
- };
- let a = codegen_operand(fx, a);
- let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
- .expect("llvm.x86.sse2.psrli.d imm8 not const");
+ _ if intrinsic.starts_with("llvm.ctpop.v") => {
+ intrinsic_args!(fx, args => (a); intrinsic);
- simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
- .try_to_bits(Size::from_bytes(4))
- .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
- {
- imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
- _ => fx.bcx.ins().iconst(types::I32, 0),
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().popcnt(lane)
});
}
- "llvm.x86.sse2.storeu.dq" => {
- intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
- let mem_addr = mem_addr.load_scalar(fx);
-
- // FIXME correctly handle the unalignment
- let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
- dest.write_cvalue(fx, a);
- }
- "llvm.x86.addcarry.64" => {
- intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
- let c_in = c_in.load_scalar(fx);
-
- llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
- }
- "llvm.x86.subborrow.64" => {
- intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
- let b_in = b_in.load_scalar(fx);
- llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
- }
_ => {
fx.tcx
.sess
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
}
-
-// llvm.x86.avx2.vperm2i128
-// llvm.x86.ssse3.pshuf.b.128
-// 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);
-}
--- /dev/null
+//! Emulate AArch64 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ intrinsic: &str,
+ _substs: SubstsRef<'tcx>,
+ args: &[mir::Operand<'tcx>],
+ ret: CPlace<'tcx>,
+ target: Option<BasicBlock>,
+) {
+ // llvm.aarch64.neon.sqshl.v*i*
+
+ match intrinsic {
+ "llvm.aarch64.isb" => {
+ fx.bcx.ins().fence();
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.abs.v") => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().iabs(lane)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.cls.v") => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().cls(lane)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.rbit.v") => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+ fx.bcx.ins().bitrev(lane)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+ crate::num::codegen_saturating_int_binop(fx, BinOp::Add, x_lane, y_lane)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sqsub.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+ crate::num::codegen_saturating_int_binop(fx, BinOp::Sub, x_lane, y_lane)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.smax.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane(
+ fx,
+ x,
+ y,
+ ret,
+ &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+ let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, x_lane, y_lane);
+ fx.bcx.ins().select(gt, x_lane, y_lane)
+ },
+ );
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.umax.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane(
+ fx,
+ x,
+ y,
+ ret,
+ &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+ let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, x_lane, y_lane);
+ fx.bcx.ins().select(gt, x_lane, y_lane)
+ },
+ );
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.smaxv.i") => {
+ intrinsic_args!(fx, args => (v); intrinsic);
+
+ simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+ let gt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b);
+ fx.bcx.ins().select(gt, a, b)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.umaxv.i") => {
+ intrinsic_args!(fx, args => (v); intrinsic);
+
+ simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+ let gt = fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b);
+ fx.bcx.ins().select(gt, a, b)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.smin.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane(
+ fx,
+ x,
+ y,
+ ret,
+ &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+ let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane);
+ fx.bcx.ins().select(gt, x_lane, y_lane)
+ },
+ );
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.umin.v") => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ simd_pair_for_each_lane(
+ fx,
+ x,
+ y,
+ ret,
+ &|fx, _lane_ty, _res_lane_ty, x_lane, y_lane| {
+ let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane);
+ fx.bcx.ins().select(gt, x_lane, y_lane)
+ },
+ );
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sminv.i") => {
+ intrinsic_args!(fx, args => (v); intrinsic);
+
+ simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+ let gt = fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b);
+ fx.bcx.ins().select(gt, a, b)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.uminv.i") => {
+ intrinsic_args!(fx, args => (v); intrinsic);
+
+ simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| {
+ let gt = fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b);
+ fx.bcx.ins().select(gt, a, b)
+ });
+ }
+
+ /*
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sshl.v")
+ || intrinsic.starts_with("llvm.aarch64.neon.sqshl.v")
+ // FIXME split this one out once saturating is implemented
+ || intrinsic.starts_with("llvm.aarch64.neon.sqshlu.v") =>
+ {
+ intrinsic_args!(fx, args => (a, b); intrinsic);
+
+ simd_pair_for_each_lane(fx, a, b, ret, &|fx, _lane_ty, _res_lane_ty, a, b| {
+ // FIXME saturate?
+ fx.bcx.ins().ishl(a, b)
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrn.v") => {
+ let (a, imm32) = match args {
+ [a, imm32] => (a, imm32),
+ _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+ };
+ let a = codegen_operand(fx, a);
+ let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+ .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+ .try_to_bits(Size::from_bytes(4))
+ .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+ {
+ imm32 if imm32 < 32 => fx.bcx.ins().sshr_imm(lane, i64::from(imm32 as u8)),
+ _ => fx.bcx.ins().iconst(types::I32, 0),
+ });
+ }
+
+ _ if intrinsic.starts_with("llvm.aarch64.neon.sqshrun.v") => {
+ let (a, imm32) = match args {
+ [a, imm32] => (a, imm32),
+ _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+ };
+ let a = codegen_operand(fx, a);
+ let imm32 = crate::constant::mir_operand_get_const_val(fx, imm32)
+ .expect("llvm.aarch64.neon.sqshrn.v* imm32 not const");
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm32
+ .try_to_bits(Size::from_bytes(4))
+ .unwrap_or_else(|| panic!("imm32 not scalar: {:?}", imm32))
+ {
+ imm32 if imm32 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm32 as u8)),
+ _ => fx.bcx.ins().iconst(types::I32, 0),
+ });
+ }
+ */
+ _ => {
+ fx.tcx.sess.warn(&format!(
+ "unsupported AArch64 llvm intrinsic {}; replacing with trap",
+ intrinsic
+ ));
+ crate::trap::trap_unimplemented(fx, intrinsic);
+ return;
+ }
+ }
+
+ let dest = target.expect("all llvm intrinsics used by stdlib should return");
+ let ret_block = fx.get_block(dest);
+ fx.bcx.ins().jump(ret_block, &[]);
+}
--- /dev/null
+//! Emulate x86 LLVM intrinsics
+
+use crate::intrinsics::*;
+use crate::prelude::*;
+
+use rustc_middle::ty::subst::SubstsRef;
+
+pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ intrinsic: &str,
+ _substs: SubstsRef<'tcx>,
+ args: &[mir::Operand<'tcx>],
+ ret: CPlace<'tcx>,
+ target: Option<BasicBlock>,
+) {
+ match intrinsic {
+ "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+ // Spin loop hint
+ }
+
+ // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
+ "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+ let lane_ty = fx.clif_type(lane_ty).unwrap();
+ assert!(lane_count <= 32);
+
+ let mut res = fx.bcx.ins().iconst(types::I32, 0);
+
+ for lane in (0..lane_count).rev() {
+ let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+ // cast float to int
+ let a_lane = match lane_ty {
+ types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
+ types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
+ _ => a_lane,
+ };
+
+ // extract sign bit of an int
+ let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_ty.bits() - 1));
+
+ // shift sign bit into result
+ let a_lane_sign = clif_intcast(fx, a_lane_sign, types::I32, false);
+ res = fx.bcx.ins().ishl_imm(res, 1);
+ res = fx.bcx.ins().bor(res, a_lane_sign);
+ }
+
+ let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32));
+ ret.write_cvalue(fx, res);
+ }
+ "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
+ let (x, y, kind) = match args {
+ [x, y, kind] => (x, y, kind),
+ _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+ };
+ let x = codegen_operand(fx, x);
+ let y = codegen_operand(fx, y);
+ let kind = crate::constant::mir_operand_get_const_val(fx, kind)
+ .expect("llvm.x86.sse2.cmp.* kind not const");
+
+ let flt_cc = match kind
+ .try_to_bits(Size::from_bytes(1))
+ .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind))
+ {
+ 0 => FloatCC::Equal,
+ 1 => FloatCC::LessThan,
+ 2 => FloatCC::LessThanOrEqual,
+ 7 => FloatCC::Ordered,
+ 3 => FloatCC::Unordered,
+ 4 => FloatCC::NotEqual,
+ 5 => FloatCC::UnorderedOrGreaterThanOrEqual,
+ 6 => FloatCC::UnorderedOrGreaterThan,
+ kind => unreachable!("kind {:?}", kind),
+ };
+
+ simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| {
+ let res_lane = match lane_ty.kind() {
+ ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
+ _ => unreachable!("{:?}", lane_ty),
+ };
+ bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
+ });
+ }
+ "llvm.x86.sse2.psrli.d" => {
+ let (a, imm8) = match args {
+ [a, imm8] => (a, imm8),
+ _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+ };
+ let a = codegen_operand(fx, a);
+ let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+ .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+ .try_to_bits(Size::from_bytes(4))
+ .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+ {
+ imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
+ _ => fx.bcx.ins().iconst(types::I32, 0),
+ });
+ }
+ "llvm.x86.sse2.pslli.d" => {
+ let (a, imm8) = match args {
+ [a, imm8] => (a, imm8),
+ _ => bug!("wrong number of args for intrinsic {intrinsic}"),
+ };
+ let a = codegen_operand(fx, a);
+ let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8)
+ .expect("llvm.x86.sse2.psrli.d imm8 not const");
+
+ simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8
+ .try_to_bits(Size::from_bytes(4))
+ .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8))
+ {
+ imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
+ _ => fx.bcx.ins().iconst(types::I32, 0),
+ });
+ }
+ "llvm.x86.sse2.storeu.dq" => {
+ intrinsic_args!(fx, args => (mem_addr, a); intrinsic);
+ let mem_addr = mem_addr.load_scalar(fx);
+
+ // FIXME correctly handle the unalignment
+ let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
+ dest.write_cvalue(fx, a);
+ }
+ "llvm.x86.addcarry.64" => {
+ intrinsic_args!(fx, args => (c_in, a, b); intrinsic);
+ let c_in = c_in.load_scalar(fx);
+
+ llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b);
+ }
+ "llvm.x86.subborrow.64" => {
+ intrinsic_args!(fx, args => (b_in, a, b); intrinsic);
+ let b_in = b_in.load_scalar(fx);
+
+ llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b);
+ }
+ _ => {
+ fx.tcx.sess.warn(&format!(
+ "unsupported x86 llvm intrinsic {}; replacing with trap",
+ intrinsic
+ ));
+ crate::trap::trap_unimplemented(fx, intrinsic);
+ return;
+ }
+ }
+
+ let dest = target.expect("all llvm intrinsics used by stdlib should return");
+ let ret_block = fx.get_block(dest);
+ fx.bcx.ins().jump(ret_block, &[]);
+}
+
+// llvm.x86.avx2.vperm2i128
+// llvm.x86.ssse3.pshuf.b.128
+// 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);
+}
mod cpuid;
mod llvm;
+mod llvm_aarch64;
+mod llvm_x86;
mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
ty => ty,
};
- let val = fx.bcx.ins().bint(int_ty, val);
- let mut res = fx.bcx.ins().ineg(val);
+ let mut res = fx.bcx.ins().bmask(int_ty, val);
if ty.is_float() {
res = fx.bcx.ins().bitcast(ty, res);
ret.write_cvalue(fx, res);
}
sym::bswap => {
- // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift
- fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
- match bcx.func.dfg.value_type(v) {
- types::I8 => v,
-
- // https://code.woboq.org/gcc/include/bits/byteswap.h.html
- types::I16 => {
- let tmp1 = bcx.ins().ishl_imm(v, 8);
- let n1 = bcx.ins().band_imm(tmp1, 0xFF00);
-
- let tmp2 = bcx.ins().ushr_imm(v, 8);
- let n2 = bcx.ins().band_imm(tmp2, 0x00FF);
-
- bcx.ins().bor(n1, n2)
- }
- types::I32 => {
- let tmp1 = bcx.ins().ishl_imm(v, 24);
- let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000);
-
- let tmp2 = bcx.ins().ishl_imm(v, 8);
- let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000);
-
- let tmp3 = bcx.ins().ushr_imm(v, 8);
- let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00);
-
- let tmp4 = bcx.ins().ushr_imm(v, 24);
- let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF);
-
- let or_tmp1 = bcx.ins().bor(n1, n2);
- let or_tmp2 = bcx.ins().bor(n3, n4);
- bcx.ins().bor(or_tmp1, or_tmp2)
- }
- types::I64 => {
- let tmp1 = bcx.ins().ishl_imm(v, 56);
- let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64);
-
- let tmp2 = bcx.ins().ishl_imm(v, 40);
- let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64);
-
- let tmp3 = bcx.ins().ishl_imm(v, 24);
- let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64);
-
- let tmp4 = bcx.ins().ishl_imm(v, 8);
- let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64);
-
- let tmp5 = bcx.ins().ushr_imm(v, 8);
- let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64);
-
- let tmp6 = bcx.ins().ushr_imm(v, 24);
- let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64);
-
- let tmp7 = bcx.ins().ushr_imm(v, 40);
- let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64);
-
- let tmp8 = bcx.ins().ushr_imm(v, 56);
- let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64);
-
- let or_tmp1 = bcx.ins().bor(n1, n2);
- let or_tmp2 = bcx.ins().bor(n3, n4);
- let or_tmp3 = bcx.ins().bor(n5, n6);
- let or_tmp4 = bcx.ins().bor(n7, n8);
-
- let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2);
- let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4);
- bcx.ins().bor(or_tmp5, or_tmp6)
- }
- types::I128 => {
- let (lo, hi) = bcx.ins().isplit(v);
- let lo = swap(bcx, lo);
- let hi = swap(bcx, hi);
- bcx.ins().iconcat(hi, lo)
- }
- ty => unreachable!("bswap {}", ty),
- }
- }
intrinsic_args!(fx, args => (arg); intrinsic);
let val = arg.load_scalar(fx);
- let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout());
+ let res = if fx.bcx.func.dfg.value_type(val) == types::I8 {
+ val
+ } else {
+ fx.bcx.ins().bswap(val)
+ };
+ let res = CValue::by_val(res, arg.layout());
ret.write_cvalue(fx, res);
}
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new);
let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
- let ret_val =
- CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout());
+ let ret_val = CValue::by_val_pair(old, is_eq, ret.layout());
ret.write_cvalue(fx, ret_val)
}
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)
+ fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val)
} else {
// Just call `memcmp` (like slices do in core) when the
// size is too large or it's not a power-of-two.
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)
+ fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0)
};
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
}
_ => unreachable!(),
};
- let ty = fx.clif_type(res_lane_ty).unwrap();
-
- let res_lane = fx.bcx.ins().bint(ty, res_lane);
- fx.bcx.ins().ineg(res_lane)
+ bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane)
});
}
let res_type =
Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
- let mut res = fx.bcx.ins().iconst(res_type, 0);
+ let mut res = type_zero_value(&mut fx.bcx, res_type);
let lanes = match fx.tcx.sess.target.endian {
Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
call_conv: crate::conv_to_call_conv(
tcx.sess.target.options.entry_abi,
- CallConv::triple_default(m.isa().triple()),
+ m.target_config().default_call_conv,
),
};
let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
let main_name = tcx.symbol_name(instance).name;
- let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
+ let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance);
let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
let mut ctx = Context::new();
.polymorphize(tcx);
let report_name = tcx.symbol_name(report).name;
- let report_sig = get_function_sig(tcx, m.isa().triple(), report);
+ let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report);
let report_func_id =
m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);
) -> CValue<'tcx> {
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
let val = fx.bcx.ins().icmp(intcc, lhs, rhs);
- let val = fx.bcx.ins().bint(types::I8, val);
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
}
_ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
};
- let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
-
let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
CValue::by_val_pair(res, has_overflow, out_layout)
}
_ => unreachable!(),
};
let val = fx.bcx.ins().fcmp(fltcc, lhs, rhs);
- let val = fx.bcx.ins().bint(types::I8, val);
return CValue::by_val(val, fx.layout_of(fx.tcx.types.bool));
}
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
_ => panic!("bin_op {:?} on ptr", bin_op),
};
- CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
+ CValue::by_val(res, fx.layout_of(fx.tcx.types.bool))
}
}
use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
use cranelift_frontend::FunctionBuilder;
-/// If the given value was produced by a `bint` instruction, return it's input, otherwise return the
-/// given value.
-pub(crate) fn maybe_unwrap_bint(bcx: &mut FunctionBuilder<'_>, arg: Value) -> Value {
- if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
- match bcx.func.dfg[arg_inst] {
- InstructionData::Unary { opcode: Opcode::Bint, arg } => arg,
- _ => arg,
- }
- } else {
- arg
- }
-}
-
/// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
/// otherwise return the given value and false.
pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
};
match bcx.func.dfg[arg_inst] {
- InstructionData::UnaryBool { opcode: Opcode::Bconst, imm } => {
- if test_zero {
- Some(!imm)
- } else {
- Some(imm)
- }
- }
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
if test_zero {
Some(imm.bits() == 0)
local: Local,
layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> {
- let var = Variable::with_u32(fx.next_ssa_var);
+ let var = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1;
fx.bcx.declare_var(var, fx.clif_type(layout.ty).unwrap());
CPlace { inner: CPlaceInner::Var(local, var), layout }
local: Local,
layout: TyAndLayout<'tcx>,
) -> CPlace<'tcx> {
- let var1 = Variable::with_u32(fx.next_ssa_var);
+ let var1 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1;
- let var2 = Variable::with_u32(fx.next_ssa_var);
+ let var2 = Variable::from_u32(fx.next_ssa_var);
fx.next_ssa_var += 1;
let (ty1, ty2) = fx.clif_pair_type(layout.ty).unwrap();
| (types::F32, types::I32)
| (types::I64, types::F64)
| (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
- _ if src_ty.is_vector() && dst_ty.is_vector() => {
- fx.bcx.ins().raw_bitcast(dst_ty, data)
- }
+ _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
_ if src_ty.is_vector() || dst_ty.is_vector() => {
// FIXME do something more efficient for transmutes between vectors and integers.
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
return;
}
CPlaceInner::VarPair(_local, var1, var2) => {
- let (data1, data2) = CValue(from.0, dst_layout).load_scalar_pair(fx);
+ let (ptr, meta) = from.force_stack(fx);
+ assert!(meta.is_none());
+ let (data1, data2) =
+ CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
transmute_value(fx, var1, data1, dst_ty1);
transmute_value(fx, var2, data2, dst_ty2);
#!/usr/bin/env bash
-exec ./y.rs test
+exec ./y.rs test "$@"
# This block is ignored by rustc
set -e
echo "[BUILD] y.rs" 1>&2
-rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1
+rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
exec ${0/.rs/.bin} $@
*/
// TODO(antoyo)
}
- fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
- let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
- let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
- let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
- self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
- .to_rvalue()
+ fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+ (
+ self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
+ .to_rvalue(),
+ self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue(),
+ )
// TODO(antoyo): Properly implement unwinding.
// the above is just to make the compilation work as it seems
// rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
}
- fn resume(&mut self, _exn: RValue<'gcc>) {
+ fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
// TODO(bjorn3): Properly implement unwinding.
self.unreachable();
}
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
-use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
use crate::base;
use crate::context::CodegenCx;
-use crate::errors::LinkageConstOrMutType;
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
Node::ForeignItem(&hir::ForeignItem {
- span,
+ span: _,
kind: hir::ForeignItemKind::Static(..),
..
}) => {
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
- check_and_apply_linkage(&self, &fn_attrs, ty, sym, span)
+ check_and_apply_linkage(&self, &fn_attrs, ty, sym)
}
item => bug!("get_static: expected static, found {:?}", item),
//debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
let attrs = self.tcx.codegen_fn_attrs(def_id);
- let span = self.tcx.def_span(def_id);
- let global = check_and_apply_linkage(&self, &attrs, ty, sym, span);
+ let global = check_and_apply_linkage(&self, &attrs, ty, sym);
let needs_dll_storage_attr = false; // TODO(antoyo)
Ok((const_alloc_to_gcc(cx, alloc), alloc))
}
-fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
+fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
let llty = cx.layout_of(ty).gcc_type(cx, true);
- if let Some(linkage) = attrs.linkage {
- // If this is a static with a linkage specified, then we need to handle
- // it a little specially. The typesystem prevents things like &T and
- // extern "C" fn() from being non-null, so we can't just declare a
- // static and call it a day. Some linkages (like weak) will make it such
- // that the static actually has a null value.
- let llty2 =
- if let ty::RawPtr(ref mt) = ty.kind() {
- cx.layout_of(mt.ty).gcc_type(cx, true)
- }
- else {
- cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
- };
+ if let Some(linkage) = attrs.import_linkage {
// Declare a symbol `foo` with the desired linkage.
- let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
+ let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
// Declare an internal global `extern_with_linkage_foo` which
// is initialized with the address of `foo`. If `foo` is
pub in_elem: Ty<'a>,
}
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
- #[primary_span]
- pub span: Span,
-}
-
#[derive(Diagnostic)]
#[diag(codegen_gcc_lto_not_supported)]
pub(crate) struct LTONotSupported;
// Unsupported.
self.context.new_rvalue_from_int(self.int_type, 0)
}
+
+ fn set_kcfi_type_metadata(&self, _function: RValue<'gcc>, _kcfi_typeid: u32) {
+ // Unsupported.
+ }
}
callee,
args.as_ptr(),
args.len() as c_uint,
- None,
+ [].as_ptr(),
+ 0 as c_uint,
);
llvm::LLVMSetTailCall(ret, True);
if output.is_some() {
.enumerate()
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
.collect::<Vec<_>>();
- let ret =
- llvm::LLVMRustBuildCall(llbuilder, ty, callee, args.as_ptr(), args.len() as c_uint, None);
+ let ret = llvm::LLVMRustBuildCall(
+ llbuilder,
+ ty,
+ callee,
+ args.as_ptr(),
+ args.len() as c_uint,
+ [].as_ptr(),
+ 0 as c_uint,
+ );
llvm::LLVMSetTailCall(ret, True);
llvm::LLVMBuildRetVoid(llbuilder);
llvm::LLVMDisposeBuilder(llbuilder);
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{
- get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
- ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
+ get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
+ ArchiveBuilderBuilder, UnknownArchiveKind,
};
use rustc_session::cstore::DllImport;
archive: &Path,
skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> {
- let mut archive = archive.to_path_buf();
- if self.sess.target.llvm_target.contains("-apple-macosx") {
- if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
- archive = new_archive
- }
- }
- let archive_ro = match ArchiveRO::open(&archive) {
+ let archive_ro = match ArchiveRO::open(archive) {
Ok(ar) => ar,
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
};
return Ok(());
}
self.additions.push(Addition::Archive {
- path: archive,
+ path: archive.to_path_buf(),
archive: archive_ro,
skip: Box::new(skip),
});
}
}
+ // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
+ // __llvm_profile_runtime, therefore we won't know until link time if this symbol
+ // should have default visibility.
+ symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
Ok((symbols_below_threshold, upstream_modules))
}
}
pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) {
- let name = module.name.clone();
+ let name = module.name;
let buffer = ThinBuffer::new(module.module_llvm.llmod(), true);
(name, buffer)
}
info!("going for that thin, thin LTO");
let green_modules: FxHashMap<_, _> =
- cached_modules.iter().map(|&(_, ref wp)| (wp.cgu_name.clone(), wp.clone())).collect();
+ cached_modules.iter().map(|(_, wp)| (wp.cgu_name.clone(), wp.clone())).collect();
let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len();
let mut thin_buffers = Vec::with_capacity(modules.len());
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
+use rustc_symbol_mangling::typeid::kcfi_typeid_for_fnabi;
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
debug!("invoke {:?} with args ({:?})", llfn, args);
let args = self.check_call("invoke", llty, llfn, args);
- let bundle = funclet.map(|funclet| funclet.bundle());
- let bundle = bundle.as_ref().map(|b| &*b.raw);
+ let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+ let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+ let mut bundles = vec![funclet_bundle];
+
+ // Set KCFI operand bundle
+ let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+ let kcfi_bundle =
+ if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+ let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+ Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+ } else {
+ None
+ };
+ if kcfi_bundle.is_some() {
+ let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+ bundles.push(kcfi_bundle);
+ }
+ bundles.retain(|bundle| bundle.is_some());
let invoke = unsafe {
llvm::LLVMRustBuildInvoke(
self.llbuilder,
args.len() as c_uint,
then,
catch,
- bundle,
+ bundles.as_ptr(),
+ bundles.len() as c_uint,
UNNAMED,
)
};
}
}
- fn cleanup_landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value) -> &'ll Value {
+ fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
+ let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
unsafe {
llvm::LLVMSetCleanup(landing_pad, llvm::True);
}
- landing_pad
+ (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
}
- fn resume(&mut self, exn: &'ll Value) {
+ fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
+ let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
+ let mut exn = self.const_undef(ty);
+ exn = self.insert_value(exn, exn0, 0);
+ exn = self.insert_value(exn, exn1, 1);
unsafe {
llvm::LLVMBuildResume(self.llbuilder, exn);
}
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
- None,
+ [].as_ptr(),
+ 0 as c_uint,
);
}
}
debug!("call {:?} with args ({:?})", llfn, args);
let args = self.check_call("call", llty, llfn, args);
- let bundle = funclet.map(|funclet| funclet.bundle());
- let bundle = bundle.as_ref().map(|b| &*b.raw);
+ let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+ let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+ let mut bundles = vec![funclet_bundle];
+
+ // Set KCFI operand bundle
+ let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+ let kcfi_bundle =
+ if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+ let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+ Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+ } else {
+ None
+ };
+ if kcfi_bundle.is_some() {
+ let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+ bundles.push(kcfi_bundle);
+ }
+ bundles.retain(|bundle| bundle.is_some());
let call = unsafe {
llvm::LLVMRustBuildCall(
self.llbuilder,
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
- bundle,
+ bundles.as_ptr(),
+ bundles.len() as c_uint,
)
};
if let Some(fn_abi) = fn_abi {
use crate::base;
use crate::common::{self, CodegenCx};
use crate::debuginfo;
-use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
+use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
use crate::llvm::{self, True};
use crate::llvm_util;
use crate::type_::Type;
def_id: DefId,
) -> &'ll Value {
let llty = cx.layout_of(ty).llvm_type(cx);
- if let Some(linkage) = attrs.linkage {
+ if let Some(linkage) = attrs.import_linkage {
debug!("get_static: sym={} linkage={:?}", sym, linkage);
- // If this is a static with a linkage specified, then we need to handle
- // it a little specially. The typesystem prevents things like &T and
- // extern "C" fn() from being non-null, so we can't just declare a
- // static and call it a day. Some linkages (like weak) will make it such
- // that the static actually has a null value.
- let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
- cx.layout_of(mt.ty).llvm_type(cx)
- } else {
- cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
- };
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let g1 = cx.declare_global(sym, llty2);
+ let g1 = cx.declare_global(sym, cx.type_i8());
llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));
// Declare an internal global `extern_with_linkage_foo` which
})
});
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
- llvm::LLVMSetInitializer(g2, g1);
+ llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty));
g2
}
} else if cx.tcx.sess.target.arch == "x86" &&
use crate::callee::get_fn;
use crate::coverageinfo;
use crate::debuginfo;
-use crate::errors::BranchProtectionRequiresAArch64;
use crate::llvm;
use crate::llvm_util;
use crate::type_::Type;
);
}
+ if sess.is_sanitizer_kcfi_enabled() {
+ let kcfi = "kcfi\0".as_ptr().cast();
+ llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
+ }
+
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
if sess.target.is_like_msvc {
match sess.opts.cg.control_flow_guard {
}
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
- if sess.target.arch != "aarch64" {
- sess.emit_err(BranchProtectionRequiresAArch64);
- } else {
+ if sess.target.arch == "aarch64" {
llvm::LLVMRustAddModuleFlag(
llmod,
llvm::LLVMModFlagBehavior::Error,
"sign-return-address-with-bkey\0".as_ptr().cast(),
u32::from(pac_opts.key == PAuthKey::B),
);
+ } else {
+ bug!(
+ "branch-protection used on non-AArch64 target; \
+ this should be checked in rustc_session."
+ );
}
}
use rustc_fs_util::path_to_c_string;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::bug;
-use rustc_middle::mir::{self, GeneratorLayout};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
// Tuples
//=-----------------------------------------------------------------------------
-/// Returns names of captured upvars for closures and generators.
-///
-/// Here are some examples:
-/// - `name__field1__field2` when the upvar is captured by value.
-/// - `_ref__name__field` when the upvar is captured by reference.
-///
-/// For generators this only contains upvars that are shared by all states.
-fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> SmallVec<String> {
- let body = tcx.optimized_mir(def_id);
-
- body.var_debug_info
- .iter()
- .filter_map(|var| {
- let is_ref = match var.value {
- mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
- // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
- // implies whether the variable is captured by value or by reference.
- matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
- }
- _ => return None,
- };
- let prefix = if is_ref { "_ref__" } else { "" };
- Some(prefix.to_owned() + var.name.as_str())
- })
- .collect()
-}
-
/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
/// For a generator, this will handle upvars shared by all states.
fn build_upvar_field_di_nodes<'ll, 'tcx>(
.all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
);
- let capture_names = closure_saved_names_of_captured_variables(cx.tcx, def_id);
+ let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
let layout = cx.layout_of(closure_or_generator_ty);
up_var_tys
)
}
-// FIXME(eddyb) maybe precompute this? Right now it's computed once
-// per generator monomorphization, but it doesn't depend on substs.
-fn generator_layout_and_saved_local_names<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
-) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
- let body = tcx.optimized_mir(def_id);
- let generator_layout = body.generator_layout().unwrap();
- let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
-
- let state_arg = mir::Local::new(1);
- for var in &body.var_debug_info {
- let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
- if place.local != state_arg {
- continue;
- }
- match place.projection[..] {
- [
- // Deref of the `Pin<&mut Self>` state argument.
- mir::ProjectionElem::Field(..),
- mir::ProjectionElem::Deref,
- // Field of a variant of the state.
- mir::ProjectionElem::Downcast(_, variant),
- mir::ProjectionElem::Field(field, _),
- ] => {
- let name = &mut generator_saved_local_names
- [generator_layout.variant_fields[variant][field]];
- if name.is_none() {
- name.replace(var.name);
- }
- }
- _ => {}
- }
- }
- (generator_layout, generator_saved_local_names)
-}
-
/// Computes the type parameters for a type, if any, for the given metadata.
fn build_generic_type_param_di_nodes<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
common::CodegenCx,
debuginfo::{
metadata::{
- build_field_di_node, closure_saved_names_of_captured_variables,
+ build_field_di_node,
enums::{tag_base_type, DiscrResult},
- file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+ file_metadata, size_and_align_of, type_di_node,
type_map::{self, Stub, UniqueTypeId},
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
UNKNOWN_LINE_NUMBER,
};
let (generator_layout, state_specific_upvar_names) =
- generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+ cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
- let common_upvar_names = closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+ let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
common::CodegenCx,
debuginfo::{
metadata::{
- closure_saved_names_of_captured_variables,
enums::tag_base_type,
- file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+ file_metadata, size_and_align_of, type_di_node,
type_map::{self, Stub, StubInfo, UniqueTypeId},
unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS,
UNKNOWN_LINE_NUMBER,
),
|cx, generator_type_di_node| {
let (generator_layout, state_specific_upvar_names) =
- generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+ cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
bug!(
};
let common_upvar_names =
- closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+ cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
// Build variant struct types
let variant_struct_type_di_nodes: SmallVec<_> = variants
use crate::value::Value;
use rustc_codegen_ssa::traits::TypeMembershipMethods;
use rustc_middle::ty::Ty;
-use rustc_symbol_mangling::typeid::typeid_for_fnabi;
+use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi};
use smallvec::SmallVec;
/// Declare a function.
self.set_type_metadata(llfn, typeid);
}
+ if self.tcx.sess.is_sanitizer_kcfi_enabled() {
+ let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
+ self.set_kcfi_type_metadata(llfn, kcfi_typeid);
+ }
+
llfn
}
pub symbol_name: &'a str,
}
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_branch_protection_requires_aarch64)]
-pub(crate) struct BranchProtectionRequiresAArch64;
-
#[derive(Diagnostic)]
#[diag(codegen_llvm_invalid_minimum_alignment)]
pub(crate) struct InvalidMinimumAlignment {
pub err: String,
}
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_linkage_const_or_mut_type)]
-pub(crate) struct LinkageConstOrMutType {
- #[primary_span]
- pub span: Span,
-}
-
#[derive(Diagnostic)]
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
pub(crate) struct SanitizerMemtagRequiresMte;
typeid: &'ll Value,
) -> Self::Value {
let vtable_byte_offset = self.const_i32(vtable_byte_offset as i32);
- self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid])
+ let type_checked_load =
+ self.call_intrinsic("llvm.type.checked.load", &[llvtable, vtable_byte_offset, typeid]);
+ self.extract_value(type_checked_load, 0)
}
fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
MD_type = 19,
MD_vcall_visibility = 28,
MD_noundef = 29,
+ MD_kcfi_type = 36,
}
/// LLVMRustAsmDialect
pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
+ pub fn LLVMIsAFunction(Val: &Value) -> Option<&Value>;
// Operations on constants of any type
pub fn LLVMConstNull(Ty: &Type) -> &Value;
NumArgs: c_uint,
Then: &'a BasicBlock,
Catch: &'a BasicBlock,
- Bundle: Option<&OperandBundleDef<'a>>,
+ OpBundles: *const Option<&OperandBundleDef<'a>>,
+ NumOpBundles: c_uint,
Name: *const c_char,
) -> &'a Value;
pub fn LLVMBuildLandingPad<'a>(
Fn: &'a Value,
Args: *const &'a Value,
NumArgs: c_uint,
- Bundle: Option<&OperandBundleDef<'a>>,
+ OpBundles: *const Option<&OperandBundleDef<'a>>,
+ NumOpBundles: c_uint,
) -> &'a Value;
pub fn LLVMRustBuildMemCpy<'a>(
B: &Builder<'a>,
)
}
}
+
+ fn set_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
+ let kcfi_type_metadata = self.const_u32(kcfi_typeid);
+ unsafe {
+ llvm::LLVMGlobalSetMetadata(
+ function,
+ llvm::MD_kcfi_type as c_uint,
+ llvm::LLVMMDNodeInContext2(
+ self.llcx,
+ &llvm::LLVMValueAsMetadata(kcfi_type_metadata),
+ 1,
+ ),
+ )
+ }
+ }
}
use std::error::Error;
use std::fs::File;
-use std::io::{self, Write};
+use std::io;
use std::path::{Path, PathBuf};
// Re-exporting for rustc_codegen_llvm::back::archive
}
}
-fn try_filter_fat_archs(
+fn try_filter_fat_archs<'a>(
archs: object::read::Result<&[impl FatArch]>,
target_arch: object::Architecture,
- archive_path: &Path,
- archive_map_data: &[u8],
-) -> io::Result<Option<PathBuf>> {
+ archive_map_data: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
None => return Ok(None),
};
- let (mut new_f, extracted_path) = tempfile::Builder::new()
- .suffix(archive_path.file_name().unwrap())
- .tempfile()?
- .keep()
- .unwrap();
-
- new_f.write_all(
+ Ok(Some((
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
- )?;
-
- Ok(Some(extracted_path))
+ desired.offset().into(),
+ )))
}
-pub fn try_extract_macho_fat_archive(
+pub fn try_extract_macho_fat_archive<'a>(
sess: &Session,
- archive_path: &Path,
-) -> io::Result<Option<PathBuf>> {
- let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+ archive_bytes: &'a [u8],
+) -> io::Result<Option<(&'a [u8], u64)>> {
let target_arch = match sess.target.arch.as_ref() {
"aarch64" => object::Architecture::Aarch64,
"x86_64" => object::Architecture::X86_64,
_ => return Ok(None),
};
- match object::macho::FatHeader::parse(&*archive_map) {
+ match object::macho::FatHeader::parse(archive_bytes) {
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
- let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
- try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
+ try_filter_fat_archs(archs, target_arch, archive_bytes)
}
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
- let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
- try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
+ try_filter_fat_archs(archs, target_arch, archive_bytes)
}
// Not a FatHeader at all, just return None.
_ => Ok(None),
archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> {
- let mut archive_path = archive_path.to_path_buf();
- if self.sess.target.llvm_target.contains("-apple-macosx") {
- if let Some(new_archive_path) =
- try_extract_macho_fat_archive(&self.sess, &archive_path)?
- {
- archive_path = new_archive_path
- }
- }
-
+ let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
return Ok(());
}
- let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
- let archive = ArchiveFile::parse(&*archive_map)
+ let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
+ if let Some((sub_archive, archive_offset)) =
+ try_extract_macho_fat_archive(&self.sess, &*archive_map)?
+ {
+ (sub_archive, Some(archive_offset))
+ } else {
+ (&*archive_map, None)
+ }
+ } else {
+ (&*archive_map, None)
+ };
+
+ let archive = ArchiveFile::parse(&*archive_bytes)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let archive_index = self.src_archives.len();
let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
+ let mut range = entry.file_range();
+ if let Some(offset) = offset {
+ range.0 += offset;
+ }
self.entries.push((
file_name.into_bytes(),
- ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
+ ArchiveEntry::FromArchive { archive_index, file_range: range },
));
}
}
sess,
crate_type,
outputs,
- codegen_results.crate_info.local_crate_name.as_str(),
+ codegen_results.crate_info.local_crate_name,
);
match crate_type {
CrateType::Rlib => {
};
for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {
- Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue,
+ Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
Some(_) => {}
None => return Err(errors::LinkRlibError::MissingFormat),
}
linker::disable_localization(&mut cmd);
- for &(ref k, ref v) in sess.target.link_env.as_ref() {
+ for (k, v) in sess.target.link_env.as_ref() {
cmd.env(k.as_ref(), v.as_ref());
}
for k in sess.target.link_env_remove.as_ref() {
&search_paths.get_or_init(|| archive_search_paths(sess)),
);
} else {
- // HACK/FIXME: Fixup a circular dependency between libgcc and libc
- // with glibc. This logic should be moved to the libc crate.
- if cnum != LOCAL_CRATE
- && sess.target.os == "linux"
- && sess.target.env == "gnu"
- && name == "c"
- {
- cmd.link_staticlib("gcc", false);
- }
cmd.link_staticlib(name, verbatim)
}
}
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() {
+ for (k, v) in tool.env() {
if k == "PATH" {
new_path.extend(env::split_paths(v));
msvc_changed_path = true;
use rustc_target::abi::{Align, Size, VariantIdx};
use std::collections::BTreeSet;
-use std::convert::TryFrom;
use std::time::{Duration, Instant};
use itertools::Itertools;
--- /dev/null
+use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
+use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::mir::mono::Linkage;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
+use rustc_session::{lint, parse::feature_err};
+use rustc_span::{sym, Span};
+use rustc_target::spec::{abi, SanitizerSet};
+
+use crate::target_features::from_target_feature;
+use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
+
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
+ use rustc_middle::mir::mono::Linkage::*;
+
+ // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+ // applicable to variable declarations and may not really make sense for
+ // Rust code in the first place but allow them anyway and trust that the
+ // user knows what they're doing. Who knows, unanticipated use cases may pop
+ // up in the future.
+ //
+ // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+ // and don't have to be, LLVM treats them as no-ops.
+ match name {
+ "appending" => Appending,
+ "available_externally" => AvailableExternally,
+ "common" => Common,
+ "extern_weak" => ExternalWeak,
+ "external" => External,
+ "internal" => Internal,
+ "linkonce" => LinkOnceAny,
+ "linkonce_odr" => LinkOnceODR,
+ "private" => Private,
+ "weak" => WeakAny,
+ "weak_odr" => WeakODR,
+ _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
+ }
+}
+
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
+ if cfg!(debug_assertions) {
+ let def_kind = tcx.def_kind(did);
+ assert!(
+ def_kind.has_codegen_attrs(),
+ "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
+ );
+ }
+
+ let did = did.expect_local();
+ let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
+ let mut codegen_fn_attrs = CodegenFnAttrs::new();
+ if tcx.should_inherit_track_caller(did) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+ }
+
+ let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+
+ let mut inline_span = None;
+ let mut link_ordinal_span = None;
+ let mut no_sanitize_span = None;
+ for attr in attrs.iter() {
+ if attr.has_name(sym::cold) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
+ } else if attr.has_name(sym::rustc_allocator) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
+ } else if attr.has_name(sym::ffi_returns_twice) {
+ if tcx.is_foreign_item(did) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
+ } else {
+ // `#[ffi_returns_twice]` is only allowed `extern fn`s.
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0724,
+ "`#[ffi_returns_twice]` may only be used on foreign functions"
+ )
+ .emit();
+ }
+ } else if attr.has_name(sym::ffi_pure) {
+ if tcx.is_foreign_item(did) {
+ if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+ // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0757,
+ "`#[ffi_const]` function cannot be `#[ffi_pure]`"
+ )
+ .emit();
+ } else {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
+ }
+ } else {
+ // `#[ffi_pure]` is only allowed on foreign functions
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0755,
+ "`#[ffi_pure]` may only be used on foreign functions"
+ )
+ .emit();
+ }
+ } else if attr.has_name(sym::ffi_const) {
+ if tcx.is_foreign_item(did) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
+ } else {
+ // `#[ffi_const]` is only allowed on foreign functions
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0756,
+ "`#[ffi_const]` may only be used on foreign functions"
+ )
+ .emit();
+ }
+ } else if attr.has_name(sym::rustc_nounwind) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+ } else if attr.has_name(sym::rustc_reallocator) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
+ } else if attr.has_name(sym::rustc_deallocator) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
+ } else if attr.has_name(sym::rustc_allocator_zeroed) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
+ } else if attr.has_name(sym::naked) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
+ } else if attr.has_name(sym::no_mangle) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+ } else if attr.has_name(sym::no_coverage) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+ } else if attr.has_name(sym::rustc_std_internal_symbol) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+ } else if attr.has_name(sym::used) {
+ let inner = attr.meta_item_list();
+ match inner.as_deref() {
+ Some([item]) if item.has_name(sym::linker) => {
+ if !tcx.features().used_with_arg {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::used_with_arg,
+ attr.span,
+ "`#[used(linker)]` is currently unstable",
+ )
+ .emit();
+ }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
+ }
+ Some([item]) if item.has_name(sym::compiler) => {
+ if !tcx.features().used_with_arg {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::used_with_arg,
+ attr.span,
+ "`#[used(compiler)]` is currently unstable",
+ )
+ .emit();
+ }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
+ }
+ Some(_) => {
+ tcx.sess.emit_err(ExpectedUsedSymbol { span: attr.span });
+ }
+ None => {
+ // Unfortunately, unconditionally using `llvm.used` causes
+ // issues in handling `.init_array` with the gold linker,
+ // but using `llvm.compiler.used` caused a nontrival amount
+ // of unintentional ecosystem breakage -- particularly on
+ // Mach-O targets.
+ //
+ // As a result, we emit `llvm.compiler.used` only on ELF
+ // targets. This is somewhat ad-hoc, but actually follows
+ // our pre-LLVM 13 behavior (prior to the ecosystem
+ // breakage), and seems to match `clang`'s behavior as well
+ // (both before and after LLVM 13), possibly because they
+ // have similar compatibility concerns to us. See
+ // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
+ // and following comments for some discussion of this, as
+ // well as the comments in `rustc_codegen_llvm` where these
+ // flags are handled.
+ //
+ // Anyway, to be clear: this is still up in the air
+ // somewhat, and is subject to change in the future (which
+ // is a good thing, because this would ideally be a bit
+ // more firmed up).
+ let is_like_elf = !(tcx.sess.target.is_like_osx
+ || tcx.sess.target.is_like_windows
+ || tcx.sess.target.is_like_wasm);
+ codegen_fn_attrs.flags |= if is_like_elf {
+ CodegenFnAttrFlags::USED
+ } else {
+ CodegenFnAttrFlags::USED_LINKER
+ };
+ }
+ }
+ } else if attr.has_name(sym::cmse_nonsecure_entry) {
+ if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0776,
+ "`#[cmse_nonsecure_entry]` requires C ABI"
+ )
+ .emit();
+ }
+ if !tcx.sess.target.llvm_target.contains("thumbv8m") {
+ struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
+ .emit();
+ }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
+ } else if attr.has_name(sym::thread_local) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
+ } else if attr.has_name(sym::track_caller) {
+ if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
+ struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
+ .emit();
+ }
+ if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::closure_track_caller,
+ attr.span,
+ "`#[track_caller]` on closures is currently unstable",
+ )
+ .emit();
+ }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
+ } else if attr.has_name(sym::export_name) {
+ if let Some(s) = attr.value_str() {
+ if s.as_str().contains('\0') {
+ // `#[export_name = ...]` will be converted to a null-terminated string,
+ // so it may not contain any null characters.
+ struct_span_err!(
+ tcx.sess,
+ attr.span,
+ E0648,
+ "`export_name` may not contain null characters"
+ )
+ .emit();
+ }
+ codegen_fn_attrs.export_name = Some(s);
+ }
+ } else if attr.has_name(sym::target_feature) {
+ if !tcx.is_closure(did.to_def_id())
+ && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
+ {
+ if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
+ // The `#[target_feature]` attribute is allowed on
+ // WebAssembly targets on all functions, including safe
+ // ones. Other targets require that `#[target_feature]` is
+ // only applied to unsafe functions (pending the
+ // `target_feature_11` feature) because on most targets
+ // execution of instructions that are not supported is
+ // considered undefined behavior. For WebAssembly which is a
+ // 100% safe target at execution time it's not possible to
+ // execute undefined instructions, and even if a future
+ // feature was added in some form for this it would be a
+ // deterministic trap. There is no undefined behavior when
+ // executing WebAssembly so `#[target_feature]` is allowed
+ // on safe functions (but again, only for WebAssembly)
+ //
+ // Note that this is also allowed if `actually_rustdoc` so
+ // if a target is documenting some wasm-specific code then
+ // it's not spuriously denied.
+ } else if !tcx.features().target_feature_11 {
+ let mut err = feature_err(
+ &tcx.sess.parse_sess,
+ sym::target_feature_11,
+ attr.span,
+ "`#[target_feature(..)]` can only be applied to `unsafe` functions",
+ );
+ err.span_label(tcx.def_span(did), "not an `unsafe` function");
+ err.emit();
+ } else {
+ check_target_feature_trait_unsafe(tcx, did, attr.span);
+ }
+ }
+ from_target_feature(
+ tcx,
+ attr,
+ supported_target_features,
+ &mut codegen_fn_attrs.target_features,
+ );
+ } else if attr.has_name(sym::linkage) {
+ if let Some(val) = attr.value_str() {
+ let linkage = Some(linkage_by_name(tcx, did, val.as_str()));
+ if tcx.is_foreign_item(did) {
+ codegen_fn_attrs.import_linkage = linkage;
+ } else {
+ codegen_fn_attrs.linkage = linkage;
+ }
+ }
+ } else if attr.has_name(sym::link_section) {
+ if let Some(val) = attr.value_str() {
+ if val.as_str().bytes().any(|b| b == 0) {
+ let msg = format!(
+ "illegal null byte in link_section \
+ value: `{}`",
+ &val
+ );
+ tcx.sess.span_err(attr.span, &msg);
+ } else {
+ codegen_fn_attrs.link_section = Some(val);
+ }
+ }
+ } else if attr.has_name(sym::link_name) {
+ codegen_fn_attrs.link_name = attr.value_str();
+ } else if attr.has_name(sym::link_ordinal) {
+ link_ordinal_span = Some(attr.span);
+ if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
+ codegen_fn_attrs.link_ordinal = ordinal;
+ }
+ } else if attr.has_name(sym::no_sanitize) {
+ no_sanitize_span = Some(attr.span);
+ if let Some(list) = attr.meta_item_list() {
+ for item in list.iter() {
+ if item.has_name(sym::address) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+ } else if item.has_name(sym::cfi) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+ } else if item.has_name(sym::kcfi) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
+ } else if item.has_name(sym::memory) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
+ } else if item.has_name(sym::memtag) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
+ } else if item.has_name(sym::shadow_call_stack) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
+ } else if item.has_name(sym::thread) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
+ } else if item.has_name(sym::hwaddress) {
+ codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
+ } else {
+ tcx.sess
+ .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
+ .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+ .emit();
+ }
+ }
+ }
+ } else if attr.has_name(sym::instruction_set) {
+ codegen_fn_attrs.instruction_set = match attr.meta_kind() {
+ Some(MetaItemKind::List(ref items)) => match items.as_slice() {
+ [NestedMetaItem::MetaItem(set)] => {
+ let segments =
+ set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+ match segments.as_slice() {
+ [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+ if !tcx.sess.target.has_thumb_interworking {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "target does not support `#[instruction_set]`"
+ )
+ .emit();
+ None
+ } else if segments[1] == sym::a32 {
+ Some(InstructionSetAttr::ArmA32)
+ } else if segments[1] == sym::t32 {
+ Some(InstructionSetAttr::ArmT32)
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "invalid instruction set specified",
+ )
+ .emit();
+ None
+ }
+ }
+ }
+ [] => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0778,
+ "`#[instruction_set]` requires an argument"
+ )
+ .emit();
+ None
+ }
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "cannot specify more than one instruction set"
+ )
+ .emit();
+ None
+ }
+ },
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0778,
+ "must specify an instruction set"
+ )
+ .emit();
+ None
+ }
+ };
+ } else if attr.has_name(sym::repr) {
+ codegen_fn_attrs.alignment = match attr.meta_item_list() {
+ Some(items) => match items.as_slice() {
+ [item] => match item.name_value_literal() {
+ Some((sym::align, literal)) => {
+ let alignment = rustc_attr::parse_alignment(&literal.kind);
+
+ match alignment {
+ Ok(align) => Some(align),
+ Err(msg) => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0589,
+ "invalid `repr(align)` attribute: {}",
+ msg
+ )
+ .emit();
+
+ None
+ }
+ }
+ }
+ _ => None,
+ },
+ [] => None,
+ _ => None,
+ },
+ None => None,
+ };
+ }
+ }
+
+ codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
+ if !attr.has_name(sym::inline) {
+ return ia;
+ }
+ match attr.meta_kind() {
+ Some(MetaItemKind::Word) => InlineAttr::Hint,
+ Some(MetaItemKind::List(ref items)) => {
+ inline_span = Some(attr.span);
+ if items.len() != 1 {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0534,
+ "expected one argument"
+ )
+ .emit();
+ InlineAttr::None
+ } else if list_contains_name(&items, sym::always) {
+ InlineAttr::Always
+ } else if list_contains_name(&items, sym::never) {
+ InlineAttr::Never
+ } else {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ items[0].span(),
+ E0535,
+ "invalid argument"
+ )
+ .help("valid inline arguments are `always` and `never`")
+ .emit();
+
+ InlineAttr::None
+ }
+ }
+ Some(MetaItemKind::NameValue(_)) => ia,
+ None => ia,
+ }
+ });
+
+ codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
+ if !attr.has_name(sym::optimize) {
+ return ia;
+ }
+ let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
+ match attr.meta_kind() {
+ Some(MetaItemKind::Word) => {
+ err(attr.span, "expected one argument");
+ ia
+ }
+ Some(MetaItemKind::List(ref items)) => {
+ inline_span = Some(attr.span);
+ if items.len() != 1 {
+ err(attr.span, "expected one argument");
+ OptimizeAttr::None
+ } else if list_contains_name(&items, sym::size) {
+ OptimizeAttr::Size
+ } else if list_contains_name(&items, sym::speed) {
+ OptimizeAttr::Speed
+ } else {
+ err(items[0].span(), "invalid argument");
+ OptimizeAttr::None
+ }
+ }
+ Some(MetaItemKind::NameValue(_)) => ia,
+ None => ia,
+ }
+ });
+
+ // #73631: closures inherit `#[target_feature]` annotations
+ if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
+ let owner_id = tcx.parent(did.to_def_id());
+ if tcx.def_kind(owner_id).has_codegen_attrs() {
+ codegen_fn_attrs
+ .target_features
+ .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
+ }
+ }
+
+ // If a function uses #[target_feature] it can't be inlined into general
+ // purpose functions as they wouldn't have the right target features
+ // enabled. For that reason we also forbid #[inline(always)] as it can't be
+ // respected.
+ if !codegen_fn_attrs.target_features.is_empty() {
+ if codegen_fn_attrs.inline == InlineAttr::Always {
+ if let Some(span) = inline_span {
+ tcx.sess.span_err(
+ span,
+ "cannot use `#[inline(always)]` with \
+ `#[target_feature]`",
+ );
+ }
+ }
+ }
+
+ if !codegen_fn_attrs.no_sanitize.is_empty() {
+ if codegen_fn_attrs.inline == InlineAttr::Always {
+ if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+ tcx.struct_span_lint_hir(
+ lint::builtin::INLINE_NO_SANITIZE,
+ hir_id,
+ no_sanitize_span,
+ "`no_sanitize` will have no effect after inlining",
+ |lint| lint.span_note(inline_span, "inlining requested here"),
+ )
+ }
+ }
+ }
+
+ if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
+ codegen_fn_attrs.inline = InlineAttr::Never;
+ }
+
+ // Weak lang items have the same semantics as "std internal" symbols in the
+ // sense that they're preserved through all our LTO passes and only
+ // strippable by the linker.
+ //
+ // Additionally weak lang items have predetermined symbol names.
+ if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
+ }
+ if let Some((name, _)) = lang_items::extract(attrs)
+ && let Some(lang_item) = LangItem::from_name(name)
+ && let Some(link_name) = lang_item.link_name()
+ {
+ codegen_fn_attrs.export_name = Some(link_name);
+ codegen_fn_attrs.link_name = Some(link_name);
+ }
+ check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
+
+ // Internal symbols to the standard library all have no_mangle semantics in
+ // that they have defined symbol names present in the function name. This
+ // also applies to weak symbols where they all have known symbol names.
+ if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
+ }
+
+ // Any linkage to LLVM intrinsics for now forcibly marks them all as never
+ // unwinds since LLVM sometimes can't handle codegen which `invoke`s
+ // intrinsic functions.
+ if let Some(name) = &codegen_fn_attrs.link_name {
+ if name.as_str().starts_with("llvm.") {
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+ }
+ }
+
+ codegen_fn_attrs
+}
+
+/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
+/// applied to the method prototype.
+fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ if let Some(impl_item) = tcx.opt_associated_item(def_id)
+ && let ty::AssocItemContainer::ImplContainer = impl_item.container
+ && let Some(trait_item) = impl_item.trait_item_def_id
+ {
+ return tcx
+ .codegen_fn_attrs(trait_item)
+ .flags
+ .intersects(CodegenFnAttrFlags::TRACK_CALLER);
+ }
+
+ false
+}
+
+fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
+ use rustc_ast::{LitIntType, LitKind, MetaItemLit};
+ if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::raw_dylib,
+ attr.span,
+ "`#[link_ordinal]` is unstable on x86",
+ )
+ .emit();
+ }
+ let meta_item_list = attr.meta_item_list();
+ let meta_item_list = meta_item_list.as_deref();
+ let sole_meta_list = match meta_item_list {
+ Some([item]) => item.lit(),
+ Some(_) => {
+ tcx.sess
+ .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
+ .note("the attribute requires exactly one argument")
+ .emit();
+ return None;
+ }
+ _ => None,
+ };
+ if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
+ sole_meta_list
+ {
+ // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
+ // the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined
+ // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
+ // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
+ //
+ // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this:
+ // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
+ // a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library
+ // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
+ // library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet
+ // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
+ // about LINK.EXE failing.)
+ if *ordinal <= u16::MAX as u128 {
+ Some(*ordinal as u16)
+ } else {
+ let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
+ tcx.sess
+ .struct_span_err(attr.span, &msg)
+ .note("the value may not exceed `u16::MAX`")
+ .emit();
+ None
+ }
+ } else {
+ tcx.sess
+ .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
+ .note("an unsuffixed integer value, e.g., `1`, is expected")
+ .emit();
+ None
+ }
+}
+
+fn check_link_name_xor_ordinal(
+ tcx: TyCtxt<'_>,
+ codegen_fn_attrs: &CodegenFnAttrs,
+ inline_span: Option<Span>,
+) {
+ if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
+ return;
+ }
+ let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
+ if let Some(span) = inline_span {
+ tcx.sess.span_err(span, msg);
+ } else {
+ tcx.sess.err(msg);
+ }
+}
+
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
+}
let projection_bounds: SmallVec<[_; 4]> = trait_data
.projection_bounds()
.map(|bound| {
- let ExistentialProjection { item_def_id, term, .. } =
+ let ExistentialProjection { def_id: item_def_id, term, .. } =
tcx.erase_late_bound_regions(bound);
// FIXME(associated_const_equality): allow for consts here
(item_def_id, term.ty().unwrap())
ty::Error(_)
| ty::Infer(_)
| ty::Placeholder(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Bound(..)
- | ty::Opaque(..)
| ty::GeneratorWitness(..) => {
bug!(
"debuginfo: Trying to create type name for \
pub struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_used_symbol)]
+pub struct ExpectedUsedSymbol {
+ #[primary_span]
+ pub span: Span,
+}
pub mod back;
pub mod base;
+pub mod codegen_attrs;
pub mod common;
pub mod coverageinfo;
pub mod debuginfo;
crate::back::symbol_export::provide(providers);
crate::base::provide(providers);
crate::target_features::provide(providers);
+ crate::codegen_attrs::provide(providers);
}
pub fn provide_extern(providers: &mut ExternProviders) {
let typeid =
bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty)));
let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes();
- let type_checked_load = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
- let func = bx.extract_value(type_checked_load, 0);
+ let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
bx.pointercast(func, llty)
} else {
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
bx.cleanup_ret(funclet, None);
} else {
let slot = self.get_personality_slot(bx);
- let lp0 = slot.project_field(bx, 0);
- let lp0 = bx.load_operand(lp0).immediate();
- let lp1 = slot.project_field(bx, 1);
- let lp1 = bx.load_operand(lp1).immediate();
+ let exn0 = slot.project_field(bx, 0);
+ let exn0 = bx.load_operand(exn0).immediate();
+ let exn1 = slot.project_field(bx, 1);
+ let exn1 = bx.load_operand(exn1).immediate();
slot.storage_dead(bx);
- let mut lp = bx.const_undef(self.landing_pad_type());
- lp = bx.insert_value(lp, lp0, 0);
- lp = bx.insert_value(lp, lp1, 1);
- bx.resume(lp);
+ bx.resume(exn0, exn1);
}
}
helper: TerminatorCodegenHelper<'tcx>,
bx: &mut Bx,
discr: &mir::Operand<'tcx>,
- switch_ty: Ty<'tcx>,
targets: &SwitchTargets,
) {
let discr = self.codegen_operand(bx, &discr);
- // `switch_ty` is redundant, sanity-check that.
- assert_eq!(discr.layout.ty, switch_ty);
+ let switch_ty = discr.layout.ty;
let mut target_iter = targets.iter();
if target_iter.len() == 1 {
// If there are two targets (one conditional, one fallback), emit `br` instead of
let (instance, mut llfn) = match *callee.layout.ty.kind() {
ty::FnDef(def_id, substs) => (
Some(
- ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs)
- .unwrap()
- .unwrap()
- .polymorphize(bx.tcx()),
+ ty::Instance::expect_resolve(
+ bx.tcx(),
+ ty::ParamEnv::reveal_all(),
+ def_id,
+ substs,
+ )
+ .polymorphize(bx.tcx()),
),
None,
),
helper.funclet_br(self, bx, target, mergeable_succ())
}
- mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => {
- self.codegen_switchint_terminator(helper, bx, discr, switch_ty, targets);
+ mir::TerminatorKind::SwitchInt { ref discr, ref targets } => {
+ self.codegen_switchint_terminator(helper, bx, discr, targets);
MergingSucc::False
}
let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
let llpersonality = self.cx.eh_personality();
- let llretty = self.landing_pad_type();
- let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality);
+ let (exn0, exn1) = cleanup_bx.cleanup_landing_pad(llpersonality);
let slot = self.get_personality_slot(&mut cleanup_bx);
slot.storage_live(&mut cleanup_bx);
- Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1))
- .store(&mut cleanup_bx, slot);
+ Pair(exn0, exn1).store(&mut cleanup_bx, slot);
cleanup_bx.br(llbb);
cleanup_llbb
}
}
- fn landing_pad_type(&self) -> Bx::Type {
- let cx = self.cx;
- cx.type_struct(&[cx.type_i8p(), cx.type_i32()], false)
- }
-
fn unreachable_block(&mut self) -> Bx::BasicBlock {
self.unreachable_block.unwrap_or_else(|| {
let llbb = Bx::append_block(self.cx, self.llfn, "unreachable");
self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
let llpersonality = self.cx.eh_personality();
- let llretty = self.landing_pad_type();
- bx.cleanup_landing_pad(llretty, llpersonality);
+ bx.cleanup_landing_pad(llpersonality);
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind);
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
match (src.layout.abi, dst.layout.abi) {
(abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
// HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
- if (src_scalar.primitive() == abi::Pointer)
- == (dst_scalar.primitive() == abi::Pointer)
- {
+ let src_is_ptr = src_scalar.primitive() == abi::Pointer;
+ let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
+ if src_is_ptr == dst_is_ptr {
assert_eq!(src.layout.size, dst.layout.size);
// NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
// conversions allow handling `bool`s the same as `u8`s.
let src = bx.from_immediate(src.immediate());
- let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
+ // LLVM also doesn't like `bitcast`s between pointers in different address spaces.
+ let src_as_dst = if src_is_ptr {
+ bx.pointercast(src, bx.backend_type(dst.layout))
+ } else {
+ bx.bitcast(src, bx.backend_type(dst.layout))
+ };
Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
return;
}
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir;
use rustc_middle::ty;
+use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_session::config::DebugInfo;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
-use rustc_target::abi::Abi;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Abi, Size, VariantIdx};
use super::operand::{OperandRef, OperandValue};
use super::place::PlaceRef;
}
}
+trait DebugInfoOffsetLocation<'tcx, Bx> {
+ fn deref(&self, bx: &mut Bx) -> Self;
+ fn layout(&self) -> TyAndLayout<'tcx>;
+ fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self;
+ fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+ for PlaceRef<'tcx, Bx::Value>
+{
+ fn deref(&self, bx: &mut Bx) -> Self {
+ bx.load_operand(*self).deref(bx.cx())
+ }
+
+ fn layout(&self) -> TyAndLayout<'tcx> {
+ self.layout
+ }
+
+ fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+ PlaceRef::project_field(*self, bx, field.index())
+ }
+
+ fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+ self.project_downcast(bx, variant)
+ }
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+ for TyAndLayout<'tcx>
+{
+ fn deref(&self, bx: &mut Bx) -> Self {
+ bx.cx().layout_of(
+ self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
+ )
+ }
+
+ fn layout(&self) -> TyAndLayout<'tcx> {
+ *self
+ }
+
+ fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+ self.field(bx.cx(), field.index())
+ }
+
+ fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+ self.for_variant(bx.cx(), variant)
+ }
+}
+
+struct DebugInfoOffset<T> {
+ /// Offset from the `base` used to calculate the debuginfo offset.
+ direct_offset: Size,
+ /// Each offset in this vector indicates one level of indirection from the base or previous
+ /// indirect offset plus a dereference.
+ indirect_offsets: Vec<Size>,
+ /// The final location debuginfo should point to.
+ result: T,
+}
+
+fn calculate_debuginfo_offset<
+ 'a,
+ 'tcx,
+ Bx: BuilderMethods<'a, 'tcx>,
+ L: DebugInfoOffsetLocation<'tcx, Bx>,
+>(
+ bx: &mut Bx,
+ local: mir::Local,
+ var: &PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
+ base: L,
+) -> DebugInfoOffset<L> {
+ let mut direct_offset = Size::ZERO;
+ // FIXME(eddyb) use smallvec here.
+ let mut indirect_offsets = vec![];
+ let mut place = base;
+
+ for elem in &var.projection[..] {
+ match *elem {
+ mir::ProjectionElem::Deref => {
+ indirect_offsets.push(Size::ZERO);
+ place = place.deref(bx);
+ }
+ mir::ProjectionElem::Field(field, _) => {
+ let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
+ *offset += place.layout().fields.offset(field.index());
+ place = place.project_field(bx, field);
+ }
+ mir::ProjectionElem::Downcast(_, variant) => {
+ place = place.downcast(bx, variant);
+ }
+ _ => span_bug!(
+ var.source_info.span,
+ "unsupported var debuginfo place `{:?}`",
+ mir::Place { local, projection: var.projection },
+ ),
+ }
+ }
+
+ DebugInfoOffset { direct_offset, indirect_offsets, result: place }
+}
+
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
bx.set_span(source_info.span);
let Some(dbg_var) = var.dbg_var else { continue };
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
- let mut direct_offset = Size::ZERO;
- // FIXME(eddyb) use smallvec here.
- let mut indirect_offsets = vec![];
- let mut place = base;
-
- for elem in &var.projection[..] {
- match *elem {
- mir::ProjectionElem::Deref => {
- indirect_offsets.push(Size::ZERO);
- place = bx.load_operand(place).deref(bx.cx());
- }
- mir::ProjectionElem::Field(field, _) => {
- let i = field.index();
- let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
- *offset += place.layout.fields.offset(i);
- place = place.project_field(bx, i);
- }
- mir::ProjectionElem::Downcast(_, variant) => {
- place = place.project_downcast(bx, variant);
- }
- _ => span_bug!(
- var.source_info.span,
- "unsupported var debuginfo place `{:?}`",
- mir::Place { local, projection: var.projection },
- ),
- }
- }
+ let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
+ calculate_debuginfo_offset(bx, local, &var, base.layout);
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
|| !matches!(&indirect_offsets[..], [Size::ZERO] | []));
if should_create_individual_allocas {
+ let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
+ calculate_debuginfo_offset(bx, local, &var, base);
+
// Create a variable which will be a pointer to the actual value
let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut {
mutbl: mir::Mutability::Mut,
assert!(bx.cx().tcx().is_static(def_id));
let static_ = bx.get_static(def_id);
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
- OperandRef::from_immediate_or_packed_pair(bx, static_, layout)
+ OperandRef { val: OperandValue::Immediate(static_), layout }
}
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
mir::Rvalue::Repeat(..) | mir::Rvalue::Aggregate(..) => {
+use rustc_ast::ast;
+use rustc_attr::InstructionSetAttr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::symbol::Symbol;
+use rustc_span::Span;
/// Features that control behaviour of rustc, rather than the codegen.
pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
}
}
-pub(crate) fn provide(providers: &mut Providers) {
- providers.supported_target_features = |tcx, cnum| {
- assert_eq!(cnum, LOCAL_CRATE);
- if tcx.sess.opts.actually_rustdoc {
- // rustdoc needs to be able to document functions that use all the features, so
- // whitelist them all
- all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
- } else {
- supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
- }
+pub fn from_target_feature(
+ tcx: TyCtxt<'_>,
+ attr: &ast::Attribute,
+ supported_target_features: &FxHashMap<String, Option<Symbol>>,
+ target_features: &mut Vec<Symbol>,
+) {
+ let Some(list) = attr.meta_item_list() else { return };
+ let bad_item = |span| {
+ let msg = "malformed `target_feature` attribute input";
+ let code = "enable = \"..\"";
+ tcx.sess
+ .struct_span_err(span, msg)
+ .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
+ .emit();
};
+ let rust_features = tcx.features();
+ for item in list {
+ // Only `enable = ...` is accepted in the meta-item list.
+ if !item.has_name(sym::enable) {
+ bad_item(item.span());
+ continue;
+ }
+
+ // Must be of the form `enable = "..."` (a string).
+ let Some(value) = item.value_str() else {
+ bad_item(item.span());
+ continue;
+ };
+
+ // We allow comma separation to enable multiple features.
+ target_features.extend(value.as_str().split(',').filter_map(|feature| {
+ let Some(feature_gate) = supported_target_features.get(feature) else {
+ let msg =
+ format!("the feature named `{}` is not valid for this target", feature);
+ let mut err = tcx.sess.struct_span_err(item.span(), &msg);
+ err.span_label(
+ item.span(),
+ format!("`{}` is not valid for this target", feature),
+ );
+ if let Some(stripped) = feature.strip_prefix('+') {
+ let valid = supported_target_features.contains_key(stripped);
+ if valid {
+ err.help("consider removing the leading `+` in the feature name");
+ }
+ }
+ err.emit();
+ return None;
+ };
+
+ // Only allow features whose feature gates have been enabled.
+ let allowed = match feature_gate.as_ref().copied() {
+ Some(sym::arm_target_feature) => rust_features.arm_target_feature,
+ Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
+ Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
+ Some(sym::mips_target_feature) => rust_features.mips_target_feature,
+ Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
+ Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
+ Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
+ Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
+ Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
+ Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
+ Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
+ Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
+ Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
+ Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+ Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
+ Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
+ Some(name) => bug!("unknown target feature gate {}", name),
+ None => true,
+ };
+ if !allowed {
+ feature_err(
+ &tcx.sess.parse_sess,
+ feature_gate.unwrap(),
+ item.span(),
+ &format!("the target feature `{}` is currently unstable", feature),
+ )
+ .emit();
+ }
+ Some(Symbol::intern(feature))
+ }));
+ }
+}
+
+/// Computes the set of target features used in a function for the purposes of
+/// inline assembly.
+fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
+ let mut target_features = tcx.sess.unstable_target_features.clone();
+ if tcx.def_kind(did).has_codegen_attrs() {
+ let attrs = tcx.codegen_fn_attrs(did);
+ target_features.extend(&attrs.target_features);
+ match attrs.instruction_set {
+ None => {}
+ Some(InstructionSetAttr::ArmA32) => {
+ target_features.remove(&sym::thumb_mode);
+ }
+ Some(InstructionSetAttr::ArmT32) => {
+ target_features.insert(sym::thumb_mode);
+ }
+ }
+ }
+
+ tcx.arena.alloc(target_features)
+}
+
+/// Checks the function annotated with `#[target_feature]` is not a safe
+/// trait method implementation, reporting an error if it is.
+pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(id);
+ let node = tcx.hir().get(hir_id);
+ if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
+ let parent_id = tcx.hir().get_parent_item(hir_id);
+ let parent_item = tcx.hir().expect_item(parent_id.def_id);
+ if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+ tcx.sess
+ .struct_span_err(
+ attr_span,
+ "`#[target_feature(..)]` cannot be applied to safe trait method",
+ )
+ .span_label(attr_span, "cannot be applied to safe trait method")
+ .span_label(tcx.def_span(id), "not an `unsafe` function")
+ .emit();
+ }
+ }
+}
+
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers {
+ supported_target_features: |tcx, cnum| {
+ assert_eq!(cnum, LOCAL_CRATE);
+ if tcx.sess.opts.actually_rustdoc {
+ // rustdoc needs to be able to document functions that use all the features, so
+ // whitelist them all
+ all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
+ } else {
+ supported_target_features(tcx.sess)
+ .iter()
+ .map(|&(a, b)| (a.to_string(), b))
+ .collect()
+ }
+ },
+ asm_target_features,
+ ..*providers
+ }
}
fn set_personality_fn(&mut self, personality: Self::Value);
// These are used by everyone except msvc
- fn cleanup_landing_pad(&mut self, ty: Self::Type, pers_fn: Self::Value) -> Self::Value;
- fn resume(&mut self, exn: Self::Value);
+ fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
+ fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
// These are used only by msvc
fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
fn set_type_metadata(&self, function: Self::Function, typeid: String);
fn typeid_metadata(&self, typeid: String) -> Self::Value;
+ fn set_kcfi_type_metadata(&self, function: Self::Function, typeid: u32);
}
pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
self.report_decorated(tcx, message, |_| {})
}
+ #[instrument(level = "trace", skip(self, decorate))]
+ pub(super) fn decorate(&self, err: &mut Diagnostic, decorate: impl FnOnce(&mut Diagnostic)) {
+ trace!("reporting const eval failure at {:?}", self.span);
+ // Add some more context for select error types.
+ match self.error {
+ InterpError::Unsupported(
+ UnsupportedOpInfo::ReadPointerAsBytes
+ | UnsupportedOpInfo::PartialPointerOverwrite(_)
+ | UnsupportedOpInfo::PartialPointerCopy(_),
+ ) => {
+ err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
+ err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
+ }
+ _ => {}
+ }
+ // Add spans for the stacktrace. Don't print a single-line backtrace though.
+ if self.stacktrace.len() > 1 {
+ // Helper closure to print duplicated lines.
+ let mut flush_last_line = |last_frame, times| {
+ if let Some((line, span)) = last_frame {
+ err.span_note(span, &line);
+ // Don't print [... additional calls ...] if the number of lines is small
+ if times < 3 {
+ for _ in 0..times {
+ err.span_note(span, &line);
+ }
+ } else {
+ err.span_note(
+ span,
+ format!("[... {} additional calls {} ...]", times, &line),
+ );
+ }
+ }
+ };
+
+ let mut last_frame = None;
+ let mut times = 0;
+ for frame_info in &self.stacktrace {
+ let frame = (frame_info.to_string(), frame_info.span);
+ if last_frame.as_ref() == Some(&frame) {
+ times += 1;
+ } else {
+ flush_last_line(last_frame, times);
+ last_frame = Some(frame);
+ times = 0;
+ }
+ }
+ flush_last_line(last_frame, times);
+ }
+ // Let the caller attach any additional information it wants.
+ decorate(err);
+ }
+
/// Create a diagnostic for this const eval error.
///
/// Sets the message passed in via `message` and adds span labels with detailed error
message: &str,
decorate: impl FnOnce(&mut Diagnostic),
) -> ErrorHandled {
- let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
- trace!("reporting const eval failure at {:?}", self.span);
- if let Some(span_msg) = span_msg {
- err.span_label(self.span, span_msg);
- }
- // Add some more context for select error types.
- match self.error {
- InterpError::Unsupported(
- UnsupportedOpInfo::ReadPointerAsBytes
- | UnsupportedOpInfo::PartialPointerOverwrite(_)
- | UnsupportedOpInfo::PartialPointerCopy(_),
- ) => {
- err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
- err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
- }
- _ => {}
- }
- // Add spans for the stacktrace. Don't print a single-line backtrace though.
- if self.stacktrace.len() > 1 {
- // Helper closure to print duplicated lines.
- let mut flush_last_line = |last_frame, times| {
- if let Some((line, span)) = last_frame {
- err.span_label(span, &line);
- // Don't print [... additional calls ...] if the number of lines is small
- if times < 3 {
- for _ in 0..times {
- err.span_label(span, &line);
- }
- } else {
- err.span_label(
- span,
- format!("[... {} additional calls {} ...]", times, &line),
- );
- }
- }
- };
-
- let mut last_frame = None;
- let mut times = 0;
- for frame_info in &self.stacktrace {
- let frame = (frame_info.to_string(), frame_info.span);
- if last_frame.as_ref() == Some(&frame) {
- times += 1;
- } else {
- flush_last_line(last_frame, times);
- last_frame = Some(frame);
- times = 0;
- }
- }
- flush_last_line(last_frame, times);
- }
- // Let the caller attach any additional information it wants.
- decorate(err);
- };
-
debug!("self.error: {:?}", self.error);
// Special handling for certain errors
match &self.error {
// Don't emit a new diagnostic for these errors
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
- return ErrorHandled::TooGeneric;
- }
- err_inval!(AlreadyReported(error_reported)) => {
- return ErrorHandled::Reported(*error_reported);
+ ErrorHandled::TooGeneric
}
+ err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(*error_reported),
err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
// We must *always* hard error on these, even if the caller wants just a lint.
// The `message` makes little sense here, this is a more serious error than the
// caller thinks anyway.
// See <https://github.com/rust-lang/rust/pull/63152>.
let mut err = struct_error(tcx, &self.error.to_string());
- finish(&mut err, None);
- return ErrorHandled::Reported(err.emit());
+ self.decorate(&mut err, decorate);
+ ErrorHandled::Reported(err.emit())
}
- _ => {}
- };
-
- let err_msg = self.error.to_string();
-
- // Report as hard error.
- let mut err = struct_error(tcx, message);
- finish(&mut err, Some(err_msg));
- ErrorHandled::Reported(err.emit())
+ _ => {
+ // Report as hard error.
+ let mut err = struct_error(tcx, message);
+ err.span_label(self.span, self.error.to_string());
+ self.decorate(&mut err, decorate);
+ ErrorHandled::Reported(err.emit())
+ }
+ }
}
}
+use crate::const_eval::CheckAlignment;
use std::borrow::Cow;
-use std::convert::TryInto;
use either::{Left, Right};
None => InternKind::Constant,
}
};
- ecx.machine.check_alignment = false; // interning doesn't need to respect alignment
+ ecx.machine.check_alignment = CheckAlignment::No; // interning doesn't need to respect alignment
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
// we leave alignment checks off, since this `ecx` will not be used for further evaluation anyway
tcx,
root_span,
param_env,
- CompileTimeInterpreter::new(
- tcx.const_eval_limit(),
- can_access_statics,
- /*check_alignment:*/ false,
- ),
+ CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics, CheckAlignment::No),
)
}
CompileTimeInterpreter::new(
tcx.const_eval_limit(),
/*can_access_statics:*/ is_static,
- /*check_alignment:*/ tcx.sess.opts.unstable_opts.extra_const_ub_checks,
+ if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+ CheckAlignment::Error
+ } else {
+ CheckAlignment::FutureIncompat
+ },
),
);
use rustc_hir::def::DefKind;
-use rustc_hir::LangItem;
+use rustc_hir::{LangItem, CRATE_HIR_ID};
use rustc_middle::mir;
use rustc_middle::mir::interpret::PointerArithmetic;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::INVALID_ALIGNMENT;
use std::borrow::Borrow;
use std::hash::Hash;
use std::ops::ControlFlow;
pub(super) can_access_statics: bool,
/// Whether to check alignment during evaluation.
- pub(super) check_alignment: bool,
+ pub(super) check_alignment: CheckAlignment,
+}
+
+#[derive(Copy, Clone)]
+pub enum CheckAlignment {
+ /// Ignore alignment when following relocations.
+ /// This is mainly used in interning.
+ No,
+ /// Hard error when dereferencing a misaligned pointer.
+ Error,
+ /// Emit a future incompat lint when dereferencing a misaligned pointer.
+ FutureIncompat,
+}
+
+impl CheckAlignment {
+ pub fn should_check(&self) -> bool {
+ match self {
+ CheckAlignment::No => false,
+ CheckAlignment::Error | CheckAlignment::FutureIncompat => true,
+ }
+ }
}
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(crate) fn new(
const_eval_limit: Limit,
can_access_statics: bool,
- check_alignment: bool,
+ check_alignment: CheckAlignment,
) -> Self {
CompileTimeInterpreter {
steps_remaining: const_eval_limit.0,
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
#[inline(always)]
- fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+ fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
ecx.machine.check_alignment
}
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
}
+ fn alignment_check_failed(
+ ecx: &InterpCx<'mir, 'tcx, Self>,
+ has: Align,
+ required: Align,
+ check: CheckAlignment,
+ ) -> InterpResult<'tcx, ()> {
+ let err = err_ub!(AlignmentCheckFailed { has, required }).into();
+ match check {
+ CheckAlignment::Error => Err(err),
+ CheckAlignment::No => span_bug!(
+ ecx.cur_span(),
+ "`alignment_check_failed` called when no alignment check requested"
+ ),
+ CheckAlignment::FutureIncompat => {
+ let err = ConstEvalErr::new(ecx, err, None);
+ ecx.tcx.struct_span_lint_hir(
+ INVALID_ALIGNMENT,
+ ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
+ err.span,
+ err.error.to_string(),
+ |db| {
+ err.decorate(db, |_| {});
+ db
+ },
+ );
+ Ok(())
+ }
+ }
+ }
+
fn load_mir(
ecx: &InterpCx<'mir, 'tcx, Self>,
instance: ty::InstanceDef<'tcx>,
| ty::Foreign(..)
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_))
- | ty::Projection(..)
+ // FIXME(oli-obk): we could look behind opaque types
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
- // FIXME(oli-obk): we could look behind opaque types
- | ty::Opaque(..)
| ty::Infer(_)
// FIXME(oli-obk): we can probably encode closures just like structs
| ty::Closure(..)
| ty::Foreign(..)
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_))
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
- | ty::Opaque(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::Generator(..)
use std::assert_matches::assert_matches;
-use std::convert::TryFrom;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::{Float, FloatConvert};
Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
self.write_immediate(val, dest)
}
- (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+ (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
let val = self.read_immediate(src)?;
if data_a.principal() == data_b.principal() {
// A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_session::Limit;
-use rustc_span::{Pos, Span};
+use rustc_span::Span;
use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
use super::{
Right(span) => span,
}
}
+
+ pub fn lint_root(&self) -> Option<hir::HirId> {
+ self.current_source_info().and_then(|source_info| {
+ match &self.body.source_scopes[source_info.scope].local_data {
+ mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+ mir::ClearCrossCrate::Clear => None,
+ }
+ })
+ }
}
impl<'tcx> fmt::Display for FrameInfo<'tcx> {
if tcx.def_key(self.instance.def_id()).disambiguated_data.data
== DefPathData::ClosureExpr
{
- write!(f, "inside closure")?;
+ write!(f, "inside closure")
} else {
// Note: this triggers a `good_path_bug` state, which means that if we ever get here
// we must emit a diagnostic. We should never display a `FrameInfo` unless we
// actually want to emit a warning or error to the user.
- write!(f, "inside `{}`", self.instance)?;
+ write!(f, "inside `{}`", self.instance)
}
- if !self.span.is_dummy() {
- let sm = tcx.sess.source_map();
- let lo = sm.lookup_char_pos(self.span.lo());
- write!(
- f,
- " at {}:{}:{}",
- sm.filename_for_diagnostics(&lo.file.name),
- lo.line,
- lo.col.to_usize() + 1
- )?;
- }
- Ok(())
})
}
}
// This deliberately does *not* honor `requires_caller_location` since it is used for much
// more than just panics.
for frame in stack.iter().rev() {
- 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),
- mir::ClearCrossCrate::Clear => None,
- }
- });
+ let lint_root = frame.lint_root();
let span = frame.current_span();
frames.push(FrameInfo { span, instance: frame.instance, lint_root });
//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
//! and miri.
-use std::convert::TryFrom;
-
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
ty::Adt(ref adt, _) => {
ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx)
}
- ty::Projection(_)
- | ty::Opaque(_, _)
- | ty::Param(_)
- | ty::Placeholder(_)
- | ty::Infer(_) => throw_inval!(TooGeneric),
+ ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
+ throw_inval!(TooGeneric)
+ }
ty::Bound(_, _) => bug!("bound ty during ctfe"),
ty::Bool
| ty::Char
-use std::convert::TryFrom;
-
use rustc_ast::Mutability;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::TerminatorKind;
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::DefId;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi as CallAbi;
+use crate::const_eval::CheckAlignment;
+
use super::{
AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
const PANIC_ON_ALLOC_FAIL: bool;
/// Whether memory accesses should be alignment-checked.
- fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+ fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
/// Whether, when checking alignment, we should look at the actual address and thus support
/// custom alignment logic based on whatever the integer address happens to be.
/// If this returns true, Provenance::OFFSET_IS_ADDR must be true.
fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+ fn alignment_check_failed(
+ ecx: &InterpCx<'mir, 'tcx, Self>,
+ has: Align,
+ required: Align,
+ check: CheckAlignment,
+ ) -> InterpResult<'tcx, ()>;
+
/// Whether to enforce the validity invariant
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
Ok(())
}
- /// Executes a retagging operation.
+ /// Executes a retagging operation for a single pointer.
+ /// Returns the possibly adjusted pointer.
+ #[inline]
+ fn retag_ptr_value(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ _kind: mir::RetagKind,
+ val: &ImmTy<'tcx, Self::Provenance>,
+ ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
+ Ok(val.clone())
+ }
+
+ /// Executes a retagging operation on a compound value.
+ /// Replaces all pointers stored in the given place.
#[inline]
- fn retag(
+ fn retag_place_contents(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_kind: mir::RetagKind,
_place: &PlaceTy<'tcx, Self::Provenance>,
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
use rustc_target::abi::{Align, HasDataLayout, Size};
+use crate::const_eval::CheckAlignment;
+
use super::{
alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
- let align = M::enforce_alignment(&self).then_some(align);
self.check_and_deref_ptr(
ptr,
size,
align,
+ M::enforce_alignment(self),
CheckInAllocMsg::MemoryAccessTest,
|alloc_id, offset, prov| {
let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
align: Align,
msg: CheckInAllocMsg,
) -> InterpResult<'tcx> {
- self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
- let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
- Ok((size, align, ()))
- })?;
+ self.check_and_deref_ptr(
+ ptr,
+ size,
+ align,
+ CheckAlignment::Error,
+ msg,
+ |alloc_id, _, _| {
+ let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
+ Ok((size, align, ()))
+ },
+ )?;
Ok(())
}
&self,
ptr: Pointer<Option<M::Provenance>>,
size: Size,
- align: Option<Align>,
+ align: Align,
+ check: CheckAlignment,
msg: CheckInAllocMsg,
alloc_size: impl FnOnce(
AllocId,
M::ProvenanceExtra,
) -> InterpResult<'tcx, (Size, Align, T)>,
) -> InterpResult<'tcx, Option<T>> {
- fn check_offset_align<'tcx>(offset: u64, align: Align) -> InterpResult<'tcx> {
- if offset % align.bytes() == 0 {
- Ok(())
- } else {
- // The biggest power of two through which `offset` is divisible.
- let offset_pow2 = 1 << offset.trailing_zeros();
- throw_ub!(AlignmentCheckFailed {
- has: Align::from_bytes(offset_pow2).unwrap(),
- required: align,
- })
- }
- }
-
Ok(match self.ptr_try_get_alloc_id(ptr) {
Err(addr) => {
// We couldn't get a proper allocation. This is only okay if the access size is 0,
throw_ub!(DanglingIntPointer(addr, msg));
}
// Must be aligned.
- if let Some(align) = align {
- check_offset_align(addr, align)?;
+ if check.should_check() {
+ self.check_offset_align(addr, align, check)?;
}
None
}
}
// Test align. Check this last; if both bounds and alignment are violated
// we want the error to be about the bounds.
- if let Some(align) = align {
+ if check.should_check() {
if M::use_addr_for_alignment_check(self) {
// `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
- check_offset_align(ptr.addr().bytes(), align)?;
+ self.check_offset_align(ptr.addr().bytes(), align, check)?;
} else {
// Check allocation alignment and offset alignment.
if alloc_align.bytes() < align.bytes() {
- throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align });
+ M::alignment_check_failed(self, alloc_align, align, check)?;
}
- check_offset_align(offset.bytes(), align)?;
+ self.check_offset_align(offset.bytes(), align, check)?;
}
}
}
})
}
+
+ fn check_offset_align(
+ &self,
+ offset: u64,
+ align: Align,
+ check: CheckAlignment,
+ ) -> InterpResult<'tcx> {
+ if offset % align.bytes() == 0 {
+ Ok(())
+ } else {
+ // The biggest power of two through which `offset` is divisible.
+ let offset_pow2 = 1 << offset.trailing_zeros();
+ M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check)
+ }
+ }
}
/// Allocation accessors
size: Size,
align: Align,
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
- let align = M::enforce_alignment(self).then_some(align);
let ptr_and_alloc = self.check_and_deref_ptr(
ptr,
size,
align,
+ M::enforce_alignment(self),
CheckInAllocMsg::MemoryAccessTest,
|alloc_id, offset, prov| {
let alloc = self.get_alloc_raw(alloc_id)?;
impl<Prov: Provenance> From<Scalar<Prov>> for Immediate<Prov> {
#[inline(always)]
fn from(val: Scalar<Prov>) -> Self {
- Immediate::Scalar(val.into())
+ Immediate::Scalar(val)
}
}
}
pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
- Immediate::ScalarPair(val.into(), Scalar::from_machine_usize(len, cx).into())
+ Immediate::ScalarPair(val, Scalar::from_machine_usize(len, cx))
}
pub fn new_dyn_trait(
vtable: Pointer<Option<Prov>>,
cx: &impl HasDataLayout,
) -> Self {
- Immediate::ScalarPair(val.into(), Scalar::from_maybe_pointer(vtable, cx))
+ Immediate::ScalarPair(val, Scalar::from_maybe_pointer(vtable, cx))
}
#[inline]
alloc_range(b_offset, b_size),
/*read_provenance*/ b.is_ptr(),
)?;
- Some(ImmTy {
- imm: Immediate::ScalarPair(a_val.into(), b_val.into()),
- layout: mplace.layout,
- })
+ Some(ImmTy { imm: Immediate::ScalarPair(a_val, b_val), layout: mplace.layout })
}
_ => {
// Neither a scalar nor scalar pair.
-use std::convert::TryFrom;
-
use rustc_apfloat::Float;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
if let Abi::ScalarPair(..) = dest.layout.abi {
// We can use the optimized path and avoid `place_field` (which might do
// `force_allocation`).
- let pair = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
+ let pair = Immediate::ScalarPair(val, Scalar::from_bool(overflowed));
self.write_immediate(pair, dest)?;
} else {
assert!(self.tcx.sess.opts.unstable_opts.randomize_layout);
match self.meta {
MemPlaceMeta::None => Immediate::from(Scalar::from_maybe_pointer(self.ptr, cx)),
MemPlaceMeta::Meta(meta) => {
- Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx).into(), meta.into())
+ Immediate::ScalarPair(Scalar::from_maybe_pointer(self.ptr, cx), meta)
}
}
}
.size_and_align_of_mplace(&mplace)?
.unwrap_or((mplace.layout.size, mplace.layout.align.abi));
assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
- let align = M::enforce_alignment(self).then_some(align);
- self.check_ptr_access_align(
- mplace.ptr,
- size,
- align.unwrap_or(Align::ONE),
- CheckInAllocMsg::DerefTest,
- )?;
+ let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE };
+ self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?;
Ok(())
}
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;
-use super::{InterpCx, Machine};
+use super::{ImmTy, InterpCx, Machine};
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
// Stacked Borrows.
Retag(kind, place) => {
let dest = self.eval_place(**place)?;
- M::retag(self, *kind, &dest)?;
+ M::retag_place_contents(self, *kind, &dest)?;
}
Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
}
- AddressOf(_, place) | Ref(_, _, place) => {
+ Ref(_, borrow_kind, place) => {
let src = self.eval_place(place)?;
let place = self.force_allocation(&src)?;
- self.write_immediate(place.to_ref(self), &dest)?;
+ let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+ // A fresh reference was created, make sure it gets retagged.
+ let val = M::retag_ptr_value(
+ self,
+ if borrow_kind.allows_two_phase_borrow() {
+ mir::RetagKind::TwoPhase
+ } else {
+ mir::RetagKind::Default
+ },
+ &val,
+ )?;
+ self.write_immediate(*val, &dest)?;
+ }
+
+ AddressOf(_, place) => {
+ // Figure out whether this is an addr_of of an already raw place.
+ let place_base_raw = if place.has_deref() {
+ let ty = self.frame().body.local_decls[place.local].ty;
+ ty.is_unsafe_ptr()
+ } else {
+ // Not a deref, and thus not raw.
+ false
+ };
+
+ let src = self.eval_place(place)?;
+ let place = self.force_allocation(&src)?;
+ let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+ if !place_base_raw {
+ // If this was not already raw, it needs retagging.
+ val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
+ }
+ self.write_immediate(*val, &dest)?;
}
NullaryOp(null_op, ty) => {
Goto { target } => self.go_to_block(target),
- SwitchInt { ref discr, ref targets, switch_ty } => {
+ SwitchInt { ref discr, ref targets } => {
let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
trace!("SwitchInt({:?})", *discr);
- assert_eq!(discr.layout.ty, switch_ty);
// Branch to the `otherwise` case by default, if no match is found.
let mut target_block = targets.otherwise();
use rustc_middle::mir::interpret::InterpResult;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use std::convert::TryInto;
use std::ops::ControlFlow;
/// Checks whether a type contains generic parameters which require substitution.
//! That's useful because it means other passes (e.g. promotion) can rely on `const`s
//! to be const-safe.
-use std::convert::TryFrom;
use std::fmt::{Display, Write};
use std::num::NonZeroUsize;
| ty::Placeholder(..)
| ty::Bound(..)
| ty::Param(..)
- | ty::Opaque(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
}
}
use rustc_data_structures::fx::FxHashSet;
use rustc_index::bit_set::BitSet;
+use rustc_infer::traits::Reveal;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
return;
}
let def_id = body.source.def_id();
- let param_env = tcx.param_env(def_id);
let mir_phase = self.mir_phase;
+ let param_env = match mir_phase.reveal() {
+ Reveal::UserFacing => tcx.param_env(def_id),
+ Reveal::All => tcx.param_env_reveal_all_normalized(def_id),
+ };
let always_live_locals = always_storage_live_locals(body);
- let storage_liveness = MaybeStorageLive::new(always_live_locals)
+ let storage_liveness = MaybeStorageLive::new(std::borrow::Cow::Owned(always_live_locals))
.into_engine(tcx, body)
.iterate_to_fixpoint()
.into_results_cursor(body);
param_env: ParamEnv<'tcx>,
mir_phase: MirPhase,
reachable_blocks: BitSet<BasicBlock>,
- storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
+ storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
place_cache: Vec<PlaceRef<'tcx>>,
value_cache: Vec<u128>,
}
};
let kind = match parent_ty.ty.kind() {
- &ty::Opaque(def_id, substs) => {
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
}
kind => kind,
self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
}
let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
- if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Opaque(..)) {
+ if !matches!(pty, ty::Adt(..) | ty::Generator(..) | ty::Alias(ty::Opaque, ..)) {
self.fail(
location,
format!(
TerminatorKind::Goto { target } => {
self.check_edge(location, *target, EdgeKind::Normal);
}
- TerminatorKind::SwitchInt { targets, switch_ty, discr } => {
- let ty = discr.ty(&self.body.local_decls, self.tcx);
- if ty != *switch_ty {
- self.fail(
- location,
- format!(
- "encountered `SwitchInt` terminator with type mismatch: {:?} != {:?}",
- ty, switch_ty,
- ),
- );
- }
+ TerminatorKind::SwitchInt { targets, discr } => {
+ let switch_ty = discr.ty(&self.body.local_decls, self.tcx);
let target_width = self.tcx.sess.target.pointer_width;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
-use std::convert::TryFrom;
use std::iter::TrustedLen;
/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
use rustc_hir::def_id::DefId;
use rustc_hir::{lang_items, LangItem};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind, Span};
Normal {
self_arg: Option<Ident>,
desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
- /// Whether the self type of the method call has an `.as_ref()` method.
- /// Used for better diagnostics.
- is_option_or_result: bool,
+ method_did: DefId,
},
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
} else {
None
};
- let parent_did = tcx.parent(method_did);
- let parent_self_ty = (tcx.def_kind(parent_did) == rustc_hir::def::DefKind::Impl)
- .then_some(parent_did)
- .and_then(|did| match tcx.type_of(did).kind() {
- ty::Adt(def, ..) => Some(def.did()),
- _ => None,
- });
- let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
- matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
- });
- CallKind::Normal { self_arg, desugaring, is_option_or_result }
+ CallKind::Normal { self_arg, desugaring, method_did }
})
}
use rustc_session::Limit;
use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
-use crate::const_eval::CompileTimeInterpreter;
+use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
let machine = CompileTimeInterpreter::new(
Limit::new(0),
/*can_access_statics:*/ false,
- /*check_alignment:*/ true,
+ CheckAlignment::Error,
);
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
// Types with identity (print the module path).
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
| ty::FnDef(def_id, substs)
- | ty::Opaque(def_id, substs)
- | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+ | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
| ty::Closure(def_id, substs)
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
pub const ALPHANUMERIC_ONLY: usize = 62;
pub const CASE_INSENSITIVE: usize = 36;
-const BASE_64: &[u8; MAX_BASE as usize] =
+const BASE_64: &[u8; MAX_BASE] =
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
#[inline]
use crate::stable_hasher;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
use std::hash::{Hash, Hasher};
#[cfg(test)]
use crate::graph::vec_graph::VecGraph;
use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
use rustc_index::vec::{Idx, IndexVec};
-use std::cmp::Ord;
use std::ops::Range;
#[cfg(test)]
-use std::cmp::Ord;
-
use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors};
use rustc_index::vec::{Idx, IndexVec};
/////////////////////////////////////////////////////////////////////////////
use std::borrow::Borrow;
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
-use std::convert::From;
+use std::cmp::Ordering;
use std::fmt::{self, Debug};
use std::hash::{Hash, Hasher};
-use std::marker::{Send, Sync};
impl<O, T: ?Sized> Deref for OwningRef<O, T> {
type Target = T;
// std types integration and convenience type defs
/////////////////////////////////////////////////////////////////////////////
-use std::boxed::Box;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
use std::sync::Arc;
mod owning_ref {
use super::super::OwningRef;
use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef};
- use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+ use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
mod owning_ref_mut {
use super::super::BoxRef;
use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut};
- use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
+ use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
-use std::convert::Into;
use std::error::Error;
use std::fs;
use std::path::Path;
use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
use std::borrow::Borrow;
use std::cmp::Ordering;
-use std::iter::FromIterator;
use std::mem;
use std::ops::{Bound, Index, IndexMut, RangeBounds};
/// Iterate over the keys, sorted
#[inline]
pub fn keys(&self) -> impl Iterator<Item = &K> + ExactSizeIterator + DoubleEndedIterator {
- self.data.iter().map(|&(ref k, _)| k)
+ self.data.iter().map(|(k, _)| k)
}
/// Iterate over values, sorted by key
#[inline]
pub fn values(&self) -> impl Iterator<Item = &V> + ExactSizeIterator + DoubleEndedIterator {
- self.data.iter().map(|&(_, ref v)| v)
+ self.data.iter().map(|(_, v)| v)
}
#[inline]
K: Borrow<Q>,
Q: Ord + ?Sized,
{
- self.data.binary_search_by(|&(ref x, _)| x.borrow().cmp(key))
+ self.data.binary_search_by(|(x, _)| x.borrow().cmp(key))
}
#[inline]
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let mut data: Vec<(K, V)> = iter.into_iter().collect();
- data.sort_unstable_by(|&(ref k1, _), &(ref k2, _)| k1.cmp(k2));
+ data.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
data.dedup_by(|&mut (ref k1, _), &mut (ref k2, _)| k1.cmp(k2) == Ordering::Equal);
SortedMap { data }
//! A variant of `SortedMap` that preserves insertion order.
use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
use crate::stable_hasher::{HashStable, StableHasher};
use rustc_index::vec::{Idx, IndexVec};
use std::fmt;
-use std::iter::ExactSizeIterator;
use std::iter::FusedIterator;
-use std::iter::Iterator;
/// Iterator which may contain instance of
/// one of two specific implementations.
use arrayvec::ArrayVec;
use std::fmt;
use std::hash::Hash;
-use std::iter::FromIterator;
use std::ops::Index;
// For pointer-sized arguments arrays
use std::fmt;
use std::hash::Hash;
-use std::iter::FromIterator;
use super::map::SsoHashMap;
}
}
- pub use std::iter::Iterator as ParallelIterator;
+ pub use Iterator as ParallelIterator;
pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
t.into_iter()
fn drop(&mut self) {
// No need to drop the tag, as it's Copy
unsafe {
- std::mem::drop(P::from_usize(self.raw.pointer_raw()));
+ drop(P::from_usize(self.raw.pointer_raw()));
}
}
}
use std::borrow::Borrow;
use std::fmt::Debug;
-use std::iter::FromIterator;
use std::slice::Iter;
use std::vec::IntoIter;
use rustc_errors::registry::{InvalidErrorCode, Registry};
use rustc_errors::{ErrorGuaranteed, PResult};
use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_lint::LintStore;
use std::borrow::Cow;
use std::cmp::max;
-use std::default::Default;
use std::env;
use std::ffi::OsString;
use std::fs;
queries.global_ctxt()?.peek_mut().enter(|tcx| {
let result = tcx.analysis(());
if sess.opts.unstable_opts.save_analysis {
- let crate_name = queries.crate_name()?.peek().clone();
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
sess.time("save_analysis", || {
save::process_crate(
tcx,
- &crate_name,
+ crate_name,
compiler.input(),
None,
- DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
+ DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
)
});
}
let crate_types = collect_crate_types(sess, attrs);
for &style in &crate_types {
let fname =
- rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
+ rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
println!("{}", fname.file_name().unwrap().to_string_lossy());
}
}
E0312: include_str!("./error_codes/E0312.md"),
E0316: include_str!("./error_codes/E0316.md"),
E0317: include_str!("./error_codes/E0317.md"),
+E0320: include_str!("./error_codes/E0320.md"),
E0321: include_str!("./error_codes/E0321.md"),
E0322: include_str!("./error_codes/E0322.md"),
E0323: include_str!("./error_codes/E0323.md"),
E0787: include_str!("./error_codes/E0787.md"),
E0788: include_str!("./error_codes/E0788.md"),
E0790: include_str!("./error_codes/E0790.md"),
+E0791: include_str!("./error_codes/E0791.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
// E0314, // closure outlives stack frame
// E0315, // cannot invoke closure outside of its lifetime
// E0319, // trait impls for defaulted traits allowed just for structs/enums
- E0320, // recursive overflow during dropck
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
-An associated const has been referenced in a pattern.
+An associated `const`, `const` parameter or `static` has been referenced
+in a pattern.
Erroneous code example:
```compile_fail,E0158
-enum EFoo { A, B, C, D }
+enum Foo {
+ One,
+ Two
+}
-trait Foo {
- const X: EFoo;
+trait Bar {
+ const X: Foo;
}
-fn test<A: Foo>(arg: EFoo) {
+fn test<A: Bar>(arg: Foo) {
match arg {
- A::X => { // error!
- println!("A::X");
- }
+ A::X => println!("A::X"), // error: E0158: associated consts cannot be
+ // referenced in patterns
+ Foo::Two => println!("Two")
}
}
```
-`const` and `static` mean different things. A `const` is a compile-time
-constant, an alias for a literal value. This property means you can match it
-directly within a pattern.
+Associated `const`s cannot be referenced in patterns because it is impossible
+for the compiler to prove exhaustiveness (that some pattern will always match).
+Take the above example, because Rust does type checking in the *generic*
+method, not the *monomorphized* specific instance. So because `Bar` could have
+theoretically infinite implementations, there's no way to always be sure that
+`A::X` is `Foo::One`. So this code must be rejected. Even if code can be
+proven exhaustive by a programmer, the compiler cannot currently prove this.
-The `static` keyword, on the other hand, guarantees a fixed location in memory.
-This does not always mean that the value is constant. For example, a global
-mutex can be declared `static` as well.
+The same holds true of `const` parameters and `static`s.
-If you want to match against a `static`, consider using a guard instead:
+If you want to match against an associated `const`, `const` parameter or
+`static` consider using a guard instead:
```
-static FORTY_TWO: i32 = 42;
+trait Trait {
+ const X: char;
+}
+
+static FOO: char = 'j';
-match Some(42) {
- Some(x) if x == FORTY_TWO => {}
- _ => {}
+fn test<A: Trait, const Y: char>(arg: char) {
+ match arg {
+ c if c == A::X => println!("A::X"),
+ c if c == Y => println!("Y"),
+ c if c == FOO => println!("FOO"),
+ _ => ()
+ }
}
```
--- /dev/null
+Recursion limit reached while creating drop-check rules.
+
+Example of erroneous code:
+
+```compile_fail,E0320
+enum A<T> {
+ B,
+ C(T, Box<A<(T, T)>>)
+}
+
+fn foo<T>() {
+ A::<T>::B; // error: overflow while adding drop-check rules for A<T>
+}
+```
+
+The Rust compiler must be able to reason about how a type is [`Drop`]ped, and
+by extension the types of its fields, to be able to generate the glue to
+properly drop a value. The code example above shows a type where this inference
+is impossible because it is recursive. Note that this is *not* the same as
+[E0072](E0072.html), where a type has an infinite size; the type here has a
+finite size but any attempt to `Drop` it would recurse infinitely. For more
+information, read [the `Drop` docs](../std/ops/trait.Drop.html).
+
+It is not possible to define a type with recursive drop-check rules. All such
+recursion must be removed.
+
+[`Drop`]: ../std/ops/trait.Drop.html
```
use std::cell::Cell;
-use std::marker::Sync;
struct NotThreadSafe<T> {
value: Cell<T>,
--- /dev/null
+Static variables with the `#[linkage]` attribute within external blocks
+must have one of the following types, which are equivalent to a nullable
+pointer in C:
+
+* `*mut T` or `*const T`, where `T` may be any type.
+
+* An enumerator type with no `#[repr]` attribute and with two variants, where
+ one of the variants has no fields, and the other has a single field of one of
+ the following non-nullable types:
+ * Reference type
+ * Function pointer type
+
+ The variants can appear in either order.
+
+For example, the following declaration is invalid:
+
+```compile_fail,E0791
+#![feature(linkage)]
+
+extern "C" {
+ #[linkage = "extern_weak"]
+ static foo: i8;
+}
+```
+
+The following declarations are valid:
+
+```
+#![feature(linkage)]
+
+extern "C" {
+ #[linkage = "extern_weak"]
+ static foo: Option<unsafe extern "C" fn()>;
+
+ #[linkage = "extern_weak"]
+ static bar: Option<&'static i8>;
+
+ #[linkage = "extern_weak"]
+ static baz: *mut i8;
+}
+```
-codegen_gcc_linkage_const_or_mut_type =
- must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
codegen_gcc_unwinding_inline_asm =
GCC backend does not support unwinding from inline asm
codegen_llvm_symbol_already_defined =
symbol `{$symbol_name}` is already defined
-codegen_llvm_branch_protection_requires_aarch64 =
- -Zbranch-protection is only supported on aarch64
-
codegen_llvm_invalid_minimum_alignment =
invalid minimum global alignment: {$err}
-codegen_llvm_linkage_const_or_mut_type =
- must have type `*const T` or `*mut T` due to `#[linkage]` attribute
-
codegen_llvm_sanitizer_memtag_requires_mte =
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
codegen_ssa_unknown_archive_kind =
Don't know how to build archive of type: {$kind}
+
+codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
variable '{$ident}' is still repeating at this depth
expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_macro_const_stability =
+ macros cannot have const stability attributes
+ .label = invalid const stability attribute
+ .label2 = const stability attribute affects this macro
+
+expand_macro_body_stability =
+ macros cannot have body stability attributes
+ .label = invalid body stability attribute
+ .label2 = body stability attribute affects this macro
+
+expand_resolve_relative_path =
+ cannot resolve relative path in non-file source `{$path}`
+
+expand_attr_no_arguments =
+ attribute must have either one or two arguments
+
+expand_not_a_meta_item =
+ not a meta item
+
+expand_only_one_word =
+ must only be one word
+
+expand_cannot_be_name_of_macro =
+ `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_arg_not_attributes =
+ second argument must be `attributes`
+
+expand_attributes_wrong_form =
+ attribute must be of form: `attributes(foo, bar)`
+
+expand_attribute_meta_item =
+ attribute must be a meta item, not a literal
+
+expand_attribute_single_word =
+ attribute must only be a single word
+
+expand_helper_attribute_name_invalid =
+ `{$name}` cannot be a name of derive helper attribute
+
+expand_expected_comma_in_list =
+ expected token: `,`
+
+expand_only_one_argument =
+ {$name} takes 1 argument
+
+expand_takes_no_arguments =
+ {$name} takes no arguments
+
+expand_feature_included_in_edition =
+ the feature `{$feature}` is included in the Rust {$edition} edition
+
+expand_feature_removed =
+ feature has been removed
+ .label = feature has been removed
+ .reason = {$reason}
+
+expand_feature_not_allowed =
+ the feature `{$name}` is not in the list of allowed features
+
+expand_recursion_limit_reached =
+ recursion limit reached while expanding `{$descr}`
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+expand_malformed_feature_attribute =
+ malformed `feature` attribute input
+ .expected = expected just one word
+
+expand_remove_expr_not_supported =
+ removing an expression is not supported in this position
+
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_wrong_fragment_kind =
+ non-{$kind} macro in {$kind} position: {$name}
+
+expand_unsupported_key_value =
+ key-value macro attributes are not supported
+
+expand_incomplete_parse =
+ macro expansion ignores token `{$token}` and any following
+ .label = caused by the macro expansion here
+ .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
+ .suggestion_add_semi = you might be missing a semicolon here
+
+expand_remove_node_not_supported =
+ removing {$descr} is not supported in this position
+
+expand_module_circular =
+ circular modules: {$modules}
+
+expand_module_in_block =
+ cannot declare a non-inline module inside a block unless it has a path attribute
+ .note = maybe `use` the module `{$name}` instead of redeclaring it
+
+expand_module_file_not_found =
+ file not found for module `{$name}`
+ .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+
+expand_module_multiple_candidates =
+ file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
+ .help = delete or rename one of them to remove the ambiguity
.where_label = this `where` clause might not match the one in the trait
.bounds_label = this bound might be missing in the impl
+hir_analysis_async_trait_impl_should_be_async =
+ method `{$method_name}` should be async because the method from the trait is async
+ .trait_item_label = required because the trait method is async
+
hir_analysis_drop_impl_on_wrong_item =
the `Drop` trait may only be implemented for local structs, enums, and unions
.label = must be a struct, enum, or union in the current crate
`extern crate` is not idiomatic in the new edition
.suggestion = convert it to a `{$msg_code}`
-hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
-
hir_analysis_const_impl_for_non_const_trait =
const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
.suggestion = mark `{$trait_name}` as const
hir_analysis_self_in_impl_self =
`Self` is not valid in the self type of an impl block
.note = replace `Self` with a different type
+
+hir_analysis_linkage_type =
+ invalid type for variable with `#[linkage]` attribute
metadata_global_alloc_required =
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
-metadata_alloc_func_required =
- `#[alloc_error_handler]` function required, but not found
-
-metadata_missing_alloc_error_handler =
- use `#![feature(default_alloc_error_handler)]` for a default error handler
-
metadata_no_transitive_needs_dep =
the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
--- /dev/null
+mir_build_unconditional_recursion = function cannot return without recursing
+ .label = cannot return without recursing
+ .help = a `loop` may express intention better if this is on purpose
+
+mir_build_unconditional_recursion_call_site_label = recursive call site
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe =
+ call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133)
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless =
+ call to unsafe function is unsafe and requires unsafe block (error E0133)
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
+ use of inline assembly is unsafe and requires unsafe block (error E0133)
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
+
+mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe
+ block (error E0133)
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe =
+ use of mutable static is unsafe and requires unsafe block (error E0133)
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
+
+mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe =
+ use of extern static is unsafe and requires unsafe block (error E0133)
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
+
+mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe =
+ dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+ .label = dereference of raw pointer
+
+mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe =
+ access to union field is unsafe and requires unsafe block (error E0133)
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe =
+ mutation of layout constrained field is unsafe and requires unsafe block (error E0133)
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
+
+mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133)
+ .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+ .label = borrow of layout constrained field with interior mutability
+
+mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133)
+ .note = can only be called if the required target features are available
+ .label = call to function with `#[target_feature]`
+
+mir_build_call_to_unsafe_fn_requires_unsafe =
+ call to unsafe function `{$function}` is unsafe and requires unsafe block
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_nameless =
+ call to unsafe function is unsafe and requires unsafe block
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ call to unsafe function `{$function}` is unsafe and requires unsafe function or block
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed =
+ call to unsafe function is unsafe and requires unsafe function or block
+ .note = consult the function's documentation for information on how to avoid undefined behavior
+ .label = call to unsafe function
+
+mir_build_inline_assembly_requires_unsafe =
+ use of inline assembly is unsafe and requires unsafe block
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
+
+mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of inline assembly is unsafe and requires unsafe function or block
+ .note = inline assembly is entirely unchecked and can cause undefined behavior
+ .label = use of inline assembly
+
+mir_build_initializing_type_with_requires_unsafe =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+ .label = initializing type with `rustc_layout_scalar_valid_range` attr
+
+mir_build_mutable_static_requires_unsafe =
+ use of mutable static is unsafe and requires unsafe block
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
+
+mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of mutable static is unsafe and requires unsafe function or block
+ .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+ .label = use of mutable static
+
+mir_build_extern_static_requires_unsafe =
+ use of extern static is unsafe and requires unsafe block
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
+
+mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ use of extern static is unsafe and requires unsafe function or block
+ .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+ .label = use of extern static
+
+mir_build_deref_raw_pointer_requires_unsafe =
+ dereference of raw pointer is unsafe and requires unsafe block
+ .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+ .label = dereference of raw pointer
+
+mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ dereference of raw pointer is unsafe and requires unsafe function or block
+ .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+ .label = dereference of raw pointer
+
+mir_build_union_field_requires_unsafe =
+ access to union field is unsafe and requires unsafe block
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ access to union field is unsafe and requires unsafe function or block
+ .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior
+ .label = access to union field
+
+mir_build_mutation_of_layout_constrained_field_requires_unsafe =
+ mutation of layout constrained field is unsafe and requires unsafe block
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
+
+mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ mutation of layout constrained field is unsafe and requires unsafe function or block
+ .note = mutating layout constrained fields cannot statically be checked for valid values
+ .label = mutation of layout constrained field
+
+mir_build_borrow_of_layout_constrained_field_requires_unsafe =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe block
+ .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+ .label = borrow of layout constrained field with interior mutability
+
+mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+ .label = borrow of layout constrained field with interior mutability
+
+mir_build_call_to_fn_with_requires_unsafe =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
+ .note = can only be called if the required target features are available
+ .label = call to function with `#[target_feature]`
+
+mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
+ call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block
+ .note = can only be called if the required target features are available
+ .label = call to function with `#[target_feature]`
+
+mir_build_unused_unsafe = unnecessary `unsafe` block
+ .label = unnecessary `unsafe` block
+
+mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
+mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
+
+mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
+ .def_note = `{$peeled_ty}` defined here
+ .type_note = the matched value is of type `{$ty}`
+ .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive
+ .reference_note = references are always considered inhabited
+ .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+mir_build_static_in_pattern = statics cannot be referenced in patterns
+
+mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns
+
+mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns
+
+mir_build_non_const_path = runtime values cannot be referenced in patterns
+
+mir_build_unreachable_pattern = unreachable pattern
+ .label = unreachable pattern
+ .catchall_label = matches any value
+
+mir_build_const_pattern_depends_on_generic_parameter =
+ constant pattern depends on a generic parameter
+
+mir_build_could_not_eval_const_pattern = could not evaluate constant pattern
+
+mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
+ lower range bound must be less than or equal to upper
+ .label = lower bound larger than upper bound
+ .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
+
+mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
+
+mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
+ [one] pattern
+ *[other] patterns
+ } in let chain
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match
+ .help = consider moving {$count ->
+ [one] it
+ *[other] them
+ } outside of the construct
+
+mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
+ [one] pattern
+ *[other] patterns
+ } in let chain
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match
+ .help = consider moving {$count ->
+ [one] it
+ *[other] them
+ } into the body
+
+mir_build_bindings_with_variant_name =
+ pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}`
+ .suggestion = to match on the variant, qualify the path
+
+mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count ->
+ [one] pattern
+ *[other] patterns
+ }
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match, so the `let` is useless
+ .help = consider removing `let`
+
+mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
+ [one] pattern
+ *[other] patterns
+ }
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match, so the `if let` is useless
+ .help = consider replacing the `if let` with a `let`
+
+mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count ->
+ [one] pattern
+ *[other] patterns
+ }
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match, so the guard is useless
+ .help = consider removing the guard and adding a `let` inside the match arm
+
+mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count ->
+ [one] pattern
+ *[other] patterns
+ }
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match, so the `else` clause is useless
+ .help = consider removing the `else` clause
+
+mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count ->
+ [one] pattern
+ *[other] patterns
+ }
+ .note = {$count ->
+ [one] this pattern
+ *[other] these patterns
+ } will always match, so the loop will never exit
+ .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it
+
+mir_build_borrow_of_moved_value = borrow of moved value
+ .label = value moved into `{$name}` here
+ .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait
+ .value_borrowed_label = value borrowed here after move
+ .suggestion = borrow this binding in the pattern to avoid moving the value
+
+mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
+ .label = first mutable borrow, by `{$name}`, occurs here
+ .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
+ .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
+ .moved = also moved into `{$name_moved}` here
moving {$size} bytes
.label = value moved from here
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
+
+monomorphize_couldnt_dump_mono_stats =
+ unexpected error occurred while dumping monomorphization stats: {$error}
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
.label = identifiers cannot start with a number
+
+parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
+ .suggestion = replace `fn` with `impl` here
session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
+session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64
+
session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
lint => "../locales/en-US/lint.ftl",
metadata => "../locales/en-US/metadata.ftl",
middle => "../locales/en-US/middle.ftl",
+ mir_build => "../locales/en-US/mir_build.ftl",
mir_dataflow => "../locales/en-US/mir_dataflow.ftl",
monomorphize => "../locales/en-US/monomorphize.ftl",
parse => "../locales/en-US/parse.ftl",
self.set_span(after);
for span_label in before.span_labels() {
if let Some(label) = span_label.label {
- self.span.push_span_label(after, label);
+ if span_label.is_primary {
+ self.span.push_span_label(after, label);
+ } else {
+ self.span.push_span_label(span_label.span, label);
+ }
}
}
self
debug_assert!(
!(suggestions
.iter()
- .flat_map(|suggs| suggs)
+ .flatten()
.any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);
i128,
u128,
std::io::Error,
- std::boxed::Box<dyn std::error::Error>,
+ Box<dyn std::error::Error>,
std::num::NonZeroU32,
hir::Target,
Edition,
}
}
+impl IntoDiagnosticArg for &ast::Path {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
+ }
+}
+
impl IntoDiagnosticArg for ast::token::Token {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(pprust::token_to_string(&self))
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
+use rustc_error_messages::{FluentArgs, SpanLabel};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::borrow::Cow;
use std::cmp::{max, min, Reverse};
draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
}
+ #[instrument(level = "trace", skip(self), ret)]
fn render_source_line(
&self,
buffer: &mut StyledBuffer,
Some(s) => normalize_whitespace(&s),
None => return Vec::new(),
};
+ trace!(?source_string);
let line_offset = buffer.num_lines();
// see how it *looks* with
// very *weird* formats
// see?
- for &(ref text, ref style) in msg.iter() {
+ for (text, style) in msg.iter() {
let text = self.translate_message(text, args);
let lines = text.split('\n').collect::<Vec<_>>();
if lines.len() > 1 {
}
}
+ #[instrument(level = "trace", skip(self, args), ret)]
fn emit_message_default(
&mut self,
msp: &MultiSpan,
buffer.append(0, ": ", header_style);
label_width += 2;
}
- for &(ref text, _) in msg.iter() {
+ for (text, _) in msg.iter() {
let text = self.translate_message(text, args);
// Account for newlines to align output to its label.
for (line, text) in normalize_whitespace(&text).lines().enumerate() {
}
}
let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
+ trace!("{annotated_files:#?}");
// Make sure our primary file comes first
- let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) =
- (self.sm.as_ref(), msp.primary_span().as_ref())
- {
- if !primary_span.is_dummy() {
- (sm.lookup_char_pos(primary_span.lo()), sm)
- } else {
- emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
- return Ok(());
- }
- } else {
+ let primary_span = msp.primary_span().unwrap_or_default();
+ let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
// If we don't have span information, emit and exit
- emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
- return Ok(());
+ return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
};
+ let primary_lo = sm.lookup_char_pos(primary_span.lo());
if let Ok(pos) =
annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
{
for annotated_file in annotated_files {
// we can't annotate anything if the source is unavailable.
if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
+ if !self.short_message {
+ // We'll just print an unannotated message.
+ for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
+ let mut annotations = line.annotations.clone();
+ annotations.sort_by_key(|a| Reverse(a.start_col));
+ let mut line_idx = buffer.num_lines();
+
+ let labels: Vec<_> = annotations
+ .iter()
+ .filter_map(|a| Some((a.label.as_ref()?, a.is_primary)))
+ .filter(|(l, _)| !l.is_empty())
+ .collect();
+
+ if annotation_id == 0 || !labels.is_empty() {
+ buffer.append(
+ line_idx,
+ &format!(
+ "{}:{}:{}",
+ sm.filename_for_diagnostics(&annotated_file.file.name),
+ sm.doctest_offset_line(
+ &annotated_file.file.name,
+ line.line_index
+ ),
+ annotations[0].start_col + 1,
+ ),
+ Style::LineAndColumn,
+ );
+ if annotation_id == 0 {
+ buffer.prepend(line_idx, "--> ", Style::LineNumber);
+ } else {
+ buffer.prepend(line_idx, "::: ", Style::LineNumber);
+ }
+ for _ in 0..max_line_num_len {
+ buffer.prepend(line_idx, " ", Style::NoStyle);
+ }
+ line_idx += 1;
+ }
+ for (label, is_primary) in labels.into_iter() {
+ let style = if is_primary {
+ Style::LabelPrimary
+ } else {
+ Style::LabelSecondary
+ };
+ buffer.prepend(line_idx, " |", Style::LineNumber);
+ for _ in 0..max_line_num_len {
+ buffer.prepend(line_idx, " ", Style::NoStyle);
+ }
+ line_idx += 1;
+ buffer.append(line_idx, " = note: ", style);
+ for _ in 0..max_line_num_len {
+ buffer.prepend(line_idx, " ", Style::NoStyle);
+ }
+ buffer.append(line_idx, label, style);
+ line_idx += 1;
+ }
+ }
+ }
continue;
}
multilines.extend(&to_add);
}
}
+ trace!("buffer: {:#?}", buffer.render());
}
if let Some(tracked) = emitted_at {
Ok(())
}
+ #[instrument(level = "trace", skip(self, args, code, children, suggestions))]
fn emit_messages_default(
&mut self,
level: &Level,
let mut multiline_annotations = vec![];
if let Some(ref sm) = emitter.source_map() {
- for span_label in msp.span_labels() {
- let fixup_lo_hi = |span: Span| {
- let lo = sm.lookup_char_pos(span.lo());
- let mut hi = sm.lookup_char_pos(span.hi());
-
- // Watch out for "empty spans". If we get a span like 6..6, we
- // want to just display a `^` at 6, so convert that to
- // 6..7. This is degenerate input, but it's best to degrade
- // gracefully -- and the parser likes to supply a span like
- // that for EOF, in particular.
-
- if lo.col_display == hi.col_display && lo.line == hi.line {
- hi.col_display += 1;
- }
- (lo, hi)
+ for SpanLabel { span, is_primary, label } in msp.span_labels() {
+ // If we don't have a useful span, pick the primary span if that exists.
+ // Worst case we'll just print an error at the top of the main file.
+ let span = match (span.is_dummy(), msp.primary_span()) {
+ (_, None) | (false, _) => span,
+ (true, Some(span)) => span,
};
- if span_label.span.is_dummy() {
- if let Some(span) = msp.primary_span() {
- // if we don't know where to render the annotation, emit it as a note
- // on the primary span.
-
- let (lo, hi) = fixup_lo_hi(span);
-
- let ann = Annotation {
- start_col: lo.col_display,
- end_col: hi.col_display,
- is_primary: span_label.is_primary,
- label: span_label
- .label
- .as_ref()
- .map(|m| emitter.translate_message(m, args).to_string()),
- annotation_type: AnnotationType::Singleline,
- };
- add_annotation_to_file(&mut output, lo.file, lo.line, ann);
- }
- continue;
+ let lo = sm.lookup_char_pos(span.lo());
+ let mut hi = sm.lookup_char_pos(span.hi());
+
+ // Watch out for "empty spans". If we get a span like 6..6, we
+ // want to just display a `^` at 6, so convert that to
+ // 6..7. This is degenerate input, but it's best to degrade
+ // gracefully -- and the parser likes to supply a span like
+ // that for EOF, in particular.
+
+ if lo.col_display == hi.col_display && lo.line == hi.line {
+ hi.col_display += 1;
}
- let (lo, hi) = fixup_lo_hi(span_label.span);
+ let label = label.as_ref().map(|m| emitter.translate_message(m, args).to_string());
if lo.line != hi.line {
let ml = MultilineAnnotation {
line_end: hi.line,
start_col: lo.col_display,
end_col: hi.col_display,
- is_primary: span_label.is_primary,
- label: span_label
- .label
- .as_ref()
- .map(|m| emitter.translate_message(m, args).to_string()),
+ is_primary,
+ label,
overlaps_exactly: false,
};
multiline_annotations.push((lo.file, ml));
let ann = Annotation {
start_col: lo.col_display,
end_col: hi.col_display,
- is_primary: span_label.is_primary,
- label: span_label
- .label
- .as_ref()
- .map(|m| emitter.translate_message(m, args).to_string()),
+ is_primary,
+ label,
annotation_type: AnnotationType::Singleline,
};
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
}
// Find overlapping multiline annotations, put them at different depths
- multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, usize::MAX - ml.line_end));
+ multiline_annotations.sort_by_key(|(_, ml)| (ml.line_start, usize::MAX - ml.line_end));
for (_, ann) in multiline_annotations.clone() {
for (_, a) in multiline_annotations.iter_mut() {
// Move all other multiline annotations overlapping with this one
// Account for the difference between the width of the current code and the
// snippet being suggested, so that the *later* suggestions are correctly
// aligned on the screen.
- acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize;
+ acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
}
prev_hi = cur_hi;
prev_line = sf.get_line(prev_hi.line - 1);
+#![deny(rustc::untranslatable_diagnostic)]
+
+use crate::errors::{
+ ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
+ AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
+ MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
+ ResolveRelativePath, TakesNoArguments,
+};
use crate::expand::{self, AstFragment, Invocation};
use crate::module::DirOwnership;
use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-use std::default::Default;
use std::iter;
use std::path::PathBuf;
use std::rc::Rc;
.unwrap_or_else(|| (None, helper_attrs));
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
if let Some((_, sp)) = const_stability {
- sess.parse_sess
- .span_diagnostic
- .struct_span_err(sp, "macros cannot have const stability attributes")
- .span_label(sp, "invalid const stability attribute")
- .span_label(
- sess.source_map().guess_head_span(span),
- "const stability attribute affects this macro",
- )
- .emit();
+ sess.emit_err(MacroConstStability {
+ span: sp,
+ head_span: sess.source_map().guess_head_span(span),
+ });
}
if let Some((_, sp)) = body_stability {
- sess.parse_sess
- .span_diagnostic
- .struct_span_err(sp, "macros cannot have body stability attributes")
- .span_label(sp, "invalid body stability attribute")
- .span_label(
- sess.source_map().guess_head_span(span),
- "body stability attribute affects this macro",
- )
- .emit();
+ sess.emit_err(MacroBodyStability {
+ span: sp,
+ head_span: sess.source_map().guess_head_span(span),
+ });
}
SyntaxExtension {
node_id: NodeId,
attrs: &[Attribute],
items: &[P<Item>],
- name: &str,
+ name: Symbol,
);
}
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
- return Err(parse_sess.span_diagnostic.struct_span_err(
+ return Err(ResolveRelativePath {
span,
- &format!(
- "cannot resolve relative path in non-file source `{}`",
- parse_sess.source_map().filename_for_diagnostics(&other)
- ),
- ));
+ path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
+ }
+ .into_diagnostic(&parse_sess.span_diagnostic));
}
};
result.pop();
/// The returned bool indicates whether an applicable suggestion has already been
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
/// indicates that an ast error was encountered.
+// FIXME(Nilstrieb) Make this function setup translatable
+#[allow(rustc::untranslatable_diagnostic)]
pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt<'_>,
expr: P<ast::Expr>,
Err(match expr.kind {
ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)),
- Ok(ast::LitKind::ByteStr(_)) => {
+ Ok(ast::LitKind::ByteStr(..)) => {
let mut err = cx.struct_span_err(expr.span, err_msg);
let span = expr.span.shrink_to_lo();
err.span_suggestion(
/// compilation should call
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
/// done as rarely as possible).
-pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) {
+pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
if !tts.is_empty() {
- cx.span_err(sp, &format!("{} takes no arguments", name));
+ cx.emit_err(TakesNoArguments { span, name });
}
}
/// expect exactly one string literal, or emit an error and return `None`.
pub fn get_single_str_from_tts(
cx: &mut ExtCtxt<'_>,
- sp: Span,
+ span: Span,
tts: TokenStream,
name: &str,
) -> Option<Symbol> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
- cx.span_err(sp, &format!("{} takes 1 argument", name));
+ cx.emit_err(OnlyOneArgument { span, name });
return None;
}
let ret = parse_expr(&mut p)?;
let _ = p.eat(&token::Comma);
if p.token != token::Eof {
- cx.span_err(sp, &format!("{} takes 1 argument", name));
+ cx.emit_err(OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
}
/// Extracts comma-separated expressions from `tts`.
/// On error, emit it, and return `None`.
-pub fn get_exprs_from_tts(
- cx: &mut ExtCtxt<'_>,
- sp: Span,
- tts: TokenStream,
-) -> Option<Vec<P<ast::Expr>>> {
+pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
let mut p = cx.new_parser_from_tts(tts);
let mut es = Vec::new();
while p.token != token::Eof {
continue;
}
if p.token != token::Eof {
- cx.span_err(sp, "expected token: `,`");
+ cx.emit_err(ExpectedCommaInList { span: p.token.span });
return None;
}
}
pub fn parse_macro_name_and_helper_attrs(
diag: &rustc_errors::Handler,
attr: &Attribute,
- descr: &str,
+ macro_type: &str,
) -> Option<(Symbol, Vec<Symbol>)> {
// Once we've located the `#[proc_macro_derive]` attribute, verify
// that it's of the form `#[proc_macro_derive(Foo)]` or
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
- diag.span_err(attr.span, "attribute must have either one or two arguments");
+ diag.emit_err(AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
- diag.span_err(list[0].span(), "not a meta item");
+ diag.emit_err(NotAMetaItem {span: list[0].span()});
return None;
};
let trait_ident = match trait_attr.ident() {
Some(trait_ident) if trait_attr.is_word() => trait_ident,
_ => {
- diag.span_err(trait_attr.span, "must only be one word");
+ diag.emit_err(OnlyOneWord { span: trait_attr.span });
return None;
}
};
if !trait_ident.name.can_be_raw() {
- diag.span_err(
- trait_attr.span,
- &format!("`{}` cannot be a name of {} macro", trait_ident, descr),
- );
+ diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
}
let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) {
- diag.span_err(attr.span(), "second argument must be `attributes`");
+ diag.emit_err(ArgumentNotAttributes { span: attr.span() });
}
attr.meta_item_list()
.unwrap_or_else(|| {
- diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
+ diag.emit_err(AttributesWrongForm { span: attr.span() });
&[]
})
.iter()
.filter_map(|attr| {
let Some(attr) = attr.meta_item() else {
- diag.span_err(attr.span(), "not a meta item");
+ diag.emit_err(AttributeMetaItem { span: attr.span() });
return None;
};
let ident = match attr.ident() {
Some(ident) if attr.is_word() => ident,
_ => {
- diag.span_err(attr.span, "must only be one word");
+ diag.emit_err(AttributeSingleWord { span: attr.span });
return None;
}
};
if !ident.name.can_be_raw() {
- diag.span_err(
- attr.span,
- &format!("`{}` cannot be a name of derive helper attribute", ident),
- );
+ diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
}
Some(ident.name)
use crate::base::ExtCtxt;
-use rustc_ast::attr;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
-use rustc_data_structures::sync::Lrc;
+use rustc_ast::{attr, token, util::literal};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
self.expr_struct(span, self.path_ident(span, id), fields)
}
- fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P<ast::Expr> {
- let token_lit = lit_kind.to_token_lit();
- self.expr(span, ast::ExprKind::Lit(token_lit))
+ pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
+ let suffix = Some(ast::UintTy::Usize.name());
+ let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
- pub fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
- self.expr_lit(
- span,
- ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
- )
- }
-
- pub fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
- self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32)))
+ pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
+ let suffix = Some(ast::UintTy::U32.name());
+ let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
- pub fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
- self.expr_lit(sp, ast::LitKind::Bool(value))
+ pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
+ let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
- pub fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
- self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
+ pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
+ let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
- pub fn expr_char(&self, sp: Span, ch: char) -> P<ast::Expr> {
- self.expr_lit(sp, ast::LitKind::Char(ch))
+ pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> {
+ let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
- pub fn expr_byte_str(&self, sp: Span, bytes: Vec<u8>) -> P<ast::Expr> {
- self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes)))
+ pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
+ let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
+ self.expr(span, ast::ExprKind::Lit(lit))
}
/// `[expr1, expr2, ...]`
//! Conditional compilation stripping.
+use crate::errors::{
+ FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
+ MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
+};
use rustc_ast::ptr::P;
use rustc_ast::token::{Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::map_in_place::MapInPlace;
-use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
use rustc_feature::{Feature, Features, State as FeatureState};
use rustc_feature::{
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
pub lint_node_id: NodeId,
}
-fn get_features(
- sess: &Session,
- span_handler: &Handler,
- krate_attrs: &[ast::Attribute],
-) -> Features {
- fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
- let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
- err.span_label(span, "feature has been removed");
- if let Some(reason) = reason {
- err.note(reason);
- }
- err.emit();
+fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
+ fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
+ sess.emit_err(FeatureRemoved {
+ span,
+ reason: reason.map(|reason| FeatureRemovedReason { reason }),
+ });
}
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
continue;
};
- let bad_input = |span| {
- struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
- };
-
for mi in list {
let name = match mi.ident() {
Some(ident) if mi.is_word() => ident.name,
Some(ident) => {
- bad_input(mi.span())
- .span_suggestion(
- mi.span(),
- "expected just one word",
- ident.name,
- Applicability::MaybeIncorrect,
- )
- .emit();
+ sess.emit_err(MalformedFeatureAttribute {
+ span: mi.span(),
+ help: MalformedFeatureAttributeHelp::Suggestion {
+ span: mi.span(),
+ suggestion: ident.name,
+ },
+ });
continue;
}
None => {
- bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+ sess.emit_err(MalformedFeatureAttribute {
+ span: mi.span(),
+ help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
+ });
continue;
}
};
- if let Some(edition) = edition_enabled_features.get(&name) {
- let msg =
- &format!("the feature `{}` is included in the Rust {} edition", name, edition);
- span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+ if let Some(&edition) = edition_enabled_features.get(&name) {
+ sess.emit_warning(FeatureIncludedInEdition {
+ span: mi.span(),
+ feature: name,
+ edition,
+ });
continue;
}
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
state
{
- feature_removed(span_handler, mi.span(), *reason);
+ feature_removed(sess, mi.span(), *reason);
continue;
}
}
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
if allowed.iter().all(|f| name.as_str() != f) {
- struct_span_err!(
- span_handler,
- mi.span(),
- E0725,
- "the feature `{}` is not in the list of allowed features",
- name
- )
- .emit();
+ sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
continue;
}
}
}
Some(attrs) => {
krate.attrs = attrs;
- let features = get_features(sess, diag, &krate.attrs);
+ let features = get_features(sess, &krate.attrs);
if err_count == diag.err_count() {
// Avoid reconfiguring malformed `cfg_attr`s.
strip_unconfigured.features = Some(&features);
// N.B., this is intentionally not part of the visit_expr() function
// in order for filter_map_expr() to be able to avoid this check
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
- let msg = "removing an expression is not supported in this position";
- self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
+ self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
}
self.process_cfg_attrs(expr);
}
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
- let error = |span, msg, suggestion: &str| {
- let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
- if !suggestion.is_empty() {
- err.span_suggestion(
- span,
- "expected syntax is",
- suggestion,
- Applicability::HasPlaceholders,
- );
- }
- err.emit();
- None
- };
let span = meta_item.span;
match meta_item.meta_item_list() {
- None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
- Some([]) => error(span, "`cfg` predicate is not specified", ""),
- Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
+ None => {
+ sess.emit_err(InvalidCfg::NotFollowedByParens { span });
+ None
+ }
+ Some([]) => {
+ sess.emit_err(InvalidCfg::NoPredicate { span });
+ None
+ }
+ Some([_, .., l]) => {
+ sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
+ None
+ }
Some([single]) => match single.meta_item() {
Some(meta_item) => Some(meta_item),
- None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
+ None => {
+ sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
+ None
+ }
},
}
}
+use rustc_ast::ast;
use rustc_macros::Diagnostic;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
-use rustc_span::Span;
+use rustc_session::Limit;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
#[derive(Diagnostic)]
#[diag(expand_expr_repeat_no_syntax_vars)]
pub span: Span,
pub msg: String,
}
+
+#[derive(Diagnostic)]
+#[diag(expand_resolve_relative_path)]
+pub(crate) struct ResolveRelativePath {
+ #[primary_span]
+ pub span: Span,
+ pub path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_const_stability)]
+pub(crate) struct MacroConstStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(label2)]
+ pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_body_stability)]
+pub(crate) struct MacroBodyStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(label2)]
+ pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attr_no_arguments)]
+pub(crate) struct AttrNoArguments {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_not_a_meta_item)]
+pub(crate) struct NotAMetaItem {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_word)]
+pub(crate) struct OnlyOneWord {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_cannot_be_name_of_macro)]
+pub(crate) struct CannotBeNameOfMacro<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub trait_ident: Ident,
+ pub macro_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_arg_not_attributes)]
+pub(crate) struct ArgumentNotAttributes {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attributes_wrong_form)]
+pub(crate) struct AttributesWrongForm {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_meta_item)]
+pub(crate) struct AttributeMetaItem {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_single_word)]
+pub(crate) struct AttributeSingleWord {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_helper_attribute_name_invalid)]
+pub(crate) struct HelperAttributeNameInvalid {
+ #[primary_span]
+ pub span: Span,
+ pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_expected_comma_in_list)]
+pub(crate) struct ExpectedCommaInList {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_argument)]
+pub(crate) struct OnlyOneArgument<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_takes_no_arguments)]
+pub(crate) struct TakesNoArguments<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_included_in_edition, code = "E0705")]
+pub(crate) struct FeatureIncludedInEdition {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub edition: Edition,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_removed, code = "E0557")]
+pub(crate) struct FeatureRemoved<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub reason: Option<FeatureRemovedReason<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(reason)]
+pub(crate) struct FeatureRemovedReason<'a> {
+ pub reason: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_not_allowed, code = "E0725")]
+pub(crate) struct FeatureNotAllowed {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_recursion_limit_reached)]
+#[help]
+pub(crate) struct RecursionLimitReached<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub descr: String,
+ pub suggested_limit: Limit,
+ pub crate_name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_malformed_feature_attribute, code = "E0556")]
+pub(crate) struct MalformedFeatureAttribute {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub help: MalformedFeatureAttributeHelp,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MalformedFeatureAttributeHelp {
+ #[label(expected)]
+ Label {
+ #[primary_span]
+ span: Span,
+ },
+ #[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
+ Suggestion {
+ #[primary_span]
+ span: Span,
+ suggestion: Symbol,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_expr_not_supported)]
+pub(crate) struct RemoveExprNotSupported {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum InvalidCfg {
+ #[diag(expand_invalid_cfg_no_parens)]
+ NotFollowedByParens {
+ #[primary_span]
+ #[suggestion(
+ expand_invalid_cfg_expected_syntax,
+ code = "cfg(/* predicate */)",
+ applicability = "has-placeholders"
+ )]
+ span: Span,
+ },
+ #[diag(expand_invalid_cfg_no_predicate)]
+ NoPredicate {
+ #[primary_span]
+ #[suggestion(
+ expand_invalid_cfg_expected_syntax,
+ code = "cfg(/* predicate */)",
+ applicability = "has-placeholders"
+ )]
+ span: Span,
+ },
+ #[diag(expand_invalid_cfg_multiple_predicates)]
+ MultiplePredicates {
+ #[primary_span]
+ span: Span,
+ },
+ #[diag(expand_invalid_cfg_predicate_literal)]
+ PredicateLiteral {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_wrong_fragment_kind)]
+pub(crate) struct WrongFragmentKind<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub kind: &'a str,
+ pub name: &'a ast::Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_unsupported_key_value)]
+pub(crate) struct UnsupportedKeyValue {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_incomplete_parse)]
+#[note]
+pub(crate) struct IncompleteParse<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub token: Cow<'a, str>,
+ #[label]
+ pub label_span: Span,
+ pub macro_path: &'a ast::Path,
+ pub kind_name: &'a str,
+
+ #[suggestion(
+ suggestion_add_semi,
+ style = "verbose",
+ code = ";",
+ applicability = "maybe-incorrect"
+ )]
+ pub add_semicolon: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_node_not_supported)]
+pub(crate) struct RemoveNodeNotSupported {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_circular)]
+pub(crate) struct ModuleCircular {
+ #[primary_span]
+ pub span: Span,
+ pub modules: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_in_block)]
+pub(crate) struct ModuleInBlock {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub name: Option<ModuleInBlockName>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(note)]
+pub(crate) struct ModuleInBlockName {
+ #[primary_span]
+ pub span: Span,
+ pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_file_not_found, code = "E0583")]
+#[help]
+pub(crate) struct ModuleFileNotFound {
+ #[primary_span]
+ pub span: Span,
+ pub name: Ident,
+ pub default_path: String,
+ pub secondary_path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_multiple_candidates, code = "E0761")]
+#[help]
+pub(crate) struct ModuleMultipleCandidates {
+ #[primary_span]
+ pub span: Span,
+ pub name: Ident,
+ pub default_path: String,
+ pub secondary_path: String,
+}
use crate::base::*;
use crate::config::StripUnconfigured;
+use crate::errors::{
+ IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
+ UnsupportedKeyValue, WrongFragmentKind,
+};
use crate::hygiene::SyntaxContext;
use crate::mbe::diagnostics::annotate_err_with_kind;
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
use rustc_ast_pretty::pprust;
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::PResult;
use rustc_feature::Features;
use rustc_parse::parser::{
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
Limit(0) => Limit(2),
limit => limit * 2,
};
- self.cx
- .struct_span_err(
- expn_data.call_site,
- &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
- )
- .help(&format!(
- "consider increasing the recursion limit by adding a \
- `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
- suggested_limit, self.cx.ecfg.crate_name,
- ))
- .emit();
+
+ self.cx.emit_err(RecursionLimitReached {
+ span: expn_data.call_site,
+ descr: expn_data.kind.descr(),
+ suggested_limit,
+ crate_name: &self.cx.ecfg.crate_name,
+ });
+
self.cx.trace_macros_diag();
}
/// A macro's expansion does not fit in this fragment kind.
/// For example, a non-type macro in a type position.
fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
- let msg = format!(
- "non-{kind} macro in {kind} position: {path}",
- kind = kind.name(),
- path = pprust::path_to_string(&mac.path),
- );
- self.cx.span_err(span, &msg);
+ self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
+
self.cx.trace_macros_diag();
}
};
let attr_item = attr.unwrap_normal_item();
if let AttrArgs::Eq(..) = attr_item.args {
- self.cx.span_err(span, "key-value macro attributes are not supported");
+ self.cx.emit_err(UnsupportedKeyValue { span });
}
let inner_tokens = attr_item.args.inner_tokens();
let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
}
};
if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
- let msg =
- "removing an expression is not supported in this position";
- self.cx.span_err(span, msg);
+ self.cx.emit_err(RemoveExprNotSupported { span });
fragment_kind.dummy(span)
} else {
fragment_kind.expect_from_annotatables(items)
}
pub fn ensure_complete_parse<'a>(
- this: &mut Parser<'a>,
+ parser: &mut Parser<'a>,
macro_path: &ast::Path,
kind_name: &str,
span: Span,
) {
- if this.token != token::Eof {
- let token = pprust::token_to_string(&this.token);
- let msg = format!("macro expansion ignores token `{}` and any following", token);
+ if parser.token != token::Eof {
+ let token = pprust::token_to_string(&parser.token);
// Avoid emitting backtrace info twice.
- let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
- let mut err = this.struct_span_err(def_site_span, &msg);
- err.span_label(span, "caused by the macro expansion here");
- let msg = format!(
- "the usage of `{}!` is likely invalid in {} context",
- pprust::path_to_string(macro_path),
- kind_name,
- );
- err.note(&msg);
+ let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
- let semi_span = this.sess.source_map().next_point(span);
- match this.sess.source_map().span_to_snippet(semi_span) {
+ let semi_span = parser.sess.source_map().next_point(span);
+ let add_semicolon = match parser.sess.source_map().span_to_snippet(semi_span) {
Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
- err.span_suggestion(
- span.shrink_to_hi(),
- "you might be missing a semicolon here",
- ";",
- Applicability::MaybeIncorrect,
- );
+ Some(span.shrink_to_hi())
}
- _ => {}
- }
- err.emit();
+ _ => None,
+ };
+
+ parser.sess.emit_err(IncompleteParse {
+ span: def_site_span,
+ token,
+ label_span: span,
+ macro_path,
+ kind_name,
+ add_semicolon,
+ });
}
}
ecx.current_expansion.lint_node_id,
&attrs,
&items,
- ident.name.as_str(),
+ ident.name,
);
}
if self.expand_cfg_true(node, attr, pos) {
continue;
}
- let msg =
- format!("removing {} is not supported in this position", Node::descr());
- self.cx.span_err(span, &msg);
+
+ self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
continue;
}
sym::cfg_attr => {
#![feature(rustc_attrs)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
#[macro_use]
extern crate rustc_macros;
pub mod errors;
pub mod expand;
pub mod module;
+
+// FIXME(Nilstrieb) Translate proc_macro diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
pub mod proc_macro;
+// FIXME(Nilstrieb) Translate macro_rules diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
pub(crate) mod mbe;
// HACK(Centril, #64197): These shouldn't really be here.
// We check that the meta-variable is correctly used.
check_occurrences(sess, node_id, tt, macros, binders, ops, valid);
}
- (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del))
+ (NestedMacroState::MacroName, TokenTree::Delimited(_, del))
if del.delim == Delimiter::Parenthesis =>
{
state = NestedMacroState::MacroNameParen;
valid,
);
}
- (NestedMacroState::MacroNameParen, &TokenTree::Delimited(_, ref del))
+ (NestedMacroState::MacroNameParen, TokenTree::Delimited(_, del))
if del.delim == Delimiter::Brace =>
{
state = NestedMacroState::Empty;
TokenTree::Sequence(sp, ref seq_rep) => {
let subfirst_owned;
let subfirst = match self.first.get(&sp.entire()) {
- Some(&Some(ref subfirst)) => subfirst,
+ Some(Some(subfirst)) => subfirst,
Some(&None) => {
subfirst_owned = self.first(&seq_rep.tts);
&subfirst_owned
use crate::base::ModuleData;
+use crate::errors::{
+ ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
+};
use rustc_ast::ptr::P;
use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
-use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_parse::new_parser_from_file;
use rustc_parse::validate_attr;
use rustc_session::parse::ParseSess;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
+use std::iter::once;
use std::path::{self, Path, PathBuf};
impl ModError<'_> {
fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
- let diag = &sess.parse_sess.span_diagnostic;
match self {
ModError::CircularInclusion(file_paths) => {
- let mut msg = String::from("circular modules: ");
- for file_path in &file_paths {
- msg.push_str(&file_path.display().to_string());
- msg.push_str(" -> ");
- }
- msg.push_str(&file_paths[0].display().to_string());
- diag.struct_span_err(span, &msg)
- }
- ModError::ModInBlock(ident) => {
- let msg = "cannot declare a non-inline module inside a block unless it has a path attribute";
- let mut err = diag.struct_span_err(span, msg);
- if let Some(ident) = ident {
- let note =
- format!("maybe `use` the module `{}` instead of redeclaring it", ident);
- err.span_note(span, ¬e);
- }
- err
+ let path_to_string = |path: &PathBuf| path.display().to_string();
+
+ let paths = file_paths
+ .iter()
+ .map(path_to_string)
+ .chain(once(path_to_string(&file_paths[0])))
+ .collect::<Vec<_>>();
+
+ let modules = paths.join(" -> ");
+
+ sess.emit_err(ModuleCircular { span, modules })
}
- ModError::FileNotFound(ident, default_path, secondary_path) => {
- let mut err = struct_span_err!(
- diag,
+ ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock {
+ span,
+ name: ident.map(|name| ModuleInBlockName { span, name }),
+ }),
+ ModError::FileNotFound(name, default_path, secondary_path) => {
+ sess.emit_err(ModuleFileNotFound {
span,
- E0583,
- "file not found for module `{}`",
- ident,
- );
- err.help(&format!(
- "to create the module `{}`, create file \"{}\" or \"{}\"",
- ident,
- default_path.display(),
- secondary_path.display(),
- ));
- err
+ name,
+ default_path: default_path.display().to_string(),
+ secondary_path: secondary_path.display().to_string(),
+ })
}
- ModError::MultipleCandidates(ident, default_path, secondary_path) => {
- let mut err = struct_span_err!(
- diag,
+ ModError::MultipleCandidates(name, default_path, secondary_path) => {
+ sess.emit_err(ModuleMultipleCandidates {
span,
- E0761,
- "file for module `{}` found at both \"{}\" and \"{}\"",
- ident,
- default_path.display(),
- secondary_path.display(),
- );
- err.help("delete or rename one of them to remove the ambiguity");
- err
+ name,
+ default_path: default_path.display().to_string(),
+ secondary_path: secondary_path.display().to_string(),
+ })
}
- ModError::ParserError(err) => err,
- }.emit()
+ ModError::ParserError(mut err) => err.emit(),
+ }
}
}
use rustc_ast as ast;
use rustc_ast::token;
use rustc_ast::tokenstream::{self, Spacing::*, TokenStream};
+use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span))
}
ast::ExprKind::IncludedBytes(bytes) => {
- let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit();
+ let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span))
}
ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind {
false,
);
let handler = Handler::with_emitter(true, None, Box::new(emitter));
+ #[allow(rustc::untranslatable_diagnostic)]
handler.span_err(msp, "foo");
assert!(
(accepted, copy_closures, "1.26.0", Some(44490), None),
/// Allows `crate` in paths.
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
+ /// Allows rustc to inject a default alloc_error_handler
+ (accepted, default_alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(66741), None),
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
(accepted, default_type_params, "1.0.0", None, None),
/// Allows `#[deprecated]` attribute.
(active, debugger_visualizer, "1.62.0", Some(95939), None),
/// Allows declarative macros 2.0 (`macro`).
(active, decl_macro, "1.17.0", Some(39412), None),
- /// Allows rustc to inject a default alloc_error_handler
- (active, default_alloc_error_handler, "1.48.0", Some(66741), None),
/// Allows default type parameters to influence type inference.
(active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
gated!(
no_sanitize, Normal,
- template!(List: "address, memory, thread"), DuplicatesOk,
+ template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize)
),
gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
}
pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
- for param in self.params {
- if name == param.name.ident().name {
- return Some(param);
- }
- }
- None
+ self.params.iter().find(|¶m| name == param.name.ident().name)
}
pub fn spans(&self) -> MultiSpan {
pub struct OwnerNodes<'tcx> {
/// Pre-computed hash of the full HIR.
pub hash_including_bodies: Fingerprint,
- /// Pre-computed hash of the item signature, sithout recursing into the body.
+ /// Pre-computed hash of the item signature, without recursing into the body.
pub hash_without_bodies: Fingerprint,
/// Full HIR for the current owner.
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
use rustc_span::symbol::Ident;
use rustc_span::Span;
-use std::iter::{Enumerate, ExactSizeIterator};
+use std::iter::Enumerate;
pub struct EnumerateAndAdjust<I> {
enumerate: Enumerate<I>,
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::edition::Edition;
+use rustc_span::{create_session_if_not_set_then, Symbol};
#[test]
fn def_path_hash_depends_on_crate_id() {
// the crate by changing the crate disambiguator (e.g. via bumping the
// crate's version number).
- let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
- let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+ create_session_if_not_set_then(Edition::Edition2024, |_| {
+ let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
+ let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
- let h0 = mk_test_hash(id0);
- let h1 = mk_test_hash(id1);
+ 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());
+ assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
+ assert_ne!(h0.local_hash(), h1.local_hash());
- fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
- let parent_hash = DefPathHash::new(stable_crate_id, 0);
+ fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+ let parent_hash = DefPathHash::new(stable_crate_id, 0);
- let key = DefKey {
- parent: None,
- disambiguated_data: DisambiguatedDefPathData {
- data: DefPathData::CrateRoot,
- disambiguator: 0,
- },
- };
+ let key = DefKey {
+ parent: None,
+ disambiguated_data: DisambiguatedDefPathData {
+ data: DefPathData::CrateRoot,
+ disambiguator: 0,
+ },
+ };
- key.compute_stable_hash(parent_hash)
- }
+ key.compute_stable_hash(parent_hash)
+ }
+ })
}
let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
let poly_trait_ref =
- ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+ ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars);
debug!(?poly_trait_ref, ?assoc_bindings);
bounds.trait_bounds.push((poly_trait_ref, span, constness));
if let Some(b) = trait_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
}
- ty::TraitRef::new(trait_def_id, substs)
+ self.tcx().mk_trait_ref(trait_def_id, substs)
}
#[instrument(level = "debug", skip(self, span))]
debug!(?substs_trait_ref_and_assoc_item);
- ty::ProjectionTy {
- item_def_id: assoc_item.def_id,
- substs: substs_trait_ref_and_assoc_item,
- }
+ self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
});
if !speculative {
// the "projection predicate" for:
//
// `<T as Iterator>::Item = u32`
- let assoc_item_def_id = projection_ty.skip_binder().item_def_id;
+ let assoc_item_def_id = projection_ty.skip_binder().def_id;
let def_kind = tcx.def_kind(assoc_item_def_id);
match (def_kind, term.unpack()) {
(hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
//
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
// parameter to have a skipped binder.
- let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
+ let param_ty = tcx.mk_ty(ty::Alias(ty::Projection, projection_ty.skip_binder()));
self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
}
}
use crate::check::intrinsicck::InlineAsmCtxt;
+use crate::errors::LinkageType;
use super::compare_method::check_type_bounds;
use super::compare_method::{compare_impl_method, compare_ty_impl};
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
}
+fn is_enum_of_nonnullable_ptr<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ adt_def: AdtDef<'tcx>,
+ substs: SubstsRef<'tcx>,
+) -> bool {
+ if adt_def.repr().inhibit_enum_layout_opt() {
+ return false;
+ }
+
+ let [var_one, var_two] = &adt_def.variants().raw[..] else {
+ return false;
+ };
+ let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+ return false;
+ };
+ matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
+}
+
+fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+ if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
+ if match tcx.type_of(def_id).kind() {
+ ty::RawPtr(_) => false,
+ ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
+ _ => true,
+ } {
+ tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) });
+ }
+ }
+}
+
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
debug!(
"check_item_type(it.def_id={:?}, it.name={})",
tcx.ensure().typeck(id.owner_id.def_id);
maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
check_static_inhabited(tcx, id.owner_id.def_id);
+ check_static_linkage(tcx, id.owner_id.def_id);
}
DefKind::Const => {
tcx.ensure().typeck(id.owner_id.def_id);
assoc_item,
assoc_item,
default.span,
- ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
+ tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
);
}
_ => {}
}
hir::ForeignItemKind::Static(..) => {
check_static_inhabited(tcx, def_id);
+ check_static_linkage(tcx, def_id);
}
_ => {}
}
impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
- ty::Opaque(def, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
self.0.push(def);
ControlFlow::CONTINUE
}
return;
}
+ if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
+ return;
+ }
+
if let Err(_) = compare_predicate_entailment(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)
{
return;
Ok(())
}
+fn compare_asyncness<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_m: &ty::AssocItem,
+ impl_m_span: Span,
+ trait_m: &ty::AssocItem,
+ trait_item_span: Option<Span>,
+) -> Result<(), ErrorGuaranteed> {
+ if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
+ match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
+ ty::Alias(ty::Opaque, ..) => {
+ // allow both `async fn foo()` and `fn foo() -> impl Future`
+ }
+ ty::Error(rustc_errors::ErrorGuaranteed { .. }) => {
+ // We don't know if it's ok, but at least it's already an error.
+ }
+ _ => {
+ return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
+ span: impl_m_span,
+ method_name: trait_m.name,
+ trait_item_span,
+ }));
+ }
+ };
+ }
+
+ Ok(())
+}
+
#[instrument(skip(tcx), level = "debug", ret)]
pub fn collect_trait_impl_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
tcx.fn_sig(impl_m.def_id),
),
);
+ impl_sig.error_reported()?;
let impl_return_ty = impl_sig.output();
// Normalize the trait signature with liberated bound vars, passing it through
)
.fold_with(&mut collector);
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
+ trait_sig.error_reported()?;
let trait_return_ty = trait_sig.output();
let wf_tys = FxIndexSet::from_iter(
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Projection(proj) = ty.kind()
- && self.tcx().def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+ if let ty::Alias(ty::Projection, proj) = ty.kind()
+ && self.tcx().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
{
- if let Some((ty, _)) = self.types.get(&proj.item_def_id) {
+ if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
}
//FIXME(RPITIT): Deny nested RPITIT in substs too
span: self.span,
kind: TypeVariableOriginKind::MiscVariable,
});
- self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
+ self.types.insert(proj.def_id, (infer_ty, proj.substs));
// Recurse into bounds
- for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
+ for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.tcx(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
ObligationCause::new(
self.span,
self.body_id,
- ObligationCauseCode::BindingObligation(proj.item_def_id, pred_span),
+ ObligationCauseCode::BindingObligation(proj.def_id, pred_span),
),
self.param_env,
pred,
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
match impl_ty_value.kind() {
- ty::Projection(proj)
- if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs =>
+ ty::Alias(ty::Projection, proj)
+ if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
{
// Don't include this predicate if the projected type is
// exactly the same as the projection. This can occur in
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- item_def_id: trait_ty.def_id,
- substs: rebased_substs,
- },
+ projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
term: impl_ty_value.into(),
},
bound_vars,
// insert the associated types where they correspond, but for now let's be "lazy" and
// propose this instead of the following valid resugaring:
// `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
- where_clauses.push(format!(
- "{} = {}",
- tcx.def_path_str(p.projection_ty.item_def_id),
- p.term,
- ));
+ where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term));
}
let where_clauses = if where_clauses.is_empty() {
String::new()
};
use std::cell::LazyCell;
-use std::convert::TryInto;
use std::iter;
use std::ops::{ControlFlow, Deref};
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
- ty::Projection(p) if p.item_def_id == self.gat => {
+ ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
for (idx, subst) in p.substs.iter().enumerate() {
match subst.unpack() {
GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => {
{
for arg in fn_output.walk() {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Projection(proj) = ty.kind()
- && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
- && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
+ && let ty::Alias(ty::Projection, proj) = ty.kind()
+ && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+ && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
{
- let span = tcx.def_span(proj.item_def_id);
- let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
+ let span = tcx.def_span(proj.def_id);
+ let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
let normalized_bound = wfcx.normalize(span, None, bound);
| ty::Tuple(..) => {
self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
}
- ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+ ty::Alias(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
ty.span,
use crate::astconv::AstConv;
use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
-use rustc_ast as ast;
-use rustc_ast::{MetaItemKind, NestedMetaItem};
-use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
-use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
+use rustc_hir::{GenericParamKind, Node};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, ToPredicate, Ty, TyCtxt};
-use rustc_session::lint;
-use rustc_session::parse::feature_err;
+use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::abi;
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
use std::iter;
impl_polarity,
is_foreign_item,
generator_kind,
- codegen_fn_attrs,
- asm_target_features,
collect_mod_item_types,
- should_inherit_track_caller,
..*providers
};
}
format!(
"{}::",
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
- self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
+ self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
),
Applicability::MaybeIncorrect,
);
.struct_span_err(
attr.span,
"the `#[rustc_must_implement_one_of]` attribute must be \
- used with at least 2 args",
+ used with at least 2 args",
)
.emit();
tcx.sess
.struct_span_err(
item.span,
- "This function doesn't have a default implementation",
+ "function doesn't have a default implementation",
)
.span_note(attr_span, "required by this annotation")
.emit();
}
Some(item) => {
tcx.sess
- .struct_span_err(item.span, "Not a function")
+ .struct_span_err(item.span, "not a function")
.span_note(attr_span, "required by this annotation")
.note(
- "All `#[rustc_must_implement_one_of]` arguments \
- must be associated function names",
+ "all `#[rustc_must_implement_one_of]` arguments must be associated \
+ function names",
)
.emit();
}
None => {
tcx.sess
- .struct_span_err(ident.span, "Function not found in this trait")
+ .struct_span_err(ident.span, "function not found in this trait")
.emit();
}
}
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
tcx.sess
- .struct_span_err(vec![dup, ident.span], "Functions names are duplicated")
- .note(
- "All `#[rustc_must_implement_one_of]` arguments \
- must be unique",
- )
+ .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
+ .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
.emit();
no_dups = false;
_ => bug!("generator_kind applied to non-local def-id {:?}", def_id),
}
}
-
-fn from_target_feature(
- tcx: TyCtxt<'_>,
- attr: &ast::Attribute,
- supported_target_features: &FxHashMap<String, Option<Symbol>>,
- target_features: &mut Vec<Symbol>,
-) {
- let Some(list) = attr.meta_item_list() else { return };
- let bad_item = |span| {
- let msg = "malformed `target_feature` attribute input";
- let code = "enable = \"..\"";
- tcx.sess
- .struct_span_err(span, msg)
- .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders)
- .emit();
- };
- let rust_features = tcx.features();
- for item in list {
- // Only `enable = ...` is accepted in the meta-item list.
- if !item.has_name(sym::enable) {
- bad_item(item.span());
- continue;
- }
-
- // Must be of the form `enable = "..."` (a string).
- let Some(value) = item.value_str() else {
- bad_item(item.span());
- continue;
- };
-
- // We allow comma separation to enable multiple features.
- target_features.extend(value.as_str().split(',').filter_map(|feature| {
- let Some(feature_gate) = supported_target_features.get(feature) else {
- let msg =
- format!("the feature named `{}` is not valid for this target", feature);
- let mut err = tcx.sess.struct_span_err(item.span(), &msg);
- err.span_label(
- item.span(),
- format!("`{}` is not valid for this target", feature),
- );
- if let Some(stripped) = feature.strip_prefix('+') {
- let valid = supported_target_features.contains_key(stripped);
- if valid {
- err.help("consider removing the leading `+` in the feature name");
- }
- }
- err.emit();
- return None;
- };
-
- // Only allow features whose feature gates have been enabled.
- let allowed = match feature_gate.as_ref().copied() {
- Some(sym::arm_target_feature) => rust_features.arm_target_feature,
- Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
- Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
- Some(sym::mips_target_feature) => rust_features.mips_target_feature,
- Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
- Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
- Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
- Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
- Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
- Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
- Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
- Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
- Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
- Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
- Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
- Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
- Some(name) => bug!("unknown target feature gate {}", name),
- None => true,
- };
- if !allowed {
- feature_err(
- &tcx.sess.parse_sess,
- feature_gate.unwrap(),
- item.span(),
- &format!("the target feature `{}` is currently unstable", feature),
- )
- .emit();
- }
- Some(Symbol::intern(feature))
- }));
- }
-}
-
-fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
- use rustc_middle::mir::mono::Linkage::*;
-
- // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
- // applicable to variable declarations and may not really make sense for
- // Rust code in the first place but allow them anyway and trust that the
- // user knows what they're doing. Who knows, unanticipated use cases may pop
- // up in the future.
- //
- // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
- // and don't have to be, LLVM treats them as no-ops.
- match name {
- "appending" => Appending,
- "available_externally" => AvailableExternally,
- "common" => Common,
- "extern_weak" => ExternalWeak,
- "external" => External,
- "internal" => Internal,
- "linkonce" => LinkOnceAny,
- "linkonce_odr" => LinkOnceODR,
- "private" => Private,
- "weak" => WeakAny,
- "weak_odr" => WeakODR,
- _ => tcx.sess.span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
- }
-}
-
-fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
- if cfg!(debug_assertions) {
- let def_kind = tcx.def_kind(did);
- assert!(
- def_kind.has_codegen_attrs(),
- "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
- );
- }
-
- let did = did.expect_local();
- let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(did));
- let mut codegen_fn_attrs = CodegenFnAttrs::new();
- if tcx.should_inherit_track_caller(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
- }
-
- let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
-
- let mut inline_span = None;
- let mut link_ordinal_span = None;
- let mut no_sanitize_span = None;
- for attr in attrs.iter() {
- if attr.has_name(sym::cold) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
- } else if attr.has_name(sym::rustc_allocator) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
- } else if attr.has_name(sym::ffi_returns_twice) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
- } else {
- // `#[ffi_returns_twice]` is only allowed `extern fn`s.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0724,
- "`#[ffi_returns_twice]` may only be used on foreign functions"
- )
- .emit();
- }
- } else if attr.has_name(sym::ffi_pure) {
- if tcx.is_foreign_item(did) {
- if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
- // `#[ffi_const]` functions cannot be `#[ffi_pure]`
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0757,
- "`#[ffi_const]` function cannot be `#[ffi_pure]`"
- )
- .emit();
- } else {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
- }
- } else {
- // `#[ffi_pure]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0755,
- "`#[ffi_pure]` may only be used on foreign functions"
- )
- .emit();
- }
- } else if attr.has_name(sym::ffi_const) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
- } else {
- // `#[ffi_const]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0756,
- "`#[ffi_const]` may only be used on foreign functions"
- )
- .emit();
- }
- } else if attr.has_name(sym::rustc_nounwind) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
- } else if attr.has_name(sym::rustc_reallocator) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
- } else if attr.has_name(sym::rustc_deallocator) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR;
- } else if attr.has_name(sym::rustc_allocator_zeroed) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED;
- } else if attr.has_name(sym::naked) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
- } else if attr.has_name(sym::no_mangle) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
- } else if attr.has_name(sym::no_coverage) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
- } else if attr.has_name(sym::rustc_std_internal_symbol) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
- } else if attr.has_name(sym::used) {
- let inner = attr.meta_item_list();
- match inner.as_deref() {
- Some([item]) if item.has_name(sym::linker) => {
- if !tcx.features().used_with_arg {
- feature_err(
- &tcx.sess.parse_sess,
- sym::used_with_arg,
- attr.span,
- "`#[used(linker)]` is currently unstable",
- )
- .emit();
- }
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
- }
- Some([item]) if item.has_name(sym::compiler) => {
- if !tcx.features().used_with_arg {
- feature_err(
- &tcx.sess.parse_sess,
- sym::used_with_arg,
- attr.span,
- "`#[used(compiler)]` is currently unstable",
- )
- .emit();
- }
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
- }
- Some(_) => {
- tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
- }
- None => {
- // Unfortunately, unconditionally using `llvm.used` causes
- // issues in handling `.init_array` with the gold linker,
- // but using `llvm.compiler.used` caused a nontrival amount
- // of unintentional ecosystem breakage -- particularly on
- // Mach-O targets.
- //
- // As a result, we emit `llvm.compiler.used` only on ELF
- // targets. This is somewhat ad-hoc, but actually follows
- // our pre-LLVM 13 behavior (prior to the ecosystem
- // breakage), and seems to match `clang`'s behavior as well
- // (both before and after LLVM 13), possibly because they
- // have similar compatibility concerns to us. See
- // https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146
- // and following comments for some discussion of this, as
- // well as the comments in `rustc_codegen_llvm` where these
- // flags are handled.
- //
- // Anyway, to be clear: this is still up in the air
- // somewhat, and is subject to change in the future (which
- // is a good thing, because this would ideally be a bit
- // more firmed up).
- let is_like_elf = !(tcx.sess.target.is_like_osx
- || tcx.sess.target.is_like_windows
- || tcx.sess.target.is_like_wasm);
- codegen_fn_attrs.flags |= if is_like_elf {
- CodegenFnAttrFlags::USED
- } else {
- CodegenFnAttrFlags::USED_LINKER
- };
- }
- }
- } else if attr.has_name(sym::cmse_nonsecure_entry) {
- if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) {
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0776,
- "`#[cmse_nonsecure_entry]` requires C ABI"
- )
- .emit();
- }
- if !tcx.sess.target.llvm_target.contains("thumbv8m") {
- struct_span_err!(tcx.sess, attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
- .emit();
- }
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
- } else if attr.has_name(sym::thread_local) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
- } else if attr.has_name(sym::track_caller) {
- if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust {
- struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
- .emit();
- }
- if tcx.is_closure(did.to_def_id()) && !tcx.features().closure_track_caller {
- feature_err(
- &tcx.sess.parse_sess,
- sym::closure_track_caller,
- attr.span,
- "`#[track_caller]` on closures is currently unstable",
- )
- .emit();
- }
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
- } else if attr.has_name(sym::export_name) {
- if let Some(s) = attr.value_str() {
- if s.as_str().contains('\0') {
- // `#[export_name = ...]` will be converted to a null-terminated string,
- // so it may not contain any null characters.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0648,
- "`export_name` may not contain null characters"
- )
- .emit();
- }
- codegen_fn_attrs.export_name = Some(s);
- }
- } else if attr.has_name(sym::target_feature) {
- if !tcx.is_closure(did.to_def_id())
- && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
- {
- if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
- // The `#[target_feature]` attribute is allowed on
- // WebAssembly targets on all functions, including safe
- // ones. Other targets require that `#[target_feature]` is
- // only applied to unsafe functions (pending the
- // `target_feature_11` feature) because on most targets
- // execution of instructions that are not supported is
- // considered undefined behavior. For WebAssembly which is a
- // 100% safe target at execution time it's not possible to
- // execute undefined instructions, and even if a future
- // feature was added in some form for this it would be a
- // deterministic trap. There is no undefined behavior when
- // executing WebAssembly so `#[target_feature]` is allowed
- // on safe functions (but again, only for WebAssembly)
- //
- // Note that this is also allowed if `actually_rustdoc` so
- // if a target is documenting some wasm-specific code then
- // it's not spuriously denied.
- } else if !tcx.features().target_feature_11 {
- let mut err = feature_err(
- &tcx.sess.parse_sess,
- sym::target_feature_11,
- attr.span,
- "`#[target_feature(..)]` can only be applied to `unsafe` functions",
- );
- err.span_label(tcx.def_span(did), "not an `unsafe` function");
- err.emit();
- } else {
- check_target_feature_trait_unsafe(tcx, did, attr.span);
- }
- }
- from_target_feature(
- tcx,
- attr,
- supported_target_features,
- &mut codegen_fn_attrs.target_features,
- );
- } else if attr.has_name(sym::linkage) {
- if let Some(val) = attr.value_str() {
- codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str()));
- }
- } else if attr.has_name(sym::link_section) {
- if let Some(val) = attr.value_str() {
- if val.as_str().bytes().any(|b| b == 0) {
- let msg = format!(
- "illegal null byte in link_section \
- value: `{}`",
- &val
- );
- tcx.sess.span_err(attr.span, &msg);
- } else {
- codegen_fn_attrs.link_section = Some(val);
- }
- }
- } else if attr.has_name(sym::link_name) {
- codegen_fn_attrs.link_name = attr.value_str();
- } else if attr.has_name(sym::link_ordinal) {
- link_ordinal_span = Some(attr.span);
- if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
- codegen_fn_attrs.link_ordinal = ordinal;
- }
- } else if attr.has_name(sym::no_sanitize) {
- no_sanitize_span = Some(attr.span);
- if let Some(list) = attr.meta_item_list() {
- for item in list.iter() {
- if item.has_name(sym::address) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
- } else if item.has_name(sym::cfi) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
- } else if item.has_name(sym::memory) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
- } else if item.has_name(sym::memtag) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
- } else if item.has_name(sym::shadow_call_stack) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK;
- } else if item.has_name(sym::thread) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
- } else if item.has_name(sym::hwaddress) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
- } else {
- tcx.sess
- .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
- .note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
- .emit();
- }
- }
- }
- } else if attr.has_name(sym::instruction_set) {
- codegen_fn_attrs.instruction_set = match attr.meta_kind() {
- Some(MetaItemKind::List(ref items)) => match items.as_slice() {
- [NestedMetaItem::MetaItem(set)] => {
- let segments =
- set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
- match segments.as_slice() {
- [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
- if !tcx.sess.target.has_thumb_interworking {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "target does not support `#[instruction_set]`"
- )
- .emit();
- None
- } else if segments[1] == sym::a32 {
- Some(InstructionSetAttr::ArmA32)
- } else if segments[1] == sym::t32 {
- Some(InstructionSetAttr::ArmT32)
- } else {
- unreachable!()
- }
- }
- _ => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "invalid instruction set specified",
- )
- .emit();
- None
- }
- }
- }
- [] => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0778,
- "`#[instruction_set]` requires an argument"
- )
- .emit();
- None
- }
- _ => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "cannot specify more than one instruction set"
- )
- .emit();
- None
- }
- },
- _ => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0778,
- "must specify an instruction set"
- )
- .emit();
- None
- }
- };
- } else if attr.has_name(sym::repr) {
- codegen_fn_attrs.alignment = match attr.meta_item_list() {
- Some(items) => match items.as_slice() {
- [item] => match item.name_value_literal() {
- Some((sym::align, literal)) => {
- let alignment = rustc_attr::parse_alignment(&literal.kind);
-
- match alignment {
- Ok(align) => Some(align),
- Err(msg) => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0589,
- "invalid `repr(align)` attribute: {}",
- msg
- )
- .emit();
-
- None
- }
- }
- }
- _ => None,
- },
- [] => None,
- _ => None,
- },
- None => None,
- };
- }
- }
-
- codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
- if !attr.has_name(sym::inline) {
- return ia;
- }
- match attr.meta_kind() {
- Some(MetaItemKind::Word) => InlineAttr::Hint,
- Some(MetaItemKind::List(ref items)) => {
- inline_span = Some(attr.span);
- if items.len() != 1 {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0534,
- "expected one argument"
- )
- .emit();
- InlineAttr::None
- } else if list_contains_name(&items, sym::always) {
- InlineAttr::Always
- } else if list_contains_name(&items, sym::never) {
- InlineAttr::Never
- } else {
- struct_span_err!(
- tcx.sess.diagnostic(),
- items[0].span(),
- E0535,
- "invalid argument"
- )
- .help("valid inline arguments are `always` and `never`")
- .emit();
-
- InlineAttr::None
- }
- }
- Some(MetaItemKind::NameValue(_)) => ia,
- None => ia,
- }
- });
-
- codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| {
- if !attr.has_name(sym::optimize) {
- return ia;
- }
- let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit();
- match attr.meta_kind() {
- Some(MetaItemKind::Word) => {
- err(attr.span, "expected one argument");
- ia
- }
- Some(MetaItemKind::List(ref items)) => {
- inline_span = Some(attr.span);
- if items.len() != 1 {
- err(attr.span, "expected one argument");
- OptimizeAttr::None
- } else if list_contains_name(&items, sym::size) {
- OptimizeAttr::Size
- } else if list_contains_name(&items, sym::speed) {
- OptimizeAttr::Speed
- } else {
- err(items[0].span(), "invalid argument");
- OptimizeAttr::None
- }
- }
- Some(MetaItemKind::NameValue(_)) => ia,
- None => ia,
- }
- });
-
- // #73631: closures inherit `#[target_feature]` annotations
- if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) {
- let owner_id = tcx.parent(did.to_def_id());
- if tcx.def_kind(owner_id).has_codegen_attrs() {
- codegen_fn_attrs
- .target_features
- .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
- }
- }
-
- // If a function uses #[target_feature] it can't be inlined into general
- // purpose functions as they wouldn't have the right target features
- // enabled. For that reason we also forbid #[inline(always)] as it can't be
- // respected.
- if !codegen_fn_attrs.target_features.is_empty() {
- if codegen_fn_attrs.inline == InlineAttr::Always {
- if let Some(span) = inline_span {
- tcx.sess.span_err(
- span,
- "cannot use `#[inline(always)]` with \
- `#[target_feature]`",
- );
- }
- }
- }
-
- if !codegen_fn_attrs.no_sanitize.is_empty() {
- if codegen_fn_attrs.inline == InlineAttr::Always {
- if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(did);
- tcx.struct_span_lint_hir(
- lint::builtin::INLINE_NO_SANITIZE,
- hir_id,
- no_sanitize_span,
- "`no_sanitize` will have no effect after inlining",
- |lint| lint.span_note(inline_span, "inlining requested here"),
- )
- }
- }
- }
-
- if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
- codegen_fn_attrs.inline = InlineAttr::Never;
- }
-
- // Weak lang items have the same semantics as "std internal" symbols in the
- // sense that they're preserved through all our LTO passes and only
- // strippable by the linker.
- //
- // Additionally weak lang items have predetermined symbol names.
- if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
- }
- if let Some((name, _)) = lang_items::extract(attrs)
- && let Some(lang_item) = LangItem::from_name(name)
- && let Some(link_name) = lang_item.link_name()
- {
- codegen_fn_attrs.export_name = Some(link_name);
- codegen_fn_attrs.link_name = Some(link_name);
- }
- check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
-
- // Internal symbols to the standard library all have no_mangle semantics in
- // that they have defined symbol names present in the function name. This
- // also applies to weak symbols where they all have known symbol names.
- if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
- }
-
- // Any linkage to LLVM intrinsics for now forcibly marks them all as never
- // unwinds since LLVM sometimes can't handle codegen which `invoke`s
- // intrinsic functions.
- if let Some(name) = &codegen_fn_attrs.link_name {
- if name.as_str().starts_with("llvm.") {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
- }
- }
-
- codegen_fn_attrs
-}
-
-/// Computes the set of target features used in a function for the purposes of
-/// inline assembly.
-fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx FxHashSet<Symbol> {
- let mut target_features = tcx.sess.unstable_target_features.clone();
- if tcx.def_kind(did).has_codegen_attrs() {
- let attrs = tcx.codegen_fn_attrs(did);
- target_features.extend(&attrs.target_features);
- match attrs.instruction_set {
- None => {}
- Some(InstructionSetAttr::ArmA32) => {
- target_features.remove(&sym::thumb_mode);
- }
- Some(InstructionSetAttr::ArmT32) => {
- target_features.insert(sym::thumb_mode);
- }
- }
- }
-
- tcx.arena.alloc(target_features)
-}
-
-/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
-/// applied to the method prototype.
-fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- if let Some(impl_item) = tcx.opt_associated_item(def_id)
- && let ty::AssocItemContainer::ImplContainer = impl_item.container
- && let Some(trait_item) = impl_item.trait_item_def_id
- {
- return tcx
- .codegen_fn_attrs(trait_item)
- .flags
- .intersects(CodegenFnAttrFlags::TRACK_CALLER);
- }
-
- false
-}
-
-fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
- use rustc_ast::{LitIntType, LitKind, MetaItemLit};
- if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
- feature_err(
- &tcx.sess.parse_sess,
- sym::raw_dylib,
- attr.span,
- "`#[link_ordinal]` is unstable on x86",
- )
- .emit();
- }
- let meta_item_list = attr.meta_item_list();
- let meta_item_list = meta_item_list.as_deref();
- let sole_meta_list = match meta_item_list {
- Some([item]) => item.lit(),
- Some(_) => {
- tcx.sess
- .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
- .note("the attribute requires exactly one argument")
- .emit();
- return None;
- }
- _ => None,
- };
- if let Some(MetaItemLit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) =
- sole_meta_list
- {
- // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header,
- // the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined
- // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information
- // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t.
- //
- // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this:
- // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies
- // a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library
- // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import
- // library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet
- // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
- // about LINK.EXE failing.)
- if *ordinal <= u16::MAX as u128 {
- Some(*ordinal as u16)
- } else {
- let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
- tcx.sess
- .struct_span_err(attr.span, &msg)
- .note("the value may not exceed `u16::MAX`")
- .emit();
- None
- }
- } else {
- tcx.sess
- .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
- .note("an unsuffixed integer value, e.g., `1`, is expected")
- .emit();
- None
- }
-}
-
-fn check_link_name_xor_ordinal(
- tcx: TyCtxt<'_>,
- codegen_fn_attrs: &CodegenFnAttrs,
- inline_span: Option<Span>,
-) {
- if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() {
- return;
- }
- let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
- if let Some(span) = inline_span {
- tcx.sess.span_err(span, msg);
- } else {
- tcx.sess.err(msg);
- }
-}
-
-/// Checks the function annotated with `#[target_feature]` is not a safe
-/// trait method implementation, reporting an error if it is.
-fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(id);
- let node = tcx.hir().get(hir_id);
- if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
- let parent_id = tcx.hir().get_parent_item(hir_id);
- let parent_item = tcx.hir().expect_item(parent_id.def_id);
- if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
- tcx.sess
- .struct_span_err(
- attr_span,
- "`#[target_feature(..)]` cannot be applied to safe trait method",
- )
- .span_label(attr_span, "cannot be applied to safe trait method")
- .span_label(tcx.def_span(id), "not an `unsafe` function")
- .emit();
- }
- }
-}
GenericParamKind, HirId, Node,
};
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint;
let generics = tcx.generics_of(parent_def_id.to_def_id());
let param_def_idx = generics.param_def_id_to_index[¶m_id.to_def_id()];
// In the above example this would be .params[..N#0]
- let params = generics.params[..param_def_idx as usize].to_owned();
+ let params = generics.params_to(param_def_idx as usize, tcx).to_owned();
let param_def_id_to_index =
params.iter().map(|param| (param.def_id, param.index)).collect();
Some(tcx.typeck_root_def_id(def_id))
}
Node::Item(item) => match item.kind {
- ItemKind::OpaqueTy(hir::OpaqueTy {
- origin:
- hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
- in_trait,
- ..
- }) => {
- if in_trait {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
- } else {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
- }
- Some(fn_def_id.to_def_id())
- }
- ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+ ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
ty::Param(param_ty) => {
self.arg_is_constrained[param_ty.index as usize] = true;
}
- ty::Projection(_) => return ControlFlow::Continue(()),
+ ty::Alias(ty::Projection, _) => return ControlFlow::Continue(()),
_ => (),
}
t.super_visit_with(self)
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
- // We use an `IndexSet` to preserves order of insertion.
+ // We use an `IndexSet` to preserve order of insertion.
// Preserving the order of insertion is important here so as not to break UI tests.
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) => *generics,
- ItemKind::Trait(_, _, ref generics, ..) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
- *generics
- }
- ItemKind::TraitAlias(ref generics, _) => {
+ ItemKind::Trait(_, _, ref generics, ..) | ItemKind::TraitAlias(ref generics, _) => {
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
*generics
}
// For a predicate from a where clause to become a bound on an
// associated type:
// * It must use the identity substs of the item.
- // * Since any generic parameters on the item are not in scope,
- // this means that the item is not a GAT, and its identity
- // substs are the same as the trait's.
+ // * We're in the scope of the trait, so we can't name any
+ // parameters of the GAT. That means that all we need to
+ // check are that the substs of the projection are the
+ // identity substs of the trait.
// * It must be an associated type for this trait (*not* a
// supertrait).
- if let ty::Projection(projection) = ty.kind() {
+ if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
- && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+ && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
} else {
false
}
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
- // into a ty::Projection(<Self as Foo>::Assoc<3>)
+ // into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
let item_hir_id = tcx
.hir()
.parent_iter(hir_id)
// the def_id that this query was called with. We filter to only type and const args here
// as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
// but it can't hurt to be safe ^^
- if let ty::Projection(projection) = ty.kind() {
- let generics = tcx.generics_of(projection.item_def_id);
+ if let ty::Alias(ty::Projection, projection) = ty.kind() {
+ let generics = tcx.generics_of(projection.def_id);
let arg_index = segment
.args
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let scope = tcx.hir().get_defining_scope(hir_id);
- let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
+ let mut locator = ConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
debug!(?scope);
if let Some(concrete) = concrete {
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
debug!(?scope);
- let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+ let mut locator = ConstraintChecker { def_id, tcx, found: concrete };
match tcx.hir().get(scope) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
- ty::Projection(..) if !self.include_nonconstraining => {
+ ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
// projections are not injective
return ControlFlow::CONTINUE;
}
pub ident: Ident,
}
+#[derive(Diagnostic)]
+#[diag(hir_analysis_async_trait_impl_should_be_async)]
+pub struct AsyncTraitImplShouldBeAsync {
+ #[primary_span]
+ // #[label]
+ pub span: Span,
+ #[label(trait_item_label)]
+ pub trait_item_span: Option<Span>,
+ pub method_name: Symbol,
+}
+
#[derive(Diagnostic)]
#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
pub struct DropImplOnWrongItem {
pub suggestion_code: String,
}
-#[derive(Diagnostic)]
-#[diag(hir_analysis_expected_used_symbol)]
-pub struct ExpectedUsedSymbol {
- #[primary_span]
- pub span: Span,
-}
-
#[derive(Diagnostic)]
#[diag(hir_analysis_const_impl_for_non_const_trait)]
pub struct ConstImplForNonConstTrait {
#[note]
pub note: (),
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_linkage_type, code = "E0791")]
+pub(crate) struct LinkageType {
+ #[primary_span]
+ pub span: Span,
+}
}
}
- ty::Projection(obj) => {
+ ty::Alias(ty::Projection, obj) => {
// This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
// explicit predicates as well.
debug!("Projection");
check_explicit_predicates(
tcx,
- tcx.parent(obj.item_def_id),
+ tcx.parent(obj.def_id),
obj.substs,
required_predicates,
explicit_map,
// ```
//
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
- let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
+ let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.def_id, proj_ty.substs);
required_predicates
.entry(ty::OutlivesPredicate(ty.into(), outlived_region))
.or_insert(span);
self.add_constraints_from_substs(current, def.did(), substs, variance);
}
- ty::Projection(ref data) => {
+ ty::Alias(_, ref data) => {
self.add_constraints_from_invariant_substs(current, data.substs, variance);
}
- ty::Opaque(_, substs) => {
- self.add_constraints_from_invariant_substs(current, substs, variance);
- }
-
ty::Dynamic(data, r, _) => {
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance);
#[instrument(level = "trace", skip(self), ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
- ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs),
- ty::Projection(proj)
- if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ if matches!(
+ self.tcx.def_kind(*def_id),
+ DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+ ) =>
{
- self.visit_opaque(proj.item_def_id, proj.substs)
+ self.visit_opaque(*def_id, substs)
}
_ => t.super_visit_with(self),
}
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
- trait_ref: ty::TraitRef { def_id: _, substs },
+ trait_ref: ty::TraitRef { def_id: _, substs, .. },
constness: _,
polarity: _,
})) => {
}
}
ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
+ projection_ty: ty::AliasTy { substs, .. },
term,
})) => {
for subst in &substs[1..] {
fn print_literal(&mut self, lit: &hir::Lit) {
self.maybe_print_comment(lit.span.lo());
- self.word(lit.node.to_token_lit().to_string())
+ self.word(lit.node.to_string())
}
fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) {
self.print_qpath(qpath, true);
self.popen();
if let Some(ddpos) = ddpos.as_opt_usize() {
- let ddpos = ddpos as usize;
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
if ddpos != 0 {
self.word_space(",");
self.can_coerce(arm_ty, ret_ty)
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
// The match arms need to unify for the case of `impl Trait`.
- && !matches!(ret_ty.kind(), ty::Opaque(..))
+ && !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
}
_ => false,
};
let substs = sig.output().walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Opaque(def_id, substs) = *ty.kind()
+ && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind()
&& def_id == rpit_def_id
{
Some(substs)
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
ty::PredicateKind::Clause(ty::Clause::Trait(
- trait_pred.with_self_type(self.tcx, ty),
+ trait_pred.with_self_ty(self.tcx, ty),
))
}
ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty);
- proj_pred.projection_ty.substs = self.tcx.mk_substs_trait(
- ty,
- proj_pred.projection_ty.substs.iter().skip(1),
- );
+ proj_pred = proj_pred.with_self_ty(self.tcx, ty);
ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
}
_ => continue,
callee_expr,
call_expr,
callee_ty,
- pick,
+ &pick,
segment,
);
if pick.illegal_sized_bound.is_some() {
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::cast::{CastKind, CastTy};
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
use rustc_session::lint;
use rustc_session::Session;
VTable(Option<DefId>),
/// Slice
Length,
- /// The unsize info of this projection
- OfProjection(ty::ProjectionTy<'tcx>),
- /// The unsize info of this opaque ty
- OfOpaque(DefId, SubstsRef<'tcx>),
+ /// The unsize info of this projection or opaque type
+ OfAlias(ty::AliasTy<'tcx>),
/// The unsize info of this parameter
OfParam(ty::ParamTy),
}
// Pointers to foreign types are thin, despite being unsized
ty::Foreign(..) => Some(PointerKind::Thin),
// We should really try to normalize here.
- ty::Projection(pi) => Some(PointerKind::OfProjection(pi)),
- ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
+ ty::Alias(_, pi) => Some(PointerKind::OfAlias(pi)),
ty::Param(p) => Some(PointerKind::OfParam(p)),
// Insufficient type information.
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
- (_, DynStar) | (DynStar, _) => {
+ (_, DynStar) => {
if fcx.tcx.features().dyn_star {
bug!("should be handled by `try_coerce`")
} else {
Err(CastError::IllegalCast)
}
}
+
+ (DynStar, _) => Err(CastError::IllegalCast),
}
}
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
- Some(
- PointerKind::OfProjection(_)
- | PointerKind::OfOpaque(_, _)
- | PointerKind::OfParam(_),
- ) => Err(CastError::IntToFatCast(None)),
+ Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
+ Err(CastError::IntToFatCast(None))
+ }
}
}
use crate::coercion::CoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
use crate::FnCtxt;
-use crate::{GeneratorTypes, UnsafetyState};
+use crate::GeneratorTypes;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
can_be_generator: Option<hir::Movability>,
) -> Option<GeneratorTypes<'tcx>> {
let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
- fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
let tcx = fcx.tcx;
let hir = tcx.hir();
expected_ty: Ty<'tcx>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
- ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates(
- self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
- ),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
+ .deduce_signature_from_predicates(
+ self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+ ),
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
// `deduce_expectations_from_expected_type` introduces
// late-bound lifetimes defined elsewhere, which we now
// anonymize away, so as not to confuse the user.
- let bound_sig = self.tcx.anonymize_late_bound_regions(bound_sig);
+ let bound_sig = self.tcx.anonymize_bound_vars(bound_sig);
let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig);
get_future_output(obligation.predicate, obligation.cause.span)
})?
}
- ty::Opaque(def_id, substs) => self
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
.tcx
.bound_explicit_item_bounds(def_id)
.subst_iter_copied(self.tcx, substs)
.find_map(|(p, s)| get_future_output(p, s))?,
ty::Error(_) => return None,
- ty::Projection(proj)
- if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ ty::Alias(ty::Projection, proj)
+ if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
{
self.tcx
- .bound_explicit_item_bounds(proj.item_def_id)
+ .bound_explicit_item_bounds(proj.def_id)
.subst_iter_copied(self.tcx, proj.substs)
.find_map(|(p, s)| get_future_output(p, s))?
}
// The `Future` trait has only one associated item, `Output`,
// so check that this is what we see.
let output_assoc_item = self.tcx.associated_item_def_ids(future_trait)[0];
- if output_assoc_item != predicate.projection_ty.item_def_id {
+ if output_assoc_item != predicate.projection_ty.def_id {
span_bug!(
cause_span,
"projecting associated item `{:?}` from future, which is not Output `{:?}`",
- predicate.projection_ty.item_def_id,
+ predicate.projection_ty.def_id,
output_assoc_item,
);
}
{
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
- if let ty::Opaque(def_id, _) = ty.kind()
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind()
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
&& let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
- error: Option<TypeError<'_>>,
+ error: Option<TypeError<'tcx>>,
) {
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
match (self.tcx.hir().find(parent), error) {
err.downgrade_to_delayed_bug();
}
}
+ (
+ Some(hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Binary(_, lhs, rhs), ..
+ })),
+ Some(TypeError::Sorts(ExpectedFound { expected, .. })),
+ ) if rhs.hir_id == expr.hir_id
+ && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) =>
+ {
+ err.span_label(lhs.span, &format!("expected because this is `{expected}`"));
+ }
_ => {}
}
}
};
match (&expected_ty.kind(), &checked_ty.kind()) {
- (&ty::Int(ref exp), &ty::Int(ref found)) => {
+ (ty::Int(exp), ty::Int(found)) => {
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
{
(Some(exp), Some(found)) if exp < found => (true, false),
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
true
}
- (&ty::Uint(ref exp), &ty::Uint(ref found)) => {
+ (ty::Uint(exp), ty::Uint(found)) => {
let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
{
(Some(exp), Some(found)) if exp < found => (true, false),
suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
true
}
- (&ty::Float(ref exp), &ty::Float(ref found)) => {
+ (ty::Float(exp), ty::Float(found)) => {
if found.bit_width() < exp.bit_width() {
suggest_to_change_suffix_or_into(err, false, true);
} else if literal_is_ty_suffixed(expr) {
}
true
}
- (&ty::Float(ref exp), &ty::Uint(ref found)) => {
+ (ty::Float(exp), ty::Uint(found)) => {
// if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
err.multipart_suggestion_verbose(
}
true
}
- (&ty::Float(ref exp), &ty::Int(ref found)) => {
+ (ty::Float(exp), ty::Int(found)) => {
// if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
if exp.bit_width() > found.bit_width().unwrap_or(256) {
err.multipart_suggestion_verbose(
// the fields with the base_expr. This could cause us to hit errors later
// when certain fields are assumed to exist that in fact do not.
if error_happened {
+ if let Some(base_expr) = base_expr {
+ self.check_expr(base_expr);
+ }
return;
}
// I don't use 'is_range_literal' because only double-sided, half-open ranges count.
if let ExprKind::Struct(
QPath::LangItem(LangItem::Range, ..),
- &[ref range_start, ref range_end],
+ [range_start, range_end],
_,
) = last_expr_field.expr.kind
&& let variant_field =
ty::Param(param_ty) => {
self.point_at_param_definition(&mut err, param_ty);
}
- ty::Opaque(_, _) => {
+ ty::Alias(ty::Opaque, _) => {
self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
}
_ => {}
// Consume the expressions supplying values for each field.
for field in fields {
self.consume_expr(field.expr);
+
+ // The struct path probably didn't resolve
+ if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
+ self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
+ }
}
let with_expr = match *opt_with {
ty::Adt(adt, substs) if adt.is_struct() => {
// Consume those fields of the with expression that are needed.
for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() {
- let is_mentioned = fields.iter().any(|f| {
- self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index
- });
+ let is_mentioned = fields
+ .iter()
+ .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index));
if !is_mentioned {
let field_place = self.mc.cat_projection(
&*with_expr,
if formal_ret.has_infer_types() {
for ty in ret_ty.walk() {
if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
- && let ty::Opaque(def_id, _) = *ty.kind()
+ && let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
&& let Some(def_id) = def_id.as_local()
&& self.opaque_type_origin(def_id, DUMMY_SP).is_some() {
return None;
match lit.node {
ast::LitKind::Str(..) => tcx.mk_static_str(),
- ast::LitKind::ByteStr(ref v) => {
+ ast::LitKind::ByteStr(ref v, _) => {
tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64))
}
ast::LitKind::Byte(_) => tcx.types.u8,
blk: &'tcx hir::Block<'tcx>,
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
- let prev = self.ps.replace(self.ps.get().recurse(blk));
-
// In some cases, blocks have just one exit, but other blocks
// can be targeted by multiple breaks. This can happen both
// with labeled blocks as well as when we desugar
self.write_ty(blk.hir_id, ty);
- self.ps.set(prev);
ty
}
}
}
}
- ty::Opaque(new_def_id, _)
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: new_def_id, .. })
| ty::Closure(new_def_id, _)
| ty::FnDef(new_def_id, _) => {
def_id = new_def_id;
_ => {
// Look for a user-provided impl of a `Fn` trait, and point to it.
let new_def_id = self.probe(|_| {
- let trait_ref = ty::TraitRef::new(
+ let trait_ref = self.tcx.mk_trait_ref(
call_kind.to_def_id(self.tcx),
- self.tcx.mk_substs(
- [
- ty::GenericArg::from(callee_ty),
- self.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::MiscVariable,
- span: rustc_span::DUMMY_SP,
- })
- .into(),
- ]
- .into_iter(),
- ),
+ [
+ callee_ty,
+ self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: rustc_span::DUMMY_SP,
+ }),
+ ],
);
let obligation = traits::Obligation::new(
self.tcx,
if arg == param_to_point_at {
return true;
} else if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Projection(..) = ty.kind()
+ && let ty::Alias(ty::Projection, ..) = ty.kind()
{
// This logic may seem a bit strange, but typically when
// we have a projection type in a function signature, the
pub use suggestions::*;
use crate::coercion::DynamicCoerceMany;
-use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
+use crate::{Diverges, EnclosingBreakables, Inherited};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir_analysis::astconv::AstConv;
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
- pub(super) ps: Cell<UnsafetyState>,
-
/// Whether the last checked node generates a divergence (e.g.,
/// `return` will set this to `Always`). In general, when entering
/// an expression or other node in the tree, the initial value
ret_coercion: None,
ret_coercion_span: Cell::new(None),
resume_yield_tys: None,
- ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
diverges: Cell::new(Diverges::Maybe),
enclosing_breakables: RefCell::new(EnclosingBreakables {
stack: Vec::new(),
use rustc_infer::infer;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty};
+use rustc_middle::ty::{
+ self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::symbol::sym;
use rustc_span::Span;
let fn_sig = substs.as_closure().sig();
Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
- && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
// args tuple will always be substs[1]
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
{
ty::Dynamic(data, _, ty::Dyn) => {
data.iter().find_map(|pred| {
if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
- && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
// for existential projection, substs are shifted over by 1
&& let ty::Tuple(args) = proj.substs.type_at(0).kind()
{
let def_id = self.tcx.generics_of(self.body_id.owner).type_param(¶m, self.tcx).def_id;
self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| {
if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
- && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
&& proj.projection_ty.self_ty() == found
// args tuple will always be substs[1]
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
return true
}
}
- &hir::FnRetTy::Return(ref ty) => {
+ hir::FnRetTy::Return(ty) => {
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
// Check that we're in fact trying to clone into the expected type
&& self.can_coerce(*pointee_ty, expected_ty)
+ && let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
// And the expected type doesn't implement `Clone`
- && !self.predicate_must_hold_considering_regions(&traits::Obligation {
- cause: traits::ObligationCause::dummy(),
- param_env: self.param_env,
- recursion_depth: 0,
- predicate: ty::Binder::dummy(ty::TraitRef {
- def_id: clone_trait_did,
- substs: self.tcx.mk_substs([expected_ty.into()].iter()),
- })
- .without_const()
- .to_predicate(self.tcx),
- })
+ && !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
+ self.tcx,
+ traits::ObligationCause::dummy(),
+ self.param_env,
+ trait_ref,
+ ))
{
diag.span_note(
callee_expr.span,
"`{expected_ty}` does not implement `Clone`, so `{found_ty}` was cloned instead"
),
);
+ let owner = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+ if let ty::Param(param) = expected_ty.kind()
+ && let Some(generics) = self.tcx.hir().get_generics(owner)
+ {
+ suggest_constraining_type_params(
+ self.tcx,
+ generics,
+ diag,
+ vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
+ );
+ } else {
+ self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
+ }
}
}
}
ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
// FIXME: support adding the attribute to TAITs
- ty::Opaque(def, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
let mut has_emitted = false;
for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
// We only look at the `DefId`, so it is safe to skip the binder here.
revealed_ty: Ty<'tcx>,
}
-#[derive(Copy, Clone)]
-pub struct UnsafetyState {
- pub def: hir::HirId,
- pub unsafety: hir::Unsafety,
- from_fn: bool,
-}
-
-impl UnsafetyState {
- pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
- UnsafetyState { def, unsafety, from_fn: true }
- }
-
- pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
- use hir::BlockCheckMode;
- match self.unsafety {
- // If this unsafe, then if the outer function was already marked as
- // unsafe we shouldn't attribute the unsafe'ness to the block. This
- // way the block can be warned about instead of ignoring this
- // extraneous block (functions are never warned about).
- hir::Unsafety::Unsafe if self.from_fn => self,
-
- unsafety => {
- let (unsafety, def) = match blk.rules {
- BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
- BlockCheckMode::DefaultBlock => (unsafety, self.def),
- };
- UnsafetyState { def, unsafety, from_fn: false }
- }
- }
- }
-}
-
/// If this `DefId` is a "primary tables entry", returns
/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
///
self_expr: &'tcx hir::Expr<'tcx>,
call_expr: &'tcx hir::Expr<'tcx>,
unadjusted_self_ty: Ty<'tcx>,
- pick: probe::Pick<'tcx>,
+ pick: &probe::Pick<'tcx>,
segment: &hir::PathSegment<'_>,
) -> ConfirmResult<'tcx> {
debug!(
fn confirm(
&mut self,
unadjusted_self_ty: Ty<'tcx>,
- pick: probe::Pick<'tcx>,
+ pick: &probe::Pick<'tcx>,
segment: &hir::PathSegment<'_>,
) -> ConfirmResult<'tcx> {
// Adjust the self expression the user provided and obtain the adjusted type.
self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None);
- let result =
- self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
+ let result = self.confirm_method(span, self_expr, call_expr, self_ty, &pick, segment);
debug!("result = {:?}", result);
if let Some(span) = result.illegal_sized_bound {
ProbeScope::TraitsInScope,
) {
Ok(ref new_pick) if pick.differs_from(new_pick) => {
- needs_mut = true;
+ needs_mut = new_pick.self_ty.ref_mutability() != self_ty.ref_mutability();
}
_ => {}
}
self.var_for_def(span, param)
});
- let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+ let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
// Construct an obligation
let poly_trait_ref = ty::Binder::dummy(trait_ref);
self.var_for_def(span, param)
});
- let trait_ref = ty::TraitRef::new(trait_def_id, substs);
+ let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
// Construct an obligation
let poly_trait_ref = ty::Binder::dummy(trait_ref);
use rustc_trait_selection::traits::query::CanonicalTyGoal;
use rustc_trait_selection::traits::NormalizeExt;
use rustc_trait_selection::traits::{self, ObligationCause};
+use std::cell::RefCell;
use std::cmp::max;
use std::iter;
-use std::mem;
use std::ops::Deref;
use smallvec::{smallvec, SmallVec};
/// This is the OriginalQueryValues for the steps queries
/// that are answered in steps.
- orig_steps_var_values: OriginalQueryValues<'tcx>,
+ orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
steps: &'tcx [CandidateStep<'tcx>],
inherent_candidates: Vec<Candidate<'tcx>>,
extension_candidates: Vec<Candidate<'tcx>>,
impl_dups: FxHashSet<DefId>,
- /// Collects near misses when the candidate functions are missing a `self` keyword and is only
- /// used for error reporting
- static_candidates: Vec<CandidateSource>,
-
/// When probing for names, include names that are close to the
- /// requested name (by Levensthein distance)
+ /// requested name (by Levenshtein distance)
allow_similar_names: bool,
/// Some(candidate) if there is a private candidate
private_candidate: Option<(DefKind, DefId)>,
+ /// Collects near misses when the candidate functions are missing a `self` keyword and is only
+ /// used for error reporting
+ static_candidates: RefCell<Vec<CandidateSource>>,
+
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
/// for error reporting
- unsatisfied_predicates:
+ unsatisfied_predicates: RefCell<
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
+ >,
scope_expr_id: hir::HirId,
}
op: OP,
) -> Result<R, MethodError<'tcx>>
where
- OP: FnOnce(ProbeContext<'a, 'tcx>) -> Result<R, MethodError<'tcx>>,
+ OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
{
let mut orig_values = OriginalQueryValues::default();
let param_env_and_self_ty = self.canonicalize_query(
mode,
method_name,
return_type,
- orig_values,
+ &orig_values,
steps.steps,
scope_expr_id,
);
mode: Mode,
method_name: Option<Ident>,
return_type: Option<Ty<'tcx>>,
- orig_steps_var_values: OriginalQueryValues<'tcx>,
+ orig_steps_var_values: &'a OriginalQueryValues<'tcx>,
steps: &'tcx [CandidateStep<'tcx>],
scope_expr_id: hir::HirId,
) -> ProbeContext<'a, 'tcx> {
impl_dups: FxHashSet::default(),
orig_steps_var_values,
steps,
- static_candidates: Vec::new(),
allow_similar_names: false,
private_candidate: None,
- unsatisfied_predicates: Vec::new(),
+ static_candidates: RefCell::new(Vec::new()),
+ unsatisfied_predicates: RefCell::new(Vec::new()),
scope_expr_id,
}
}
self.inherent_candidates.clear();
self.extension_candidates.clear();
self.impl_dups.clear();
- self.static_candidates.clear();
self.private_candidate = None;
+ self.static_candidates.borrow_mut().clear();
+ self.unsatisfied_predicates.borrow_mut().clear();
}
///////////////////////////////////////////////////////////////////////////
) {
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
let trait_substs = self.fresh_item_substs(trait_def_id);
- let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
+ let trait_ref = self.tcx.mk_trait_ref(trait_def_id, trait_substs);
if self.tcx.is_trait_alias(trait_def_id) {
// For trait aliases, assume all supertraits are relevant.
debug!("pick: actual search failed, assemble diagnostics");
- let static_candidates = mem::take(&mut self.static_candidates);
+ let static_candidates = std::mem::take(self.static_candidates.get_mut());
let private_candidate = self.private_candidate.take();
- let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
+ let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut());
// things failed, so lets look at all traits, for diagnostic purposes now:
self.reset();
}))
}
- fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
+ fn pick_core(&self) -> Option<PickResult<'tcx>> {
let pick = self.pick_all_method(Some(&mut vec![]));
// In this case unstable picking is done by `pick_method`.
}
fn pick_all_method(
- &mut self,
+ &self,
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
) -> Option<PickResult<'tcx>> {
- let steps = self.steps.clone();
- steps
+ self.steps
.iter()
.filter(|step| {
debug!("pick_all_method: step={:?}", step);
/// to transparently pass `&mut` pointers, in particular, without consuming
/// them for their entire lifetime.
fn pick_by_value_method(
- &mut self,
+ &self,
step: &CandidateStep<'tcx>,
self_ty: Ty<'tcx>,
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
}
fn pick_autorefd_method(
- &mut self,
+ &self,
step: &CandidateStep<'tcx>,
self_ty: Ty<'tcx>,
mutbl: hir::Mutability,
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
/// autorefs would require dereferencing the pointer, which is not safe.
fn pick_const_ptr_method(
- &mut self,
+ &self,
step: &CandidateStep<'tcx>,
self_ty: Ty<'tcx>,
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
})
}
- fn pick_method_with_unstable(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
+ fn pick_method_with_unstable(&self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
let mut possibly_unsatisfied_predicates = Vec::new();
debug!("searching {} candidates", kind);
let res = self.consider_candidates(
self_ty,
- candidates.iter(),
+ candidates,
&mut possibly_unsatisfied_predicates,
Some(&mut vec![]),
);
}
}
- debug!("searching unstable candidates");
- let res = self.consider_candidates(
- self_ty,
- self.inherent_candidates.iter().chain(&self.extension_candidates),
- &mut possibly_unsatisfied_predicates,
- None,
- );
- if res.is_none() {
- self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+ for (kind, candidates) in
+ &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
+ {
+ debug!("searching unstable {kind} candidates");
+ let res = self.consider_candidates(
+ self_ty,
+ candidates,
+ &mut possibly_unsatisfied_predicates,
+ None,
+ );
+ if res.is_some() {
+ return res;
+ }
}
- res
+
+ self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
+ None
}
fn pick_method(
- &mut self,
+ &self,
self_ty: Ty<'tcx>,
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
) -> Option<PickResult<'tcx>> {
debug!("searching {} candidates", kind);
let res = self.consider_candidates(
self_ty,
- candidates.iter(),
+ candidates,
&mut possibly_unsatisfied_predicates,
unstable_candidates.as_deref_mut(),
);
// `pick_method` may be called twice for the same self_ty if no stable methods
// match. Only extend once.
if unstable_candidates.is_some() {
- self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
+ self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
}
None
}
- fn consider_candidates<'b, ProbesIter>(
+ fn consider_candidates(
&self,
self_ty: Ty<'tcx>,
- probes: ProbesIter,
+ candidates: &[Candidate<'tcx>],
possibly_unsatisfied_predicates: &mut Vec<(
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)>,
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
- ) -> Option<PickResult<'tcx>>
- where
- ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
- 'tcx: 'b,
- {
- let mut applicable_candidates: Vec<_> = probes
- .clone()
+ ) -> Option<PickResult<'tcx>> {
+ let mut applicable_candidates: Vec<_> = candidates
+ .iter()
.map(|probe| {
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
})
}
if let Some(uc) = &mut unstable_candidates {
- applicable_candidates.retain(|&(p, _)| {
+ applicable_candidates.retain(|&(candidate, _)| {
if let stability::EvalResult::Deny { feature, .. } =
- self.tcx.eval_stability(p.item.def_id, None, self.span, None)
+ self.tcx.eval_stability(candidate.item.def_id, None, self.span, None)
{
- uc.push((p.clone(), feature));
+ uc.push((candidate.clone(), feature));
return false;
}
true
}
if applicable_candidates.len() > 1 {
- let sources = probes.map(|p| self.candidate_source(p, self_ty)).collect();
+ let sources = candidates.iter().map(|p| self.candidate_source(p, self_ty)).collect();
return Some(Err(MethodError::Ambiguity(sources)));
}
self.mode,
self.method_name,
self.return_type,
- self.orig_steps_var_values.clone(),
+ &self.orig_steps_var_values,
steps,
self.scope_expr_id,
);
// -- but this could be overcome.
}
- fn record_static_candidate(&mut self, source: CandidateSource) {
- self.static_candidates.push(source);
+ fn record_static_candidate(&self, source: CandidateSource) {
+ self.static_candidates.borrow_mut().push(source);
}
#[instrument(level = "debug", skip(self))]
use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::with_crate_prefix;
+use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
- let ty_str = self.ty_to_string(rcvr_ty);
+ let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
let is_method = mode == Mode::MethodCall;
let item_kind = if is_method {
"method"
.chain(projection_ty.substs.iter().skip(1)),
);
- let quiet_projection_ty = ty::ProjectionTy {
- substs: substs_with_infer_self,
- item_def_id: projection_ty.item_def_id,
- };
+ let quiet_projection_ty =
+ tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
let term = pred.skip_binder().term;
let obligation = format!("{} = {}", projection_ty, term);
- let quiet = format!("{} = {}", quiet_projection_ty, term);
+ let quiet = with_forced_trimmed_paths!(format!(
+ "{} = {}",
+ quiet_projection_ty, term
+ ));
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
Some((obligation, projection_ty.self_ty()))
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
let obligation = format!("{}: {}", self_ty, path);
- let quiet = format!("_: {}", path);
+ let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
bound_span_label(self_ty, &obligation, &quiet);
Some((obligation, self_ty))
}
let entry = spanned_predicates.entry(spans);
entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p);
}
+ Some(Node::Item(hir::Item {
+ kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..),
+ span: item_span,
+ ..
+ })) => {
+ tcx.sess.delay_span_bug(
+ *item_span,
+ "auto trait is invoked with no method error, but no error reported?",
+ );
+ }
Some(_) => unreachable!(),
None => (),
}
(None, None)
};
let primary_message = primary_message.unwrap_or_else(|| format!(
- "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
+ "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
+ but its trait bounds were not satisfied"
));
err.set_primary_message(&primary_message);
if let Some(label) = label {
}
}
} else {
- err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
+ let ty_str = if ty_str.len() > 50 {
+ String::new()
+ } else {
+ format!("on `{ty_str}` ")
+ };
+ err.span_label(span, format!(
+ "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"
+ ));
}
};
self.suggest_derive(err, &preds);
}
- fn suggest_derive(
+ pub fn suggest_derive(
&self,
err: &mut Diagnostic,
unsatisfied_predicates: &[(
)],
) {
let mut derives = Vec::<(String, Span, Symbol)>::new();
- let mut traits = Vec::<Span>::new();
+ let mut traits = Vec::new();
for (pred, _, _) in unsatisfied_predicates {
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
let adt = match trait_pred.self_ty().ty_adt_def() {
}
derives.push((self_name, self_span, diagnostic_name));
} else {
- traits.push(self.tcx.def_span(trait_pred.def_id()));
+ traits.push(trait_pred.def_id());
}
} else {
- traits.push(self.tcx.def_span(trait_pred.def_id()));
+ traits.push(trait_pred.def_id());
}
}
traits.sort();
let len = traits.len();
if len > 0 {
- let span: MultiSpan = traits.into();
+ let span =
+ MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
+ let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
+ for (i, &did) in traits.iter().enumerate().skip(1) {
+ if len > 2 {
+ names.push_str(", ");
+ }
+ if i == len - 1 {
+ names.push_str(" and ");
+ }
+ names.push('`');
+ names.push_str(&self.tcx.def_path_str(did));
+ names.push('`');
+ }
err.span_note(
span,
- &format!("the following trait{} must be implemented", pluralize!(len),),
+ &format!("the trait{} {} must be implemented", pluralize!(len), names),
);
}
| ty::Float(_)
| ty::Adt(_, _)
| ty::Str
- | ty::Projection(_)
+ | ty::Alias(ty::Projection, _)
| ty::Param(_) => format!("{deref_ty}"),
// we need to test something like <&[_]>::len or <(&[u32])>::len
// and Vec::function();
t.def_id() == info.def_id
}
ty::PredicateKind::Clause(ty::Clause::Projection(p)) => {
- p.projection_ty.item_def_id == info.def_id
+ p.projection_ty.def_id == info.def_id
}
_ => false,
}
// Byte string patterns behave the same way as array patterns
// They can denote both statically and dynamically-sized byte arrays.
let mut pat_ty = ty;
- if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
+ if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
let expected = self.structurally_resolved_type(span, expected);
if let ty::Ref(_, inner_ty, _) = expected.kind()
&& matches!(inner_ty.kind(), ty::Slice(_))
impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if let ty::Opaque(def_id, _) = *t.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
if def_id == self.def_id.to_def_id() {
return ControlFlow::Break(());
}
// dump a .txt file with just the edges:
let txt_path = format!("{}.txt", path);
let mut file = BufWriter::new(File::create(&txt_path).unwrap());
- for &(ref source, ref target) in &edges {
+ for (source, target) in &edges {
write!(file, "{:?} -> {:?}\n", source, target).unwrap();
}
}
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
-use std::iter::FromIterator;
-use std::vec::Vec;
const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
const EXCEPT: Symbol = sym::except;
use rustc_errors::ErrorGuaranteed;
use rustc_fs_util::{link_or_copy, LinkOrCopy};
use rustc_session::{Session, StableCrateId};
+use rustc_span::Symbol;
use std::fs as std_fs;
use std::io::{self, ErrorKind};
-use std::mem;
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
pub fn prepare_session_directory(
sess: &Session,
- crate_name: &str,
+ crate_name: Symbol,
stable_crate_id: StableCrateId,
) -> Result<(), ErrorGuaranteed> {
if sess.opts.incremental.is_none() {
}
delete_session_dir_lock_file(sess, &lock_file_path);
- mem::drop(directory_lock);
+ drop(directory_lock);
}
}
}
Ok(UNIX_EPOCH + duration)
}
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
// Let's make it explicit that the file lock is released at this point,
// or rather, that we held on to it until here
- mem::drop(lock);
+ drop(lock);
}
Err(_) => {
debug!(
// Let's make it explicit that the file lock is released at this point,
// or rather, that we held on to it until here
- mem::drop(lock);
+ drop(lock);
}
Ok(())
self.words[start_word_index] |= !(start_mask - 1);
// And all trailing bits (i.e. from 0..=end) in the end word,
// including the end.
- self.words[end_word_index] |= end_mask | end_mask - 1;
+ self.words[end_word_index] |= end_mask | (end_mask - 1);
} else {
self.words[start_word_index] |= end_mask | (end_mask - start_mask);
}
use std::fmt;
use std::fmt::Debug;
use std::hash::Hash;
-use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut, RangeBounds};
use std::slice;
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
#[subdiagnostic]
pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
- #[subdiagnostic(eager)]
+ #[subdiagnostic]
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
}
}
}
-impl<'tcx> ToTrace<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
fn to_trace(
tcx: TyCtxt<'tcx>,
cause: &ObligationCause<'tcx>,
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
- let a_ty = tcx.mk_projection(a.item_def_id, a.substs);
- let b_ty = tcx.mk_projection(b.item_def_id, b.substs);
+ let a_ty = tcx.mk_projection(a.def_id, a.substs);
+ let b_ty = tcx.mk_projection(b.def_id, b.substs);
TypeTrace {
cause: cause.clone(),
values: Terms(ExpectedFound::new(a_is_expected, a_ty.into(), b_ty.into())),
| ty::Dynamic(..)
| ty::Never
| ty::Tuple(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Foreign(..)
- | ty::Param(..)
- | ty::Opaque(..) => {
+ | ty::Param(..) => {
if t.flags().intersects(self.needs_canonical_flags) {
t.super_fold_with(self)
} else {
// relatable.
Ok(t)
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
let s = self.relate(substs, substs)?;
Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
}
self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
}
- (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+ ) if a_def_id == b_def_id => {
self.fields.infcx.super_combine_tys(self, a, b)?;
}
- (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
- if self.fields.define_opaque_types && did.is_local() =>
+ (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+ | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+ if self.fields.define_opaque_types && def_id.is_local() =>
{
self.fields.obligations.extend(
infcx
where
T: Relate<'tcx>,
{
+ // A binder is equal to itself if it's structually equal to itself
+ if a == b {
+ return Ok(a);
+ }
+
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
use crate::traits::error_reporting::report_object_safety_error;
use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
- StatementAsExpression,
};
-use crate::errors::SuggAddLetForLetChains;
-use hir::intravisit::{walk_expr, walk_stmt};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::ops::{ControlFlow, Deref};
+use std::path::PathBuf;
use std::{cmp, fmt, iter};
mod note;
+mod suggest;
pub(crate) mod need_type_info;
pub use need_type_info::TypeAnnotationNeeded;
impl<'tcx> InferCtxt<'tcx> {
pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
let (def_id, substs) = match *ty.kind() {
- ty::Opaque(def_id, substs) => (def_id, substs),
- ty::Projection(data)
- if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ if matches!(
+ self.tcx.def_kind(def_id),
+ DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
+ ) =>
{
- (data.item_def_id, data.substs)
+ (def_id, substs)
}
_ => return None,
};
.kind()
.map_bound(|kind| match kind {
ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate))
- if projection_predicate.projection_ty.item_def_id == item_def_id =>
+ if projection_predicate.projection_ty.def_id == item_def_id =>
{
projection_predicate.term.ty()
}
}
}
- fn suggest_remove_semi_or_return_binding(
- &self,
- err: &mut Diagnostic,
- first_id: Option<hir::HirId>,
- first_ty: Ty<'tcx>,
- first_span: Span,
- second_id: Option<hir::HirId>,
- second_ty: Ty<'tcx>,
- second_span: Span,
- ) {
- let remove_semicolon = [
- (first_id, self.resolve_vars_if_possible(second_ty)),
- (second_id, self.resolve_vars_if_possible(first_ty)),
- ]
- .into_iter()
- .find_map(|(id, ty)| {
- let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
- self.could_remove_semicolon(blk, ty)
- });
- match remove_semicolon {
- Some((sp, StatementAsExpression::NeedsBoxing)) => {
- err.multipart_suggestion(
- "consider removing this semicolon and boxing the expressions",
- vec![
- (first_span.shrink_to_lo(), "Box::new(".to_string()),
- (first_span.shrink_to_hi(), ")".to_string()),
- (second_span.shrink_to_lo(), "Box::new(".to_string()),
- (second_span.shrink_to_hi(), ")".to_string()),
- (sp, String::new()),
- ],
- Applicability::MachineApplicable,
- );
- }
- Some((sp, StatementAsExpression::CorrectType)) => {
- err.span_suggestion_short(
- sp,
- "consider removing this semicolon",
- "",
- Applicability::MachineApplicable,
- );
- }
- None => {
- for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
- if let Some(id) = id
- && let hir::Node::Block(blk) = self.tcx.hir().get(id)
- && self.consider_returning_binding(blk, ty, err)
- {
- break;
- }
- }
- }
- }
- }
-
- fn suggest_boxing_for_return_impl_trait(
- &self,
- err: &mut Diagnostic,
- return_sp: Span,
- arm_spans: impl Iterator<Item = Span>,
- ) {
- err.multipart_suggestion(
- "you could change the return type to be a boxed trait object",
- vec![
- (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
- (return_sp.shrink_to_hi(), ">".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- let sugg = arm_spans
- .flat_map(|sp| {
- [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
- .into_iter()
- })
- .collect::<Vec<_>>();
- err.multipart_suggestion(
- "if you change the return type to expect trait objects, box the returned expressions",
- sugg,
- Applicability::MaybeIncorrect,
- );
- }
-
/// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
/// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
/// populate `other_value` with `other_ty`.
.map(|(mod_str, _)| mod_str.len() + separator_len)
.sum();
- debug!(
- "cmp: separator_len={}, split_idx={}, min_len={}",
- separator_len, split_idx, min_len
- );
+ debug!(?separator_len, ?split_idx, ?min_len, "cmp");
if split_idx >= min_len {
// paths are identical, highlight everything
} else {
let (common, uniq1) = t1_str.split_at(split_idx);
let (_, uniq2) = t2_str.split_at(split_idx);
- debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
+ debug!(?common, ?uniq1, ?uniq2, "cmp");
values.0.push_normal(common);
values.0.push_highlighted(uniq1);
}
ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
};
- let vals = match self.values_str(values) {
- Some((expected, found)) => Some((expected, found)),
- None => {
- // Derived error. Cancel the emitter.
- // NOTE(eddyb) this was `.cancel()`, but `diag`
- // is borrowed, so we can't fully defuse it.
- diag.downgrade_to_delayed_bug();
- return;
- }
+ let Some(vals) = self.values_str(values) else {
+ // Derived error. Cancel the emitter.
+ // NOTE(eddyb) this was `.cancel()`, but `diag`
+ // is borrowed, so we can't fully defuse it.
+ diag.downgrade_to_delayed_bug();
+ return;
};
- (vals, exp_found, is_simple_error, Some(values))
+ (Some(vals), exp_found, is_simple_error, Some(values))
}
};
label_or_note(span, &terr.to_string());
}
- if let Some((expected, found)) = expected_found {
+ if let Some((expected, found, exp_p, found_p)) = expected_found {
let (expected_label, found_label, exp_found) = match exp_found {
Mismatch::Variable(ef) => (
ef.expected.prefix_string(self.tcx),
}
TypeError::Sorts(values) => {
let extra = expected == found;
- let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
- (true, ty::Opaque(def_id, _)) => {
- let sm = self.tcx.sess.source_map();
- let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
- format!(
- " (opaque type at <{}:{}:{}>)",
- sm.filename_for_diagnostics(&pos.file.name),
- pos.line,
- pos.col.to_usize() + 1,
- )
- }
- (true, ty::Projection(proj))
- if self.tcx.def_kind(proj.item_def_id)
- == DefKind::ImplTraitPlaceholder =>
- {
- let sm = self.tcx.sess.source_map();
- let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
- format!(
- " (trait associated opaque type at <{}:{}:{}>)",
- sm.filename_for_diagnostics(&pos.file.name),
- pos.line,
- pos.col.to_usize() + 1,
- )
+ let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
+ let mut s = match (extra, ty.kind()) {
+ (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
+ let sm = self.tcx.sess.source_map();
+ let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
+ format!(
+ " (opaque type at <{}:{}:{}>)",
+ sm.filename_for_diagnostics(&pos.file.name),
+ pos.line,
+ pos.col.to_usize() + 1,
+ )
+ }
+ (true, ty::Alias(ty::Projection, proj))
+ if self.tcx.def_kind(proj.def_id)
+ == DefKind::ImplTraitPlaceholder =>
+ {
+ let sm = self.tcx.sess.source_map();
+ let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
+ format!(
+ " (trait associated opaque type at <{}:{}:{}>)",
+ sm.filename_for_diagnostics(&pos.file.name),
+ pos.line,
+ pos.col.to_usize() + 1,
+ )
+ }
+ (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
+ (false, _) => "".to_string(),
+ };
+ if let Some(path) = path {
+ s.push_str(&format!(
+ "\nthe full type name has been written to '{}'",
+ path.display(),
+ ));
}
- (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
- (false, _) => "".to_string(),
+ s
};
if !(values.expected.is_simple_text() && values.found.is_simple_text())
|| (exp_found.map_or(false, |ef| {
expected,
&found_label,
found,
- &sort_string(values.expected),
- &sort_string(values.found),
+ &sort_string(values.expected, exp_p),
+ &sort_string(values.found, found_p),
);
}
}
debug!(?diag);
}
- fn suggest_tuple_pattern(
- &self,
- cause: &ObligationCause<'tcx>,
- exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
- diag: &mut Diagnostic,
- ) {
- // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
- // some modifications due to that being in typeck and this being in infer.
- if let ObligationCauseCode::Pattern { .. } = cause.code() {
- if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
- let compatible_variants: Vec<_> = expected_adt
- .variants()
- .iter()
- .filter(|variant| {
- variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
- })
- .filter_map(|variant| {
- let sole_field = &variant.fields[0];
- let sole_field_ty = sole_field.ty(self.tcx, substs);
- if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
- let variant_path =
- with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
- // FIXME #56861: DRYer prelude filtering
- if let Some(path) = variant_path.strip_prefix("std::prelude::") {
- if let Some((_, path)) = path.split_once("::") {
- return Some(path.to_string());
- }
- }
- Some(variant_path)
- } else {
- None
- }
- })
- .collect();
- match &compatible_variants[..] {
- [] => {}
- [variant] => {
- diag.multipart_suggestion_verbose(
- &format!("try wrapping the pattern in `{}`", variant),
- vec![
- (cause.span.shrink_to_lo(), format!("{}(", variant)),
- (cause.span.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- }
- _ => {
- // More than one matching variant.
- diag.multipart_suggestions(
- &format!(
- "try wrapping the pattern in a variant of `{}`",
- self.tcx.def_path_str(expected_adt.did())
- ),
- compatible_variants.into_iter().map(|variant| {
- vec![
- (cause.span.shrink_to_lo(), format!("{}(", variant)),
- (cause.span.shrink_to_hi(), ")".to_string()),
- ]
- }),
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
- }
- }
-
- /// A possible error is to forget to add `.await` when using futures:
- ///
- /// ```compile_fail,E0308
- /// async fn make_u32() -> u32 {
- /// 22
- /// }
- ///
- /// fn take_u32(x: u32) {}
- ///
- /// async fn foo() {
- /// let x = make_u32();
- /// take_u32(x);
- /// }
- /// ```
- ///
- /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
- /// expected type. If this is the case, and we are inside of an async body, it suggests adding
- /// `.await` to the tail of the expression.
- fn suggest_await_on_expect_found(
- &self,
- cause: &ObligationCause<'tcx>,
- exp_span: Span,
- exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
- diag: &mut Diagnostic,
- ) {
- debug!(
- "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
- exp_span, exp_found.expected, exp_found.found,
- );
-
- if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
- return;
- }
-
- match (
- self.get_impl_future_output_ty(exp_found.expected),
- self.get_impl_future_output_ty(exp_found.found),
- ) {
- (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
- .code()
- {
- ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
- let then_span = self.find_block_span_from_hir_id(*then_id);
- diag.multipart_suggestion(
- "consider `await`ing on both `Future`s",
- vec![
- (then_span.shrink_to_hi(), ".await".to_string()),
- (exp_span.shrink_to_hi(), ".await".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- }
- ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
- prior_arms,
- ..
- }) => {
- if let [.., arm_span] = &prior_arms[..] {
- diag.multipart_suggestion(
- "consider `await`ing on both `Future`s",
- vec![
- (arm_span.shrink_to_hi(), ".await".to_string()),
- (exp_span.shrink_to_hi(), ".await".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- } else {
- diag.help("consider `await`ing on both `Future`s");
- }
- }
- _ => {
- diag.help("consider `await`ing on both `Future`s");
- }
- },
- (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
- diag.span_suggestion_verbose(
- exp_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
- }
- (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
- {
- ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
- diag.span_suggestion_verbose(
- then_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
- }
- ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
- let then_span = self.find_block_span_from_hir_id(*then_id);
- diag.span_suggestion_verbose(
- then_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
- }
- ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
- ref prior_arms,
- ..
- }) => {
- diag.multipart_suggestion_verbose(
- "consider `await`ing on the `Future`",
- prior_arms
- .iter()
- .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
- .collect(),
- Applicability::MaybeIncorrect,
- );
- }
- _ => {}
- },
- _ => {}
- }
- }
-
- fn suggest_accessing_field_where_appropriate(
- &self,
- cause: &ObligationCause<'tcx>,
- exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
- diag: &mut Diagnostic,
- ) {
- debug!(
- "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
- cause, exp_found
- );
- if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
- if expected_def.is_enum() {
- return;
- }
-
- if let Some((name, ty)) = expected_def
- .non_enum_variant()
- .fields
- .iter()
- .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
- .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
- .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
- {
- if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
- if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
- let suggestion = if expected_def.is_struct() {
- format!("{}.{}", snippet, name)
- } else if expected_def.is_union() {
- format!("unsafe {{ {}.{} }}", snippet, name)
- } else {
- return;
- };
- diag.span_suggestion(
- span,
- &format!(
- "you might have meant to use field `{}` whose type is `{}`",
- name, ty
- ),
- suggestion,
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
- }
- }
-
- /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
- /// suggests it.
- fn suggest_as_ref_where_appropriate(
- &self,
- span: Span,
- exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
- diag: &mut Diagnostic,
- ) {
- if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
- && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
- {
- diag.span_suggestion(
- span,
- msg,
- // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
- format!("{}.as_ref()", snippet.trim_start_matches('&')),
- Applicability::MachineApplicable,
- );
- }
- }
-
- pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
- if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
- (expected.kind(), found.kind())
- {
- if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
- if exp_def == &found_def {
- let have_as_ref = &[
- (
- sym::Option,
- "you can convert from `&Option<T>` to `Option<&T>` using \
- `.as_ref()`",
- ),
- (
- sym::Result,
- "you can convert from `&Result<T, E>` to \
- `Result<&T, &E>` using `.as_ref()`",
- ),
- ];
- if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
- self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
- }) {
- let mut show_suggestion = true;
- for (exp_ty, found_ty) in
- iter::zip(exp_substs.types(), found_substs.types())
- {
- match *exp_ty.kind() {
- ty::Ref(_, exp_ty, _) => {
- match (exp_ty.kind(), found_ty.kind()) {
- (_, ty::Param(_))
- | (_, ty::Infer(_))
- | (ty::Param(_), _)
- | (ty::Infer(_), _) => {}
- _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
- _ => show_suggestion = false,
- };
- }
- ty::Param(_) | ty::Infer(_) => {}
- _ => show_suggestion = false,
- }
- }
- if show_suggestion {
- return Some(*msg);
- }
- }
- }
- }
- }
- None
- }
-
pub fn report_and_explain_type_error(
&self,
trace: TypeTrace<'tcx>,
let code = trace.cause.code();
if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
&& let hir::MatchSource::TryDesugar = source
- && let Some((expected_ty, found_ty)) = self.values_str(trace.values)
+ && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
{
err.note(&format!(
"`?` operator cannot convert from `{}` to `{}`",
diag
}
- /// Try to find code with pattern `if Some(..) = expr`
- /// use a `visitor` to mark the `if` which its span contains given error span,
- /// and then try to find a assignment in the `cond` part, which span is equal with error span
- fn suggest_let_for_letchains(
- &self,
- err: &mut Diagnostic,
- cause: &ObligationCause<'_>,
- span: Span,
- ) {
- let hir = self.tcx.hir();
- let fn_hir_id = hir.get_parent_node(cause.body_id);
- if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
- let hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Fn(_sig, _, body_id), ..
- }) = node {
- let body = hir.body(*body_id);
-
- /// Find the if expression with given span
- struct IfVisitor {
- pub result: bool,
- pub found_if: bool,
- pub err_span: Span,
- }
-
- impl<'v> Visitor<'v> for IfVisitor {
- fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
- if self.result { return; }
- match ex.kind {
- hir::ExprKind::If(cond, _, _) => {
- self.found_if = true;
- walk_expr(self, cond);
- self.found_if = false;
- }
- _ => walk_expr(self, ex),
- }
- }
-
- fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
- if let hir::StmtKind::Local(hir::Local {
- span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
- }) = &ex.kind
- && self.found_if
- && span.eq(&self.err_span) {
- self.result = true;
- }
- walk_stmt(self, ex);
- }
-
- fn visit_body(&mut self, body: &'v hir::Body<'v>) {
- hir::intravisit::walk_body(self, body);
- }
- }
-
- let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
- visitor.visit_body(&body);
- if visitor.result {
- err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
- }
- }
- }
-
fn emit_tuple_wrap_err(
&self,
err: &mut Diagnostic,
fn values_str(
&self,
values: ValuePairs<'tcx>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+ {
match values {
infer::Regions(exp_found) => self.expected_found_str(exp_found),
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
found: exp_found.found.print_only_trait_path(),
};
match self.expected_found_str(pretty_exp_found) {
- Some((expected, found)) if expected == found => {
+ Some((expected, found, _, _)) if expected == found => {
self.expected_found_str(exp_found)
}
ret => ret,
found: exp_found.found.print_only_trait_path(),
};
match self.expected_found_str(pretty_exp_found) {
- Some((expected, found)) if expected == found => {
+ Some((expected, found, _, _)) if expected == found => {
self.expected_found_str(exp_found)
}
ret => ret,
fn expected_found_str_term(
&self,
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+ {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
- (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
+ (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
+ let (mut exp, mut fnd) = self.cmp(expected, found);
+ // Use the terminal width as the basis to determine when to compress the printed
+ // out type, but give ourselves some leeway to avoid ending up creating a file for
+ // a type that is somewhat shorter than the path we'd write to.
+ let len = self.tcx.sess().diagnostic_width() + 40;
+ let exp_s = exp.content();
+ let fnd_s = fnd.content();
+ let mut exp_p = None;
+ let mut fnd_p = None;
+ if exp_s.len() > len {
+ let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
+ exp = DiagnosticStyledString::highlighted(exp_s);
+ exp_p = exp_path;
+ }
+ if fnd_s.len() > len {
+ let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
+ fnd = DiagnosticStyledString::highlighted(fnd_s);
+ fnd_p = fnd_path;
+ }
+ (exp, fnd, exp_p, fnd_p)
+ }
_ => (
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+ None,
+ None,
),
})
}
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
&self,
exp_found: ty::error::ExpectedFound<T>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+ {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
Some((
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+ None,
+ None,
))
}
// fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
// suggest:
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
- ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
+ ty::Closure(..) | ty::Alias(ty::Opaque, ..) if return_impl_trait => {
new_binding_suggestion(&mut err, type_param_span);
}
_ => {
debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
- if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
- (&sup_origin, &sub_origin)
+ if let infer::Subtype(ref sup_trace) = sup_origin
+ && let infer::Subtype(ref sub_trace) = sub_origin
+ && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
+ && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
+ && sub_expected == sup_expected
+ && sub_found == sup_found
{
- debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
- debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
- debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
- debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
-
- if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
- (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
- {
- if sub_expected == sup_expected && sub_found == sup_found {
- note_and_explain_region(
- self.tcx,
- &mut err,
- "...but the lifetime must also be valid for ",
- sub_region,
- "...",
- None,
- );
- err.span_note(
- sup_trace.cause.span,
- &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
- );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "...but the lifetime must also be valid for ",
+ sub_region,
+ "...",
+ None,
+ );
+ err.span_note(
+ sup_trace.cause.span,
+ &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
+ );
- err.note_expected_found(&"", sup_expected, &"", sup_found);
- err.emit();
- return;
- }
- }
+ err.note_expected_found(&"", sup_expected, &"", sup_found);
+ err.emit();
+ return;
}
self.note_region_origin(&mut err, &sup_origin);
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
match *ty.kind() {
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
- ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
ty::Generator(def_id, ..) => {
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
}
}
}
}
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
- /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
- /// is enough to fix the error.
- pub fn could_remove_semicolon(
- &self,
- blk: &'tcx hir::Block<'tcx>,
- expected_ty: Ty<'tcx>,
- ) -> Option<(Span, StatementAsExpression)> {
- let blk = blk.innermost_block();
- // Do not suggest if we have a tail expr.
- if blk.expr.is_some() {
- return None;
- }
- let last_stmt = blk.stmts.last()?;
- let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
- return None;
- };
- let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
- let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
- _ if last_expr_ty.references_error() => return None,
- _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
- StatementAsExpression::CorrectType
- }
- (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
- if last_def_id == exp_def_id =>
- {
- StatementAsExpression::CorrectType
- }
- (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
- debug!(
- "both opaque, likely future {:?} {:?} {:?} {:?}",
- last_def_id, last_bounds, exp_def_id, exp_bounds
- );
-
- let last_local_id = last_def_id.as_local()?;
- let exp_local_id = exp_def_id.as_local()?;
-
- match (
- &self.tcx.hir().expect_item(last_local_id).kind,
- &self.tcx.hir().expect_item(exp_local_id).kind,
- ) {
- (
- hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
- hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
- ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
- match (left, right) {
- (
- hir::GenericBound::Trait(tl, ml),
- hir::GenericBound::Trait(tr, mr),
- ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
- && ml == mr =>
- {
- true
- }
- (
- hir::GenericBound::LangItemTrait(langl, _, _, argsl),
- hir::GenericBound::LangItemTrait(langr, _, _, argsr),
- ) if langl == langr => {
- // FIXME: consider the bounds!
- debug!("{:?} {:?}", argsl, argsr);
- true
- }
- _ => false,
- }
- }) =>
- {
- StatementAsExpression::NeedsBoxing
- }
- _ => StatementAsExpression::CorrectType,
- }
- }
- _ => return None,
- };
- let span = if last_stmt.span.from_expansion() {
- let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
- self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
- } else {
- last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
- };
- Some((span, needs_box))
- }
-
- /// Suggest returning a local binding with a compatible type if the block
- /// has no return expression.
- pub fn consider_returning_binding(
- &self,
- blk: &'tcx hir::Block<'tcx>,
- expected_ty: Ty<'tcx>,
- err: &mut Diagnostic,
- ) -> bool {
- let blk = blk.innermost_block();
- // Do not suggest if we have a tail expr.
- if blk.expr.is_some() {
- return false;
- }
- let mut shadowed = FxIndexSet::default();
- let mut candidate_idents = vec![];
- let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
- if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
- && let Some(pat_ty) = self
- .typeck_results
- .as_ref()
- .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
- {
- let pat_ty = self.resolve_vars_if_possible(pat_ty);
- if self.same_type_modulo_infer(pat_ty, expected_ty)
- && !(pat_ty, expected_ty).references_error()
- && shadowed.insert(ident.name)
- {
- candidate_idents.push((*ident, pat_ty));
- }
- }
- true
- };
-
- let hir = self.tcx.hir();
- for stmt in blk.stmts.iter().rev() {
- let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
- local.pat.walk(&mut find_compatible_candidates);
- }
- match hir.find(hir.get_parent_node(blk.hir_id)) {
- Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
- match hir.find(hir.get_parent_node(*hir_id)) {
- Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
- pat.walk(&mut find_compatible_candidates);
- }
- Some(
- hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
- | hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::Fn(_, body),
- ..
- })
- | hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
- ..
- })
- | hir::Node::Expr(hir::Expr {
- kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
- ..
- }),
- ) => {
- for param in hir.body(*body).params {
- param.pat.walk(&mut find_compatible_candidates);
- }
- }
- Some(hir::Node::Expr(hir::Expr {
- kind:
- hir::ExprKind::If(
- hir::Expr { kind: hir::ExprKind::Let(let_), .. },
- then_block,
- _,
- ),
- ..
- })) if then_block.hir_id == *hir_id => {
- let_.pat.walk(&mut find_compatible_candidates);
- }
- _ => {}
- }
- }
- _ => {}
- }
-
- match &candidate_idents[..] {
- [(ident, _ty)] => {
- let sm = self.tcx.sess.source_map();
- if let Some(stmt) = blk.stmts.last() {
- let stmt_span = sm.stmt_span(stmt.span, blk.span);
- let sugg = if sm.is_multiline(blk.span)
- && let Some(spacing) = sm.indentation_before(stmt_span)
- {
- format!("\n{spacing}{ident}")
- } else {
- format!(" {ident}")
- };
- err.span_suggestion_verbose(
- stmt_span.shrink_to_hi(),
- format!("consider returning the local binding `{ident}`"),
- sugg,
- Applicability::MaybeIncorrect,
- );
- } else {
- let sugg = if sm.is_multiline(blk.span)
- && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
- {
- format!("\n{spacing} {ident}\n{spacing}")
- } else {
- format!(" {ident} ")
- };
- let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
- err.span_suggestion_verbose(
- sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
- format!("consider returning the local binding `{ident}`"),
- sugg,
- Applicability::MaybeIncorrect,
- );
- }
- true
- }
- values if (1..3).contains(&values.len()) => {
- let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
- err.span_note(spans, "consider returning one of these bindings");
- true
- }
- _ => false,
- }
- }
-}
use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span};
use std::borrow::Cow;
use std::iter;
fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
if in_type.is_ty_infer() {
- "empty"
+ ""
} else if self.name == "_" {
// FIXME: Consider specializing this message if there is a single `_`
// in the type.
printer
}
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ called_method_def_id: Option<DefId>,
+) -> String {
let printer = fmt_printer(infcx, Namespace::TypeNS);
let ty = infcx.resolve_vars_if_possible(ty);
- match ty.kind() {
+ match (ty.kind(), called_method_def_id) {
// We don't want the regular output for `fn`s because it includes its path in
// invalid pseudo-syntax, we want the `fn`-pointer output instead.
- ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+ (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+ (_, Some(def_id))
+ if ty.is_ty_infer()
+ && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
+ {
+ "Vec<_>".to_string()
+ }
+ _ if ty.is_ty_infer() => "/* Type */".to_string(),
// FIXME: The same thing for closures, but this only works when the closure
// does not capture anything.
//
.map(|args| {
args.tuple_fields()
.iter()
- .map(|arg| ty_to_string(infcx, arg))
+ .map(|arg| ty_to_string(infcx, arg, None))
.collect::<Vec<_>>()
.join(", ")
})
let ret = if fn_sig.output().skip_binder().is_unit() {
String::new()
} else {
- format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
+ format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
};
format!("fn({}){}", args, ret)
}
}
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ #[instrument(level = "debug", skip(self, error_code))]
pub fn emit_inference_failure_err(
&self,
body_id: Option<hir::BodyId>,
let mut infer_subdiags = Vec::new();
let mut multi_suggestions = Vec::new();
match kind {
- InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+ InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
infer_subdiags.push(SourceKindSubdiag::LetLike {
span: insert_span,
name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
arg_name: arg_data.name,
kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
- type_name: ty_to_string(self, ty),
+ type_name: ty_to_string(self, ty, def_id),
});
}
InferSourceKind::ClosureArg { insert_span, ty } => {
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
arg_name: arg_data.name,
kind: "closure",
- type_name: ty_to_string(self, ty),
+ type_name: ty_to_string(self, ty, None),
});
}
InferSourceKind::GenericArg {
parent_name,
});
- let args = fmt_printer(self, Namespace::TypeNS)
- .comma_sep(generic_args.iter().copied().map(|arg| {
- if arg.is_suggestable(self.tcx, true) {
- return arg;
- }
+ let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
+ == Some(generics_def_id)
+ {
+ "Vec<_>".to_string()
+ } else {
+ fmt_printer(self, Namespace::TypeNS)
+ .comma_sep(generic_args.iter().copied().map(|arg| {
+ if arg.is_suggestable(self.tcx, true) {
+ return arg;
+ }
- match arg.unpack() {
- GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
- GenericArgKind::Type(_) => self
- .next_ty_var(TypeVariableOrigin {
- span: rustc_span::DUMMY_SP,
- kind: TypeVariableOriginKind::MiscVariable,
- })
- .into(),
- GenericArgKind::Const(arg) => self
- .next_const_var(
- arg.ty(),
- ConstVariableOrigin {
+ match arg.unpack() {
+ GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
+ GenericArgKind::Type(_) => self
+ .next_ty_var(TypeVariableOrigin {
span: rustc_span::DUMMY_SP,
- kind: ConstVariableOriginKind::MiscVariable,
- },
- )
- .into(),
- }
- }))
- .unwrap()
- .into_buffer();
+ kind: TypeVariableOriginKind::MiscVariable,
+ })
+ .into(),
+ GenericArgKind::Const(arg) => self
+ .next_const_var(
+ arg.ty(),
+ ConstVariableOrigin {
+ span: rustc_span::DUMMY_SP,
+ kind: ConstVariableOriginKind::MiscVariable,
+ },
+ )
+ .into(),
+ }
+ }))
+ .unwrap()
+ .into_buffer()
+ };
if !have_turbofish {
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
));
}
InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
- let ty_info = ty_to_string(self, ty);
+ let ty_info = ty_to_string(self, ty, None);
multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
ty_info,
data,
insert_span: Span,
pattern_name: Option<Ident>,
ty: Ty<'tcx>,
+ def_id: Option<DefId>,
},
ClosureArg {
insert_span: Span,
if ty.is_closure() {
("closure", closure_as_fn_str(infcx, ty))
} else if !ty.is_ty_infer() {
- ("normal", ty_to_string(infcx, ty))
+ ("normal", ty_to_string(infcx, ty, None))
} else {
("other", String::new())
}
/// Uses `fn source_cost` to determine whether this inference source is preferable to
/// previous sources. We generally prefer earlier sources.
#[instrument(level = "debug", skip(self))]
- fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+ fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
let cost = self.source_cost(&new_source) + self.attempt;
debug!(?cost);
self.attempt += 1;
+ if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
+ && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
+ && ty.is_ty_infer()
+ {
+ // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+ // `let x: _ = iter.collect();`, as this is a very common case.
+ *def_id = Some(did);
+ }
if cost < self.infer_source_cost {
self.infer_source_cost = cost;
self.infer_source = Some(new_source);
match inner.unpack() {
GenericArgKind::Lifetime(_) => {}
GenericArgKind::Type(ty) => {
- if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) {
+ if matches!(
+ ty.kind(),
+ ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Generator(..)
+ ) {
// Opaque types can't be named by the user right now.
//
// Both the generic arguments of closures and generators can
insert_span: local.pat.span.shrink_to_hi(),
pattern_name: local.pat.simple_ident(),
ty,
+ def_id: None,
},
})
}
false
};
- let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
- def_id: trait_def_id,
- substs: expected_substs,
- });
- let actual_trait_ref = self
+ let expected_trait_ref = self
.cx
- .resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
+ .resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
+ let actual_trait_ref =
+ self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
// Search the expected and actual trait references to see (a)
// whether the sub/sup placeholders appear in them (sometimes
Applicability::MaybeIncorrect,
);
}
- if let Some((param_span, param_ty)) = param.clone() {
+ if let Some((param_span, ref param_ty)) = param {
err.span_suggestion_verbose(
param_span,
add_static_bound,
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
span: trace.cause.span,
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
- expected_found: self.values_str(trace.values),
+ expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
}
.add_to_diagnostic(err),
infer::Reborrow(span) => {
--- /dev/null
+use crate::errors::RegionOriginNote;
+use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
+use crate::infer::{self, SubregionOrigin};
+use rustc_errors::{
+ fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+};
+use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::{self, Region};
+
+use super::ObligationCauseAsDiagArg;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
+ match *origin {
+ infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
+ span: trace.cause.span,
+ requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
+ expected_found: self.values_str(trace.values),
+ }
+ .add_to_diagnostic(err),
+ infer::Reborrow(span) => {
+ RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+ }
+ infer::ReborrowUpvar(span, ref upvar_id) => {
+ let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+ RegionOriginNote::WithName {
+ span,
+ msg: fluent::infer_reborrow,
+ name: &var_name.to_string(),
+ continues: false,
+ }
+ .add_to_diagnostic(err);
+ }
+ infer::RelateObjectBound(span) => {
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
+ .add_to_diagnostic(err);
+ }
+ infer::DataBorrowed(ty, span) => {
+ RegionOriginNote::WithName {
+ span,
+ msg: fluent::infer_data_borrowed,
+ name: &self.ty_to_string(ty),
+ continues: false,
+ }
+ .add_to_diagnostic(err);
+ }
+ infer::ReferenceOutlivesReferent(ty, span) => {
+ RegionOriginNote::WithName {
+ span,
+ msg: fluent::infer_reference_outlives_referent,
+ name: &self.ty_to_string(ty),
+ continues: false,
+ }
+ .add_to_diagnostic(err);
+ }
+ infer::RelateParamBound(span, ty, opt_span) => {
+ RegionOriginNote::WithName {
+ span,
+ msg: fluent::infer_relate_param_bound,
+ name: &self.ty_to_string(ty),
+ continues: opt_span.is_some(),
+ }
+ .add_to_diagnostic(err);
+ if let Some(span) = opt_span {
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
+ .add_to_diagnostic(err);
+ }
+ }
+ infer::RelateRegionParamBound(span) => {
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
+ .add_to_diagnostic(err);
+ }
+ infer::CompareImplItemObligation { span, .. } => {
+ RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
+ .add_to_diagnostic(err);
+ }
+ infer::CheckAssociatedTypeBounds { ref parent, .. } => {
+ self.note_region_origin(err, &parent);
+ }
+ infer::AscribeUserTypeProvePredicate(span) => {
+ RegionOriginNote::Plain {
+ span,
+ msg: fluent::infer_ascribe_user_type_prove_predicate,
+ }
+ .add_to_diagnostic(err);
+ }
+ }
+ }
+
+ pub(super) fn report_concrete_failure(
+ &self,
+ origin: SubregionOrigin<'tcx>,
+ sub: Region<'tcx>,
+ sup: Region<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ match origin {
+ infer::Subtype(box trace) => {
+ let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
+ let mut err = self.report_and_explain_type_error(trace, terr);
+ match (*sub, *sup) {
+ (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+ (ty::RePlaceholder(_), _) => {
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "",
+ sup,
+ " doesn't meet the lifetime requirements",
+ None,
+ );
+ }
+ (_, ty::RePlaceholder(_)) => {
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "the required lifetime does not necessarily outlive ",
+ sub,
+ "",
+ None,
+ );
+ }
+ _ => {
+ note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "...does not necessarily outlive ",
+ sub,
+ "",
+ None,
+ );
+ }
+ }
+ err
+ }
+ infer::Reborrow(span) => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0312,
+ "lifetime of reference outlives lifetime of borrowed content..."
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "...the reference is valid for ",
+ sub,
+ "...",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "...but the borrowed content is only valid for ",
+ sup,
+ "",
+ None,
+ );
+ err
+ }
+ infer::ReborrowUpvar(span, ref upvar_id) => {
+ let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0313,
+ "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
+ var_name
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "...the borrowed pointer is valid for ",
+ sub,
+ "...",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ &format!("...but `{}` is only valid for ", var_name),
+ sup,
+ "",
+ None,
+ );
+ err
+ }
+ infer::RelateObjectBound(span) => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0476,
+ "lifetime of the source pointer does not outlive lifetime bound of the \
+ object type"
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "object type is valid for ",
+ sub,
+ "",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "source pointer is only valid for ",
+ sup,
+ "",
+ None,
+ );
+ err
+ }
+ infer::RelateParamBound(span, ty, opt_span) => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0477,
+ "the type `{}` does not fulfill the required lifetime",
+ self.ty_to_string(ty)
+ );
+ match *sub {
+ ty::ReStatic => note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "type must satisfy ",
+ sub,
+ if opt_span.is_some() { " as required by this binding" } else { "" },
+ opt_span,
+ ),
+ _ => note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "type must outlive ",
+ sub,
+ if opt_span.is_some() { " as required by this binding" } else { "" },
+ opt_span,
+ ),
+ }
+ err
+ }
+ infer::RelateRegionParamBound(span) => {
+ let mut err =
+ struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "lifetime parameter instantiated with ",
+ sup,
+ "",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "but lifetime parameter must outlive ",
+ sub,
+ "",
+ None,
+ );
+ err
+ }
+ infer::DataBorrowed(ty, span) => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0490,
+ "a value of type `{}` is borrowed for too long",
+ self.ty_to_string(ty)
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "the type is valid for ",
+ sub,
+ "",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "but the borrow lasts for ",
+ sup,
+ "",
+ None,
+ );
+ err
+ }
+ infer::ReferenceOutlivesReferent(ty, span) => {
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0491,
+ "in type `{}`, reference has a longer lifetime than the data it references",
+ self.ty_to_string(ty)
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "the pointer is valid for ",
+ sub,
+ "",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "but the referenced data is only valid for ",
+ sup,
+ "",
+ None,
+ );
+ err
+ }
+ infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
+ .report_extra_impl_obligation(
+ span,
+ impl_item_def_id,
+ trait_item_def_id,
+ &format!("`{}: {}`", sup, sub),
+ ),
+ infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
+ let mut err = self.report_concrete_failure(*parent, sub, sup);
+
+ let trait_item_span = self.tcx.def_span(trait_item_def_id);
+ let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
+ err.span_label(
+ trait_item_span,
+ format!("definition of `{}` from trait", item_name),
+ );
+
+ let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
+ let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
+
+ let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
+ impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
+ let clauses: Vec<_> = trait_predicates
+ .predicates
+ .into_iter()
+ .filter(|&(pred, _)| !impl_predicates.contains(pred))
+ .map(|(pred, _)| format!("{}", pred))
+ .collect();
+
+ if !clauses.is_empty() {
+ let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
+ let where_clause_span = generics.tail_span_for_predicate_suggestion();
+
+ let suggestion = format!(
+ "{} {}",
+ generics.add_where_or_trailing_comma(),
+ clauses.join(", "),
+ );
+ err.span_suggestion(
+ where_clause_span,
+ &format!(
+ "try copying {} from the trait",
+ if clauses.len() > 1 { "these clauses" } else { "this clause" }
+ ),
+ suggestion,
+ rustc_errors::Applicability::MaybeIncorrect,
+ );
+ }
+
+ err
+ }
+ infer::AscribeUserTypeProvePredicate(span) => {
+ let mut err =
+ struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "lifetime instantiated with ",
+ sup,
+ "",
+ None,
+ );
+ note_and_explain_region(
+ self.tcx,
+ &mut err,
+ "but lifetime must outlive ",
+ sub,
+ "",
+ None,
+ );
+ err
+ }
+ }
+ }
+
+ pub(super) fn report_placeholder_failure(
+ &self,
+ placeholder_origin: SubregionOrigin<'tcx>,
+ sub: Region<'tcx>,
+ sup: Region<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ // I can't think how to do better than this right now. -nikomatsakis
+ debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
+ match placeholder_origin {
+ infer::Subtype(box ref trace)
+ if matches!(
+ &trace.cause.code().peel_derives(),
+ ObligationCauseCode::BindingObligation(..)
+ | ObligationCauseCode::ExprBindingObligation(..)
+ ) =>
+ {
+ // Hack to get around the borrow checker because trace.cause has an `Rc`.
+ if let ObligationCauseCode::BindingObligation(_, span)
+ | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
+ &trace.cause.code().peel_derives()
+ {
+ let span = *span;
+ let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+ err.span_note(span, "the lifetime requirement is introduced here");
+ err
+ } else {
+ unreachable!()
+ }
+ }
+ infer::Subtype(box trace) => {
+ let terr = TypeError::RegionsPlaceholderMismatch;
+ return self.report_and_explain_type_error(trace, terr);
+ }
+ _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
+ }
+ }
+}
--- /dev/null
+use hir::def::CtorKind;
+use hir::intravisit::{walk_expr, walk_stmt, Visitor};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_middle::traits::{
+ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
+ StatementAsExpression,
+};
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
+use rustc_span::{sym, BytePos, Span};
+
+use crate::errors::SuggAddLetForLetChains;
+
+use super::TypeErrCtxt;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ pub(super) fn suggest_remove_semi_or_return_binding(
+ &self,
+ err: &mut Diagnostic,
+ first_id: Option<hir::HirId>,
+ first_ty: Ty<'tcx>,
+ first_span: Span,
+ second_id: Option<hir::HirId>,
+ second_ty: Ty<'tcx>,
+ second_span: Span,
+ ) {
+ let remove_semicolon = [
+ (first_id, self.resolve_vars_if_possible(second_ty)),
+ (second_id, self.resolve_vars_if_possible(first_ty)),
+ ]
+ .into_iter()
+ .find_map(|(id, ty)| {
+ let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
+ self.could_remove_semicolon(blk, ty)
+ });
+ match remove_semicolon {
+ Some((sp, StatementAsExpression::NeedsBoxing)) => {
+ err.multipart_suggestion(
+ "consider removing this semicolon and boxing the expressions",
+ vec![
+ (first_span.shrink_to_lo(), "Box::new(".to_string()),
+ (first_span.shrink_to_hi(), ")".to_string()),
+ (second_span.shrink_to_lo(), "Box::new(".to_string()),
+ (second_span.shrink_to_hi(), ")".to_string()),
+ (sp, String::new()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ }
+ Some((sp, StatementAsExpression::CorrectType)) => {
+ err.span_suggestion_short(
+ sp,
+ "consider removing this semicolon",
+ "",
+ Applicability::MachineApplicable,
+ );
+ }
+ None => {
+ for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
+ if let Some(id) = id
+ && let hir::Node::Block(blk) = self.tcx.hir().get(id)
+ && self.consider_returning_binding(blk, ty, err)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ pub(super) fn suggest_boxing_for_return_impl_trait(
+ &self,
+ err: &mut Diagnostic,
+ return_sp: Span,
+ arm_spans: impl Iterator<Item = Span>,
+ ) {
+ err.multipart_suggestion(
+ "you could change the return type to be a boxed trait object",
+ vec![
+ (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
+ (return_sp.shrink_to_hi(), ">".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ let sugg = arm_spans
+ .flat_map(|sp| {
+ [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
+ .into_iter()
+ })
+ .collect::<Vec<_>>();
+ err.multipart_suggestion(
+ "if you change the return type to expect trait objects, box the returned expressions",
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ }
+
+ pub(super) fn suggest_tuple_pattern(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
+ // some modifications due to that being in typeck and this being in infer.
+ if let ObligationCauseCode::Pattern { .. } = cause.code() {
+ if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
+ let compatible_variants: Vec<_> = expected_adt
+ .variants()
+ .iter()
+ .filter(|variant| {
+ variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
+ })
+ .filter_map(|variant| {
+ let sole_field = &variant.fields[0];
+ let sole_field_ty = sole_field.ty(self.tcx, substs);
+ if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
+ let variant_path =
+ with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
+ // FIXME #56861: DRYer prelude filtering
+ if let Some(path) = variant_path.strip_prefix("std::prelude::") {
+ if let Some((_, path)) = path.split_once("::") {
+ return Some(path.to_string());
+ }
+ }
+ Some(variant_path)
+ } else {
+ None
+ }
+ })
+ .collect();
+ match &compatible_variants[..] {
+ [] => {}
+ [variant] => {
+ diag.multipart_suggestion_verbose(
+ &format!("try wrapping the pattern in `{}`", variant),
+ vec![
+ (cause.span.shrink_to_lo(), format!("{}(", variant)),
+ (cause.span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ // More than one matching variant.
+ diag.multipart_suggestions(
+ &format!(
+ "try wrapping the pattern in a variant of `{}`",
+ self.tcx.def_path_str(expected_adt.did())
+ ),
+ compatible_variants.into_iter().map(|variant| {
+ vec![
+ (cause.span.shrink_to_lo(), format!("{}(", variant)),
+ (cause.span.shrink_to_hi(), ")".to_string()),
+ ]
+ }),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ }
+ }
+
+ /// A possible error is to forget to add `.await` when using futures:
+ ///
+ /// ```compile_fail,E0308
+ /// async fn make_u32() -> u32 {
+ /// 22
+ /// }
+ ///
+ /// fn take_u32(x: u32) {}
+ ///
+ /// async fn foo() {
+ /// let x = make_u32();
+ /// take_u32(x);
+ /// }
+ /// ```
+ ///
+ /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
+ /// expected type. If this is the case, and we are inside of an async body, it suggests adding
+ /// `.await` to the tail of the expression.
+ pub(super) fn suggest_await_on_expect_found(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ exp_span: Span,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ debug!(
+ "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
+ exp_span, exp_found.expected, exp_found.found,
+ );
+
+ if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
+ return;
+ }
+
+ match (
+ self.get_impl_future_output_ty(exp_found.expected),
+ self.get_impl_future_output_ty(exp_found.found),
+ ) {
+ (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
+ .code()
+ {
+ ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+ let then_span = self.find_block_span_from_hir_id(*then_id);
+ diag.multipart_suggestion(
+ "consider `await`ing on both `Future`s",
+ vec![
+ (then_span.shrink_to_hi(), ".await".to_string()),
+ (exp_span.shrink_to_hi(), ".await".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+ prior_arms,
+ ..
+ }) => {
+ if let [.., arm_span] = &prior_arms[..] {
+ diag.multipart_suggestion(
+ "consider `await`ing on both `Future`s",
+ vec![
+ (arm_span.shrink_to_hi(), ".await".to_string()),
+ (exp_span.shrink_to_hi(), ".await".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ diag.help("consider `await`ing on both `Future`s");
+ }
+ }
+ _ => {
+ diag.help("consider `await`ing on both `Future`s");
+ }
+ },
+ (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
+ diag.span_suggestion_verbose(
+ exp_span.shrink_to_hi(),
+ "consider `await`ing on the `Future`",
+ ".await",
+ Applicability::MaybeIncorrect,
+ );
+ }
+ (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
+ {
+ ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
+ diag.span_suggestion_verbose(
+ then_span.shrink_to_hi(),
+ "consider `await`ing on the `Future`",
+ ".await",
+ Applicability::MaybeIncorrect,
+ );
+ }
+ ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+ let then_span = self.find_block_span_from_hir_id(*then_id);
+ diag.span_suggestion_verbose(
+ then_span.shrink_to_hi(),
+ "consider `await`ing on the `Future`",
+ ".await",
+ Applicability::MaybeIncorrect,
+ );
+ }
+ ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+ ref prior_arms,
+ ..
+ }) => {
+ diag.multipart_suggestion_verbose(
+ "consider `await`ing on the `Future`",
+ prior_arms
+ .iter()
+ .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
+ .collect(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {}
+ },
+ _ => {}
+ }
+ }
+
+ pub(super) fn suggest_accessing_field_where_appropriate(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ debug!(
+ "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
+ cause, exp_found
+ );
+ if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
+ if expected_def.is_enum() {
+ return;
+ }
+
+ if let Some((name, ty)) = expected_def
+ .non_enum_variant()
+ .fields
+ .iter()
+ .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
+ .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
+ .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
+ {
+ if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+ let suggestion = if expected_def.is_struct() {
+ format!("{}.{}", snippet, name)
+ } else if expected_def.is_union() {
+ format!("unsafe {{ {}.{} }}", snippet, name)
+ } else {
+ return;
+ };
+ diag.span_suggestion(
+ span,
+ &format!(
+ "you might have meant to use field `{}` whose type is `{}`",
+ name, ty
+ ),
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ }
+ }
+
+ /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
+ /// suggests it.
+ pub(super) fn suggest_as_ref_where_appropriate(
+ &self,
+ span: Span,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
+ {
+ diag.span_suggestion(
+ span,
+ msg,
+ // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+ format!("{}.as_ref()", snippet.trim_start_matches('&')),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
+ if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
+ (expected.kind(), found.kind())
+ {
+ if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
+ if exp_def == &found_def {
+ let have_as_ref = &[
+ (
+ sym::Option,
+ "you can convert from `&Option<T>` to `Option<&T>` using \
+ `.as_ref()`",
+ ),
+ (
+ sym::Result,
+ "you can convert from `&Result<T, E>` to \
+ `Result<&T, &E>` using `.as_ref()`",
+ ),
+ ];
+ if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
+ self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
+ }) {
+ let mut show_suggestion = true;
+ for (exp_ty, found_ty) in
+ std::iter::zip(exp_substs.types(), found_substs.types())
+ {
+ match *exp_ty.kind() {
+ ty::Ref(_, exp_ty, _) => {
+ match (exp_ty.kind(), found_ty.kind()) {
+ (_, ty::Param(_))
+ | (_, ty::Infer(_))
+ | (ty::Param(_), _)
+ | (ty::Infer(_), _) => {}
+ _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
+ _ => show_suggestion = false,
+ };
+ }
+ ty::Param(_) | ty::Infer(_) => {}
+ _ => show_suggestion = false,
+ }
+ }
+ if show_suggestion {
+ return Some(*msg);
+ }
+ }
+ }
+ }
+ }
+ None
+ }
+
+ /// Try to find code with pattern `if Some(..) = expr`
+ /// use a `visitor` to mark the `if` which its span contains given error span,
+ /// and then try to find a assignment in the `cond` part, which span is equal with error span
+ pub(super) fn suggest_let_for_letchains(
+ &self,
+ err: &mut Diagnostic,
+ cause: &ObligationCause<'_>,
+ span: Span,
+ ) {
+ let hir = self.tcx.hir();
+ let fn_hir_id = hir.get_parent_node(cause.body_id);
+ if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
+ let hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Fn(_sig, _, body_id), ..
+ }) = node {
+ let body = hir.body(*body_id);
+
+ /// Find the if expression with given span
+ struct IfVisitor {
+ pub result: bool,
+ pub found_if: bool,
+ pub err_span: Span,
+ }
+
+ impl<'v> Visitor<'v> for IfVisitor {
+ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+ if self.result { return; }
+ match ex.kind {
+ hir::ExprKind::If(cond, _, _) => {
+ self.found_if = true;
+ walk_expr(self, cond);
+ self.found_if = false;
+ }
+ _ => walk_expr(self, ex),
+ }
+ }
+
+ fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+ if let hir::StmtKind::Local(hir::Local {
+ span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
+ }) = &ex.kind
+ && self.found_if
+ && span.eq(&self.err_span) {
+ self.result = true;
+ }
+ walk_stmt(self, ex);
+ }
+
+ fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+ hir::intravisit::walk_body(self, body);
+ }
+ }
+
+ let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
+ visitor.visit_body(&body);
+ if visitor.result {
+ err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
+ }
+ }
+ }
+}
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
+ /// is enough to fix the error.
+ pub fn could_remove_semicolon(
+ &self,
+ blk: &'tcx hir::Block<'tcx>,
+ expected_ty: Ty<'tcx>,
+ ) -> Option<(Span, StatementAsExpression)> {
+ let blk = blk.innermost_block();
+ // Do not suggest if we have a tail expr.
+ if blk.expr.is_some() {
+ return None;
+ }
+ let last_stmt = blk.stmts.last()?;
+ let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
+ return None;
+ };
+ let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
+ let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
+ _ if last_expr_ty.references_error() => return None,
+ _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
+ StatementAsExpression::CorrectType
+ }
+ (
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, .. }),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, .. }),
+ ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType,
+ (
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: last_def_id, substs: last_bounds, .. }),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: exp_def_id, substs: exp_bounds, .. }),
+ ) => {
+ debug!(
+ "both opaque, likely future {:?} {:?} {:?} {:?}",
+ last_def_id, last_bounds, exp_def_id, exp_bounds
+ );
+
+ let last_local_id = last_def_id.as_local()?;
+ let exp_local_id = exp_def_id.as_local()?;
+
+ match (
+ &self.tcx.hir().expect_item(last_local_id).kind,
+ &self.tcx.hir().expect_item(exp_local_id).kind,
+ ) {
+ (
+ hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
+ hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
+ ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
+ match (left, right) {
+ (
+ hir::GenericBound::Trait(tl, ml),
+ hir::GenericBound::Trait(tr, mr),
+ ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
+ && ml == mr =>
+ {
+ true
+ }
+ (
+ hir::GenericBound::LangItemTrait(langl, _, _, argsl),
+ hir::GenericBound::LangItemTrait(langr, _, _, argsr),
+ ) if langl == langr => {
+ // FIXME: consider the bounds!
+ debug!("{:?} {:?}", argsl, argsr);
+ true
+ }
+ _ => false,
+ }
+ }) =>
+ {
+ StatementAsExpression::NeedsBoxing
+ }
+ _ => StatementAsExpression::CorrectType,
+ }
+ }
+ _ => return None,
+ };
+ let span = if last_stmt.span.from_expansion() {
+ let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
+ self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
+ } else {
+ last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
+ };
+ Some((span, needs_box))
+ }
+
+ /// Suggest returning a local binding with a compatible type if the block
+ /// has no return expression.
+ pub fn consider_returning_binding(
+ &self,
+ blk: &'tcx hir::Block<'tcx>,
+ expected_ty: Ty<'tcx>,
+ err: &mut Diagnostic,
+ ) -> bool {
+ let blk = blk.innermost_block();
+ // Do not suggest if we have a tail expr.
+ if blk.expr.is_some() {
+ return false;
+ }
+ let mut shadowed = FxIndexSet::default();
+ let mut candidate_idents = vec![];
+ let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
+ if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
+ && let Some(pat_ty) = self
+ .typeck_results
+ .as_ref()
+ .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
+ {
+ let pat_ty = self.resolve_vars_if_possible(pat_ty);
+ if self.same_type_modulo_infer(pat_ty, expected_ty)
+ && !(pat_ty, expected_ty).references_error()
+ && shadowed.insert(ident.name)
+ {
+ candidate_idents.push((*ident, pat_ty));
+ }
+ }
+ true
+ };
+
+ let hir = self.tcx.hir();
+ for stmt in blk.stmts.iter().rev() {
+ let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
+ local.pat.walk(&mut find_compatible_candidates);
+ }
+ match hir.find(hir.get_parent_node(blk.hir_id)) {
+ Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
+ match hir.find(hir.get_parent_node(*hir_id)) {
+ Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
+ pat.walk(&mut find_compatible_candidates);
+ }
+ Some(
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+ | hir::Node::ImplItem(hir::ImplItem {
+ kind: hir::ImplItemKind::Fn(_, body),
+ ..
+ })
+ | hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
+ ..
+ })
+ | hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
+ ..
+ }),
+ ) => {
+ for param in hir.body(*body).params {
+ param.pat.walk(&mut find_compatible_candidates);
+ }
+ }
+ Some(hir::Node::Expr(hir::Expr {
+ kind:
+ hir::ExprKind::If(
+ hir::Expr { kind: hir::ExprKind::Let(let_), .. },
+ then_block,
+ _,
+ ),
+ ..
+ })) if then_block.hir_id == *hir_id => {
+ let_.pat.walk(&mut find_compatible_candidates);
+ }
+ _ => {}
+ }
+ }
+ _ => {}
+ }
+
+ match &candidate_idents[..] {
+ [(ident, _ty)] => {
+ let sm = self.tcx.sess.source_map();
+ if let Some(stmt) = blk.stmts.last() {
+ let stmt_span = sm.stmt_span(stmt.span, blk.span);
+ let sugg = if sm.is_multiline(blk.span)
+ && let Some(spacing) = sm.indentation_before(stmt_span)
+ {
+ format!("\n{spacing}{ident}")
+ } else {
+ format!(" {ident}")
+ };
+ err.span_suggestion_verbose(
+ stmt_span.shrink_to_hi(),
+ format!("consider returning the local binding `{ident}`"),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ let sugg = if sm.is_multiline(blk.span)
+ && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
+ {
+ format!("\n{spacing} {ident}\n{spacing}")
+ } else {
+ format!(" {ident} ")
+ };
+ let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
+ err.span_suggestion_verbose(
+ sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
+ format!("consider returning the local binding `{ident}`"),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ true
+ }
+ values if (1..3).contains(&values.len()) => {
+ let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
+ err.span_note(spans, "consider returning one of these bindings");
+ true
+ }
+ _ => false,
+ }
+ }
+}
| ty::Dynamic(..)
| ty::Never
| ty::Tuple(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Foreign(..)
| ty::Param(..)
| ty::Closure(..)
- | ty::GeneratorWitness(..)
- | ty::Opaque(..) => t.super_fold_with(self),
+ | ty::GeneratorWitness(..) => t.super_fold_with(self),
ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
}
where
T: Relate<'tcx>,
{
+ // GLB of a binder and itself is just itself
+ if a == b {
+ return Ok(a);
+ }
+
debug!("binders(a={:?}, b={:?})", a, b);
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
// When higher-ranked types are involved, computing the GLB is
Ok(v)
}
- (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
- infcx.super_combine_tys(this, a, b)
- }
- (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
- if this.define_opaque_types() && did.is_local() =>
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+ ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+ (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+ | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+ if this.define_opaque_types() && def_id.is_local() =>
{
this.add_obligations(
infcx
where
T: Relate<'tcx>,
{
+ // LUB of a binder and itself is just itself
+ if a == b {
+ return Ok(a);
+ }
+
debug!("binders(a={:?}, b={:?})", a, b);
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
// When higher-ranked types are involved, computing the LUB is
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
- values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+ values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)),
}
}
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
- tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
- match arg.unpack() {
- GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
- tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ struct ReplaceParamAndInferWithPlaceholder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ idx: usize,
+ }
+
+ impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ if let ty::Infer(_) = t.kind() {
+ self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize(idx),
+ name: ty::BoundVar::from_usize({
+ let idx = self.idx;
+ self.idx += 1;
+ idx
+ }),
}))
- .into()
+ } else {
+ t.super_fold_with(self)
}
- GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
- let ty = ct.ty();
- // If the type references param or infer, replace that too...
+ }
+
+ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Infer(_) = c.kind() {
+ let ty = c.ty();
+ // If the type references param or infer then ICE ICE ICE
if ty.has_non_region_param() || ty.has_non_region_infer() {
- bug!("const `{ct}`'s type should not reference params or types");
+ bug!("const `{c}`'s type should not reference params or types");
}
- tcx.mk_const(
+ self.tcx.mk_const(
ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize(idx),
+ name: ty::BoundVar::from_usize({
+ let idx = self.idx;
+ self.idx += 1;
+ idx
+ }),
},
ty,
)
- .into()
+ } else {
+ c.super_fold_with(self)
}
- _ => arg,
}
- }))
+ }
+
+ substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
}
/// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
fn relate_projection_ty(
&mut self,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
value_ty: Ty<'tcx>,
) -> Ty<'tcx> {
use rustc_span::DUMMY_SP;
match *value_ty.kind() {
- ty::Projection(other_projection_ty) => {
+ ty::Alias(ty::Projection, other_projection_ty) => {
let var = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
return Ok(value_ty);
}
- ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
+ ty::Alias(ty::Projection, projection_ty)
+ if D::normalization() == NormalizationStrategy::Lazy =>
+ {
return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
}
}
};
let (a, b) = match (a.kind(), b.kind()) {
- (&ty::Opaque(..), _) => (a, generalize(b, false)?),
- (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+ (&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
+ (_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
_ => unreachable!(),
};
let cause = ObligationCause::dummy_with_span(self.delegate.span());
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
- (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
- infcx.super_combine_tys(self, a, b).or_else(|err| {
- self.tcx().sess.delay_span_bug(
- self.delegate.span(),
- "failure to relate an opaque to itself should result in an error later on",
- );
- if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
- })
- }
- (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+ ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
+ self.tcx().sess.delay_span_bug(
+ self.delegate.span(),
+ "failure to relate an opaque to itself should result in an error later on",
+ );
+ if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+ }),
+ (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+ | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+ if def_id.is_local() =>
+ {
self.relate_opaques(a, b)
}
- (&ty::Projection(projection_ty), _)
+ (&ty::Alias(ty::Projection, projection_ty), _)
if D::normalization() == NormalizationStrategy::Lazy =>
{
Ok(self.relate_projection_ty(projection_ty, b))
}
- (_, &ty::Projection(projection_ty))
+ (_, &ty::Alias(ty::Projection, projection_ty))
if D::normalization() == NormalizationStrategy::Lazy =>
{
Ok(self.relate_projection_ty(projection_ty, a))
--- /dev/null
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ fn note_error_origin(
+ &self,
+ err: &mut Diagnostic,
+ cause: &ObligationCause<'tcx>,
+ exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
+ terr: TypeError<'tcx>,
+ ) {
+ match *cause.code() {
+ ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
+ let ty = self.resolve_vars_if_possible(root_ty);
+ if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
+ {
+ // don't show type `_`
+ if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
+ && let ty::Adt(def, substs) = ty.kind()
+ && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
+ {
+ err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
+ } else {
+ err.span_label(span, format!("this expression has type `{}`", ty));
+ }
+ }
+ if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
+ && ty.is_box() && ty.boxed_ty() == found
+ && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ {
+ err.span_suggestion(
+ span,
+ "consider dereferencing the boxed value",
+ format!("*{}", snippet),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
+ err.span_label(span, "expected due to this");
+ }
+ ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+ arm_block_id,
+ arm_span,
+ arm_ty,
+ prior_arm_block_id,
+ prior_arm_span,
+ prior_arm_ty,
+ source,
+ ref prior_arms,
+ scrut_hir_id,
+ opt_suggest_box_span,
+ scrut_span,
+ ..
+ }) => match source {
+ hir::MatchSource::TryDesugar => {
+ if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
+ let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+ let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
+ let arg_expr = args.first().expect("try desugaring call w/out arg");
+ self.typeck_results.as_ref().and_then(|typeck_results| {
+ typeck_results.expr_ty_opt(arg_expr)
+ })
+ } else {
+ bug!("try desugaring w/out call expr as scrutinee");
+ };
+
+ match scrut_ty {
+ Some(ty) if expected == ty => {
+ let source_map = self.tcx.sess.source_map();
+ err.span_suggestion(
+ source_map.end_point(cause.span),
+ "try removing this `?`",
+ "",
+ Applicability::MachineApplicable,
+ );
+ }
+ _ => {}
+ }
+ }
+ }
+ _ => {
+ // `prior_arm_ty` can be `!`, `expected` will have better info when present.
+ let t = self.resolve_vars_if_possible(match exp_found {
+ Some(ty::error::ExpectedFound { expected, .. }) => expected,
+ _ => prior_arm_ty,
+ });
+ let source_map = self.tcx.sess.source_map();
+ let mut any_multiline_arm = source_map.is_multiline(arm_span);
+ if prior_arms.len() <= 4 {
+ for sp in prior_arms {
+ any_multiline_arm |= source_map.is_multiline(*sp);
+ err.span_label(*sp, format!("this is found to be of type `{}`", t));
+ }
+ } else if let Some(sp) = prior_arms.last() {
+ any_multiline_arm |= source_map.is_multiline(*sp);
+ err.span_label(
+ *sp,
+ format!("this and all prior arms are found to be of type `{}`", t),
+ );
+ }
+ let outer_error_span = if any_multiline_arm {
+ // Cover just `match` and the scrutinee expression, not
+ // the entire match body, to reduce diagram noise.
+ cause.span.shrink_to_lo().to(scrut_span)
+ } else {
+ cause.span
+ };
+ let msg = "`match` arms have incompatible types";
+ err.span_label(outer_error_span, msg);
+ self.suggest_remove_semi_or_return_binding(
+ err,
+ prior_arm_block_id,
+ prior_arm_ty,
+ prior_arm_span,
+ arm_block_id,
+ arm_ty,
+ arm_span,
+ );
+ if let Some(ret_sp) = opt_suggest_box_span {
+ // Get return type span and point to it.
+ self.suggest_boxing_for_return_impl_trait(
+ err,
+ ret_sp,
+ prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
+ );
+ }
+ }
+ },
+ ObligationCauseCode::IfExpression(box IfExpressionCause {
+ then_id,
+ else_id,
+ then_ty,
+ else_ty,
+ outer_span,
+ opt_suggest_box_span,
+ }) => {
+ let then_span = self.find_block_span_from_hir_id(then_id);
+ let else_span = self.find_block_span_from_hir_id(else_id);
+ err.span_label(then_span, "expected because of this");
+ if let Some(sp) = outer_span {
+ err.span_label(sp, "`if` and `else` have incompatible types");
+ }
+ self.suggest_remove_semi_or_return_binding(
+ err,
+ Some(then_id),
+ then_ty,
+ then_span,
+ Some(else_id),
+ else_ty,
+ else_span,
+ );
+ if let Some(ret_sp) = opt_suggest_box_span {
+ self.suggest_boxing_for_return_impl_trait(
+ err,
+ ret_sp,
+ [then_span, else_span].into_iter(),
+ );
+ }
+ }
+ ObligationCauseCode::LetElse => {
+ err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
+ err.help("...or use `match` instead of `let...else`");
+ }
+ _ => {
+ if let ObligationCauseCode::BindingObligation(_, span)
+ | ObligationCauseCode::ExprBindingObligation(_, span, ..)
+ = cause.code().peel_derives()
+ && let TypeError::RegionsPlaceholderMismatch = terr
+ {
+ err.span_note( * span,
+ "the lifetime requirement is introduced here");
+ }
+ }
+ }
+ }
+}
+
+impl<'tcx> InferCtxt<'tcx> {
+ /// Given a [`hir::Block`], get the span of its last expression or
+ /// statement, peeling off any inner blocks.
+ pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
+ let block = block.innermost_block();
+ if let Some(expr) = &block.expr {
+ expr.span
+ } else if let Some(stmt) = block.stmts.last() {
+ // possibly incorrect trailing `;` in the else arm
+ stmt.span
+ } else {
+ // empty block; point at its entirety
+ block.span
+ }
+ }
+
+ /// Given a [`hir::HirId`] for a block, get the span of its last expression
+ /// or statement, peeling off any inner blocks.
+ pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
+ match self.tcx.hir().get(hir_id) {
+ hir::Node::Block(blk) => self.find_block_span(blk),
+ // The parser was in a weird state if either of these happen, but
+ // it's better not to panic.
+ hir::Node::Expr(e) => e.span,
+ _ => rustc_span::DUMMY_SP,
+ }
+ }
+}
lt_op: |lt| lt,
ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() {
- ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })
+ if replace_opaque_type(def_id) =>
+ {
let def_span = self.tcx.def_span(def_id);
let span = if span.contains(def_span) { def_span } else { span };
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
}
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
- ty::Opaque(def_id, substs) if def_id.is_local() => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local();
let origin = match self.defining_use_anchor {
DefiningAnchor::Bind(_) => {
DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
DefiningAnchor::Error => return None,
};
- if let ty::Opaque(did2, _) = *b.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
// We could accept this, but there are various ways to handle this situation, and we don't
// want to make a decision on it right now. Likely this case is so super rare anyway, that
// no one encounters it in practice.
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
// where it is of no concern, so we only check for TAITs.
- if let Some(OpaqueTyOrigin::TyAlias) =
- did2.as_local().and_then(|did2| self.opaque_type_origin(did2, cause.span))
+ if let Some(OpaqueTyOrigin::TyAlias) = b_def_id
+ .as_local()
+ .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span))
{
self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
span: cause.span,
- hidden_type: self.tcx.def_span(did2),
+ hidden_type: self.tcx.def_span(b_def_id),
opaque_type: self.tcx.def_span(def_id),
});
}
substs.as_generator().resume_ty().visit_with(self);
}
- ty::Opaque(def_id, ref substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref substs, .. }) => {
// Skip lifetime paramters that are not captures.
let variances = self.tcx.variances_of(*def_id);
}
}
- ty::Projection(proj)
- if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ ty::Alias(ty::Projection, proj)
+ if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
{
// Skip lifetime paramters that are not captures.
- let variances = self.tcx.variances_of(proj.item_def_id);
+ let variances = self.tcx.variances_of(proj.def_id);
for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
if *v != ty::Variance::Bivariant {
// We can't normalize associated types from `rustc_infer`,
// but we can eagerly register inference variables for them.
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
- ty::Projection(projection_ty)
+ ty::Alias(ty::Projection, projection_ty)
if !projection_ty.has_escaping_bound_vars()
- && tcx.def_kind(projection_ty.item_def_id)
+ && tcx.def_kind(projection_ty.def_id)
!= DefKind::ImplTraitPlaceholder =>
{
self.infer_projection(
}
// Replace all other mentions of the same opaque type with the hidden type,
// as the bounds must hold on the hidden type after all.
- ty::Opaque(def_id2, substs2)
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. })
if def_id.to_def_id() == def_id2 && substs == substs2 =>
{
hidden_ty
}
// FIXME(RPITIT): This can go away when we move to associated types
- ty::Projection(proj)
- if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
- {
- hidden_ty
- }
+ ty::Alias(
+ ty::Projection,
+ ty::AliasTy { def_id: def_id2, substs: substs2, .. },
+ ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty,
_ => ty,
},
lt_op: |lt| lt,
// is not in a position to judge which is the best technique, so
// we just product the projection as a component and leave it to
// the consumer to decide (but see `EscapingProjection` below).
- Projection(ty::ProjectionTy<'tcx>),
+ Projection(ty::AliasTy<'tcx>),
// In the case where a projection has escaping regions -- meaning
// regions bound within the type itself -- we always use
// outlives any other lifetime, which is unsound.
// See https://github.com/rust-lang/rust/issues/84305 for
// more details.
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
out.push(Component::Opaque(def_id, substs));
},
// trait-ref. Therefore, if we see any higher-ranked regions,
// we simply fallback to the most restrictive rule, which
// requires that `Pi: 'a` for all `i`.
- ty::Projection(ref data) => {
+ ty::Alias(ty::Projection, ref data) => {
if !data.has_escaping_bound_vars() {
// best case: no escaping regions, so push the
// projection and skip the subtree (thus generating no
substs,
true,
|ty| match *ty.kind() {
- ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
_ => bug!("expected only projection types from env, not {:?}", ty),
},
);
&mut self,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
) {
self.generic_must_outlive(
origin,
region,
GenericKind::Projection(projection_ty),
- projection_ty.item_def_id,
+ projection_ty.def_id,
projection_ty.substs,
false,
|ty| match ty.kind() {
- ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
+ ty::Alias(ty::Projection, projection_ty) => {
+ (projection_ty.def_id, projection_ty.substs)
+ }
_ => bug!("expected only projection types from env, not {:?}", ty),
},
);
),
Component::Projection(projection_ty) => self.projection_opaque_bounds(
GenericKind::Projection(projection_ty),
- projection_ty.item_def_id,
+ projection_ty.def_id,
projection_ty.substs,
visited,
),
pub fn infer_projection(
&self,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Ty<'tcx> {
- let def_id = projection_ty.item_def_id;
+ let def_id = projection_ty.def_id;
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType,
span: self.tcx.def_span(def_id),
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub enum GenericKind<'tcx> {
Param(ty::ParamTy),
- Projection(ty::ProjectionTy<'tcx>),
+ Projection(ty::AliasTy<'tcx>),
Opaque(DefId, SubstsRef<'tcx>),
}
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
GenericKind::Param(ref p) => p.to_ty(tcx),
- GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
+ GenericKind::Projection(ref p) => tcx.mk_projection(p.def_id, p.substs),
GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
}
}
Ok(self.tcx().ty_error_with_guaranteed(e))
}
- (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+ ) if a_def_id == b_def_id => {
self.fields.infcx.super_combine_tys(self, a, b)?;
Ok(a)
}
- (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
- if self.fields.define_opaque_types && did.is_local() =>
+ (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+ | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+ if self.fields.define_opaque_types && def_id.is_local() =>
{
self.fields.obligations.extend(
infcx
where
T: Relate<'tcx>,
{
+ // A binder is always a subtype of itself if it's structually equal to itself
+ if a == b {
+ return Ok(a);
+ }
+
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
Ok(a)
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct ProjectionCacheKey<'tcx> {
- ty: ty::ProjectionTy<'tcx>,
+ ty: ty::AliasTy<'tcx>,
}
impl<'tcx> ProjectionCacheKey<'tcx> {
- pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+ pub fn new(ty: ty::AliasTy<'tcx>) -> Self {
Self { ty }
}
}
pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>, result: EvaluationResult) {
let mut map = self.map();
match map.get(&key) {
- Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
+ Some(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => {
info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
let mut ty = ty.clone();
if result.must_apply_considering_regions() {
Component::Projection(projection) => {
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
- let ty =
- tcx.mk_projection(projection.item_def_id, projection.substs);
+ let ty = tcx.mk_projection(projection.def_id, projection.substs);
Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
ty::OutlivesPredicate(ty, r_min),
)))
sess: Lrc<Session>,
metadata_loader: Box<MetadataLoaderDyn>,
krate: &ast::Crate,
- crate_name: &str,
+ crate_name: Symbol,
) -> BoxedResolver {
trace!("create_resolver");
BoxedResolver::new(sess, move |sess, resolver_arenas| {
metadata_loader: &'a dyn MetadataLoader,
register_lints: impl Fn(&Session, &mut LintStore),
mut krate: ast::Crate,
- crate_name: &str,
+ crate_name: Symbol,
) -> Result<(ast::Crate, LintStore)> {
krate = sess.time("attributes_injection", || {
rustc_builtin_macros::cmdline_attrs::inject(
lint_store: &LintStore,
registered_tools: &RegisteredTools,
check_node: impl EarlyCheckNode<'a>,
- node_name: &str,
+ node_name: Symbol,
) {
- sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
- rustc_lint::check_ast_node(
- sess,
- true,
- lint_store,
- registered_tools,
- None,
- rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
- check_node,
- );
- });
+ sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
+ || {
+ rustc_lint::check_ast_node(
+ sess,
+ true,
+ lint_store,
+ registered_tools,
+ None,
+ rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
+ check_node,
+ );
+ },
+ );
}
// Cannot implement directly for `LintStore` due to trait coherence.
node_id: ast::NodeId,
attrs: &[ast::Attribute],
items: &[rustc_ast::ptr::P<ast::Item>],
- name: &str,
+ name: Symbol,
) {
pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
}
sess: &Session,
lint_store: &LintStore,
mut krate: ast::Crate,
- crate_name: &str,
+ crate_name: Symbol,
resolver: &mut Resolver<'_>,
) -> Result<ast::Crate> {
trace!("configure_and_expand");
sess: &Session,
outputs: &OutputFilenames,
exact_name: bool,
- crate_name: &str,
+ crate_name: Symbol,
) -> Vec<PathBuf> {
let mut out_filenames = Vec::new();
for output_type in sess.opts.output_types.keys() {
compiler: &Compiler,
krate: &ast::Crate,
boxed_resolver: &RefCell<BoxedResolver>,
- crate_name: &str,
+ crate_name: Symbol,
) -> Result<OutputFilenames> {
let _timer = sess.timer("prepare_outputs");
dep_graph: DepGraph,
resolver: Rc<RefCell<BoxedResolver>>,
outputs: OutputFilenames,
- crate_name: &str,
+ crate_name: Symbol,
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
});
let ty::ResolverOutputs {
- definitions,
global_ctxt: untracked_resolutions,
ast_lowering: untracked_resolver_for_lowering,
+ untracked,
} = resolver_outputs;
let gcx = sess.time("setup_global_ctxt", || {
lint_store,
arena,
hir_arena,
- definitions,
untracked_resolutions,
+ untracked,
krate,
dep_graph,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
use rustc_session::config::{self, OutputFilenames, OutputType};
use rustc_session::{output::find_crate_name, Session};
use rustc_span::symbol::sym;
+use rustc_span::Symbol;
use std::any::Any;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>,
- crate_name: Query<String>,
+ crate_name: Query<Symbol>,
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
dep_graph: Query<DepGraph>,
&*self.codegen_backend().metadata_loader(),
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
krate,
- &crate_name,
+ crate_name,
)?;
// Compute the dependency graph (in the background). We want to do
})
}
- pub fn crate_name(&self) -> Result<&Query<String>> {
+ pub fn crate_name(&self) -> Result<&Query<Symbol>> {
self.crate_name.compute(|| {
Ok({
let parse_result = self.parse()?;
) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
trace!("expansion");
self.expansion.compute(|| {
- let crate_name = self.crate_name()?.peek().clone();
+ let crate_name = *self.crate_name()?.peek();
let (krate, lint_store) = self.register_plugins()?.take();
let _timer = self.session().timer("configure_and_expand");
let sess = self.session();
sess.clone(),
self.codegen_backend().metadata_loader(),
&krate,
- &crate_name,
+ crate_name,
);
let krate = resolver.access(|resolver| {
- passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
+ passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
})?;
Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
})
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
self.prepare_outputs.compute(|| {
let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
- let crate_name = self.crate_name()?.peek();
+ let crate_name = *self.crate_name()?.peek();
passes::prepare_outputs(
self.session(),
self.compiler,
krate,
&*boxed_resolver,
- &crate_name,
+ crate_name,
)
})
}
pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
self.global_ctxt.compute(|| {
- let crate_name = self.crate_name()?.peek().clone();
+ let crate_name = *self.crate_name()?.peek();
let outputs = self.prepare_outputs()?.take();
let dep_graph = self.dep_graph()?.peek().clone();
let (krate, resolver, lint_store) = self.expansion()?.take();
dep_graph,
resolver,
outputs,
- &crate_name,
+ crate_name,
&self.queries,
&self.gcx,
&self.arena,
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
use std::collections::{BTreeMap, BTreeSet};
-use std::iter::FromIterator;
use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};
use self::LiteralKind::*;
use self::TokenKind::*;
use crate::cursor::EOF_CHAR;
-use std::convert::TryFrom;
/// Parsed token.
/// It doesn't contain information about data that has been parsed,
})?;
}
Some(c) => {
- let digit =
+ let digit: u32 =
c.to_digit(16).ok_or(EscapeError::InvalidCharInUnicodeEscape)?;
n_digits += 1;
if n_digits > 6 {
// Stop updating value since we're sure that it's incorrect already.
continue;
}
- let digit = digit as u32;
value = value * 16 + digit;
}
};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, InnerSpan, Span};
use rustc_target::abi::{Abi, VariantIdx};
-use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
+use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
+use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
use crate::nonstandard_style::{method_context, MethodLateContext};
}
impl EarlyLintPass for WhileTrue {
+ #[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
if let ast::ExprKind::While(cond, _, label) = &e.kind
&& let cond = pierce_parens(cond)
}
if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
if cx.tcx.find_field_index(ident, &variant)
- == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
+ == Some(cx.typeck_results().field_index(fieldpat.hir_id))
{
cx.struct_span_lint(
NON_SHORTHAND_FIELD_PATTERNS,
}
}
+ #[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
if let ast::ExprKind::Block(ref blk, _) = e.kind {
// Don't warn about generated blocks; that'll just pollute the output.
}
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
+ #[inline]
fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
let doc_hidden = self.doc_hidden()
|| attrs.iter().any(|attr| {
if def.has_dtor(cx.tcx) {
return;
}
+
+ // If the type contains a raw pointer, it may represent something like a handle,
+ // and recommending Copy might be a bad idea.
+ for field in def.all_fields() {
+ let did = field.did;
+ if cx.tcx.type_of(did).is_unsafe_ptr() {
+ return;
+ }
+ }
let param_env = ty::ParamEnv::empty();
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return;
}
+
+ // We shouldn't recommend implementing `Copy` on stateful things,
+ // such as iterators.
+ if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
+ if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], param_env)
+ == EvaluationResult::EvaluatedToOk
+ {
+ return;
+ }
+ }
+
+ // Default value of clippy::trivially_copy_pass_by_ref
+ const MAX_SIZE: u64 = 256;
+
+ if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
+ if size > MAX_SIZE {
+ return;
+ }
+ }
+
if can_type_implement_copy(
cx.tcx,
param_env,
| (Closure(..), Closure(..))
| (Generator(..), Generator(..))
| (GeneratorWitness(..), GeneratorWitness(..))
- | (Projection(..), Projection(..))
- | (Opaque(..), Opaque(..)) => false,
+ | (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
+ | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
// These definitely should have been caught above.
(Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
return CheckLintNameResult::Tool(Ok(&lint_ids));
}
},
- Some(&Id(ref id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
+ Some(Id(id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))),
// If the lint was registered as removed or renamed by the lint tool, we don't need
// to treat tool_lints and rustc lints different and can use the code below.
_ => {}
}
}
match self.by_name.get(&complete_name) {
- Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
+ Some(Renamed(new_name, _)) => CheckLintNameResult::Warning(
format!("lint `{}` has been renamed to `{}`", complete_name, new_name),
Some(new_name.to_owned()),
),
- Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
+ Some(Removed(reason)) => CheckLintNameResult::Warning(
format!("lint `{}` has been removed: {}", complete_name, reason),
None,
),
CheckLintNameResult::Ok(&lint_ids)
}
},
- Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
+ Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
Some(&Ignored) => CheckLintNameResult::Ok(&[]),
}
}
CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name)))
}
},
- Some(&Id(ref id)) => {
+ Some(Id(id)) => {
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
}
Some(other) => {
tcx.associated_items(trait_id)
.find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
.and_then(|assoc| {
- let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
+ let proj = tcx.mk_projection(assoc.def_id, [self_ty]);
tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
})
}
use rustc_ast::visit::{self as ast_visit, Visitor};
use rustc_ast::{self as ast, walk_list, HasAttrs};
use rustc_middle::ty::RegisteredTools;
-use rustc_session::lint::{BufferedEarlyLint, LintBuffer};
+use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::Span;
-macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({
- for pass in $cx.passes.iter_mut() {
- pass.$f(&$cx.context, $($args),*);
- }
+macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
+ $cx.pass.$f(&$cx.context, $($args),*);
}) }
-pub struct EarlyContextAndPasses<'a> {
+/// Implements the AST traversal for early lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
context: EarlyContext<'a>,
- passes: Vec<EarlyLintPassObject>,
+ pass: T,
}
-impl<'a> EarlyContextAndPasses<'a> {
- fn check_id(&mut self, id: ast::NodeId) {
+impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
+ // This always-inlined function is for the hot call site.
+ #[inline(always)]
+ fn inlined_check_id(&mut self, id: ast::NodeId) {
for early_lint in self.context.buffered.take(id) {
let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
self.context.lookup_with_diagnostics(
}
}
+ // This non-inlined function is for the cold call sites.
+ fn check_id(&mut self, id: ast::NodeId) {
+ self.inlined_check_id(id)
+ }
+
/// Merge the lints specified by any lint attributes into the
/// current lint context, call the provided function, then reset the
/// lints in effect to their previous state.
debug!(?id);
let push = self.context.builder.push(attrs, is_crate_node, None);
- self.check_id(id);
+ self.inlined_check_id(id);
debug!("early context: enter_attrs({:?})", attrs);
- run_early_passes!(self, enter_lint_attrs, attrs);
+ lint_callback!(self, enter_lint_attrs, attrs);
f(self);
debug!("early context: exit_attrs({:?})", attrs);
- run_early_passes!(self, exit_lint_attrs, attrs);
+ lint_callback!(self, exit_lint_attrs, attrs);
self.context.builder.pop(push);
}
}
-impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> {
+impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
fn visit_param(&mut self, param: &'a ast::Param) {
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
- run_early_passes!(cx, check_param, param);
+ lint_callback!(cx, check_param, param);
ast_visit::walk_param(cx, param);
});
}
fn visit_item(&mut self, it: &'a ast::Item) {
self.with_lint_attrs(it.id, &it.attrs, |cx| {
- run_early_passes!(cx, check_item, it);
+ lint_callback!(cx, check_item, it);
ast_visit::walk_item(cx, it);
- run_early_passes!(cx, check_item_post, it);
+ lint_callback!(cx, check_item_post, it);
})
}
}
fn visit_pat(&mut self, p: &'a ast::Pat) {
- run_early_passes!(self, check_pat, p);
+ lint_callback!(self, check_pat, p);
self.check_id(p.id);
ast_visit::walk_pat(self, p);
- run_early_passes!(self, check_pat_post, p);
+ lint_callback!(self, check_pat_post, p);
}
fn visit_pat_field(&mut self, field: &'a ast::PatField) {
fn visit_expr(&mut self, e: &'a ast::Expr) {
self.with_lint_attrs(e.id, &e.attrs, |cx| {
- run_early_passes!(cx, check_expr, e);
+ lint_callback!(cx, check_expr, e);
ast_visit::walk_expr(cx, e);
})
}
// Note that statements get their attributes from
// the AST struct that they wrap (e.g. an item)
self.with_lint_attrs(s.id, s.attrs(), |cx| {
- run_early_passes!(cx, check_stmt, s);
+ lint_callback!(cx, check_stmt, s);
cx.check_id(s.id);
});
// The visitor for the AST struct wrapped
}
fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
- run_early_passes!(self, check_fn, fk, span, id);
+ lint_callback!(self, check_fn, fk, span, id);
self.check_id(id);
ast_visit::walk_fn(self, fk);
fn visit_variant(&mut self, v: &'a ast::Variant) {
self.with_lint_attrs(v.id, &v.attrs, |cx| {
- run_early_passes!(cx, check_variant, v);
+ lint_callback!(cx, check_variant, v);
ast_visit::walk_variant(cx, v);
})
}
fn visit_ty(&mut self, t: &'a ast::Ty) {
- run_early_passes!(self, check_ty, t);
+ lint_callback!(self, check_ty, t);
self.check_id(t.id);
ast_visit::walk_ty(self, t);
}
fn visit_ident(&mut self, ident: Ident) {
- run_early_passes!(self, check_ident, ident);
+ lint_callback!(self, check_ident, ident);
}
fn visit_local(&mut self, l: &'a ast::Local) {
self.with_lint_attrs(l.id, &l.attrs, |cx| {
- run_early_passes!(cx, check_local, l);
+ lint_callback!(cx, check_local, l);
ast_visit::walk_local(cx, l);
})
}
fn visit_block(&mut self, b: &'a ast::Block) {
- run_early_passes!(self, check_block, b);
+ lint_callback!(self, check_block, b);
self.check_id(b.id);
ast_visit::walk_block(self, b);
}
fn visit_arm(&mut self, a: &'a ast::Arm) {
self.with_lint_attrs(a.id, &a.attrs, |cx| {
- run_early_passes!(cx, check_arm, a);
+ lint_callback!(cx, check_arm, a);
ast_visit::walk_arm(cx, a);
})
}
}
fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
- run_early_passes!(self, check_generic_arg, arg);
+ lint_callback!(self, check_generic_arg, arg);
ast_visit::walk_generic_arg(self, arg);
}
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
- run_early_passes!(cx, check_generic_param, param);
+ lint_callback!(cx, check_generic_param, param);
ast_visit::walk_generic_param(cx, param);
});
}
fn visit_generics(&mut self, g: &'a ast::Generics) {
- run_early_passes!(self, check_generics, g);
+ lint_callback!(self, check_generics, g);
ast_visit::walk_generics(self, g);
}
}
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
- run_early_passes!(self, check_poly_trait_ref, t);
+ lint_callback!(self, check_poly_trait_ref, t);
ast_visit::walk_poly_trait_ref(self, t);
}
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt {
ast_visit::AssocCtxt::Trait => {
- run_early_passes!(cx, check_trait_item, item);
+ lint_callback!(cx, check_trait_item, item);
ast_visit::walk_assoc_item(cx, item, ctxt);
}
ast_visit::AssocCtxt::Impl => {
- run_early_passes!(cx, check_impl_item, item);
+ lint_callback!(cx, check_impl_item, item);
ast_visit::walk_assoc_item(cx, item, ctxt);
}
});
}
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
- run_early_passes!(self, check_attribute, attr);
+ lint_callback!(self, check_attribute, attr);
}
fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
- run_early_passes!(self, check_mac_def, mac);
+ lint_callback!(self, check_mac_def, mac);
self.check_id(id);
}
fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
- run_early_passes!(self, check_mac, mac);
+ lint_callback!(self, check_mac, mac);
ast_visit::walk_mac(self, mac);
}
}
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_early_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedEarlyLintPass<'a> {
+ passes: &'a mut [EarlyLintPassObject],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
+ fn name(&self) -> &'static str {
+ panic!()
+ }
+}
+
+macro_rules! impl_early_lint_pass {
+ ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => (
+ impl EarlyLintPass for RuntimeCombinedEarlyLintPass<'_> {
+ $(fn $f(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
+ for pass in self.passes.iter_mut() {
+ pass.$f(context, $($param),*);
+ }
+ })*
+ }
+ )
+}
+
+crate::early_lint_methods!(impl_early_lint_pass, []);
+
/// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
/// This trait generalizes over those nodes.
pub trait EarlyCheckNode<'a>: Copy {
fn attrs<'b>(self) -> &'b [ast::Attribute]
where
'a: 'b;
- fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+ fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
where
'a: 'b;
}
{
&self.attrs
}
- fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+ fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
where
'a: 'b,
{
- run_early_passes!(cx, check_crate, self);
+ lint_callback!(cx, check_crate, self);
ast_visit::walk_crate(cx, self);
- run_early_passes!(cx, check_crate_post, self);
+ lint_callback!(cx, check_crate_post, self);
}
}
{
self.1
}
- fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>)
+ fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
where
'a: 'b,
{
builtin_lints: impl EarlyLintPass + 'static,
check_node: impl EarlyCheckNode<'a>,
) {
+ let context = EarlyContext::new(
+ sess,
+ !pre_expansion,
+ lint_store,
+ registered_tools,
+ lint_buffer.unwrap_or_default(),
+ );
+
+ // Note: `passes` is often empty. In that case, it's faster to run
+ // `builtin_lints` directly rather than bundling it up into the
+ // `RuntimeCombinedEarlyLintPass`.
let passes =
if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
- let mut passes: Vec<EarlyLintPassObject> = passes.iter().map(|p| (p)()).collect();
- passes.push(Box::new(builtin_lints));
-
- let mut cx = EarlyContextAndPasses {
- context: EarlyContext::new(
- sess,
- !pre_expansion,
- lint_store,
- registered_tools,
- lint_buffer.unwrap_or_default(),
- ),
- passes,
- };
+ if passes.is_empty() {
+ check_ast_node_inner(sess, check_node, context, builtin_lints);
+ } else {
+ let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect();
+ passes.push(Box::new(builtin_lints));
+ let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] };
+ check_ast_node_inner(sess, check_node, context, pass);
+ }
+}
+
+pub fn check_ast_node_inner<'a, T: EarlyLintPass>(
+ sess: &Session,
+ check_node: impl EarlyCheckNode<'a>,
+ context: EarlyContext<'_>,
+ pass: T,
+) {
+ let mut cx = EarlyContextAndPass { context, pass };
+
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
// All of the buffered lints should have been emitted at this point.
}
}
+ #[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
// byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
match &expr.kind {
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::lint::LintPass;
use rustc_span::Span;
use std::any::Any;
}
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
- for pass in $cx.passes.iter_mut() {
- pass.$f(&$cx.context, $($args),*);
- }
+ $cx.pass.$f(&$cx.context, $($args),*);
}) }
-struct LateContextAndPasses<'tcx> {
+/// Implements the AST traversal for late lint passes. `T` provides the the
+/// `check_*` methods.
+pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> {
context: LateContext<'tcx>,
- passes: Vec<LateLintPassObject<'tcx>>,
+ pass: T,
}
-impl<'tcx> LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
/// Merge the lints specified by any lint attributes into the
/// current lint context, call the provided function, then reset the
/// lints in effect to their previous state.
}
}
-impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> {
+impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> {
type NestedFilter = nested_filter::All;
/// Because lints are scoped lexically, we want to walk nested
}
}
+// Combines multiple lint passes into a single pass, at runtime. Each
+// `check_foo` method in `$methods` within this pass simply calls `check_foo`
+// once per `$pass`. Compare with `declare_combined_late_lint_pass`, which is
+// similar, but combines lint passes at compile time.
+struct RuntimeCombinedLateLintPass<'a, 'tcx> {
+ passes: &'a mut [LateLintPassObject<'tcx>],
+}
+
+#[allow(rustc::lint_pass_impl_without_macro)]
+impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
+ fn name(&self) -> &'static str {
+ panic!()
+ }
+}
+
+macro_rules! impl_late_lint_pass {
+ ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => {
+ impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'_, 'tcx> {
+ $(fn $f(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
+ for pass in self.passes.iter_mut() {
+ pass.$f(context, $($param),*);
+ }
+ })*
+ }
+ };
+}
+
+crate::late_lint_methods!(impl_late_lint_pass, []);
+
pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
tcx: TyCtxt<'tcx>,
module_def_id: LocalDefId,
only_module: true,
};
+ // Note: `passes` is often empty. In that case, it's faster to run
+ // `builtin_lints` directly rather than bundling it up into the
+ // `RuntimeCombinedLateLintPass`.
let mut passes: Vec<_> =
- unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
- passes.push(Box::new(builtin_lints));
+ unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+ if passes.is_empty() {
+ late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
+ } else {
+ passes.push(Box::new(builtin_lints));
+ let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+ late_lint_mod_inner(tcx, module_def_id, context, pass);
+ }
+}
- let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
+ tcx: TyCtxt<'tcx>,
+ module_def_id: LocalDefId,
+ context: LateContext<'tcx>,
+ pass: T,
+) {
+ let mut cx = LateContextAndPass { context, pass };
let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
cx.process_mod(module, hir_id);
only_module: false,
};
- let mut passes =
- unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();
- passes.push(Box::new(builtin_lints));
+ // Note: `passes` is often empty. In that case, it's faster to run
+ // `builtin_lints` directly rather than bundling it up into the
+ // `RuntimeCombinedLateLintPass`.
+ let mut passes: Vec<_> =
+ unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+ if passes.is_empty() {
+ late_lint_crate_inner(tcx, context, builtin_lints);
+ } else {
+ passes.push(Box::new(builtin_lints));
+ let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+ late_lint_crate_inner(tcx, context, pass);
+ }
+}
- let mut cx = LateContextAndPasses { context, passes };
+fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
+ tcx: TyCtxt<'tcx>,
+ context: LateContext<'tcx>,
+ pass: T,
+) {
+ let mut cx = LateContextAndPass { context, pass };
// Visit the whole crate.
cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
]
);
-// FIXME: Make a separate lint type which do not require typeck tables
+// FIXME: Make a separate lint type which does not require typeck tables.
+
late_lint_methods!(
declare_combined_late_lint_pass,
[
// Keeps a global list of foreign declarations.
ClashingExternDeclarations: ClashingExternDeclarations::new(),
]
- ],
- ['tcx]
+ ]
);
late_lint_methods!(
NamedAsmLabels: NamedAsmLabels,
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
]
- ],
- ['tcx]
+ ]
);
pub fn new_lint_store(internal_lints: bool) -> LintStore {
return;
}
- match it.kind {
+ match &it.kind {
ast::ItemKind::TyAlias(..)
| ast::ItemKind::Enum(..)
| ast::ItemKind::Struct(..)
| ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident),
+
+ // N.B. This check is only for inherent associated types, so that we don't lint against
+ // trait impls where we should have warned for the trait definition already.
+ ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
+ for it in items {
+ if let ast::AssocItemKind::Type(..) = it.kind {
+ self.check_case(cx, "associated type", &it.ident);
+ }
+ }
+ }
_ => (),
}
}
let Some(proj_term) = proj.term.ty() else { continue };
let proj_ty =
- cx.tcx.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
+ cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs);
// For every instance of the projection type in the bounds,
// replace them with the term we're assigning to the associated
// type in our opaque type.
// with `impl Send: OtherTrait`.
for (assoc_pred, assoc_pred_span) in cx
.tcx
- .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+ .bound_explicit_item_bounds(proj.projection_ty.def_id)
.subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
{
let assoc_pred = assoc_pred.fold_with(proj_replacer);
// then we can emit a suggestion to add the bound.
let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
(
- ty::Opaque(def_id, _),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)),
) => Some(AddBound {
suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
#[macro_export]
macro_rules! late_lint_methods {
- ($macro:path, $args:tt, [$hir:tt]) => (
- $macro!($args, [$hir], [
- fn check_body(a: &$hir hir::Body<$hir>);
- fn check_body_post(a: &$hir hir::Body<$hir>);
+ ($macro:path, $args:tt) => (
+ $macro!($args, [
+ fn check_body(a: &'tcx hir::Body<'tcx>);
+ fn check_body_post(a: &'tcx hir::Body<'tcx>);
fn check_crate();
fn check_crate_post();
- fn check_mod(a: &$hir hir::Mod<$hir>, b: hir::HirId);
- fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
- fn check_item(a: &$hir hir::Item<$hir>);
- fn check_item_post(a: &$hir hir::Item<$hir>);
- fn check_local(a: &$hir hir::Local<$hir>);
- fn check_block(a: &$hir hir::Block<$hir>);
- fn check_block_post(a: &$hir hir::Block<$hir>);
- fn check_stmt(a: &$hir hir::Stmt<$hir>);
- fn check_arm(a: &$hir hir::Arm<$hir>);
- fn check_pat(a: &$hir hir::Pat<$hir>);
- fn check_expr(a: &$hir hir::Expr<$hir>);
- fn check_expr_post(a: &$hir hir::Expr<$hir>);
- fn check_ty(a: &$hir hir::Ty<$hir>);
- fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
- fn check_generics(a: &$hir hir::Generics<$hir>);
- fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>);
+ fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId);
+ fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>);
+ fn check_item(a: &'tcx hir::Item<'tcx>);
+ fn check_item_post(a: &'tcx hir::Item<'tcx>);
+ fn check_local(a: &'tcx hir::Local<'tcx>);
+ fn check_block(a: &'tcx hir::Block<'tcx>);
+ fn check_block_post(a: &'tcx hir::Block<'tcx>);
+ fn check_stmt(a: &'tcx hir::Stmt<'tcx>);
+ fn check_arm(a: &'tcx hir::Arm<'tcx>);
+ fn check_pat(a: &'tcx hir::Pat<'tcx>);
+ fn check_expr(a: &'tcx hir::Expr<'tcx>);
+ fn check_expr_post(a: &'tcx hir::Expr<'tcx>);
+ fn check_ty(a: &'tcx hir::Ty<'tcx>);
+ fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>);
+ fn check_generics(a: &'tcx hir::Generics<'tcx>);
+ fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>);
fn check_fn(
- a: rustc_hir::intravisit::FnKind<$hir>,
- b: &$hir hir::FnDecl<$hir>,
- c: &$hir hir::Body<$hir>,
+ a: rustc_hir::intravisit::FnKind<'tcx>,
+ b: &'tcx hir::FnDecl<'tcx>,
+ c: &'tcx hir::Body<'tcx>,
d: Span,
e: hir::HirId);
- fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
- fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
- fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
- fn check_struct_def(a: &$hir hir::VariantData<$hir>);
- fn check_field_def(a: &$hir hir::FieldDef<$hir>);
- fn check_variant(a: &$hir hir::Variant<$hir>);
- fn check_path(a: &hir::Path<$hir>, b: hir::HirId);
- fn check_attribute(a: &$hir ast::Attribute);
+ fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
+ fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
+ fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
+ fn check_struct_def(a: &'tcx hir::VariantData<'tcx>);
+ fn check_field_def(a: &'tcx hir::FieldDef<'tcx>);
+ fn check_variant(a: &'tcx hir::Variant<'tcx>);
+ fn check_path(a: &hir::Path<'tcx>, b: hir::HirId);
+ fn check_attribute(a: &'tcx ast::Attribute);
/// Called when entering a syntax node that can have lint attributes such
/// as `#[allow(...)]`. Called with *all* the attributes of that node.
- fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+ fn enter_lint_attrs(a: &'tcx [ast::Attribute]);
/// Counterpart to `enter_lint_attrs`.
- fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+ fn exit_lint_attrs(a: &'tcx [ast::Attribute]);
]);
)
}
// contains a few lint-specific methods with no equivalent in `Visitor`.
macro_rules! declare_late_lint_pass {
- ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
- pub trait LateLintPass<$hir>: LintPass {
- $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})*
+ ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+ pub trait LateLintPass<'tcx>: LintPass {
+ $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})*
}
)
}
-late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+// Declare the `LateLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
+late_lint_methods!(declare_late_lint_pass, []);
impl LateLintPass<'_> for HardwiredLints {}
#[macro_export]
macro_rules! expand_combined_late_lint_pass_method {
- ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
- $($self.$passes.$name $params;)*
+ ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+ $($self.$pass.$name $params;)*
})
}
)
}
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `LateLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
#[macro_export]
macro_rules! declare_combined_late_lint_pass {
- ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+ ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
#[allow(non_snake_case)]
$v struct $name {
- $($passes: $passes,)*
+ $($pass: $pass,)*
}
impl $name {
$v fn new() -> Self {
Self {
- $($passes: $constructor,)*
+ $($pass: $constructor,)*
}
}
$v fn get_lints() -> LintArray {
let mut lints = Vec::new();
- $(lints.extend_from_slice(&$passes::get_lints());)*
+ $(lints.extend_from_slice(&$pass::get_lints());)*
lints
}
}
impl<'tcx> LateLintPass<'tcx> for $name {
- expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+ expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
}
#[allow(rustc::lint_pass_impl_without_macro)]
)
}
+// Declare the `EarlyLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
early_lint_methods!(declare_early_lint_pass, []);
#[macro_export]
macro_rules! expand_combined_early_lint_pass_method {
- ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
- $($self.$passes.$name $params;)*
+ ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+ $($self.$pass.$name $params;)*
})
}
)
}
+/// Combines multiple lints passes into a single lint pass, at compile time,
+/// for maximum speed. Each `check_foo` method in `$methods` within this pass
+/// simply calls `check_foo` once per `$pass`. Compare with
+/// `EarlyLintPassObjects`, which is similar, but combines lint passes at
+/// runtime.
#[macro_export]
macro_rules! declare_combined_early_lint_pass {
- ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
+ ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
#[allow(non_snake_case)]
$v struct $name {
- $($passes: $passes,)*
+ $($pass: $pass,)*
}
impl $name {
$v fn new() -> Self {
Self {
- $($passes: $constructor,)*
+ $($pass: $constructor,)*
}
}
$v fn get_lints() -> LintArray {
let mut lints = Vec::new();
- $(lints.extend_from_slice(&$passes::get_lints());)*
+ $(lints.extend_from_slice(&$pass::get_lints());)*
lints
}
}
impl EarlyLintPass for $name {
- expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
+ expand_combined_early_lint_pass_methods!([$($pass),*], $methods);
}
#[allow(rustc::lint_pass_impl_without_macro)]
use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;
-use std::cmp;
use std::iter;
use std::ops::ControlFlow;
_ => {}
};
- fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
+ fn is_valid<T: PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
match binop.node {
hir::BinOpKind::Lt => v > min && v <= max,
hir::BinOpKind::Le => v >= min && v < max,
// While opaque types are checked for earlier, if a projection in a struct field
// normalizes to an opaque type, then it will reach this branch.
- ty::Opaque(..) => {
+ ty::Alias(ty::Opaque, ..) => {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
}
// `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
// so they are currently ignored for the purposes of this lint.
- ty::Param(..) | ty::Projection(..) if matches!(self.mode, CItemKind::Definition) => {
+ ty::Param(..) | ty::Alias(ty::Projection, ..)
+ if matches!(self.mode, CItemKind::Definition) =>
+ {
FfiSafe
}
ty::Param(..)
- | ty::Projection(..)
+ | ty::Alias(ty::Projection, ..)
| ty::Infer(..)
| ty::Bound(..)
| ty::Error(_)
return ControlFlow::CONTINUE;
}
- if let ty::Opaque(..) = ty.kind() {
+ if let ty::Alias(ty::Opaque, ..) = ty.kind() {
ControlFlow::Break(ty)
} else {
ty.super_visit_with(self)
if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
&& let ty = cx.typeck_results().expr_ty(&await_expr)
- && let ty::Opaque(future_def_id, _) = ty.kind()
+ && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
&& cx.tcx.ty_is_opaque_future(ty)
// FIXME: This also includes non-async fns that return `impl Future`.
&& let async_fn_def_id = cx.tcx.parent(*future_def_id)
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
}
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
- ty::Opaque(def, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
elaborate_predicates_with_span(
cx.tcx,
cx.tcx.explicit_item_bounds(def).iter().cloned(),
lhs_needs_parens
|| (followed_by_block
&& match &inner.kind {
- ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true,
+ ExprKind::Ret(_)
+ | ExprKind::Break(..)
+ | ExprKind::Yield(..)
+ | ExprKind::Yeet(..) => true,
ExprKind::Range(_lhs, Some(rhs), _limits) => {
matches!(rhs.kind, ExprKind::Block(..))
}
}
impl EarlyLintPass for UnusedParens {
+ #[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
match e.kind {
ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
}
+ #[inline]
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
<Self as UnusedDelimLint>::check_expr(self, cx, e);
fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
if let ast::UseTreeKind::Nested(ref items) = use_tree.kind {
// Recursively check nested UseTrees
- for &(ref tree, _) in items {
+ for (tree, _) in items {
self.check_use_tree(cx, tree, item);
}
declare_lint! {
/// The `trivial_casts` lint detects trivial casts which could be replaced
- /// with coercion, which may require [type ascription] or a temporary
- /// variable.
+ /// with coercion, which may require a temporary variable.
///
/// ### Example
///
/// with FFI interfaces or complex type aliases, where it triggers
/// incorrectly, or in situations where it will be more difficult to
/// clearly express the intent. It may be possible that this will become a
- /// warning in the future, possibly with [type ascription] providing a
- /// convenient way to work around the current issues. See [RFC 401] for
- /// historical context.
- ///
- /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
- /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+ /// warning in the future, possibly with an explicit syntax for coercions
+ /// providing a convenient way to work around the current issues.
+ /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+ /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+ ///
+ /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+ /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+ /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
pub TRIVIAL_CASTS,
Allow,
"detects trivial casts which could be removed"
/// with FFI interfaces or complex type aliases, where it triggers
/// incorrectly, or in situations where it will be more difficult to
/// clearly express the intent. It may be possible that this will become a
- /// warning in the future, possibly with [type ascription] providing a
- /// convenient way to work around the current issues. See [RFC 401] for
- /// historical context.
- ///
- /// [type ascription]: https://github.com/rust-lang/rust/issues/23416
- /// [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+ /// warning in the future, possibly with an explicit syntax for coercions
+ /// providing a convenient way to work around the current issues.
+ /// See [RFC 401 (coercions)][rfc-401], [RFC 803 (type ascription)][rfc-803] and
+ /// [RFC 3307 (remove type ascription)][rfc-3307] for historical context.
+ ///
+ /// [rfc-401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
+ /// [rfc-803]: https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md
+ /// [rfc-3307]: https://github.com/rust-lang/rfcs/blob/master/text/3307-de-rfc-type-ascription.md
pub TRIVIAL_NUMERIC_CASTS,
Allow,
"detects trivial casts of numeric types which could be removed"
};
}
+declare_lint! {
+ /// The `invalid_alignment` lint detects dereferences of misaligned pointers during
+ /// constant evluation.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![feature(const_ptr_read)]
+ /// const FOO: () = unsafe {
+ /// let x = &[0_u8; 4];
+ /// let y = x.as_ptr().cast::<u32>();
+ /// y.read(); // the address of a `u8` array is unknown and thus we don't know if
+ /// // it is aligned enough for reading a `u32`.
+ /// };
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// The compiler allowed dereferencing raw pointers irrespective of alignment
+ /// during const eval due to the const evaluator at the time not making it easy
+ /// or cheap to check. Now that it is both, this is not accepted anymore.
+ ///
+ /// Since it was undefined behaviour to begin with, this breakage does not violate
+ /// Rust's stability guarantees. Using undefined behaviour can cause arbitrary
+ /// behaviour, including failure to build.
+ ///
+ /// [future-incompatible]: ../index.md#future-incompatible-lints
+ pub INVALID_ALIGNMENT,
+ Deny,
+ "raw pointers must be aligned before dereferencing",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #68585 <https://github.com/rust-lang/rust/issues/104616>",
+ reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
+ };
+}
+
declare_lint! {
/// The `exported_private_dependencies` lint detects private dependencies
/// that are exposed in a public interface.
if !is_crossed {
cmd.arg("--system-libs");
- } else if target.contains("windows-gnu") {
- println!("cargo:rustc-link-lib=shell32");
- println!("cargo:rustc-link-lib=uuid");
- } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
- println!("cargo:rustc-link-lib=z");
- } else if target.starts_with("arm")
+ }
+
+ if (target.starts_with("arm") && !target.contains("freebsd"))
|| target.starts_with("mips-")
|| target.starts_with("mipsel-")
|| target.starts_with("powerpc-")
{
// 32-bit targets need to link libatomic.
println!("cargo:rustc-link-lib=atomic");
+ } else if target.contains("windows-gnu") {
+ println!("cargo:rustc-link-lib=shell32");
+ println!("cargo:rustc-link-lib=uuid");
+ } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
+ println!("cargo:rustc-link-lib=z");
}
cmd.args(&components);
case LLVMRustCodeModel::Large:
return CodeModel::Large;
case LLVMRustCodeModel::None:
+#if LLVM_VERSION_LT(16, 0)
return None;
+#else
+ return std::nullopt;
+#endif
default:
report_fatal_error("Bad CodeModel.");
}
}
extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
- return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None));
+ return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg,
+#if LLVM_VERSION_LT(16, 0)
+ None
+#else
+ std::nullopt
+#endif
+ ));
}
#if LLVM_VERSION_GE(15, 0)
#endif
switch (Kind) {
case LLVMRustChecksumKind::None:
+#if LLVM_VERSION_LT(16, 0)
return None;
+#else
+ return std::nullopt;
+#endif
case LLVMRustChecksumKind::MD5:
return DIFile::ChecksumKind::CSK_MD5;
case LLVMRustChecksumKind::SHA1:
extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
- OperandBundleDef *Bundle) {
+ OperandBundleDef **OpBundles,
+ unsigned NumOpBundles) {
Value *Callee = unwrap(Fn);
FunctionType *FTy = unwrap<FunctionType>(Ty);
- unsigned Len = Bundle ? 1 : 0;
- ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
return wrap(unwrap(B)->CreateCall(
- FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
+ FTy, Callee, makeArrayRef(unwrap(Args), NumArgs),
+ makeArrayRef(*OpBundles, NumOpBundles)));
}
extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
- OperandBundleDef *Bundle, const char *Name) {
+ OperandBundleDef **OpBundles, unsigned NumOpBundles,
+ const char *Name) {
Value *Callee = unwrap(Fn);
FunctionType *FTy = unwrap<FunctionType>(Ty);
- unsigned Len = Bundle ? 1 : 0;
- ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
makeArrayRef(unwrap(Args), NumArgs),
- Bundles, Name));
+ makeArrayRef(*OpBundles, NumOpBundles),
+ Name));
}
extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
// If we're not in a "rustc_" crate, bail.
- let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+ let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
let slug_name = slug.segments.first()?.ident.to_string();
if !slug_name.starts_with(slug_prefix) {
}
}
(Meta::Path(_), "subdiagnostic") => {
- return Ok(quote! { #diag.subdiagnostic(#binding); });
+ if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
+ let DiagnosticDeriveKind::Diagnostic { handler } = &self.parent.kind else {
+ // No eager translation for lints.
+ return Ok(quote! { #diag.subdiagnostic(#binding); });
+ };
+ return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+ } else {
+ return Ok(quote! { #diag.subdiagnostic(#binding); });
+ }
}
- (Meta::NameValue(_), "subdiagnostic") => {
+ (Meta::List(_), "subdiagnostic") => {
throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+ diag.help("`subdiagnostic` does not support nested attributes")
})
}
- (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
- if nested.len() != 1 {
- throw_invalid_attr!(attr, &meta, |diag| {
- diag.help(
- "`eager` is the only supported nested attribute for `subdiagnostic`",
- )
- })
- }
-
- let handler = match &self.parent.kind {
- DiagnosticDeriveKind::Diagnostic { handler } => handler,
- DiagnosticDeriveKind::LintDiagnostic => {
- throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("eager subdiagnostics are not supported on lints")
- })
- }
- };
-
- let nested_attr = nested.first().expect("pop failed for single element list");
- match nested_attr {
- NestedMeta::Meta(meta @ Meta::Path(_))
- if meta.path().segments.last().unwrap().ident.to_string().as_str()
- == "eager" =>
- {
- return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
- }
- _ => {
- throw_invalid_nested_attr!(attr, nested_attr, |diag| {
- diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
- })
- }
- }
- }
_ => (),
}
//! Validates all used crates and extern libraries and loads their metadata
use crate::errors::{
- AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
- GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler,
- NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime,
- ProfilerBuiltinsNeedsCore,
+ ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
+ GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
+ NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
};
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
use rustc_ast::{self as ast, *};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
use rustc_expand::base::SyntaxExtension;
use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
pub struct CrateLoader<'a> {
// Immutable configuration.
sess: &'a Session,
- metadata_loader: Box<MetadataLoaderDyn>,
+ metadata_loader: &'a MetadataLoaderDyn,
+ definitions: ReadGuard<'a, Definitions>,
local_crate_name: Symbol,
// Mutable output.
- cstore: CStore,
- used_extern_options: FxHashSet<Symbol>,
+ cstore: &'a mut CStore,
+ used_extern_options: &'a mut FxHashSet<Symbol>,
}
pub enum LoadedMacro {
);
}
}
+
+ pub fn new(sess: &Session) -> CStore {
+ let mut stable_crate_ids = FxHashMap::default();
+ stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+ CStore {
+ // We add an empty entry for LOCAL_CRATE (which maps to zero) in
+ // order to make array indices in `metas` match with the
+ // corresponding `CrateNum`. This first entry will always remain
+ // `None`.
+ metas: IndexVec::from_elem_n(None, 1),
+ injected_panic_runtime: None,
+ allocator_kind: None,
+ alloc_error_handler_kind: None,
+ has_global_allocator: false,
+ has_alloc_error_handler: false,
+ stable_crate_ids,
+ unused_externs: Vec::new(),
+ }
+ }
}
impl<'a> CrateLoader<'a> {
pub fn new(
sess: &'a Session,
- metadata_loader: Box<MetadataLoaderDyn>,
- local_crate_name: &str,
+ metadata_loader: &'a MetadataLoaderDyn,
+ local_crate_name: Symbol,
+ cstore: &'a mut CStore,
+ definitions: ReadGuard<'a, Definitions>,
+ used_extern_options: &'a mut FxHashSet<Symbol>,
) -> Self {
- let mut stable_crate_ids = FxHashMap::default();
- stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
-
CrateLoader {
sess,
metadata_loader,
- local_crate_name: Symbol::intern(local_crate_name),
- cstore: CStore {
- // We add an empty entry for LOCAL_CRATE (which maps to zero) in
- // order to make array indices in `metas` match with the
- // corresponding `CrateNum`. This first entry will always remain
- // `None`.
- metas: IndexVec::from_elem_n(None, 1),
- injected_panic_runtime: None,
- allocator_kind: None,
- alloc_error_handler_kind: None,
- has_global_allocator: false,
- has_alloc_error_handler: false,
- stable_crate_ids,
- unused_externs: Vec::new(),
- },
- used_extern_options: Default::default(),
+ local_crate_name,
+ cstore,
+ used_extern_options,
+ definitions,
}
}
-
pub fn cstore(&self) -> &CStore {
&self.cstore
}
- pub fn into_cstore(self) -> CStore {
- self.cstore
- }
-
fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
for (cnum, data) in self.cstore.iter_crate_data() {
if data.name() != name {
} else {
// The alloc crate provides a default allocation error handler if
// one isn't specified.
- if !self.sess.features_untracked().default_alloc_error_handler {
- self.sess.emit_err(AllocFuncRequired);
- self.sess.emit_note(MissingAllocErrorHandler);
- }
self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
}
}
pub fn process_extern_crate(
&mut self,
item: &ast::Item,
- definitions: &Definitions,
def_id: LocalDefId,
) -> Option<CrateNum> {
match item.kind {
);
let name = match orig_name {
Some(orig_name) => {
- validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
+ validate_crate_name(self.sess, orig_name, Some(item.span));
orig_name
}
None => item.ident.name,
let cnum = self.resolve_crate(name, item.span, dep_kind)?;
- let path_len = definitions.def_path(def_id).data.len();
+ let path_len = self.definitions.def_path(def_id).data.len();
self.update_extern_crate(
cnum,
ExternCrate {
#[diag(metadata_global_alloc_required)]
pub struct GlobalAllocRequired;
-#[derive(Diagnostic)]
-#[diag(metadata_alloc_func_required)]
-pub struct AllocFuncRequired;
-
-#[derive(Diagnostic)]
-#[diag(metadata_missing_alloc_error_handler)]
-pub struct MissingAllocErrorHandler;
-
#[derive(Diagnostic)]
#[diag(metadata_no_transitive_needs_dep)]
pub struct NoTransitiveNeedsDep<'a> {
.unwrap_or(MetadataKind::None);
let crate_name = tcx.crate_name(LOCAL_CRATE);
- let out_filename =
- filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(()));
+ let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
// To avoid races with another rustc process scanning the output directory,
// we need to write the file somewhere else and atomically move it to its
// final destination, with an `fs::rename` call. In order for the rename to
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
{
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
- if let rustc_span::FileName::Real(ref mut old_name) = name {
- if let rustc_span::RealFileName::LocalPath(local) = old_name {
- if let Ok(rest) = local.strip_prefix(real_dir) {
- *old_name = rustc_span::RealFileName::Remapped {
- local_path: None,
- virtual_name: virtual_dir.join(rest),
- };
+ for subdir in ["library", "compiler"] {
+ if let rustc_span::FileName::Real(ref mut old_name) = name {
+ if let rustc_span::RealFileName::LocalPath(local) = old_name {
+ if let Ok(rest) = local.strip_prefix(real_dir.join(subdir)) {
+ *old_name = rustc_span::RealFileName::Remapped {
+ local_path: None,
+ virtual_name: virtual_dir.join(subdir).join(rest),
+ };
+ }
}
}
}
fn as_any(&self) -> &dyn Any {
self
}
+ fn untracked_as_any(&mut self) -> &mut dyn Any {
+ self
+ }
fn crate_name(&self, cnum: CrateNum) -> Symbol {
self.get_crate_data(cnum).root.name
// associated types.
tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Projection(data) = ty.kind()
- && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ && let ty::Alias(ty::Projection, data) = ty.kind()
+ && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
{
true
} else {
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
- let ast_item = tcx.hir().expect_trait_item(def_id.expect_local());
- self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
+ let impl_defaultness = tcx.impl_defaultness(def_id.expect_local());
+ self.tables.impl_defaultness.set(def_id.index, impl_defaultness);
let trait_item = tcx.associated_item(def_id);
self.tables.assoc_container.set(def_id.index, trait_item.container);
match trait_item.kind {
ty::AssocKind::Const => {}
ty::AssocKind::Fn => {
- let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
- match *m {
- hir::TraitFn::Required(ref names) => {
- record_array!(self.tables.fn_arg_names[def_id] <- *names)
- }
- hir::TraitFn::Provided(body) => {
- record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
- }
- };
- self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
+ record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
+ self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id));
self.tables.constness.set(def_id.index, hir::Constness::NotConst);
}
ty::AssocKind::Type => {
// the assumption that they are numbered 1 to n.
// FIXME (#2166): This is not nearly enough to support correct versioning
// but is enough to get transitive crate dependencies working.
- self.lazy_array(deps.iter().map(|&(_, ref dep)| dep))
+ self.lazy_array(deps.iter().map(|(_, dep)| dep))
}
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
self.lazy_array(
exported_symbols
.iter()
- .filter(|&&(ref exported_symbol, _)| match *exported_symbol {
+ .filter(|&(exported_symbol, _)| match *exported_symbol {
ExportedSymbol::NoDefId(symbol_name) => symbol_name != metadata_symbol_name,
_ => true,
})
use rustc_serialize::opaque::FileEncoder;
use rustc_serialize::Encoder as _;
use rustc_span::hygiene::MacroKind;
-use std::convert::TryInto;
use std::marker::PhantomData;
use std::num::NonZeroUsize;
// Interned types
[] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
[] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
- [] consts: rustc_middle::ty::ConstS<'tcx>,
+ [] consts: rustc_middle::ty::ConstData<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
// since we need to allocate this type on both the `rustc_hir` arena
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
use rustc_target::spec::abi::Abi;
#[inline]
.filter_map(|(def_id, info)| {
let _ = info.as_owner()?;
let def_path_hash = definitions.def_path_hash(def_id);
- let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
+ let span = tcx.source_span(def_id);
debug_assert_eq!(span.parent(), None);
Some((def_path_hash, span))
})
providers.hir_attrs = |tcx, id| {
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
};
- providers.source_span =
- |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
providers.def_span = |tcx, def_id| {
let def_id = def_id.expect_local();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
/// The `#[target_feature(enable = "...")]` attribute and the enabled
/// features (only enabled features are supported right now).
pub target_features: Vec<Symbol>,
- /// The `#[linkage = "..."]` attribute and the value we found.
+ /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
pub linkage: Option<Linkage>,
+ /// The `#[linkage = "..."]` attribute on foreign items and the value we found.
+ pub import_linkage: Option<Linkage>,
/// The `#[link_section = "..."]` attribute, or what executable section this
/// should be placed in.
pub link_section: Option<Symbol>,
link_ordinal: None,
target_features: vec![],
linkage: None,
+ import_linkage: None,
link_section: None,
no_sanitize: SanitizerSet::empty(),
instruction_set: None,
use rustc_macros::HashStable;
use rustc_span::Symbol;
-use std::cmp::Ord;
use std::fmt::{self, Debug, Formatter};
rustc_index::newtype_index! {
mod queries;
mod value;
-use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::io::{Read, Write};
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
-use std::convert::{TryFrom, TryInto};
use std::fmt;
////////////////////////////////////////////////////////////////////////////////
-use std::convert::{TryFrom, TryInto};
use std::fmt;
use either::{Either, Left, Right};
use either::Either;
use std::borrow::Cow;
-use std::convert::TryInto;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::ops::{ControlFlow, Index, IndexMut};
use std::{iter, mem};
};
injection_phase > self.phase
}
+
+ #[inline]
+ pub fn is_custom_mir(&self) -> bool {
+ self.injection_phase.is_some()
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
///////////////////////////////////////////////////////////////////////////
// Places
-impl<V, T> ProjectionElem<V, T> {
+impl<V, T, U> ProjectionElem<V, T, U> {
/// Returns `true` if the target of this projection may refer to a different region of memory
/// than the base.
fn is_indirect(&self) -> bool {
/// Alias for projections as they appear in `UserTypeProjection`, where we
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
-pub type ProjectionKind = ProjectionElem<(), ()>;
+pub type ProjectionKind = ProjectionElem<(), (), ()>;
rustc_index::newtype_index! {
/// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]
pub fn function_handle(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- substs: SubstsRef<'tcx>,
+ substs: impl IntoIterator<Item = GenericArg<'tcx>>,
span: Span,
) -> Self {
let ty = tcx.mk_fn_def(def_id, substs);
MonoItem::GlobalAsm(..) => LOCAL_CRATE,
}
}
+
+ /// Returns the item's `DefId`
+ pub fn def_id(&self) -> DefId {
+ match *self {
+ MonoItem::Fn(Instance { def, .. }) => def.def_id(),
+ MonoItem::Static(def_id) => def_id,
+ MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
+ }
+ }
}
impl<'tcx> fmt::Display for MonoItem<'tcx> {
use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection};
use crate::mir::coverage::{CodeRegion, CoverageKind};
+use crate::traits::Reveal;
use crate::ty::adjustment::PointerCast;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, List, Ty};
MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
}
}
+
+ pub fn reveal(&self) -> Reveal {
+ match *self {
+ MirPhase::Built | MirPhase::Analysis(_) => Reveal::UserFacing,
+ MirPhase::Runtime(_) => Reveal::All,
+ }
+ }
}
/// See [`MirPhase::Analysis`].
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub enum RetagKind {
- /// The initial retag when entering a function.
+ /// The initial retag of arguments when entering a function.
FnEntry,
/// Retag preparing for a two-phase borrow.
TwoPhase,
SwitchInt {
/// The discriminant value being tested.
discr: Operand<'tcx>,
-
- /// The type of value being tested.
- /// This is always the same as the type of `discr`.
- /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
- switch_ty: Ty<'tcx>,
-
targets: SwitchTargets,
},
pub projection: &'tcx List<PlaceElem<'tcx>>,
}
+/// The different kinds of projections that can be used in the projection of a `Place`.
+///
+/// `T1` is the generic type for a field projection. For an actual projection on a `Place`
+/// this parameter will always be `Ty`, but the field type can be unavailable when
+/// building (by using `PlaceBuilder`) places that correspond to upvars.
+/// `T2` is the generic type for an `OpaqueCast` (is generic since it's abstracted over
+/// in dataflow analysis, see `AbstractElem`).
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
-pub enum ProjectionElem<V, T> {
+pub enum ProjectionElem<V, T1, T2> {
Deref,
- Field(Field, T),
+ Field(Field, T1),
/// Index into a slice/array.
///
/// Note that this does not also dereference, and so it does not exactly correspond to slice
/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
- OpaqueCast(T),
+ OpaqueCast(T2),
}
/// Alias for projections as they appear in places, where the base is a place
/// and the index is a local.
-pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
+pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>;
+
+/// Alias for projections that appear in `PlaceBuilder::Upvar`, for which
+/// we cannot provide any field types.
+pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>;
+
+impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> {
+ fn from(elem: PlaceElem<'tcx>) -> Self {
+ match elem {
+ ProjectionElem::Deref => ProjectionElem::Deref,
+ ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()),
+ ProjectionElem::Index(v) => ProjectionElem::Index(v),
+ ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+ ProjectionElem::ConstantIndex { offset, min_length, from_end }
+ }
+ ProjectionElem::Subslice { from, to, from_end } => {
+ ProjectionElem::Subslice { from, to, from_end }
+ }
+ ProjectionElem::Downcast(opt_sym, variant_idx) => {
+ ProjectionElem::Downcast(opt_sym, variant_idx)
+ }
+ ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
+ }
+ }
+}
///////////////////////////////////////////////////////////////////////////
// Operands
/// `place_ty.field_ty(tcx, f)` computes the type at a given field
/// of a record or enum-variant. (Most clients of `PlaceTy` can
/// instead just extract the relevant type directly from their
- /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
- /// not carry a `Ty` for `T`.)
+ /// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do
+ /// not carry a `Ty` for `T1` or `T2`.)
///
/// Note that the resulting type has not been normalized.
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
/// `Ty` or downcast variant corresponding to that projection.
/// The `handle_field` callback must map a `Field` to its `Ty`,
/// (which should be trivial when `T` = `Ty`).
- pub fn projection_ty_core<V, T>(
+ pub fn projection_ty_core<V, T1, T2>(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- elem: &ProjectionElem<V, T>,
- mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
- mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
+ elem: &ProjectionElem<V, T1, T2>,
+ mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>,
+ mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>,
) -> PlaceTy<'tcx>
where
V: ::std::fmt::Debug,
- T: ::std::fmt::Debug + Copy,
+ T1: ::std::fmt::Debug + Copy,
+ T2: ::std::fmt::Debug + Copy,
{
if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
bug!("cannot use non field projection on downcasted place")
{
match self {
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
- &Operand::Constant(ref c) => c.literal.ty(),
+ Operand::Constant(c) => c.literal.ty(),
}
}
}
-use crate::mir;
-use crate::mir::interpret::Scalar;
-use crate::ty::{self, Ty, TyCtxt};
use smallvec::{smallvec, SmallVec};
use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
}
impl<'tcx> TerminatorKind<'tcx> {
- pub fn if_(
- tcx: TyCtxt<'tcx>,
- cond: Operand<'tcx>,
- t: BasicBlock,
- f: BasicBlock,
- ) -> TerminatorKind<'tcx> {
- TerminatorKind::SwitchInt {
- discr: cond,
- switch_ty: tcx.types.bool,
- targets: SwitchTargets::static_if(0, f, t),
- }
+ pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
+ TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
}
pub fn successors(&self) -> Successors<'_> {
}
}
- pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> {
+ pub fn as_switch(&self) -> Option<(&Operand<'tcx>, &SwitchTargets)> {
match self {
- TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
- Some((discr, *switch_ty, targets))
- }
+ TerminatorKind::SwitchInt { discr, targets } => Some((discr, targets)),
_ => None,
}
}
match *self {
Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
- SwitchInt { ref targets, switch_ty, .. } => ty::tls::with(|tcx| {
- let param_env = ty::ParamEnv::empty();
- let switch_ty = tcx.lift(switch_ty).unwrap();
- let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
- targets
- .values
- .iter()
- .map(|&u| {
- mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
- .to_string()
- .into()
- })
- .chain(iter::once("otherwise".into()))
- .collect()
- }),
+ SwitchInt { ref targets, .. } => targets
+ .values
+ .iter()
+ .map(|&u| Cow::Owned(u.to_string()))
+ .chain(iter::once("otherwise".into()))
+ .collect(),
Call { target: Some(_), cleanup: Some(_), .. } => {
vec!["return".into(), "unwind".into()]
}
TerminatorKind::SwitchInt {
discr,
- switch_ty,
targets: _
} => {
self.visit_operand(discr, location);
- self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location));
}
TerminatorKind::Drop {
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
- type CacheSelector = DefaultCacheSelector<Self>;
+ // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`,
+ // it would be reasonable to use associated type defaults, to remove the duplication...
+ //
+ // ...But r-a doesn't support them yet and using a default here causes r-a to not infer
+ // return types of queries which is very annoying. Thus, until r-a support associated
+ // type defaults, plese restrain from using them here <3
+ //
+ // r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
+ type CacheSelector;
/// Given an instance of this key, what crate is it referring to?
/// This is used to find the provider.
}
impl Key for () {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for ty::InstanceDef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for ty::Instance<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for DefId {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.krate == LOCAL_CRATE
}
impl Key for ty::WithOptConstParam<LocalDefId> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for SimplifiedType {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for (DefId, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for (DefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl Key for (LocalDefId, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for (LocalDefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for (DefId, Option<Ident>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl Key for (DefId, LocalDefId, Ident) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl Key for (CrateNum, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
}
impl Key for (CrateNum, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
}
impl Key for (DefId, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl<'tcx> Key for SubstsRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
}
impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE
}
impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.1.def_id().krate == LOCAL_CRATE
}
impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
}
impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
}
impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.def_id().krate == LOCAL_CRATE
}
impl<'tcx> Key for GenericArg<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for mir::ConstantKind<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for ty::Const<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for Ty<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for TyAndLayout<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for ty::ParamEnv<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.value.query_crate_is_local()
}
impl Key for Symbol {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for Option<Symbol> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for (Symbol, u32, u32) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
}
impl Key for HirId {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
/// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
/// of rustc_middle::hir::source_map.
query source_span(key: LocalDefId) -> Span {
+ // Accesses untracked data
+ eval_always
desc { "getting the source span" }
}
TupleElem,
/// This is the trait reference from the given projection.
- ProjectionWf(ty::ProjectionTy<'tcx>),
+ ProjectionWf(ty::AliasTy<'tcx>),
/// Must satisfy all of the where-clause predicates of the
/// given item.
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_span::source_map::Span;
-use std::iter::FromIterator;
pub mod type_op {
use crate::ty::fold::TypeFoldable;
}
}
-pub type CanonicalProjectionGoal<'tcx> =
- Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
- RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+ RegionSubProjection(ty::Region<'tcx>, ty::AliasTy<'tcx>),
RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
}
.find(|m| m.kind == ty::AssocKind::Fn)
.unwrap()
.def_id;
- tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, []))
+ tcx.mk_fn_def(method_def_id, [source])
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
fn decode(decoder: &mut D) -> Self {
- let consts: ty::ConstS<'tcx> = Decodable::decode(decoder);
+ let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
decoder.interner().mk_const(consts.kind, consts.ty)
}
}
pub use kind::*;
pub use valtree::*;
-/// Use this rather than `ConstS`, whenever possible.
+/// Use this rather than `ConstData, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_pass_by_value]
-pub struct Const<'tcx>(pub Interned<'tcx, ConstS<'tcx>>);
+pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
impl<'tcx> fmt::Debug for Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Typed constant value.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
-pub struct ConstS<'tcx> {
+pub struct ConstData<'tcx> {
pub ty: Ty<'tcx>,
pub kind: ConstKind<'tcx>,
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstS<'_>, 40);
+static_assert_size!(ConstData<'_>, 40);
impl<'tcx> Const<'tcx> {
#[inline]
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
-use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::num::NonZeroU8;
-use std::convert::TryInto;
-
use super::Const;
use crate::mir;
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::hir::place::Place as HirPlace;
-use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_lifetime;
use crate::traits;
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
- self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
- ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
- GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
- PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
- RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
+ FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+ ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
+ ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
Visibility,
};
-use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
-use rustc_data_structures::unord::UnordSet;
-use rustc_data_structures::vec_map::VecMap;
+use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
-use rustc_hir::hir_id::OwnerId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
- Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
- Node, TraitCandidate, TraitItemKind,
+ Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
};
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
-use rustc_middle::mir::FakeReadCause;
use rustc_query_system::dep_graph::DepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{CrateType, OutputFilenames};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::{CrateStoreDyn, Untracked};
use rustc_session::lint::Lint;
use rustc_session::Limit;
use rustc_session::Session;
use std::any::Any;
use std::borrow::Borrow;
use std::cmp::Ordering;
-use std::collections::hash_map::{self, Entry};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::ops::{Bound, Deref};
use std::sync::Arc;
-use super::{ImplPolarity, RvalueScopes};
-
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
type ListTy = &'tcx List<Ty<'tcx>>;
- type ProjectionTy = ty::ProjectionTy<'tcx>;
+ type AliasTy = ty::AliasTy<'tcx>;
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderType = ty::PlaceholderType;
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
- const_: InternedSet<'tcx, ConstS<'tcx>>,
+ const_: InternedSet<'tcx, ConstData<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
/// Interns a type.
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
- fn intern_ty(
- &self,
- kind: TyKind<'tcx>,
- sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
- ) -> Ty<'tcx> {
+ fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
Ty(Interned::new_unchecked(
self.type_
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
- let stable_hash =
- self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+ let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
internee: kind,
&self,
flags: &ty::flags::FlagComputation,
sess: &'a Session,
- definitions: &'a rustc_hir::definitions::Definitions,
- cstore: &'a CrateStoreDyn,
- source_span: &'a IndexVec<LocalDefId, Span>,
+ untracked: &'a Untracked,
val: &T,
) -> Fingerprint {
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
Fingerprint::ZERO
} else {
let mut hasher = StableHasher::new();
- let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span);
+ let mut hcx = StableHashingContext::new(sess, untracked);
val.hash_stable(&mut hcx, &mut hasher);
hasher.finish()
}
&self,
kind: Binder<'tcx, PredicateKind<'tcx>>,
sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
+ untracked: &Untracked,
) -> Predicate<'tcx> {
Predicate(Interned::new_unchecked(
self.predicate
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_predicate(kind);
- let stable_hash =
- self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+ let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
internee: kind,
pub unit: Const<'tcx>,
}
-pub struct LocalTableInContext<'a, V> {
- hir_owner: OwnerId,
- data: &'a ItemLocalMap<V>,
-}
-
-/// Validate that the given HirId (respectively its `local_id` part) can be
-/// safely used as a key in the maps of a TypeckResults. For that to be
-/// the case, the HirId must have the same `owner` as all the other IDs in
-/// this table (signified by `hir_owner`). Otherwise the HirId
-/// would be in a different frame of reference and using its `local_id`
-/// would result in lookup errors, or worse, in silently wrong data being
-/// stored/returned.
-#[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
- if hir_id.owner != hir_owner {
- invalid_hir_id_for_typeck_results(hir_owner, hir_id);
- }
-}
-
-#[cold]
-#[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
- ty::tls::with(|tcx| {
- bug!(
- "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
- tcx.hir().node_to_string(hir_id),
- hir_id.owner,
- hir_owner
- )
- });
-}
-
-impl<'a, V> LocalTableInContext<'a, V> {
- pub fn contains_key(&self, id: hir::HirId) -> bool {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.contains_key(&id.local_id)
- }
-
- pub fn get(&self, id: hir::HirId) -> Option<&V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.get(&id.local_id)
- }
-
- pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
- self.data.iter()
- }
-}
-
-impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
- type Output = V;
-
- fn index(&self, key: hir::HirId) -> &V {
- self.get(key).expect("LocalTableInContext: key not found")
- }
-}
-
-pub struct LocalTableInContextMut<'a, V> {
- hir_owner: OwnerId,
- data: &'a mut ItemLocalMap<V>,
-}
-
-impl<'a, V> LocalTableInContextMut<'a, V> {
- pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.get_mut(&id.local_id)
- }
-
- pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.entry(id.local_id)
- }
-
- pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.insert(id.local_id, val)
- }
-
- pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.remove(&id.local_id)
- }
-}
-
-/// Whenever a value may be live across a generator yield, the type of that value winds up in the
-/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
-/// captured types that can be useful for diagnostics. In particular, it stores the span that
-/// caused a given type to be recorded, along with the scope that enclosed the value (which can
-/// be used to find the await that the value is live across).
-///
-/// For example:
-///
-/// ```ignore (pseudo-Rust)
-/// async move {
-/// let x: T = expr;
-/// foo.await
-/// ...
-/// }
-/// ```
-///
-/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
-/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct GeneratorInteriorTypeCause<'tcx> {
- /// Type of the captured binding.
- pub ty: Ty<'tcx>,
- /// Span of the binding that was captured.
- pub span: Span,
- /// Span of the scope of the captured binding.
- pub scope_span: Option<Span>,
- /// Span of `.await` or `yield` expression.
- pub yield_span: Span,
- /// Expr which the type evaluated from.
- pub expr: Option<hir::HirId>,
-}
-
-// This type holds diagnostic information on generators and async functions across crate boundaries
-// and is used to provide better error messages
-#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
-pub struct GeneratorDiagnosticData<'tcx> {
- pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
- pub hir_owner: DefId,
- pub nodes_types: ItemLocalMap<Ty<'tcx>>,
- pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-}
-
-#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
-pub struct TypeckResults<'tcx> {
- /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
- pub hir_owner: OwnerId,
-
- /// Resolved definitions for `<T>::X` associated paths and
- /// method calls, including those of overloaded operators.
- type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
-
- /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
- /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
- /// about the field you also need definition of the variant to which the field
- /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
- field_indices: ItemLocalMap<usize>,
-
- /// Stores the types for various nodes in the AST. Note that this table
- /// is not guaranteed to be populated outside inference. See
- /// typeck::check::fn_ctxt for details.
- node_types: ItemLocalMap<Ty<'tcx>>,
-
- /// Stores the type parameters which were substituted to obtain the type
- /// of this node. This only applies to nodes that refer to entities
- /// parameterized by type parameters, such as generic fns, types, or
- /// other items.
- node_substs: ItemLocalMap<SubstsRef<'tcx>>,
-
- /// This will either store the canonicalized types provided by the user
- /// or the substitutions that the user explicitly gave (if any) attached
- /// to `id`. These will not include any inferred values. The canonical form
- /// is used to capture things like `_` or other unspecified values.
- ///
- /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
- /// canonical substitutions would include only `for<X> { Vec<X> }`.
- ///
- /// See also `AscribeUserType` statement in MIR.
- user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
-
- /// Stores the canonicalized types provided by the user. See also
- /// `AscribeUserType` statement in MIR.
- pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
-
- adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-
- /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
- pat_binding_modes: ItemLocalMap<BindingMode>,
-
- /// Stores the types which were implicitly dereferenced in pattern binding modes
- /// for later usage in THIR lowering. For example,
- ///
- /// ```
- /// match &&Some(5i32) {
- /// Some(n) => {},
- /// _ => {},
- /// }
- /// ```
- /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
- ///
- /// See:
- /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
- pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
-
- /// Records the reasons that we picked the kind of each closure;
- /// not all closures are present in the map.
- closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
-
- /// For each fn, records the "liberated" types of its arguments
- /// and return type. Liberated means that all bound regions
- /// (including late-bound regions) are replaced with free
- /// equivalents. This table is not used in codegen (since regions
- /// are erased there) and hence is not serialized to metadata.
- ///
- /// This table also contains the "revealed" values for any `impl Trait`
- /// that appear in the signature and whose values are being inferred
- /// by this function.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::fmt::Debug;
- /// fn foo(x: &u32) -> impl Debug { *x }
- /// ```
- ///
- /// The function signature here would be:
- ///
- /// ```ignore (illustrative)
- /// for<'a> fn(&'a u32) -> Foo
- /// ```
- ///
- /// where `Foo` is an opaque type created for this function.
- ///
- ///
- /// The *liberated* form of this would be
- ///
- /// ```ignore (illustrative)
- /// fn(&'a u32) -> u32
- /// ```
- ///
- /// Note that `'a` is not bound (it would be an `ReFree`) and
- /// that the `Foo` opaque type is replaced by its hidden type.
- liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
-
- /// For each FRU expression, record the normalized types of the fields
- /// of the struct - this is needed because it is non-trivial to
- /// normalize while preserving regions. This table is used only in
- /// MIR construction and hence is not serialized to metadata.
- fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
-
- /// For every coercion cast we add the HIR node ID of the cast
- /// expression to this set.
- coercion_casts: ItemLocalSet,
-
- /// Set of trait imports actually used in the method resolution.
- /// This is used for warning unused imports. During type
- /// checking, this `Lrc` should not be cloned: it must have a ref-count
- /// of 1 so that we can insert things into the set mutably.
- pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
-
- /// If any errors occurred while type-checking this body,
- /// this field will be set to `Some(ErrorGuaranteed)`.
- pub tainted_by_errors: Option<ErrorGuaranteed>,
-
- /// All the opaque types that have hidden types set
- /// by this function. We also store the
- /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
- /// even if they are only set in dead code (which doesn't show up in MIR).
- pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
-
- /// Tracks the minimum captures required for a closure;
- /// see `MinCaptureInformationMap` for more details.
- pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
-
- /// Tracks the fake reads required for a closure and the reason for the fake read.
- /// When performing pattern matching for closures, there are times we don't end up
- /// reading places that are mentioned in a closure (because of _ patterns). However,
- /// to ensure the places are initialized, we introduce fake reads.
- /// Consider these two examples:
- /// ``` (discriminant matching with only wildcard arm)
- /// let x: u8;
- /// let c = || match x { _ => () };
- /// ```
- /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
- /// want to capture it. However, we do still want an error here, because `x` should have
- /// to be initialized at the point where c is created. Therefore, we add a "fake read"
- /// instead.
- /// ``` (destructured assignments)
- /// let c = || {
- /// let (t1, t2) = t;
- /// }
- /// ```
- /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
- /// we never capture `t`. This becomes an issue when we build MIR as we require
- /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
- /// issue by fake reading `t`.
- pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
-
- /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
- /// by applying extended parameter rules.
- /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
- pub rvalue_scopes: RvalueScopes,
-
- /// Stores the type, expression, span and optional scope span of all types
- /// that are live across the yield of this generator (if a generator).
- pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-
- /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
- /// as `&[u8]`, depending on the pattern in which they are used.
- /// This hashset records all instances where we behave
- /// like this to allow `const_to_pat` to reliably handle this situation.
- pub treat_byte_string_as_slice: ItemLocalSet,
-
- /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
- /// on closure size.
- pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
-}
-
-impl<'tcx> TypeckResults<'tcx> {
- pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
- TypeckResults {
- hir_owner,
- type_dependent_defs: Default::default(),
- field_indices: Default::default(),
- user_provided_types: Default::default(),
- user_provided_sigs: Default::default(),
- node_types: Default::default(),
- node_substs: Default::default(),
- adjustments: Default::default(),
- pat_binding_modes: Default::default(),
- pat_adjustments: Default::default(),
- closure_kind_origins: Default::default(),
- liberated_fn_sigs: Default::default(),
- fru_field_types: Default::default(),
- coercion_casts: Default::default(),
- used_trait_imports: Lrc::new(Default::default()),
- tainted_by_errors: None,
- concrete_opaque_types: Default::default(),
- closure_min_captures: Default::default(),
- closure_fake_reads: Default::default(),
- rvalue_scopes: Default::default(),
- generator_interior_types: ty::Binder::dummy(Default::default()),
- treat_byte_string_as_slice: Default::default(),
- closure_size_eval: Default::default(),
- }
- }
-
- /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
- pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
- match *qpath {
- hir::QPath::Resolved(_, ref path) => path.res,
- hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
- .type_dependent_def(id)
- .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
- }
- }
-
- pub fn type_dependent_defs(
- &self,
- ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
- }
-
- pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
- }
-
- pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
- self.type_dependent_def(id).map(|(_, def_id)| def_id)
- }
-
- pub fn type_dependent_defs_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
- }
-
- pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
- }
-
- pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
- }
-
- pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
- }
-
- pub fn user_provided_types_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
- }
-
- pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
- }
-
- pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
- }
-
- pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
- let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
- vec.iter()
- .map(|item| {
- GeneratorInteriorTypeCause {
- ty: item.ty,
- span: item.span,
- scope_span: item.scope_span,
- yield_span: item.yield_span,
- expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
- }
- })
- .collect::<Vec<_>>()
- });
- GeneratorDiagnosticData {
- generator_interior_types: generator_interior_type,
- hir_owner: self.hir_owner.to_def_id(),
- nodes_types: self.node_types.clone(),
- adjustments: self.adjustments.clone(),
- }
- }
-
- pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
- self.node_type_opt(id).unwrap_or_else(|| {
- bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
- })
- }
-
- pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_types.get(&id.local_id).cloned()
- }
-
- pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
- }
-
- pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
- }
-
- pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_substs.get(&id.local_id).cloned()
- }
-
- /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
- /// doesn't provide type parameter substitutions.
- ///
- /// [`expr_ty`]: TypeckResults::expr_ty
- pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
- self.node_type(pat.hir_id)
- }
-
- /// Returns the type of an expression as a monotype.
- ///
- /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
- /// some cases, we insert `Adjustment` annotations such as auto-deref or
- /// auto-ref. The type returned by this function does not consider such
- /// adjustments. See `expr_ty_adjusted()` instead.
- ///
- /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
- /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
- /// instead of `fn(ty) -> T with T = isize`.
- pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
- self.node_type(expr.hir_id)
- }
-
- pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
- self.node_type_opt(expr.hir_id)
- }
-
- pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
- }
-
- pub fn adjustments_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
- }
-
- pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
- validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
- self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
- }
-
- /// Returns the type of `expr`, considering any `Adjustment`
- /// entry recorded for that expression.
- pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
- self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
- }
-
- pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
- self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
- }
-
- pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
- // Only paths and method calls/overloaded operators have
- // entries in type_dependent_defs, ignore the former here.
- if let hir::ExprKind::Path(_) = expr.kind {
- return false;
- }
-
- matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
- }
-
- pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
- self.pat_binding_modes().get(id).copied().or_else(|| {
- s.delay_span_bug(sp, "missing binding mode");
- None
- })
- }
-
- pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
- }
-
- pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
- }
-
- pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
- }
-
- pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
- }
-
- /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
- /// by the closure.
- pub fn closure_min_captures_flattened(
- &self,
- closure_def_id: LocalDefId,
- ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
- self.closure_min_captures
- .get(&closure_def_id)
- .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
- .into_iter()
- .flatten()
- }
-
- pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
- }
-
- pub fn closure_kind_origins_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
- }
-
- pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
- }
-
- pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
- }
-
- pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
- }
-
- pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
- }
-
- pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
- validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
- self.coercion_casts.contains(&hir_id.local_id)
- }
-
- pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
- self.coercion_casts.insert(id);
- }
-
- pub fn coercion_casts(&self) -> &ItemLocalSet {
- &self.coercion_casts
- }
-}
-
-rustc_index::newtype_index! {
- pub struct UserTypeAnnotationIndex {
- derive [HashStable]
- DEBUG_FORMAT = "UserType({})",
- const START_INDEX = 0,
- }
-}
-
-/// Mapping of type annotation indices to canonical user type annotations.
-pub type CanonicalUserTypeAnnotations<'tcx> =
- IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
-
-#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CanonicalUserTypeAnnotation<'tcx> {
- pub user_ty: Box<CanonicalUserType<'tcx>>,
- pub span: Span,
- pub inferred_ty: Ty<'tcx>,
-}
-
-/// Canonicalized user type annotation.
-pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
-
-impl<'tcx> CanonicalUserType<'tcx> {
- /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
- /// i.e., each thing is mapped to a canonical variable with the same index.
- pub fn is_identity(&self) -> bool {
- match self.value {
- UserType::Ty(_) => false,
- UserType::TypeOf(_, user_substs) => {
- if user_substs.user_self_ty.is_some() {
- return false;
- }
-
- iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
- match kind.unpack() {
- GenericArgKind::Type(ty) => match ty.kind() {
- ty::Bound(debruijn, b) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(*debruijn, ty::INNERMOST);
- cvar == b.var
- }
- _ => false,
- },
-
- GenericArgKind::Lifetime(r) => match *r {
- ty::ReLateBound(debruijn, br) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debruijn, ty::INNERMOST);
- cvar == br.var
- }
- _ => false,
- },
-
- GenericArgKind::Const(ct) => match ct.kind() {
- ty::ConstKind::Bound(debruijn, b) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debruijn, ty::INNERMOST);
- cvar == b
- }
- _ => false,
- },
- }
- })
- }
- }
- }
-}
-
-/// A user-given type annotation attached to a constant. These arise
-/// from constants that are named via paths, like `Foo::<A>::new` and
-/// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum UserType<'tcx> {
- Ty(Ty<'tcx>),
-
- /// The canonical type is the result of `type_of(def_id)` with the
- /// given substitutions applied.
- TypeOf(DefId, UserSubsts<'tcx>),
-}
-
impl<'tcx> CommonTypes<'tcx> {
fn new(
interners: &CtxtInterners<'tcx>,
sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
+ untracked: &Untracked,
) -> CommonTypes<'tcx> {
- let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore, source_span);
+ let mk = |ty| interners.intern_ty(ty, sess, untracked);
CommonTypes {
unit: mk(Tuple(List::empty())),
};
CommonConsts {
- unit: mk_const(ty::ConstS {
+ unit: mk_const(ty::ConstData {
kind: ty::ConstKind::Value(ty::ValTree::zst()),
ty: types.unit,
}),
/// Common consts, pre-interned for your convenience.
pub consts: CommonConsts<'tcx>,
- definitions: RwLock<Definitions>,
-
+ untracked: Untracked,
/// Output of the resolver.
pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
/// The entire crate as AST. This field serves as the input for the hir_crate query,
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
- definitions: Definitions,
untracked_resolutions: ty::ResolverGlobalCtxt,
+ untracked: Untracked,
krate: Lrc<ast::Crate>,
dep_graph: DepGraph,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
queries: &'tcx dyn query::QueryEngine<'tcx>,
query_kinds: &'tcx [DepKindStruct<'tcx>],
- crate_name: &str,
+ crate_name: Symbol,
output_filenames: OutputFilenames,
) -> GlobalCtxt<'tcx> {
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err);
});
let interners = CtxtInterners::new(arena);
- let common_types = CommonTypes::new(
- &interners,
- s,
- &definitions,
- &*untracked_resolutions.cstore,
- // This is only used to create a stable hashing context.
- &untracked_resolutions.source_span,
- );
+ let common_types = CommonTypes::new(&interners, s, &untracked);
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
hir_arena,
interners,
dep_graph,
- definitions: RwLock::new(definitions),
prof: s.prof.clone(),
types: common_types,
lifetimes: common_lifetimes,
consts: common_consts,
+ untracked,
untracked_resolutions,
untracked_crate: Steal::new(krate),
on_disk_cache,
pred_rcache: Default::default(),
selection_cache: Default::default(),
evaluation_cache: Default::default(),
- crate_name: Symbol::intern(crate_name),
+ crate_name,
data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()),
output_filenames: Arc::new(output_filenames),
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
} else {
- self.untracked_resolutions.cstore.def_key(id)
+ self.untracked.cstore.def_key(id)
}
}
if let Some(id) = id.as_local() {
self.definitions_untracked().def_path(id)
} else {
- self.untracked_resolutions.cstore.def_path(id)
+ self.untracked.cstore.def_path(id)
}
}
if let Some(def_id) = def_id.as_local() {
self.definitions_untracked().def_path_hash(def_id)
} else {
- self.untracked_resolutions.cstore.def_path_hash(def_id)
+ self.untracked.cstore.def_path_hash(def_id)
}
}
if crate_num == LOCAL_CRATE {
self.sess.local_stable_crate_id()
} else {
- self.untracked_resolutions.cstore.stable_crate_id(crate_num)
+ self.untracked.cstore.stable_crate_id(crate_num)
}
}
if stable_crate_id == self.sess.local_stable_crate_id() {
LOCAL_CRATE
} else {
- self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
}
}
// If this is a DefPathHash from the local crate, we can look up the
// DefId in the tcx's `Definitions`.
if stable_crate_id == self.sess.local_stable_crate_id() {
- self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
+ self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
} else {
// If this is a DefPathHash from an upstream crate, let the CrateStore map
// it to a DefId.
- let cstore = &*self.untracked_resolutions.cstore;
+ let cstore = &*self.untracked.cstore;
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
cstore.def_path_hash_to_def_id(cnum, hash)
}
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;
+ let cstore = &*self.untracked.cstore;
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
};
// This is fine because:
// - those queries are `eval_always` so we won't miss their result changing;
// - this write will have happened before these queries are called.
- let key = self.definitions.write().create_def(parent, data);
+ let key = self.untracked.definitions.write().create_def(parent, data);
let feed = TyCtxtFeed { tcx: self.tcx, key };
feed.def_span(self.span);
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
- let definitions = &self.definitions;
+ let definitions = &self.untracked.definitions;
std::iter::from_generator(|| {
let mut i = 0;
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
- let definitions = self.definitions.leak();
+ let definitions = self.untracked.definitions.leak();
definitions.def_path_table()
}
self.ensure().hir_crate(());
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
- let definitions = self.definitions.leak();
+ let definitions = self.untracked.definitions.leak();
definitions.def_path_hash_to_def_index_map()
}
/// 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_untracked(self) -> &'tcx CrateStoreDyn {
- &*self.untracked_resolutions.cstore
+ &*self.untracked.cstore
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
- self.definitions.read()
+ self.untracked.definitions.read()
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
- self.untracked_resolutions.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+ self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
}
#[inline(always)]
self,
f: impl FnOnce(StableHashingContext<'_>) -> R,
) -> R {
- let definitions = self.definitions_untracked();
- let hcx = StableHashingContext::new(
- self.sess,
- &*definitions,
- &*self.untracked_resolutions.cstore,
- &self.untracked_resolutions.source_span,
- );
- f(hcx)
+ f(StableHashingContext::new(self.sess, &self.untracked))
}
pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
Bound,
Param,
Infer,
- Projection,
- Opaque,
+ Alias,
Foreign
)?;
direct_interners! {
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
- const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>,
+ const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
/// Given a `ty`, return whether it's an `impl Future<...>`.
pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
- let ty::Opaque(def_id, _) = ty.kind() else { return false };
+ let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
self.interners.intern_ty(
st,
self.sess,
- &self.definitions.read(),
- &*self.untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
- &self.untracked_resolutions.source_span,
+ &self.untracked,
)
}
self.interners.intern_predicate(
binder,
self.sess,
- &self.definitions.read(),
- &*self.untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
- &self.untracked_resolutions.source_span,
+ &self.untracked,
)
}
}
#[inline]
- pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- debug_assert_eq!(
- self.generics_of(def_id).count(),
- substs.len(),
- "wrong number of generic parameters for {def_id:?}: {substs:?}",
- );
+ pub fn mk_fn_def(
+ self,
+ def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ let substs = self.check_substs(def_id, substs);
self.mk_ty(FnDef(def_id, substs))
}
+ #[inline(always)]
+ fn check_substs(
+ self,
+ _def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> SubstsRef<'tcx> {
+ let substs = substs.into_iter().map(Into::into);
+ #[cfg(debug_assertions)]
+ {
+ let n = self.generics_of(_def_id).count();
+ assert_eq!(
+ (n, Some(n)),
+ substs.size_hint(),
+ "wrong number of generic parameters for {_def_id:?}: {:?}",
+ substs.collect::<Vec<_>>(),
+ );
+ }
+ self.mk_substs(substs)
+ }
+
#[inline]
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
self.mk_ty(FnPtr(fty))
}
#[inline]
- pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- debug_assert_eq!(
- self.generics_of(item_def_id).count(),
- substs.len(),
- "wrong number of generic parameters for {item_def_id:?}: {substs:?}",
- );
- self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
+ pub fn mk_projection(
+ self,
+ item_def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
}
#[inline]
#[inline]
pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.mk_const_internal(ty::ConstS { kind: kind.into(), ty })
+ self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
}
#[inline]
#[inline]
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Opaque(def_id, substs))
+ self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
trait_def_id: DefId,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
- let substs = substs.into_iter().map(Into::into);
- let n = self.generics_of(trait_def_id).count();
- debug_assert_eq!(
- (n, Some(n)),
- substs.size_hint(),
- "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?",
- substs.collect::<Vec<_>>(),
- );
- let substs = self.mk_substs(substs);
- ty::TraitRef::new(trait_def_id, substs)
+ let substs = self.check_substs(trait_def_id, substs);
+ ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
+ }
+
+ pub fn mk_alias_ty(
+ self,
+ def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> ty::AliasTy<'tcx> {
+ let substs = self.check_substs(def_id, substs);
+ ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
}
pub fn mk_bound_variable_kinds<
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
};
+ providers.source_span =
+ |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
}
use std::ops::ControlFlow;
use crate::ty::{
- visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
+ visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
return ControlFlow::Break(());
}
- Opaque(did, _) => {
- let parent = self.tcx.parent(*did);
+ Alias(Opaque, AliasTy { def_id, .. }) => {
+ let parent = self.tcx.parent(*def_id);
if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
- && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
- && parent_did == did
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = self.tcx.type_of(parent).kind()
+ && parent_opaque_def_id == def_id
{
// Okay
} else {
}
}
- Dynamic(dty, _, _) => {
- for pred in *dty {
- match pred.skip_binder() {
- ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
- // Okay
- }
- _ => return ControlFlow::Break(()),
- }
- }
- }
-
Param(param) => {
// FIXME: It would be nice to make this not use string manipulation,
// but it's pretty hard to do this, since `ty::ParamTy` is missing
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
use hir::def::DefKind;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
),
RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
- report_maybe_different(
- f,
- &values.expected.sort_string(tcx),
- &values.found.sort_string(tcx),
- )
+ let (mut expected, mut found) = with_forced_trimmed_paths!((
+ values.expected.sort_string(tcx),
+ values.found.sort_string(tcx),
+ ));
+ if expected == found {
+ expected = values.expected.sort_string(tcx);
+ found = values.found.sort_string(tcx);
+ }
+ report_maybe_different(f, &expected, &found)
}),
Traits(values) => ty::tls::with(|tcx| {
+ let (mut expected, mut found) = with_forced_trimmed_paths!((
+ tcx.def_path_str(values.expected),
+ tcx.def_path_str(values.found),
+ ));
+ if expected == found {
+ expected = tcx.def_path_str(values.expected);
+ found = tcx.def_path_str(values.found);
+ }
report_maybe_different(
f,
- &format!("trait `{}`", tcx.def_path_str(values.expected)),
- &format!("trait `{}`", tcx.def_path_str(values.found)),
+ &format!("trait `{expected}`"),
+ &format!("trait `{found}`"),
)
}),
IntMismatch(ref values) => {
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
- ty::Projection(_) => "associated type".into(),
+ ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(p) => format!("type parameter `{}`", p).into(),
- ty::Opaque(..) => "opaque type".into(),
+ ty::Alias(ty::Opaque, ..) => "opaque type".into(),
ty::Error(_) => "type error".into(),
}
}
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
- ty::Projection(_) => "associated type".into(),
+ ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(_) => "type parameter".into(),
- ty::Opaque(..) => "opaque type".into(),
+ ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
}
}
diag.note("no two closures, even if identical, have the same type");
diag.help("consider boxing your closure and/or using it as a trait object");
}
- (ty::Opaque(..), ty::Opaque(..)) => {
+ (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
// Issue #63167
diag.note("distinct uses of `impl Trait` result in different opaque types");
}
#traits-as-parameters",
);
}
- (ty::Projection(_), ty::Projection(_)) => {
+ (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
diag.note("an associated type was expected, but a different one was found");
}
- (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
- if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+ (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+ if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
{
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
let path =
self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
- let item_name = self.item_name(proj.item_def_id);
+ let item_name = self.item_name(proj.def_id);
let item_args = self.format_generic_args(assoc_substs);
let path = if path.ends_with('>') {
diag.note("you might be missing a type parameter or trait bound");
}
}
- (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
- | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
+ (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+ | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
if !sp.contains(p_span) {
diag.span_label(p_span, "this type parameter");
}
}
- (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+ (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
self.expected_projection(
diag,
proj_ty,
cause.code(),
);
}
- (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+ (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
diag: &mut Diagnostic,
msg: &str,
body_owner_def_id: DefId,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
- let assoc = self.associated_item(proj_ty.item_def_id);
+ let assoc = self.associated_item(proj_ty.def_id);
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
if let Some(hir_generics) = item.generics() {
fn expected_projection(
self,
diag: &mut Diagnostic,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
values: ExpectedFound<Ty<'tcx>>,
body_owner_def_id: DefId,
cause_code: &ObligationCauseCode<'_>,
);
let impl_comparison =
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
- let assoc = self.associated_item(proj_ty.item_def_id);
+ let assoc = self.associated_item(proj_ty.def_id);
if !callable_scope || impl_comparison {
// We do not want to suggest calling functions when the reason of the
// type error is a comparison of an `impl` with its `trait` or when the
diag,
assoc.container_id(self),
current_method_ident,
- proj_ty.item_def_id,
+ proj_ty.def_id,
values.expected,
);
// Possibly suggest constraining the associated type to conform to the
self,
diag: &mut Diagnostic,
msg: &str,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
- let assoc = self.associated_item(proj_ty.item_def_id);
- if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
+ let assoc = self.associated_item(proj_ty.def_id);
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
let opaque_local_def_id = def_id.as_local();
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
match &self.hir().expect_item(opaque_local_def_id).kind {
.filter_map(|(_, item)| {
let method = self.fn_sig(item.def_id);
match *method.output().skip_binder().kind() {
- ty::Projection(ty::ProjectionTy { item_def_id, .. })
+ ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
if item_def_id == proj_ty_item_def_id =>
{
Some((
}
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
- let length_limit = 50;
- let type_limit = 4;
+ let width = self.sess.diagnostic_width();
+ let length_limit = width.saturating_sub(30);
+ let mut type_limit = 50;
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
.pretty_print_type(ty)
.expect("could not write to `String`")
.into_buffer();
- if regular.len() <= length_limit {
+ if regular.len() <= width {
return (regular, None);
}
- let short = FmtPrinter::new_with_limit(
- self,
- hir::def::Namespace::TypeNS,
- rustc_session::Limit(type_limit),
- )
- .pretty_print_type(ty)
- .expect("could not write to `String`")
- .into_buffer();
+ let mut short;
+ loop {
+ // Look for the longest properly trimmed path that still fits in length_limit.
+ short = with_forced_trimmed_paths!(
+ FmtPrinter::new_with_limit(
+ self,
+ hir::def::Namespace::TypeNS,
+ rustc_session::Limit(type_limit),
+ )
+ .pretty_print_type(ty)
+ .expect("could not write to `String`")
+ .into_buffer()
+ );
+ if short.len() <= length_limit || type_limit == 0 {
+ break;
+ }
+ type_limit -= 1;
+ }
if regular == short {
return (regular, None);
}
use std::hash::Hash;
use std::iter;
-use self::SimplifiedTypeGen::*;
+use self::SimplifiedType::*;
-pub type SimplifiedType = SimplifiedTypeGen<DefId>;
-
-/// See `simplify_type`
-///
-/// Note that we keep this type generic over the type of identifier it uses
-/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
-/// keys (in which case we use a DefPathHash as id-type) but in the general case
-/// the non-stable but fast to construct DefId-version is the better choice.
+/// See `simplify_type`.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
-pub enum SimplifiedTypeGen<D>
-where
- D: Copy + Debug + Eq,
-{
+pub enum SimplifiedType {
BoolSimplifiedType,
CharSimplifiedType,
IntSimplifiedType(ty::IntTy),
UintSimplifiedType(ty::UintTy),
FloatSimplifiedType(ty::FloatTy),
- AdtSimplifiedType(D),
- ForeignSimplifiedType(D),
+ AdtSimplifiedType(DefId),
+ ForeignSimplifiedType(DefId),
StrSimplifiedType,
ArraySimplifiedType,
SliceSimplifiedType,
/// A trait object, all of whose components are markers
/// (e.g., `dyn Send + Sync`).
MarkerTraitObjectSimplifiedType,
- TraitSimplifiedType(D),
- ClosureSimplifiedType(D),
- GeneratorSimplifiedType(D),
+ TraitSimplifiedType(DefId),
+ ClosureSimplifiedType(DefId),
+ GeneratorSimplifiedType(DefId),
GeneratorWitnessSimplifiedType(usize),
FunctionSimplifiedType(usize),
PlaceholderSimplifiedType,
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
TreatParams::AsInfer => None,
},
- ty::Opaque(..) | ty::Projection(_) => match treat_params {
+ ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
//
}
}
-impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
- pub fn def(self) -> Option<D> {
+impl SimplifiedType {
+ pub fn def(self) -> Option<DefId> {
match self {
AdtSimplifiedType(d)
| ForeignSimplifiedType(d)
_ => None,
}
}
-
- pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
- where
- F: Fn(D) -> U,
- U: Copy + Debug + Eq,
- {
- match self {
- BoolSimplifiedType => BoolSimplifiedType,
- CharSimplifiedType => CharSimplifiedType,
- IntSimplifiedType(t) => IntSimplifiedType(t),
- UintSimplifiedType(t) => UintSimplifiedType(t),
- FloatSimplifiedType(t) => FloatSimplifiedType(t),
- AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
- ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)),
- StrSimplifiedType => StrSimplifiedType,
- ArraySimplifiedType => ArraySimplifiedType,
- SliceSimplifiedType => SliceSimplifiedType,
- RefSimplifiedType(m) => RefSimplifiedType(m),
- PtrSimplifiedType(m) => PtrSimplifiedType(m),
- NeverSimplifiedType => NeverSimplifiedType,
- MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
- TupleSimplifiedType(n) => TupleSimplifiedType(n),
- TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
- ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
- GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
- GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
- FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
- PlaceholderSimplifiedType => PlaceholderSimplifiedType,
- }
- }
}
/// Given generic arguments from an obligation and an impl,
match impl_ty.kind() {
// Start by checking whether the type in the impl may unify with
// pretty much everything. Just return `true` in that case.
- ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
+ ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
// These types only unify with inference variables or their own
// variant.
ty::Bool
_ => false,
},
- ty::Opaque(..) => true,
-
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
// projections can unify with other stuff.
//
// Looking forward to lazy normalization this is the safer strategy anyways.
- ty::Projection(_) => true,
+ ty::Alias(..) => true,
ty::Error(_) => true,
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
- &ty::Generator(_, ref substs, _) => {
+ ty::Generator(_, substs, _) => {
let substs = substs.as_generator();
let should_remove_further_specializable =
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
self.add_substs(substs);
}
- &ty::Projection(data) => {
+ &ty::Alias(ty::Projection, data) => {
self.add_flags(TypeFlags::HAS_TY_PROJECTION);
self.add_projection_ty(data);
}
- &ty::Opaque(_, substs) => {
+ &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
self.add_flags(TypeFlags::HAS_TY_OPAQUE);
self.add_substs(substs);
}
&ty::Slice(tt) => self.add_ty(tt),
- &ty::RawPtr(ref m) => {
+ ty::RawPtr(m) => {
self.add_ty(m.ty);
}
}
}
- fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
+ fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
self.add_substs(projection_ty.substs);
}
self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
}
- /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
- /// assigned starting at 0 and increasing monotonically in the order traversed
- /// by the fold operation.
- ///
- /// The chief purpose of this function is to canonicalize regions so that two
- /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
- /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
- /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
- pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
- where
- T: TypeFoldable<'tcx>,
- {
- let mut counter = 0;
- let inner = self
- .replace_late_bound_regions(sig, |_| {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_u32(counter),
- kind: ty::BrAnon(counter, None),
- };
- let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
- counter += 1;
- r
- })
- .0;
- let bound_vars = self.mk_bound_variable_kinds(
- (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
- );
- Binder::bind_with_vars(inner, bound_vars)
- }
-
/// Anonymize all bound variables in `value`, this is mostly used to improve caching.
pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
where
}
}
+ pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
+ if let Some(index) = param_index.checked_sub(self.parent_count) {
+ &self.params[..index]
+ } else {
+ tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+ .params_to(param_index, tcx)
+ }
+ }
+
/// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
pub fn region_param(
&'tcx self,
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,
- Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+ Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
// use a query for more complex cases
Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
)
}
+ pub fn expect_resolve(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+ ) -> Instance<'tcx> {
+ match ty::Instance::resolve(tcx, param_env, def_id, substs) {
+ Ok(Some(instance)) => instance,
+ _ => bug!(
+ "failed to resolve instance for {}",
+ tcx.def_path_str_with_substs(def_id, substs)
+ ),
+ }
+ }
+
// This should be kept up to date with `resolve`.
pub fn resolve_opt_const_arg(
tcx: TyCtxt<'tcx>,
pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
let substs = tcx.intern_substs(&[ty.into()]);
- Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+ Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
}
#[instrument(level = "debug", skip(tcx), ret)]
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
- ty::Param(_) | ty::Projection(_) => {
+ ty::Param(_) | ty::Alias(ty::Projection, _) => {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
}
}
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
let normalized = tcx.normalize_erasing_regions(param_env, ty);
if ty == normalized {
Err(err)
}
}
- ty::Projection(_)
+ ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
- | ty::Opaque(..)
| ty::Param(_)
| ty::Infer(_)
| ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
-use rustc_hir::definitions::Definitions;
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::Untracked;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
use std::{fmt, str};
pub use crate::ty::diagnostics::*;
+pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
- tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
- CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
- GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
- UserType, UserTypeAnnotationIndex,
+ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
+ TyCtxtFeed,
};
pub use self::instance::{Instance, InstanceDef, ShortInstance};
pub use self::list::List;
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
- Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
- ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
- VarianceDiagInfo,
+ Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
+pub use self::typeck_results::{
+ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+ GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
+ UserTypeAnnotationIndex,
+};
pub mod _match;
pub mod abstract_const;
mod rvalue_scopes;
mod structural_impls;
mod sty;
+mod typeck_results;
// Data types
pub type RegisteredTools = FxHashSet<Ident>;
pub struct ResolverOutputs {
- pub definitions: Definitions,
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
+ pub untracked: Untracked,
}
#[derive(Debug)]
pub struct ResolverGlobalCtxt {
- pub cstore: Box<CrateStoreDyn>,
pub visibilities: FxHashMap<LocalDefId, Visibility>,
/// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
pub has_pub_restricted: bool,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
- /// Reference span for definitions.
- pub source_span: IndexVec<LocalDefId, Span>,
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
pub predicates: Vec<Predicate<'tcx>>,
}
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
pub enum ImplSubject<'tcx> {
Trait(TraitRef<'tcx>),
Inherent(Ty<'tcx>),
}
}
- pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self }
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
}
pub fn def_id(self) -> DefId {
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
+ &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => core::intrinsics::unreachable(),
}
TermKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
- (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ProjectionPredicate<'tcx> {
- pub projection_ty: ProjectionTy<'tcx>,
+ pub projection_ty: AliasTy<'tcx>,
pub term: Term<'tcx>,
}
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
pub fn projection_def_id(&self) -> DefId {
// Ok to skip binder since trait `DefId` does not care about regions.
- self.skip_binder().projection_ty.item_def_id
+ self.skip_binder().projection_ty.def_id
+ }
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ Self {
+ projection_ty: tcx.mk_alias_ty(
+ self.projection_ty.def_id,
+ [self_ty.into()].into_iter().chain(self.projection_ty.substs.iter().skip(1)),
+ ),
+ ..self
+ }
}
}
}
}
- pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
- typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field")
- }
-
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
variant
.fields
use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::DefIndex;
use rustc_index::vec::{Idx, IndexVec};
-use crate::middle::exported_symbols::ExportedSymbol;
-use crate::mir::Body;
-use crate::ty::{
- self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
-};
+use crate::ty;
pub trait ParameterizedOverTcx: 'static {
- #[allow(unused_lifetimes)]
type Value<'tcx>;
}
ty::TraitDef,
ty::Visibility<DefIndex>,
ty::adjustment::CoerceUnsizedInfo,
- ty::fast_reject::SimplifiedTypeGen<DefId>,
+ ty::fast_reject::SimplifiedType,
rustc_ast::Attribute,
rustc_ast::DelimArgs,
rustc_attr::ConstStability,
rustc_type_ir::Variance,
}
-// HACK(compiler-errors): This macro rule can only take an ident,
-// not a path, due to parsing ambiguity reasons. That means we gotta
-// import all of these types above.
+// HACK(compiler-errors): This macro rule can only take a fake path,
+// not a real, due to parsing ambiguity reasons.
#[macro_export]
macro_rules! parameterized_over_tcx {
- ($($ident:ident),+ $(,)?) => {
+ ($($($fake_path:ident)::+),+ $(,)?) => {
$(
- impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
- type Value<'tcx> = $ident<'tcx>;
+ impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> {
+ type Value<'tcx> = $($fake_path)::+<'tcx>;
}
)*
}
}
parameterized_over_tcx! {
- Ty,
- FnSig,
- GenericPredicates,
- TraitRef,
- Const,
- Predicate,
- Clause,
- GeneratorDiagnosticData,
- Body,
- ExportedSymbol,
+ crate::middle::exported_symbols::ExportedSymbol,
+ crate::mir::Body,
+ ty::Ty,
+ ty::FnSig,
+ ty::GenericPredicates,
+ ty::TraitRef,
+ ty::Const,
+ ty::Predicate,
+ ty::Clause,
+ ty::GeneratorDiagnosticData,
}
self.path_append(
|cx: Self| {
if trait_qualify_parent {
- let trait_ref = ty::TraitRef::new(
- parent_def_id,
- cx.tcx().intern_substs(parent_substs),
- );
+ let trait_ref =
+ cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
} else {
cx.print_def_path(parent_def_id, parent_substs)
| ty::Uint(_)
| ty::Str
| ty::FnPtr(_)
- | ty::Projection(_)
+ | ty::Alias(..)
| ty::Placeholder(..)
| ty::Param(_)
- | ty::Opaque(..)
| ty::Infer(_)
| ty::Bound(..)
| ty::Error(_)
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
use rustc_hir::LangItem;
use rustc_session::config::TrimmedDefPaths;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_session::Limit;
use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::FileNameDisplayPreference;
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
use std::cell::Cell;
use std::char;
use std::collections::BTreeMap;
-use std::convert::TryFrom;
use std::fmt::{self, Write as _};
use std::iter;
use std::ops::{ControlFlow, Deref, DerefMut};
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
+ static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
}
/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
/// if no other `Vec` is found.
fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
+ fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH);
/// Prevent selection of visible paths. `Display` impl of DefId will prefer
/// visible (public) reexports of types as paths.
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
self.try_print_visible_def_path_recur(def_id, &mut callers)
}
+ // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
+ // For associated items on traits it prints out the trait's name and the associated item's name.
+ // For enum variants, if they have an unique name, then we only print the name, otherwise we
+ // print the enum name and the variant name. Otherwise, we do not print anything and let the
+ // caller use the `print_def_path` fallback.
+ fn force_print_trimmed_def_path(
+ mut self,
+ def_id: DefId,
+ ) -> Result<(Self::Path, bool), Self::Error> {
+ let key = self.tcx().def_key(def_id);
+ let visible_parent_map = self.tcx().visible_parent_map(());
+ let kind = self.tcx().def_kind(def_id);
+
+ let get_local_name = |this: &Self, name, def_id, key: DefKey| {
+ if let Some(visible_parent) = visible_parent_map.get(&def_id)
+ && let actual_parent = this.tcx().opt_parent(def_id)
+ && let DefPathData::TypeNs(_) = key.disambiguated_data.data
+ && Some(*visible_parent) != actual_parent
+ {
+ this
+ .tcx()
+ .module_children(visible_parent)
+ .iter()
+ .filter(|child| child.res.opt_def_id() == Some(def_id))
+ .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
+ .map(|child| child.ident.name)
+ .unwrap_or(name)
+ } else {
+ name
+ }
+ };
+ if let DefKind::Variant = kind
+ && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
+ {
+ // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
+ self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?;
+ return Ok((self, true));
+ }
+ if let Some(symbol) = key.get_opt_name() {
+ if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
+ && let Some(parent) = self.tcx().opt_parent(def_id)
+ && let parent_key = self.tcx().def_key(parent)
+ && let Some(symbol) = parent_key.get_opt_name()
+ {
+ // Trait
+ self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+ self.write_str("::")?;
+ } else if let DefKind::Variant = kind
+ && let Some(parent) = self.tcx().opt_parent(def_id)
+ && let parent_key = self.tcx().def_key(parent)
+ && let Some(symbol) = parent_key.get_opt_name()
+ {
+ // Enum
+
+ // For associated items and variants, we want the "full" path, namely, include
+ // the parent type in the path. For example, `Iterator::Item`.
+ self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+ self.write_str("::")?;
+ } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait
+ | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
+ {
+ } else {
+ // If not covered above, like for example items out of `impl` blocks, fallback.
+ return Ok((self, false));
+ }
+ self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
+ return Ok((self, true));
+ }
+ Ok((self, false))
+ }
+
/// Try to see if this path can be trimmed to a unique symbol name.
fn try_print_trimmed_def_path(
mut self,
def_id: DefId,
) -> Result<(Self::Path, bool), Self::Error> {
+ if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
+ if trimmed {
+ return Ok((s, true));
+ }
+ self = s;
+ }
if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
|| matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
|| NO_TRIMMED_PATH.with(|flag| flag.get())
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
- ty::Projection(ref data) => {
+ ty::Alias(ty::Projection, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
- && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
{
- return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+ return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
} else {
p!(print(data))
}
}
ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// FIXME(eddyb) print this with `print_def_path`.
// We use verbose printing in 'NO_QUERIES' mode, to
// avoid needing to call `predicates_of`. This should
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
- if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
+ *self.tcx().type_of(parent).kind()
+ {
if d == def_id {
// If the type alias directly starts with the `impl` of the
// opaque type we're printing, then skip the `::{opaque#1}`.
p!("@", print_def_path(did.to_def_id(), substs));
} else {
let span = self.tcx().def_span(did);
+ let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ FileNameDisplayPreference::Short
+ } else {
+ FileNameDisplayPreference::Remapped
+ };
p!(write(
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
- self.tcx().sess.source_map().span_to_embeddable_string(span)
+ self.tcx().sess.source_map().span_to_string(span, preference)
));
}
} else {
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
- && let ty::Projection(proj) = ty.kind()
- && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
+ && let ty::Alias(ty::Projection, proj) = ty.kind()
+ && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
&& assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
&& assoc.name == rustc_span::sym::Return
{
}
ty::ExistentialProjection<'tcx> {
- let name = cx.tcx().associated_item(self.item_def_id).name;
+ let name = cx.tcx().associated_item(self.def_id).name;
p!(write("{} = ", name), print(self.term))
}
}
}
- ty::ProjectionTy<'tcx> {
- p!(print_def_path(self.item_def_id, self.substs));
+ ty::AliasTy<'tcx> {
+ p!(print_def_path(self.def_id, self.substs));
}
ty::ClosureKind {
T: Relate<'tcx>;
}
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
}
}
-impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
- a: ty::ProjectionTy<'tcx>,
- b: ty::ProjectionTy<'tcx>,
- ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
- if a.item_def_id != b.item_def_id {
- Err(TypeError::ProjectionMismatched(expected_found(
- relation,
- a.item_def_id,
- b.item_def_id,
- )))
+ a: ty::AliasTy<'tcx>,
+ b: ty::AliasTy<'tcx>,
+ ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
+ if a.def_id != b.def_id {
+ Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relation.relate(a.substs, b.substs)?;
- Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
+ Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
}
}
}
a: ty::ExistentialProjection<'tcx>,
b: ty::ExistentialProjection<'tcx>,
) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
- if a.item_def_id != b.item_def_id {
- Err(TypeError::ProjectionMismatched(expected_found(
- relation,
- a.item_def_id,
- b.item_def_id,
- )))
+ if a.def_id != b.def_id {
+ Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let term = relation.relate_with_variance(
ty::Invariant,
a.substs,
b.substs,
)?;
- Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
+ Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
}
}
}
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, a.substs, b.substs)?;
- Ok(ty::TraitRef { def_id: a.def_id, substs })
+ Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
}
}
}
}
}
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
Ok(a)
}
- (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a),
+ (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => Ok(a),
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
}
// these two are already handled downstream in case of lazy normalization
- (&ty::Projection(a_data), &ty::Projection(b_data)) => {
+ (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
let projection_ty = relation.relate(a_data, b_data)?;
- Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
+ Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
}
- (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
- if a_def_id == b_def_id =>
- {
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+ ) if a_def_id == b_def_id => {
if relation.intercrate() {
// During coherence, opaque types should be treated as equal to each other, even if their generic params
// differ, as they could resolve to the same hidden type, even for different generic params.
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
- ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
- ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
+ ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
ty::Bool
| ty::Char
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
- ty::Projection(ref data) => data.visit_with(visitor),
- ty::Opaque(_, ref substs) => substs.visit_with(visitor),
+ ty::Alias(_, ref data) => data.visit_with(visitor),
ty::Bool
| ty::Char
/// * `GR`: The "return type", which is the type of value returned upon
/// completion of the generator.
/// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
/// concatenated with a tuple containing the types of the upvars.
}
/// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
pub struct GeneratorSubsts<'tcx> {
pub substs: SubstsRef<'tcx>,
}
match (*self, *other) {
(Trait(_), Trait(_)) => Ordering::Equal,
(Projection(ref a), Projection(ref b)) => {
- tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
+ tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
}
(AutoTrait(ref a), AutoTrait(ref b)) => {
tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
+ /// This field exists to prevent the creation of `TraitRef` without
+ /// calling [TyCtxt::mk_trait_ref].
+ pub(super) _use_mk_trait_ref_instead: (),
}
impl<'tcx> TraitRef<'tcx> {
- pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
- TraitRef { def_id, substs }
- }
-
- pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
tcx.mk_trait_ref(
self.def_id,
[self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
- ty::Binder::dummy(TraitRef {
- def_id,
- substs: InternalSubsts::identity_for_item(tcx, def_id),
- })
+ ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
}
#[inline]
substs: SubstsRef<'tcx>,
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
- ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
+ tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
}
}
/// contain any bound vars that would be bound by the
/// binder. This is commonly used to 'inject' a value T into a
/// different binding level.
+ #[track_caller]
pub fn dummy(value: T) -> Binder<'tcx, T> {
- assert!(!value.has_escaping_bound_vars());
+ assert!(
+ !value.has_escaping_bound_vars(),
+ "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+ );
Binder(value, ty::List::empty())
}
}
}
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+ pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+ let bound_vars = self.1;
+ self.0.into_iter().map(|v| Binder(v, bound_vars))
+ }
+}
+
+/// Represents the projection of an associated type.
+///
+/// For a projection, this would be `<Ty as Trait<...>>::N`.
+///
+/// For an opaque type, there is no explicit syntax.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionTy<'tcx> {
- /// The parameters of the associated item.
+pub struct AliasTy<'tcx> {
+ /// The parameters of the associated or opaque item.
+ ///
+ /// For a projection, these are the substitutions for the trait and the
+ /// GAT substitutions, if there are any.
+ ///
+ /// For RPIT the substitutions are for the generics of the function,
+ /// while for TAIT it is used for the generic parameters of the alias.
pub substs: SubstsRef<'tcx>,
- /// The `DefId` of the `TraitItem` for the associated type `N`.
+ /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
+ /// or the `OpaqueType` item if this is an opaque.
///
- /// Note that this is not the `DefId` of the `TraitRef` containing this
- /// associated type, which is in `tcx.associated_item(item_def_id).container`,
- /// aka. `tcx.parent(item_def_id).unwrap()`.
- pub item_def_id: DefId,
+ /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+ /// underlying type if the type is an opaque.
+ ///
+ /// Note that if this is an associated type, this is not the `DefId` of the
+ /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+ /// aka. `tcx.parent(def_id)`.
+ pub def_id: DefId,
+
+ /// This field exists to prevent the creation of `ProjectionTy` without using
+ /// [TyCtxt::mk_alias_ty].
+ pub(super) _use_mk_alias_ty_instead: (),
}
-impl<'tcx> ProjectionTy<'tcx> {
+impl<'tcx> AliasTy<'tcx> {
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
- match tcx.def_kind(self.item_def_id) {
- DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+ match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
- tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+ tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
}
kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
}
&self,
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
- let def_id = tcx.parent(self.item_def_id);
- assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
- let trait_generics = tcx.generics_of(def_id);
+ debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
+ let trait_def_id = self.trait_def_id(tcx);
+ let trait_generics = tcx.generics_of(trait_def_id);
(
- ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
+ tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
&self.substs[trait_generics.count()..],
)
}
/// as well.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
- ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+ tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
}
pub fn self_ty(&self) -> Ty<'tcx> {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ExistentialProjection<'tcx> {
- pub item_def_id: DefId,
+ pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub term: Term<'tcx>,
}
/// then this function would return an `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
- let def_id = tcx.parent(self.item_def_id);
+ let def_id = tcx.parent(self.def_id);
let subst_count = tcx.generics_of(def_id).count() - 1;
let substs = tcx.intern_substs(&self.substs[..subst_count]);
ty::ExistentialTraitRef { def_id, substs }
debug_assert!(!self_ty.has_escaping_bound_vars());
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- item_def_id: self.item_def_id,
- substs: tcx.mk_substs_trait(self_ty, self.substs),
- },
+ projection_ty: tcx
+ .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
term: self.term,
}
}
projection_predicate.projection_ty.substs.type_at(0);
Self {
- item_def_id: projection_predicate.projection_ty.item_def_id,
+ def_id: projection_predicate.projection_ty.def_id,
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
term: projection_predicate.term,
}
}
pub fn item_def_id(&self) -> DefId {
- self.skip_binder().item_def_id
+ self.skip_binder().def_id
}
}
#[inline]
pub fn is_impl_trait(self) -> bool {
- matches!(self.kind(), Opaque(..))
+ matches!(self.kind(), Alias(ty::Opaque, ..))
}
#[inline]
ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
- ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
+ ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
// type parameters only have unit metadata if they're sized, so return true
// to make sure we double check this during confirmation
- ty::Param(_) | ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
+ ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true),
ty::Infer(ty::TyVar(_))
| ty::Bound(..)
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
- ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
+ ty::Alias(..) | ty::Param(_) => false,
ty::Infer(ty::TyVar(_)) => false,
ty::Generator(..) | ty::GeneratorWitness(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
- ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
+ ty::Adt(..) | ty::Closure(..) => false,
+
+ // Needs normalization or revealing to determine, so no is the safe answer.
+ ty::Alias(..) => false,
- ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
+ ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
ty::Bound(..) | ty::Placeholder(..) => {
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
- (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
+ &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => intrinsics::unreachable(),
}
}
}
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
--- /dev/null
+use crate::{
+ hir::place::Place as HirPlace,
+ infer::canonical::Canonical,
+ ty::{
+ self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
+ GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
+ },
+};
+use rustc_data_structures::{fx::FxHashMap, sync::Lrc, unord::UnordSet, vec_map::VecMap};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::{
+ def::{DefKind, Res},
+ def_id::{DefId, LocalDefId, LocalDefIdMap},
+ hir_id::OwnerId,
+ HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
+};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable;
+use rustc_middle::mir::FakeReadCause;
+use rustc_session::Session;
+use rustc_span::Span;
+use std::{
+ collections::hash_map::{self, Entry},
+ hash::Hash,
+ iter,
+};
+
+use super::RvalueScopes;
+
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct TypeckResults<'tcx> {
+ /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
+ pub hir_owner: OwnerId,
+
+ /// Resolved definitions for `<T>::X` associated paths and
+ /// method calls, including those of overloaded operators.
+ type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
+
+ /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
+ /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
+ /// about the field you also need definition of the variant to which the field
+ /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
+ field_indices: ItemLocalMap<usize>,
+
+ /// Stores the types for various nodes in the AST. Note that this table
+ /// is not guaranteed to be populated outside inference. See
+ /// typeck::check::fn_ctxt for details.
+ node_types: ItemLocalMap<Ty<'tcx>>,
+
+ /// Stores the type parameters which were substituted to obtain the type
+ /// of this node. This only applies to nodes that refer to entities
+ /// parameterized by type parameters, such as generic fns, types, or
+ /// other items.
+ node_substs: ItemLocalMap<SubstsRef<'tcx>>,
+
+ /// This will either store the canonicalized types provided by the user
+ /// or the substitutions that the user explicitly gave (if any) attached
+ /// to `id`. These will not include any inferred values. The canonical form
+ /// is used to capture things like `_` or other unspecified values.
+ ///
+ /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
+ /// canonical substitutions would include only `for<X> { Vec<X> }`.
+ ///
+ /// See also `AscribeUserType` statement in MIR.
+ user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
+
+ /// Stores the canonicalized types provided by the user. See also
+ /// `AscribeUserType` statement in MIR.
+ pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
+
+ adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+
+ /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
+ pat_binding_modes: ItemLocalMap<BindingMode>,
+
+ /// Stores the types which were implicitly dereferenced in pattern binding modes
+ /// for later usage in THIR lowering. For example,
+ ///
+ /// ```
+ /// match &&Some(5i32) {
+ /// Some(n) => {},
+ /// _ => {},
+ /// }
+ /// ```
+ /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
+ ///
+ /// See:
+ /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
+ pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+ /// Records the reasons that we picked the kind of each closure;
+ /// not all closures are present in the map.
+ closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
+
+ /// For each fn, records the "liberated" types of its arguments
+ /// and return type. Liberated means that all bound regions
+ /// (including late-bound regions) are replaced with free
+ /// equivalents. This table is not used in codegen (since regions
+ /// are erased there) and hence is not serialized to metadata.
+ ///
+ /// This table also contains the "revealed" values for any `impl Trait`
+ /// that appear in the signature and whose values are being inferred
+ /// by this function.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::fmt::Debug;
+ /// fn foo(x: &u32) -> impl Debug { *x }
+ /// ```
+ ///
+ /// The function signature here would be:
+ ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn(&'a u32) -> Foo
+ /// ```
+ ///
+ /// where `Foo` is an opaque type created for this function.
+ ///
+ ///
+ /// The *liberated* form of this would be
+ ///
+ /// ```ignore (illustrative)
+ /// fn(&'a u32) -> u32
+ /// ```
+ ///
+ /// Note that `'a` is not bound (it would be an `ReFree`) and
+ /// that the `Foo` opaque type is replaced by its hidden type.
+ liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
+
+ /// For each FRU expression, record the normalized types of the fields
+ /// of the struct - this is needed because it is non-trivial to
+ /// normalize while preserving regions. This table is used only in
+ /// MIR construction and hence is not serialized to metadata.
+ fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+ /// For every coercion cast we add the HIR node ID of the cast
+ /// expression to this set.
+ coercion_casts: ItemLocalSet,
+
+ /// Set of trait imports actually used in the method resolution.
+ /// This is used for warning unused imports. During type
+ /// checking, this `Lrc` should not be cloned: it must have a ref-count
+ /// of 1 so that we can insert things into the set mutably.
+ pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
+
+ /// If any errors occurred while type-checking this body,
+ /// this field will be set to `Some(ErrorGuaranteed)`.
+ pub tainted_by_errors: Option<ErrorGuaranteed>,
+
+ /// All the opaque types that have hidden types set
+ /// by this function. We also store the
+ /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
+ /// even if they are only set in dead code (which doesn't show up in MIR).
+ pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+
+ /// Tracks the minimum captures required for a closure;
+ /// see `MinCaptureInformationMap` for more details.
+ pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
+
+ /// Tracks the fake reads required for a closure and the reason for the fake read.
+ /// When performing pattern matching for closures, there are times we don't end up
+ /// reading places that are mentioned in a closure (because of _ patterns). However,
+ /// to ensure the places are initialized, we introduce fake reads.
+ /// Consider these two examples:
+ /// ``` (discriminant matching with only wildcard arm)
+ /// let x: u8;
+ /// let c = || match x { _ => () };
+ /// ```
+ /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
+ /// want to capture it. However, we do still want an error here, because `x` should have
+ /// to be initialized at the point where c is created. Therefore, we add a "fake read"
+ /// instead.
+ /// ``` (destructured assignments)
+ /// let c = || {
+ /// let (t1, t2) = t;
+ /// }
+ /// ```
+ /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
+ /// we never capture `t`. This becomes an issue when we build MIR as we require
+ /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
+ /// issue by fake reading `t`.
+ pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+
+ /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
+ /// by applying extended parameter rules.
+ /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
+ pub rvalue_scopes: RvalueScopes,
+
+ /// Stores the type, expression, span and optional scope span of all types
+ /// that are live across the yield of this generator (if a generator).
+ pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+
+ /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
+ /// as `&[u8]`, depending on the pattern in which they are used.
+ /// This hashset records all instances where we behave
+ /// like this to allow `const_to_pat` to reliably handle this situation.
+ pub treat_byte_string_as_slice: ItemLocalSet,
+
+ /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
+ /// on closure size.
+ pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+}
+
+/// Whenever a value may be live across a generator yield, the type of that value winds up in the
+/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
+/// captured types that can be useful for diagnostics. In particular, it stores the span that
+/// caused a given type to be recorded, along with the scope that enclosed the value (which can
+/// be used to find the await that the value is live across).
+///
+/// For example:
+///
+/// ```ignore (pseudo-Rust)
+/// async move {
+/// let x: T = expr;
+/// foo.await
+/// ...
+/// }
+/// ```
+///
+/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
+/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct GeneratorInteriorTypeCause<'tcx> {
+ /// Type of the captured binding.
+ pub ty: Ty<'tcx>,
+ /// Span of the binding that was captured.
+ pub span: Span,
+ /// Span of the scope of the captured binding.
+ pub scope_span: Option<Span>,
+ /// Span of `.await` or `yield` expression.
+ pub yield_span: Span,
+ /// Expr which the type evaluated from.
+ pub expr: Option<hir::HirId>,
+}
+
+// This type holds diagnostic information on generators and async functions across crate boundaries
+// and is used to provide better error messages
+#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
+pub struct GeneratorDiagnosticData<'tcx> {
+ pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+ pub hir_owner: DefId,
+ pub nodes_types: ItemLocalMap<Ty<'tcx>>,
+ pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+}
+
+impl<'tcx> TypeckResults<'tcx> {
+ pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
+ TypeckResults {
+ hir_owner,
+ type_dependent_defs: Default::default(),
+ field_indices: Default::default(),
+ user_provided_types: Default::default(),
+ user_provided_sigs: Default::default(),
+ node_types: Default::default(),
+ node_substs: Default::default(),
+ adjustments: Default::default(),
+ pat_binding_modes: Default::default(),
+ pat_adjustments: Default::default(),
+ closure_kind_origins: Default::default(),
+ liberated_fn_sigs: Default::default(),
+ fru_field_types: Default::default(),
+ coercion_casts: Default::default(),
+ used_trait_imports: Lrc::new(Default::default()),
+ tainted_by_errors: None,
+ concrete_opaque_types: Default::default(),
+ closure_min_captures: Default::default(),
+ closure_fake_reads: Default::default(),
+ rvalue_scopes: Default::default(),
+ generator_interior_types: ty::Binder::dummy(Default::default()),
+ treat_byte_string_as_slice: Default::default(),
+ closure_size_eval: Default::default(),
+ }
+ }
+
+ /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
+ pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
+ match *qpath {
+ hir::QPath::Resolved(_, ref path) => path.res,
+ hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
+ .type_dependent_def(id)
+ .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
+ }
+ }
+
+ pub fn type_dependent_defs(
+ &self,
+ ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
+ }
+
+ pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
+ }
+
+ pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
+ self.type_dependent_def(id).map(|(_, def_id)| def_id)
+ }
+
+ pub fn type_dependent_defs_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
+ }
+
+ pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
+ }
+
+ pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
+ }
+
+ pub fn field_index(&self, id: hir::HirId) -> usize {
+ self.field_indices().get(id).cloned().expect("no index for a field")
+ }
+
+ pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+ self.field_indices().get(id).cloned()
+ }
+
+ pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
+ }
+
+ pub fn user_provided_types_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
+ }
+
+ pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
+ }
+
+ pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
+ }
+
+ pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
+ let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
+ vec.iter()
+ .map(|item| {
+ GeneratorInteriorTypeCause {
+ ty: item.ty,
+ span: item.span,
+ scope_span: item.scope_span,
+ yield_span: item.yield_span,
+ expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
+ }
+ })
+ .collect::<Vec<_>>()
+ });
+ GeneratorDiagnosticData {
+ generator_interior_types: generator_interior_type,
+ hir_owner: self.hir_owner.to_def_id(),
+ nodes_types: self.node_types.clone(),
+ adjustments: self.adjustments.clone(),
+ }
+ }
+
+ pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
+ self.node_type_opt(id).unwrap_or_else(|| {
+ bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+ })
+ }
+
+ pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_types.get(&id.local_id).cloned()
+ }
+
+ pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
+ }
+
+ pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
+ }
+
+ pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_substs.get(&id.local_id).cloned()
+ }
+
+ /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
+ /// doesn't provide type parameter substitutions.
+ ///
+ /// [`expr_ty`]: TypeckResults::expr_ty
+ pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
+ self.node_type(pat.hir_id)
+ }
+
+ /// Returns the type of an expression as a monotype.
+ ///
+ /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
+ /// some cases, we insert `Adjustment` annotations such as auto-deref or
+ /// auto-ref. The type returned by this function does not consider such
+ /// adjustments. See `expr_ty_adjusted()` instead.
+ ///
+ /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
+ /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
+ /// instead of `fn(ty) -> T with T = isize`.
+ pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+ self.node_type(expr.hir_id)
+ }
+
+ pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+ self.node_type_opt(expr.hir_id)
+ }
+
+ pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
+ }
+
+ pub fn adjustments_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
+ }
+
+ pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
+ validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
+ self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
+ }
+
+ /// Returns the type of `expr`, considering any `Adjustment`
+ /// entry recorded for that expression.
+ pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+ self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
+ }
+
+ pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+ self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
+ }
+
+ pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
+ // Only paths and method calls/overloaded operators have
+ // entries in type_dependent_defs, ignore the former here.
+ if let hir::ExprKind::Path(_) = expr.kind {
+ return false;
+ }
+
+ matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
+ }
+
+ pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
+ self.pat_binding_modes().get(id).copied().or_else(|| {
+ s.delay_span_bug(sp, "missing binding mode");
+ None
+ })
+ }
+
+ pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
+ }
+
+ pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
+ }
+
+ pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
+ }
+
+ pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
+ }
+
+ /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
+ /// by the closure.
+ pub fn closure_min_captures_flattened(
+ &self,
+ closure_def_id: LocalDefId,
+ ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
+ self.closure_min_captures
+ .get(&closure_def_id)
+ .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
+ .into_iter()
+ .flatten()
+ }
+
+ pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
+ }
+
+ pub fn closure_kind_origins_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
+ }
+
+ pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
+ }
+
+ pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
+ }
+
+ pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
+ }
+
+ pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
+ }
+
+ pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+ validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
+ self.coercion_casts.contains(&hir_id.local_id)
+ }
+
+ pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
+ self.coercion_casts.insert(id);
+ }
+
+ pub fn coercion_casts(&self) -> &ItemLocalSet {
+ &self.coercion_casts
+ }
+}
+
+/// Validate that the given HirId (respectively its `local_id` part) can be
+/// safely used as a key in the maps of a TypeckResults. For that to be
+/// the case, the HirId must have the same `owner` as all the other IDs in
+/// this table (signified by `hir_owner`). Otherwise the HirId
+/// would be in a different frame of reference and using its `local_id`
+/// would result in lookup errors, or worse, in silently wrong data being
+/// stored/returned.
+#[inline]
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+ if hir_id.owner != hir_owner {
+ invalid_hir_id_for_typeck_results(hir_owner, hir_id);
+ }
+}
+
+#[cold]
+#[inline(never)]
+fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+ ty::tls::with(|tcx| {
+ bug!(
+ "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+ tcx.hir().node_to_string(hir_id),
+ hir_id.owner,
+ hir_owner
+ )
+ });
+}
+
+pub struct LocalTableInContext<'a, V> {
+ hir_owner: OwnerId,
+ data: &'a ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContext<'a, V> {
+ pub fn contains_key(&self, id: hir::HirId) -> bool {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.contains_key(&id.local_id)
+ }
+
+ pub fn get(&self, id: hir::HirId) -> Option<&V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.get(&id.local_id)
+ }
+
+ pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
+ self.data.iter()
+ }
+}
+
+impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
+ type Output = V;
+
+ fn index(&self, key: hir::HirId) -> &V {
+ self.get(key).expect("LocalTableInContext: key not found")
+ }
+}
+
+pub struct LocalTableInContextMut<'a, V> {
+ hir_owner: OwnerId,
+ data: &'a mut ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContextMut<'a, V> {
+ pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.get_mut(&id.local_id)
+ }
+
+ pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.entry(id.local_id)
+ }
+
+ pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.insert(id.local_id, val)
+ }
+
+ pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.remove(&id.local_id)
+ }
+}
+
+rustc_index::newtype_index! {
+ pub struct UserTypeAnnotationIndex {
+ derive [HashStable]
+ DEBUG_FORMAT = "UserType({})",
+ const START_INDEX = 0,
+ }
+}
+
+/// Mapping of type annotation indices to canonical user type annotations.
+pub type CanonicalUserTypeAnnotations<'tcx> =
+ IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
+
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CanonicalUserTypeAnnotation<'tcx> {
+ pub user_ty: Box<CanonicalUserType<'tcx>>,
+ pub span: Span,
+ pub inferred_ty: Ty<'tcx>,
+}
+
+/// Canonicalized user type annotation.
+pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
+
+impl<'tcx> CanonicalUserType<'tcx> {
+ /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
+ /// i.e., each thing is mapped to a canonical variable with the same index.
+ pub fn is_identity(&self) -> bool {
+ match self.value {
+ UserType::Ty(_) => false,
+ UserType::TypeOf(_, user_substs) => {
+ if user_substs.user_self_ty.is_some() {
+ return false;
+ }
+
+ iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
+ match kind.unpack() {
+ GenericArgKind::Type(ty) => match ty.kind() {
+ ty::Bound(debruijn, b) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(*debruijn, ty::INNERMOST);
+ cvar == b.var
+ }
+ _ => false,
+ },
+
+ GenericArgKind::Lifetime(r) => match *r {
+ ty::ReLateBound(debruijn, br) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(debruijn, ty::INNERMOST);
+ cvar == br.var
+ }
+ _ => false,
+ },
+
+ GenericArgKind::Const(ct) => match ct.kind() {
+ ty::ConstKind::Bound(debruijn, b) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(debruijn, ty::INNERMOST);
+ cvar == b
+ }
+ _ => false,
+ },
+ }
+ })
+ }
+ }
+ }
+}
+
+/// A user-given type annotation attached to a constant. These arise
+/// from constants that are named via paths, like `Foo::<A>::new` and
+/// so forth.
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum UserType<'tcx> {
+ Ty(Ty<'tcx>),
+
+ /// The canonical type is the result of `type_of(def_id)` with the
+ /// given substitutions applied.
+ TypeOf(DefId, UserSubsts<'tcx>),
+}
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::mir;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::GrowableBitSet;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_span::{sym, DUMMY_SP};
use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
ty::Tuple(_) => break,
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
let normalized = normalize(ty);
if ty == normalized {
return ty;
break;
}
}
- (ty::Projection(_) | ty::Opaque(..), _)
- | (_, ty::Projection(_) | ty::Opaque(..)) => {
+ (ty::Alias(..), _) | (_, ty::Alias(..)) => {
// If either side is a projection, attempt to
// progress via normalization. (Should be safe to
// apply to both sides as normalization is
pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
ty::EarlyBinder(self.impl_subject(def_id))
}
+
+ /// Returns names of captured upvars for closures and generators.
+ ///
+ /// Here are some examples:
+ /// - `name__field1__field2` when the upvar is captured by value.
+ /// - `_ref__name__field` when the upvar is captured by reference.
+ ///
+ /// For generators this only contains upvars that are shared by all states.
+ pub fn closure_saved_names_of_captured_variables(
+ self,
+ def_id: DefId,
+ ) -> SmallVec<[String; 16]> {
+ let body = self.optimized_mir(def_id);
+
+ body.var_debug_info
+ .iter()
+ .filter_map(|var| {
+ let is_ref = match var.value {
+ mir::VarDebugInfoContents::Place(place)
+ if place.local == mir::Local::new(1) =>
+ {
+ // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
+ // implies whether the variable is captured by value or by reference.
+ matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
+ }
+ _ => return None,
+ };
+ let prefix = if is_ref { "_ref__" } else { "" };
+ Some(prefix.to_owned() + var.name.as_str())
+ })
+ .collect()
+ }
+
+ // FIXME(eddyb) maybe precompute this? Right now it's computed once
+ // per generator monomorphization, but it doesn't depend on substs.
+ pub fn generator_layout_and_saved_local_names(
+ self,
+ def_id: DefId,
+ ) -> (
+ &'tcx ty::GeneratorLayout<'tcx>,
+ IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
+ ) {
+ let tcx = self;
+ let body = tcx.optimized_mir(def_id);
+ let generator_layout = body.generator_layout().unwrap();
+ let mut generator_saved_local_names =
+ IndexVec::from_elem(None, &generator_layout.field_tys);
+
+ let state_arg = mir::Local::new(1);
+ for var in &body.var_debug_info {
+ let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
+ if place.local != state_arg {
+ continue;
+ }
+ match place.projection[..] {
+ [
+ // Deref of the `Pin<&mut Self>` state argument.
+ mir::ProjectionElem::Field(..),
+ mir::ProjectionElem::Deref,
+ // Field of a variant of the state.
+ mir::ProjectionElem::Downcast(_, variant),
+ mir::ProjectionElem::Field(field, _),
+ ] => {
+ let name = &mut generator_saved_local_names
+ [generator_layout.variant_fields[variant][field]];
+ if name.is_none() {
+ name.replace(var.name);
+ }
+ }
+ _ => {}
+ }
+ }
+ (generator_layout, generator_saved_local_names)
+ }
}
struct OpaqueTypeExpander<'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Opaque(def_id, substs) = *t.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => false,
+ | ty::Placeholder(_) => false,
}
}
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => false,
+ | ty::Placeholder(_) => false,
}
}
//
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
// called for known, fully-monomorphized types.
- ty::Projection(_)
- | ty::Opaque(..)
- | ty::Param(_)
- | ty::Bound(..)
- | ty::Placeholder(_)
- | ty::Infer(_) => false,
+ ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
+ false
+ }
ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
}
// These require checking for `Copy` bounds or `Adt` destructors.
ty::Adt(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
- | ty::Opaque(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::Generator(..) => Ok(smallvec![ty]),
| ty::Never
| ty::Foreign(_) => true,
- ty::Opaque(..)
+ ty::Alias(..)
| ty::Dynamic(..)
| ty::Error(_)
| ty::Bound(..)
| ty::Param(_)
| ty::Placeholder(_)
- | ty::Projection(_)
| ty::Infer(_) => false,
// Not trivial because they have components, and instead of looking inside,
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
- if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
+ if let ty::Alias(..) = t.kind() {
return ControlFlow::CONTINUE;
}
}
-use std::convert::TryFrom;
use std::fmt;
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
let fn_ptr = Pointer::from(fn_alloc_id);
Scalar::from_pointer(fn_ptr, &tcx)
}
- VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
- VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
+ VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size),
+ VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size),
VtblEntry::Vacant => continue,
VtblEntry::Method(instance) => {
// Prepare the fn ptr we write into the vtable.
stack.push(ty.into());
stack.push(lt.into());
}
- ty::Projection(data) => {
+ ty::Alias(_, data) => {
stack.extend(data.substs.iter().rev());
}
ty::Dynamic(obj, lt, _) => {
}));
}
ty::Adt(_, substs)
- | ty::Opaque(_, substs)
| ty::Closure(_, substs)
| ty::Generator(_, substs, _)
| ty::FnDef(_, substs) => {
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_infer = { path = "../rustc_infer" }
+rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
remainder_span,
pattern,
None,
- Some((None, initializer_span)),
+ Some((Some(&destination), initializer_span)),
);
this.visit_primary_bindings(
pattern,
// the case of `!`, no return value is required, as the block will never return.
// Opaque types of empty bodies also need this unit assignment, in order to infer that their
// type is actually unit. Otherwise there will be no defining use found in the MIR.
- if destination_ty.is_unit() || matches!(destination_ty.kind(), ty::Opaque(..)) {
+ if destination_ty.is_unit()
+ || matches!(destination_ty.kind(), ty::Alias(ty::Opaque, ..))
+ {
// We only want to assign an implicit `()` as the return value of the block if the
// block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
+use rustc_hir::HirId;
use rustc_index::vec::IndexVec;
use rustc_middle::{
mir::*,
thir::*,
- ty::{Ty, TyCtxt},
+ ty::{ParamEnv, Ty, TyCtxt},
};
use rustc_span::Span;
pub(super) fn build_custom_mir<'tcx>(
tcx: TyCtxt<'tcx>,
did: DefId,
+ hir_id: HirId,
thir: &Thir<'tcx>,
expr: ExprId,
params: &IndexVec<ParamId, Param<'tcx>>,
parent_scope: None,
inlined: None,
inlined_parent_scope: None,
- local_data: ClearCrossCrate::Clear,
+ local_data: ClearCrossCrate::Set(SourceScopeLocalData {
+ lint_root: hir_id,
+ safety: Safety::Safe,
+ }),
});
body.injection_phase = Some(parse_attribute(attr));
let mut pctxt = ParseCtxt {
tcx,
+ param_env: tcx.param_env(did),
thir,
source_scope: OUTERMOST_SOURCE_SCOPE,
body: &mut body,
struct ParseCtxt<'tcx, 'body> {
tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
thir: &'body Thir<'tcx>,
source_scope: SourceScope,
use rustc_middle::mir::interpret::{ConstValue, Scalar};
+use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::{mir::*, thir::*, ty};
+use rustc_span::Span;
+use rustc_target::abi::VariantIdx;
+
+use crate::build::custom::ParseError;
+use crate::build::expr::as_constant::as_constant_inner;
use super::{parse_by_kind, PResult, ParseCtxt};
@call("mir_retag_raw", args) => {
Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
},
+ @call("mir_set_discriminant", args) => {
+ let place = self.parse_place(args[0])?;
+ let var = self.parse_integer_literal(args[1])? as u32;
+ Ok(StatementKind::SetDiscriminant {
+ place: Box::new(place),
+ variant_index: VariantIdx::from_u32(var),
+ })
+ },
ExprKind::Assign { lhs, rhs } => {
let lhs = self.parse_place(*lhs)?;
let rhs = self.parse_rvalue(*rhs)?;
}
pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
- parse_by_kind!(self, expr_id, _, "terminator",
+ parse_by_kind!(self, expr_id, expr, "terminator",
@call("mir_return", _args) => {
Ok(TerminatorKind::Return)
},
@call("mir_goto", args) => {
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
},
+ @call("mir_unreachable", _args) => {
+ Ok(TerminatorKind::Unreachable)
+ },
+ @call("mir_drop", args) => {
+ Ok(TerminatorKind::Drop {
+ place: self.parse_place(args[0])?,
+ target: self.parse_block(args[1])?,
+ unwind: None,
+ })
+ },
+ @call("mir_drop_and_replace", args) => {
+ Ok(TerminatorKind::DropAndReplace {
+ place: self.parse_place(args[0])?,
+ value: self.parse_operand(args[1])?,
+ target: self.parse_block(args[2])?,
+ unwind: None,
+ })
+ },
+ @call("mir_call", args) => {
+ let destination = self.parse_place(args[0])?;
+ let target = self.parse_block(args[1])?;
+ self.parse_call(args[2], destination, target)
+ },
+ ExprKind::Match { scrutinee, arms } => {
+ let discr = self.parse_operand(*scrutinee)?;
+ self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
+ },
+ )
+ }
+
+ fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult<SwitchTargets> {
+ let Some((otherwise, rest)) = arms.split_last() else {
+ return Err(ParseError {
+ span,
+ item_description: format!("no arms"),
+ expected: "at least one arm".to_string(),
+ })
+ };
+
+ let otherwise = &self.thir[*otherwise];
+ let PatKind::Wild = otherwise.pattern.kind else {
+ return Err(ParseError {
+ span: otherwise.span,
+ item_description: format!("{:?}", otherwise.pattern.kind),
+ expected: "wildcard pattern".to_string(),
+ })
+ };
+ let otherwise = self.parse_block(otherwise.body)?;
+
+ let mut values = Vec::new();
+ let mut targets = Vec::new();
+ for arm in rest {
+ let arm = &self.thir[*arm];
+ let PatKind::Constant { value } = arm.pattern.kind else {
+ return Err(ParseError {
+ span: arm.pattern.span,
+ item_description: format!("{:?}", arm.pattern.kind),
+ expected: "constant pattern".to_string(),
+ })
+ };
+ values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty));
+ targets.push(self.parse_block(arm.body)?);
+ }
+
+ Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
+ }
+
+ fn parse_call(
+ &self,
+ expr_id: ExprId,
+ destination: Place<'tcx>,
+ target: BasicBlock,
+ ) -> PResult<TerminatorKind<'tcx>> {
+ parse_by_kind!(self, expr_id, _, "function call",
+ ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
+ let fun = self.parse_operand(*fun)?;
+ let args = args
+ .iter()
+ .map(|arg| self.parse_operand(*arg))
+ .collect::<PResult<Vec<_>>>()?;
+ Ok(TerminatorKind::Call {
+ func: fun,
+ args,
+ destination,
+ target: Some(target),
+ cleanup: None,
+ from_hir_call: *from_hir_call,
+ fn_span: *fn_span,
+ })
+ },
)
}
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, _, "rvalue",
+ @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
| ExprKind::ConstParam { .. }
| ExprKind::ConstBlock { .. } => {
Ok(Operand::Constant(Box::new(
- crate::build::expr::as_constant::as_constant_inner(expr, |_| None, self.tcx)
+ as_constant_inner(expr, |_| None, self.tcx)
)))
},
_ => self.parse_place(expr_id).map(Operand::Copy),
}
fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
- parse_by_kind!(self, expr_id, _, "place",
- ExprKind::Deref { arg } => Ok(
- self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
- ),
- _ => self.parse_local(expr_id).map(Place::from),
- )
+ self.parse_place_inner(expr_id).map(|(x, _)| x)
+ }
+
+ fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> {
+ let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
+ @call("mir_field", args) => {
+ let (parent, ty) = self.parse_place_inner(args[0])?;
+ let field = Field::from_u32(self.parse_integer_literal(args[1])? as u32);
+ let field_ty = ty.field_ty(self.tcx, field);
+ let proj = PlaceElem::Field(field, field_ty);
+ let place = parent.project_deeper(&[proj], self.tcx);
+ return Ok((place, PlaceTy::from_ty(field_ty)));
+ },
+ @call("mir_variant", args) => {
+ (args[0], PlaceElem::Downcast(
+ None,
+ VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32)
+ ))
+ },
+ ExprKind::Deref { arg } => {
+ parse_by_kind!(self, *arg, _, "does not matter",
+ @call("mir_make_place", args) => return self.parse_place_inner(args[0]),
+ _ => (*arg, PlaceElem::Deref),
+ )
+ },
+ ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_local(*index)?)),
+ ExprKind::Field { lhs, name: field, .. } => (*lhs, PlaceElem::Field(*field, expr.ty)),
+ _ => {
+ let place = self.parse_local(expr_id).map(Place::from)?;
+ return Ok((place, PlaceTy::from_ty(expr.ty)))
+ },
+ );
+ let (parent, ty) = self.parse_place_inner(parent)?;
+ let place = parent.project_deeper(&[proj], self.tcx);
+ let ty = ty.projection_ty(self.tcx, proj);
+ Ok((place, ty))
}
fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
},
)
}
+
+ fn parse_integer_literal(&self, expr_id: ExprId) -> PResult<u128> {
+ parse_by_kind!(self, expr_id, expr, "constant",
+ ExprKind::Literal { .. }
+ | ExprKind::NamedConst { .. }
+ | ExprKind::NonHirLiteral { .. }
+ | ExprKind::ConstBlock { .. } => Ok({
+ let value = as_constant_inner(expr, |_| None, self.tcx);
+ value.literal.eval_bits(self.tcx, self.param_env, value.ty())
+ }),
+ )
+ }
}
let allocation = tcx.intern_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Slice(_)) =>
{
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
let allocation = tcx.intern_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
}
use rustc_middle::hir::place::Projection as HirProjection;
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
use rustc_middle::middle::region;
+use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::AssertKind::BoundsCheck;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_index::vec::Idx;
use std::assert_matches::assert_matches;
+use std::convert::From;
use std::iter;
-/// The "outermost" place that holds this value.
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub(crate) enum PlaceBase {
+/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
+/// place by pushing more and more projections onto the end, and then convert the final set into a
+/// place using the `into_place` method.
+///
+/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
+/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
+#[derive(Clone, Debug, PartialEq)]
+pub(in crate::build) enum PlaceBuilder<'tcx> {
/// Denotes the start of a `Place`.
- Local(Local),
+ ///
+ /// We use `PlaceElem` since this has all `Field` types available.
+ Local { local: Local, projection: Vec<PlaceElem<'tcx>> },
/// When building place for an expression within a closure, the place might start off a
/// captured path. When `capture_disjoint_fields` is enabled, we might not know the capture
/// index (within the desugared closure) of the captured path until most of the projections
- /// are applied. We use `PlaceBase::Upvar` to keep track of the root variable off of which the
+ /// are applied. We use `PlaceBuilder::Upvar` to keep track of the root variable off of which the
/// captured path starts, the closure the capture belongs to and the trait the closure
/// implements.
///
- /// Once we have figured out the capture index, we can convert the place builder to start from
- /// `PlaceBase::Local`.
+ /// Once we have figured out the capture index, we can convert the place builder to
+ /// `PlaceBuilder::Local`.
///
/// Consider the following example
/// ```rust
///
/// When `capture_disjoint_fields` is enabled, `t.0.0.0` is captured and we won't be able to
/// figure out that it is captured until all the `Field` projections are applied.
- Upvar {
- /// HirId of the upvar
- var_hir_id: LocalVarId,
- /// DefId of the closure
- closure_def_id: LocalDefId,
- },
+ ///
+ /// Note: in contrast to `PlaceBuilder::Local` we have not yet determined all `Field` types
+ /// and will only do so once converting to `PlaceBuilder::Local`.
+ Upvar { upvar: Upvar, projection: Vec<UpvarProjectionElem<'tcx>> },
}
-/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
-/// place by pushing more and more projections onto the end, and then convert the final set into a
-/// place using the `to_place` method.
-///
-/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
-/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
-#[derive(Clone, Debug, PartialEq)]
-pub(in crate::build) struct PlaceBuilder<'tcx> {
- base: PlaceBase,
- projection: Vec<PlaceElem<'tcx>>,
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub(crate) struct Upvar {
+ var_hir_id: LocalVarId,
+ closure_def_id: LocalDefId,
}
/// Given a list of MIR projections, convert them to list of HIR ProjectionKind.
/// part of a path that is captured by a closure. We stop applying projections once we see the first
/// projection that isn't captured by a closure.
fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
- mir_projections: &[PlaceElem<'tcx>],
+ mir_projections: &[UpvarProjectionElem<'tcx>],
) -> Vec<HirProjectionKind> {
let mut hir_projections = Vec::new();
let mut variant = None;
fn find_capture_matching_projections<'a, 'tcx>(
upvars: &'a CaptureMap<'tcx>,
var_hir_id: LocalVarId,
- projections: &[PlaceElem<'tcx>],
+ projections: &[UpvarProjectionElem<'tcx>],
) -> Option<(usize, &'a Capture<'tcx>)> {
let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections);
cx: &Builder<'_, 'tcx>,
var_hir_id: LocalVarId,
closure_def_id: LocalDefId,
- projection: &[PlaceElem<'tcx>],
+ projection: &[UpvarProjectionElem<'tcx>],
) -> Option<PlaceBuilder<'tcx>> {
let Some((capture_index, capture)) =
find_capture_matching_projections(
var_hir_id, projection,
);
}
+
return None;
};
// Access the capture by accessing the field within the Closure struct.
let capture_info = &cx.upvars[capture_index];
- let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
+ let Place { local: upvar_resolved_local, projection: local_projection } =
+ capture_info.use_place;
// We used some of the projections to build the capture itself,
// now we apply the remaining to the upvar resolved place.
- trace!(?capture.captured_place, ?projection);
- let remaining_projections = strip_prefix(
+ let upvar_projection = strip_prefix(
capture.captured_place.place.base_ty,
projection,
&capture.captured_place.place.projections,
);
- upvar_resolved_place_builder.projection.extend(remaining_projections);
+
+ let upvar_resolved_place_builder = PlaceBuilder::construct_local_place_builder(
+ cx,
+ upvar_resolved_local,
+ local_projection.as_slice(),
+ upvar_projection,
+ );
+
+ assert!(matches!(upvar_resolved_place_builder, PlaceBuilder::Local { .. }));
Some(upvar_resolved_place_builder)
}
/// projection kinds are unsupported.
fn strip_prefix<'a, 'tcx>(
mut base_ty: Ty<'tcx>,
- projections: &'a [PlaceElem<'tcx>],
+ projections: &'a [UpvarProjectionElem<'tcx>],
prefix_projections: &[HirProjection<'tcx>],
-) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a {
+) -> impl Iterator<Item = UpvarProjectionElem<'tcx>> + 'a {
let mut iter = projections
.iter()
.copied()
// Filter out opaque casts, they are unnecessary in the prefix.
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
for projection in prefix_projections {
+ debug!(?projection, ?projection.ty);
+
match projection.kind {
HirProjectionKind::Deref => {
assert_matches!(iter.next(), Some(ProjectionElem::Deref));
bug!("unexpected projection kind: {:?}", projection);
}
}
+
base_ty = projection.ty;
}
+
iter
}
pub(in crate::build) fn try_to_place(&self, cx: &Builder<'_, 'tcx>) -> Option<Place<'tcx>> {
let resolved = self.resolve_upvar(cx);
let builder = resolved.as_ref().unwrap_or(self);
- let PlaceBase::Local(local) = builder.base else { return None };
- let projection = cx.tcx.intern_place_elems(&builder.projection);
- Some(Place { local, projection })
+ let PlaceBuilder::Local{local, ref projection} = builder else { return None };
+ let projection = cx.tcx.intern_place_elems(projection);
+ Some(Place { local: *local, projection })
}
/// Attempts to resolve the `PlaceBuilder`.
&self,
cx: &Builder<'_, 'tcx>,
) -> Option<PlaceBuilder<'tcx>> {
- let PlaceBase::Upvar { var_hir_id, closure_def_id } = self.base else {
+ let PlaceBuilder::Upvar{ upvar: Upvar {var_hir_id, closure_def_id }, projection} = self else {
return None;
};
- to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &self.projection)
- }
- pub(crate) fn base(&self) -> PlaceBase {
- self.base
+ to_upvars_resolved_place_builder(cx, *var_hir_id, *closure_def_id, &projection)
}
- pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] {
- &self.projection
- }
+ #[instrument(skip(cx), level = "debug")]
+ pub(crate) fn field(self, cx: &Builder<'_, 'tcx>, f: Field) -> Self {
+ match self.clone() {
+ PlaceBuilder::Local { local, projection } => {
+ let base_place = PlaceBuilder::Local { local, projection };
+ let PlaceTy { ty, variant_index } =
+ base_place.to_place(cx).ty(&cx.local_decls, cx.tcx);
+ let base_ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
+
+ let field_ty = PlaceBuilder::compute_field_ty(cx, f, base_ty, variant_index);
- pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
- self.project(PlaceElem::Field(f, ty))
+ self.project(ProjectionElem::Field(f, field_ty))
+ }
+ PlaceBuilder::Upvar { upvar, mut projection } => {
+ projection.push(ProjectionElem::Field(f, ()));
+ PlaceBuilder::Upvar { upvar, projection }
+ }
+ }
}
pub(crate) fn deref(self) -> Self {
self.project(PlaceElem::Index(index))
}
- pub(crate) fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
- self.projection.push(elem);
- self
+ #[instrument(level = "debug")]
+ pub(crate) fn project(self, elem: PlaceElem<'tcx>) -> Self {
+ let result = match self {
+ PlaceBuilder::Local { local, mut projection } => {
+ projection.push(elem);
+ PlaceBuilder::Local { local, projection }
+ }
+ PlaceBuilder::Upvar { upvar, mut projection } => {
+ projection.push(elem.into());
+ PlaceBuilder::Upvar { upvar, projection }
+ }
+ };
+
+ debug!(?result);
+ result
}
/// Same as `.clone().project(..)` but more efficient
pub(crate) fn clone_project(&self, elem: PlaceElem<'tcx>) -> Self {
- Self {
- base: self.base,
- projection: Vec::from_iter(self.projection.iter().copied().chain([elem])),
+ match self {
+ PlaceBuilder::Local { local, projection } => PlaceBuilder::Local {
+ local: *local,
+ projection: Vec::from_iter(projection.iter().copied().chain([elem])),
+ },
+ PlaceBuilder::Upvar { upvar, projection } => PlaceBuilder::Upvar {
+ upvar: *upvar,
+ projection: Vec::from_iter(projection.iter().copied().chain([elem.into()])),
+ },
}
}
+
+ /// Similar to `Place::ty` but needed during mir building.
+ ///
+ /// Applies the projections in the `PlaceBuilder` to the base
+ /// type.
+ ///
+ /// Fallible as the root of this place may be an upvar for
+ /// which no base type can be determined.
+ #[instrument(skip(cx), level = "debug")]
+ fn compute_field_ty(
+ cx: &Builder<'_, 'tcx>,
+ field: Field,
+ base_ty: Ty<'tcx>,
+ variant_index: Option<VariantIdx>,
+ ) -> Ty<'tcx> {
+ let field_idx = field.as_usize();
+ let field_ty = match base_ty.kind() {
+ ty::Adt(adt_def, substs) if adt_def.is_enum() => {
+ let variant_idx = variant_index.unwrap();
+ adt_def.variant(variant_idx).fields[field_idx].ty(cx.tcx, substs)
+ }
+ ty::Adt(adt_def, substs) => adt_def
+ .all_fields()
+ .nth(field_idx)
+ .unwrap_or_else(|| {
+ bug!(
+ "expected to take field with idx {:?} of fields of {:?}",
+ field_idx,
+ adt_def
+ )
+ })
+ .ty(cx.tcx, substs),
+ ty::Tuple(elems) => elems.iter().nth(field_idx).unwrap_or_else(|| {
+ bug!("expected to take field with idx {:?} of {:?}", field_idx, elems)
+ }),
+ ty::Closure(_, substs) => {
+ let substs = substs.as_closure();
+ let Some(f_ty) = substs.upvar_tys().nth(field_idx) else {
+ bug!("expected to take field with idx {:?} of {:?}", field_idx, substs.upvar_tys().collect::<Vec<_>>());
+ };
+
+ f_ty
+ }
+ &ty::Generator(def_id, substs, _) => {
+ if let Some(var) = variant_index {
+ let gen_body = cx.tcx.optimized_mir(def_id);
+ let Some(layout) = gen_body.generator_layout() else {
+ bug!("No generator layout for {:?}", base_ty);
+ };
+
+ let Some(&local) = layout.variant_fields[var].get(field) else {
+ bug!("expected to take field {:?} of {:?}", field, layout.variant_fields[var]);
+ };
+
+ let Some(&f_ty) = layout.field_tys.get(local) else {
+ bug!("expected to get element for {:?} in {:?}", local, layout.field_tys);
+ };
+
+ f_ty
+ } else {
+ let Some(f_ty) = substs.as_generator().prefix_tys().nth(field.index()) else {
+ bug!(
+ "expected to take index {:?} in {:?}",
+ field.index(),
+ substs.as_generator().prefix_tys().collect::<Vec<_>>()
+ );
+ };
+
+ f_ty
+ }
+ }
+ _ => bug!("couldn't create field type, unexpected base type: {:?}", base_ty),
+ };
+
+ cx.tcx.normalize_erasing_regions(cx.param_env, field_ty)
+ }
+
+ /// Creates a `PlaceBuilder::Local` from a `PlaceBuilder::Upvar` whose upvars
+ /// are resolved. This function takes two kinds of projections: `local_projection`
+ /// contains the projections of the captured upvar and `upvar_projection` the
+ /// projections that are applied to the captured upvar. The main purpose of this
+ /// function is to figure out the `Ty`s of the field projections in `upvar_projection`.
+ #[instrument(skip(cx, local, upvar_projection))]
+ fn construct_local_place_builder(
+ cx: &Builder<'_, 'tcx>,
+ local: Local,
+ local_projection: &[PlaceElem<'tcx>],
+ upvar_projection: impl Iterator<Item = UpvarProjectionElem<'tcx>>,
+ ) -> Self {
+ // We maintain a `Ty` to which we apply a projection in each iteration over `upvar_projection`.
+ // This `ancestor_ty` let's us infer the field type whenever we encounter a
+ // `ProjectionElem::Field`.
+ let (mut ancestor_ty, mut opt_variant_idx) =
+ local_projections_to_ty(cx, local, local_projection);
+
+ // We add all projection elements we encounter to this `Vec`.
+ let mut local_projection = local_projection.to_vec();
+
+ for (i, proj) in upvar_projection.enumerate() {
+ debug!("i: {:?}, proj: {:?}, local_projection: {:?}", i, proj, local_projection);
+ match proj {
+ ProjectionElem::Field(field, _) => {
+ let field_ty =
+ PlaceBuilder::compute_field_ty(cx, field, ancestor_ty, opt_variant_idx);
+ debug!(?field_ty);
+
+ local_projection.push(ProjectionElem::Field(field, field_ty));
+ ancestor_ty = field_ty;
+ opt_variant_idx = None;
+ }
+ _ => {
+ let proj = upvar_proj_to_place_elem_no_field_proj(proj);
+ (ancestor_ty, opt_variant_idx) = project_ty(cx.tcx, ancestor_ty, proj);
+ local_projection.push(proj);
+ }
+ }
+ }
+
+ PlaceBuilder::Local { local, projection: local_projection }
+ }
}
impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
fn from(local: Local) -> Self {
- Self { base: PlaceBase::Local(local), projection: Vec::new() }
+ Self::Local { local, projection: Vec::new() }
}
}
-impl<'tcx> From<PlaceBase> for PlaceBuilder<'tcx> {
- fn from(base: PlaceBase) -> Self {
- Self { base, projection: Vec::new() }
+impl<'tcx> From<Place<'tcx>> for PlaceBuilder<'tcx> {
+ fn from(p: Place<'tcx>) -> Self {
+ Self::Local { local: p.local, projection: p.projection.to_vec() }
}
}
-impl<'tcx> From<Place<'tcx>> for PlaceBuilder<'tcx> {
- fn from(p: Place<'tcx>) -> Self {
- Self { base: PlaceBase::Local(p.local), projection: p.projection.to_vec() }
+fn project_ty<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ elem: PlaceElem<'tcx>,
+) -> (Ty<'tcx>, Option<VariantIdx>) {
+ match elem {
+ ProjectionElem::Deref => {
+ let updated_ty = ty
+ .builtin_deref(true)
+ .unwrap_or_else(|| bug!("deref projection of non-dereferenceable ty {:?}", ty))
+ .ty;
+
+ (updated_ty, None)
+ }
+ ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
+ (ty.builtin_index().unwrap(), None)
+ }
+ ProjectionElem::Subslice { from, to, from_end } => {
+ let ty = match ty.kind() {
+ ty::Slice(..) => ty,
+ ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
+ ty::Array(inner, size) if from_end => {
+ let size = size.eval_usize(tcx, ty::ParamEnv::empty());
+ let len = size - (from as u64) - (to as u64);
+ tcx.mk_array(*inner, len)
+ }
+ _ => bug!("cannot subslice non-array type: `{:?}`", ty),
+ };
+
+ (ty, None)
+ }
+ ProjectionElem::Downcast(_, variant_idx) => (ty, Some(variant_idx)),
+ ProjectionElem::Field(_, ty) => (ty, None),
+ ProjectionElem::OpaqueCast(..) => bug!("didn't expect OpaqueCast"),
+ }
+}
+
+fn local_projections_to_ty<'a, 'tcx>(
+ cx: &'a Builder<'a, 'tcx>,
+ local: Local,
+ projection: &'a [PlaceElem<'tcx>],
+) -> (Ty<'tcx>, Option<VariantIdx>) {
+ let local_ty = cx.local_decls.local_decls()[local].ty;
+ projection.iter().fold((local_ty, None), |ty_variant_idx, elem| {
+ let ty = ty_variant_idx.0;
+ project_ty(cx.tcx, ty, *elem)
+ })
+}
+
+// Converts an `UpvarProjectionElem` to `PlaceElem`, ICE'ing when being passed a
+// field projection.
+fn upvar_proj_to_place_elem_no_field_proj<'tcx>(
+ upvar_proj: UpvarProjectionElem<'tcx>,
+) -> PlaceElem<'tcx> {
+ match upvar_proj {
+ ProjectionElem::Deref => ProjectionElem::Deref,
+ ProjectionElem::Index(i) => ProjectionElem::Index(i),
+ ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
+ ProjectionElem::ConstantIndex { offset, min_length, from_end }
+ }
+ ProjectionElem::Subslice { from, to, from_end } => {
+ ProjectionElem::Subslice { from, to, from_end }
+ }
+ ProjectionElem::Downcast(ty, variant_idx) => ProjectionElem::Downcast(ty, variant_idx),
+ ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
+ ProjectionElem::Field(..) => bug!("should not be called with `ProjectionElem::Field`"),
}
}
self.expr_as_place(block, expr, Mutability::Not, None)
}
+ #[instrument(skip(self, fake_borrow_temps), level = "debug")]
fn expr_as_place(
&mut self,
mut block: BasicBlock,
mutability: Mutability,
fake_borrow_temps: Option<&mut Vec<Local>>,
) -> BlockAnd<PlaceBuilder<'tcx>> {
- debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability);
-
let this = self;
let expr_span = expr.span;
let source_info = this.source_info(expr_span);
let lhs = &this.thir[lhs];
let mut place_builder =
unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
+ debug!(?place_builder);
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
if adt_def.is_enum() {
place_builder = place_builder.downcast(*adt_def, variant_index);
}
}
- block.and(place_builder.field(name, expr.ty))
+ block.and(place_builder.field(this, name))
}
ExprKind::Deref { arg } => {
let place_builder = unpack!(
}
/// Lower a captured upvar. Note we might not know the actual capture index,
- /// so we create a place starting from `PlaceBase::Upvar`, which will be resolved
+ /// so we create a place starting from `Upvar`, which will be resolved
/// once all projections that allow us to identify a capture have been applied.
fn lower_captured_upvar(
&mut self,
closure_def_id: LocalDefId,
var_hir_id: LocalVarId,
) -> BlockAnd<PlaceBuilder<'tcx>> {
- block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id }))
+ block.and(PlaceBuilder::Upvar {
+ upvar: Upvar { var_hir_id, closure_def_id },
+ projection: vec![],
+ })
}
/// Lower an index expression
source_info: SourceInfo,
) {
let tcx = self.tcx;
-
let place_ty = base_place.ty(&self.local_decls, tcx);
+
if let ty::Slice(_) = place_ty.ty.kind() {
// We need to create fake borrows to ensure that the bounds
// check that we just did stays valid. Since we can't assign to
use rustc_middle::ty::util::IntTypeExt;
use rustc_target::abi::{Abi, Primitive};
-use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
-use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
+use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary, PlaceBuilder};
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::region;
use rustc_middle::mir::AssertKind;
let exchange_malloc = Operand::function_handle(
tcx,
tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)),
- ty::List::empty(),
+ [],
expr_span,
);
let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span);
let arg_place_builder = unpack!(block = this.as_place_builder(block, arg));
- let mutability = match arg_place_builder.base() {
+ let mutability = match arg_place_builder {
// We are capturing a path that starts off a local variable in the parent.
// The mutability of the current capture is same as the mutability
// of the local declaration in the parent.
- PlaceBase::Local(local) => this.local_decls[local].mutability,
+ PlaceBuilder::Local { local, .. } => this.local_decls[local].mutability,
// Parent is a closure and we are capturing a path that is captured
// by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure.
- PlaceBase::Upvar { .. } => {
+ PlaceBuilder::Upvar { .. } => {
let enclosing_upvars_resolved = arg_place_builder.to_place(this);
match enclosing_upvars_resolved.as_ref() {
LogicalOp::And => (else_block, shortcircuit_block),
LogicalOp::Or => (shortcircuit_block, else_block),
};
- let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1);
+ let term = TerminatorKind::if_(lhs, blocks.0, blocks.1);
this.cfg.terminate(block, source_info, term);
this.cfg.push_assign_constant(
// base-supplied field, generate an operand that
// reads it from the base.
iter::zip(field_names, &**field_types)
- .map(|(n, ty)| match fields_map.get(&n) {
+ .map(|(n, _ty)| match fields_map.get(&n) {
Some(v) => v.clone(),
None => {
- let place = place_builder.clone_project(PlaceElem::Field(n, *ty));
- this.consume_by_copy_or_move(place.to_place(this))
+ let place_builder = place_builder.clone();
+ this.consume_by_copy_or_move(
+ place_builder.field(this, n).to_place(this),
+ )
}
})
.collect()
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Builds a block of MIR statements to evaluate the THIR `expr`.
- /// If the original expression was an AST statement,
- /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
- /// span of that statement (including its semicolon, if any).
- /// The scope is used if a statement temporary must be dropped.
+ ///
+ /// The `statement_scope` is used if a statement temporary must be dropped.
pub(crate) fn stmt_expr(
&mut self,
mut block: BasicBlock,
mod util;
use std::borrow::Borrow;
-use std::convert::TryFrom;
use std::mem;
impl<'a, 'tcx> Builder<'a, 'tcx> {
let then_block = this.cfg.start_new_block();
let else_block = this.cfg.start_new_block();
- let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
+ let term = TerminatorKind::if_(operand, then_block, else_block);
let source_info = this.source_info(expr_span);
this.cfg.terminate(block, source_info, term);
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place_builder = match_pair.place.downcast(adt_def, variant_index);
- candidate
- .match_pairs
- .extend(self.field_match_pairs(place_builder, subpatterns));
+ let field_match_pairs =
+ self.field_match_pairs(place_builder.clone(), subpatterns);
+ candidate.match_pairs.extend(field_match_pairs);
Ok(())
} else {
Err(match_pair)
self.source_info(match_start_span),
TerminatorKind::SwitchInt {
discr: Operand::Move(discr),
- switch_ty: discr_ty,
targets: switch_targets,
},
);
0 => (second_bb, first_bb),
v => span_bug!(test.span, "expected boolean value but got {:?}", v),
};
- TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb)
+ TerminatorKind::if_(Operand::Copy(place), true_bb, false_bb)
} else {
// The switch may be inexhaustive so we have a catch all block
debug_assert_eq!(options.len() + 1, target_blocks.len());
);
TerminatorKind::SwitchInt {
discr: Operand::Copy(place),
- switch_ty,
targets: switch_targets,
}
};
self.cfg.terminate(
block,
source_info,
- TerminatorKind::if_(self.tcx, Operand::Move(result), success_block, fail_block),
+ TerminatorKind::if_(Operand::Move(result), success_block, fail_block),
);
}
self.cfg.terminate(
eq_block,
source_info,
- TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block),
+ TerminatorKind::if_(Operand::Move(eq_result), success_block, fail_block),
);
}
//
// FIXME(#29623) we could use PatKind::Range to rule
// things out here, in some cases.
- (
- &TestKind::SwitchInt { switch_ty: _, ref options },
- &PatKind::Constant { ref value },
- ) if is_switch_ty(match_pair.pattern.ty) => {
+ (TestKind::SwitchInt { switch_ty: _, options }, PatKind::Constant { value })
+ if is_switch_ty(match_pair.pattern.ty) =>
+ {
let index = options.get_index_of(value).unwrap();
self.candidate_without_match_pair(match_pair_index, candidate);
Some(index)
}
- (&TestKind::SwitchInt { switch_ty: _, ref options }, &PatKind::Range(ref range)) => {
+ (TestKind::SwitchInt { switch_ty: _, options }, PatKind::Range(range)) => {
let not_contained =
self.values_not_contained_in_range(&*range, options).unwrap_or(false);
(
&TestKind::Len { len: test_len, op: BinOp::Eq },
- &PatKind::Slice { ref prefix, ref slice, ref suffix },
+ PatKind::Slice { prefix, slice, suffix },
) => {
let pat_len = (prefix.len() + suffix.len()) as u64;
match (test_len.cmp(&pat_len), slice) {
(
&TestKind::Len { len: test_len, op: BinOp::Ge },
- &PatKind::Slice { ref prefix, ref slice, ref suffix },
+ PatKind::Slice { prefix, slice, suffix },
) => {
// the test is `$actual_len >= test_len`
let pat_len = (prefix.len() + suffix.len()) as u64;
}
}
- (&TestKind::Range(ref test), &PatKind::Range(ref pat)) => {
+ (TestKind::Range(test), PatKind::Range(pat)) => {
use std::cmp::Ordering::*;
if test == pat {
no_overlap
}
- (&TestKind::Range(ref range), &PatKind::Constant { value }) => {
+ (TestKind::Range(range), &PatKind::Constant { value }) => {
if let Some(false) = self.const_range_contains(&*range, value) {
// `value` is not contained in the testing range,
// so `value` can be matched only if this test fails.
let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0`
- let place = downcast_place
- .clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty));
+ let place = downcast_place.clone().field(self, subpattern.field);
// e.g., `(x as Variant).0 @ P1`
MatchPair::new(place, &subpattern.pattern, self)
});
method_name: Symbol,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> ConstantKind<'tcx> {
- let substs = tcx.mk_substs(substs.into_iter().map(Into::into));
-
// The unhygienic comparison here is acceptable because this is only
// used on known traits.
let item = tcx
-use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::matches::MatchPair;
use crate::build::Builder;
use rustc_middle::ty;
use rustc_middle::ty::TypeVisitable;
use smallvec::SmallVec;
-use std::convert::TryInto;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub(crate) fn field_match_pairs<'pat>(
subpatterns
.iter()
.map(|fieldpat| {
- let place =
- place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
+ let place = place.clone().field(self, fieldpat.field);
+
MatchPair::new(place, &fieldpat.pattern, self)
})
.collect()
// Only add the OpaqueCast projection if the given place is an opaque type and the
// expected type from the pattern is not.
- let may_need_cast = match place.base() {
- PlaceBase::Local(local) => {
- let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
+ let may_need_cast = match place {
+ PlaceBuilder::Local { local, ref projection } => {
+ let ty = Place::ty_from(local, projection, &cx.local_decls, cx.tcx).ty;
ty != pattern.ty && ty.has_opaque_types()
}
_ => true,
return custom::build_custom_mir(
tcx,
fn_def.did.to_def_id(),
+ fn_id,
thir,
expr,
arguments,
use crate::build::ExprCategory;
+use crate::errors::*;
use rustc_middle::thir::visit::{self, Visitor};
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_middle::mir::BorrowKind;
use rustc_middle::thir::*;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
-use std::borrow::Cow;
use std::ops::Bound;
struct UnsafetyVisitor<'a, 'tcx> {
self.warn_unused_unsafe(
hir_id,
block_span,
- Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")),
+ Some(UnusedUnsafeEnclosing::Block {
+ span: self.tcx.sess.source_map().guess_head_span(enclosing_span),
+ }),
);
f(self);
} else {
hir_id,
span,
if self.unsafe_op_in_unsafe_fn_allowed() {
- self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn"))
+ self.body_unsafety
+ .unsafe_fn_sig_span()
+ .map(|span| UnusedUnsafeEnclosing::Function { span })
} else {
None
},
}
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
SafetyContext::UnsafeFn => {
- let (description, note) = kind.description_and_note(self.tcx);
// unsafe_op_in_unsafe_fn is disallowed
- self.tcx.struct_span_lint_hir(
- UNSAFE_OP_IN_UNSAFE_FN,
- self.hir_context,
- span,
- format!("{} is unsafe and requires unsafe block (error E0133)", description,),
- |lint| lint.span_label(span, kind.simple_description()).note(note),
- )
+ kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span);
}
SafetyContext::Safe => {
- let (description, note) = kind.description_and_note(self.tcx);
- let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
- struct_span_err!(
- self.tcx.sess,
- span,
- E0133,
- "{} is unsafe and requires unsafe{} block",
- description,
- fn_sugg,
- )
- .span_label(span, kind.simple_description())
- .note(note)
- .emit();
+ kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed);
}
}
}
&self,
hir_id: hir::HirId,
block_span: Span,
- enclosing_unsafe: Option<(Span, &'static str)>,
+ enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
) {
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
- let msg = "unnecessary `unsafe` block";
- self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| {
- lint.span_label(block_span, msg);
- if let Some((span, kind)) = enclosing_unsafe {
- lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
- }
- lint
- });
+ self.tcx.emit_spanned_lint(
+ UNUSED_UNSAFE,
+ hir_id,
+ block_span,
+ UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe },
+ );
}
/// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
fn unsafe_op_in_unsafe_fn_allowed(&self) -> bool {
self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, self.hir_context).0 == Level::Allow
}
+
+ /// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
+ fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
+ if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
+ let inner_thir = &inner_thir.borrow();
+ let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did);
+ let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
+ inner_visitor.visit_expr(&inner_thir[expr]);
+ // Unsafe blocks can be used in the inner body, make sure to take it into account
+ self.safety_context = inner_visitor.safety_context;
+ }
+ }
}
// Searches for accesses to layout constrained fields.
} else {
ty::WithOptConstParam::unknown(closure_id)
};
- let (closure_thir, expr) = self.tcx.thir_body(closure_def).unwrap_or_else(|_| {
- (self.tcx.alloc_steal_thir(Thir::new()), ExprId::from_u32(0))
- });
- let closure_thir = &closure_thir.borrow();
- let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
- let mut closure_visitor =
- UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
- closure_visitor.visit_expr(&closure_thir[expr]);
- // Unsafe blocks can be used in closures, make sure to take it into account
- self.safety_context = closure_visitor.safety_context;
+ self.visit_inner_body(closure_def);
+ }
+ ExprKind::ConstBlock { did, substs: _ } => {
+ let def_id = did.expect_local();
+ self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
}
ExprKind::Field { lhs, .. } => {
let lhs = &self.thir[lhs];
use UnsafeOpKind::*;
impl UnsafeOpKind {
- pub fn simple_description(&self) -> &'static str {
- match self {
- CallToUnsafeFunction(..) => "call to unsafe function",
- UseOfInlineAssembly => "use of inline assembly",
- InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr",
- UseOfMutableStatic => "use of mutable static",
- UseOfExternStatic => "use of extern static",
- DerefOfRawPointer => "dereference of raw pointer",
- AccessToUnionField => "access to union field",
- MutationOfLayoutConstrainedField => "mutation of layout constrained field",
- BorrowOfLayoutConstrainedField => {
- "borrow of layout constrained field with interior mutability"
- }
- CallToFunctionWith(..) => "call to function with `#[target_feature]`",
- }
- }
-
- pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) {
+ pub fn emit_unsafe_op_in_unsafe_fn_lint(
+ &self,
+ tcx: TyCtxt<'_>,
+ hir_id: hir::HirId,
+ span: Span,
+ ) {
match self {
- CallToUnsafeFunction(did) => (
- if let Some(did) = did {
- Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did)))
- } else {
- Cow::Borrowed(self.simple_description())
+ CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
+ span,
+ function: &tcx.def_path_str(did.unwrap()),
},
- "consult the function's documentation for information on how to avoid undefined \
- behavior",
),
- UseOfInlineAssembly => (
- Cow::Borrowed(self.simple_description()),
- "inline assembly is entirely unchecked and can cause undefined behavior",
+ CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span },
),
- InitializingTypeWith => (
- Cow::Borrowed(self.simple_description()),
- "initializing a layout restricted type's field with a value outside the valid \
- range is undefined behavior",
+ UseOfInlineAssembly => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span },
),
- UseOfMutableStatic => (
- Cow::Borrowed(self.simple_description()),
- "mutable statics can be mutated by multiple threads: aliasing violations or data \
- races will cause undefined behavior",
+ InitializingTypeWith => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span },
),
- UseOfExternStatic => (
- Cow::Borrowed(self.simple_description()),
- "extern statics are not controlled by the Rust type system: invalid data, \
- aliasing violations or data races will cause undefined behavior",
+ UseOfMutableStatic => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span },
),
- DerefOfRawPointer => (
- Cow::Borrowed(self.simple_description()),
- "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
- and cause data races: all of these are undefined behavior",
+ UseOfExternStatic => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span },
),
- AccessToUnionField => (
- Cow::Borrowed(self.simple_description()),
- "the field may not be properly initialized: using uninitialized data will cause \
- undefined behavior",
+ DerefOfRawPointer => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span },
+ ),
+ AccessToUnionField => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span },
),
- MutationOfLayoutConstrainedField => (
- Cow::Borrowed(self.simple_description()),
- "mutating layout constrained fields cannot statically be checked for valid values",
+ MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span },
),
- BorrowOfLayoutConstrainedField => (
- Cow::Borrowed(self.simple_description()),
- "references to fields of layout constrained fields lose the constraints. Coupled \
- with interior mutability, the field can be changed to invalid values",
+ BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span },
),
- CallToFunctionWith(did) => (
- Cow::from(format!(
- "call to function `{}` with `#[target_feature]`",
- tcx.def_path_str(*did)
- )),
- "can only be called if the required target features are available",
+ CallToFunctionWith(did) => tcx.emit_spanned_lint(
+ UNSAFE_OP_IN_UNSAFE_FN,
+ hir_id,
+ span,
+ UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
+ span,
+ function: &tcx.def_path_str(*did),
+ },
),
}
}
+
+ pub fn emit_requires_unsafe_err(
+ &self,
+ tcx: TyCtxt<'_>,
+ span: Span,
+ unsafe_op_in_unsafe_fn_allowed: bool,
+ ) {
+ match self {
+ CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ span,
+ function: &tcx.def_path_str(did.unwrap()),
+ });
+ }
+ CallToUnsafeFunction(did) if did.is_some() => {
+ tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe {
+ span,
+ function: &tcx.def_path_str(did.unwrap()),
+ });
+ }
+ CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess.emit_err(
+ CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span },
+ );
+ }
+ CallToUnsafeFunction(..) => {
+ tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span });
+ }
+ UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ UseOfInlineAssembly => {
+ tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span });
+ }
+ InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ InitializingTypeWith => {
+ tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span });
+ }
+ UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ UseOfMutableStatic => {
+ tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span });
+ }
+ UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ UseOfExternStatic => {
+ tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span });
+ }
+ DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ DerefOfRawPointer => {
+ tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span });
+ }
+ AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess
+ .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span });
+ }
+ AccessToUnionField => {
+ tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span });
+ }
+ MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess.emit_err(
+ MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ span,
+ },
+ );
+ }
+ MutationOfLayoutConstrainedField => {
+ tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span });
+ }
+ BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess.emit_err(
+ BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span },
+ );
+ }
+ BorrowOfLayoutConstrainedField => {
+ tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span });
+ }
+ CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => {
+ tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ span,
+ function: &tcx.def_path_str(*did),
+ });
+ }
+ CallToFunctionWith(did) => {
+ tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe {
+ span,
+ function: &tcx.def_path_str(*did),
+ });
+ }
+ }
+ }
}
pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {
return;
}
- // Closures are handled by their owner, if it has a body
- if tcx.is_closure(def.did.to_def_id()) {
- let hir = tcx.hir();
- let owner = hir.enclosing_body_owner(hir.local_def_id_to_hir_id(def.did));
- tcx.ensure().thir_check_unsafety(owner);
+ // Closures and inline consts are handled by their owner, if it has a body
+ if tcx.is_typeck_child(def.did.to_def_id()) {
return;
}
--- /dev/null
+use crate::thir::pattern::MatchCheckCtxt;
+use rustc_errors::Handler;
+use rustc_errors::{
+ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
+};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{self, Ty};
+use rustc_span::{symbol::Ident, Span};
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unconditional_recursion)]
+#[help]
+pub struct UnconditionalRecursion {
+ #[label]
+ pub span: Span,
+ #[label(mir_build_unconditional_recursion_call_site_label)]
+ pub call_sites: Vec<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)]
+pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
+#[note]
+pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+ mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed,
+ code = "E0133"
+)]
+#[note]
+pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfInlineAssemblyRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")]
+#[note]
+pub struct InitializingTypeWithRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+ code = "E0133"
+)]
+#[note]
+pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfMutableStaticRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")]
+#[note]
+pub struct UseOfExternStaticRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")]
+#[note]
+pub struct DerefOfRawPointerRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_union_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct AccessToUnionFieldRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+ code = "E0133"
+)]
+#[note]
+pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[note]
+pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+ mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
+ code = "E0133"
+)]
+#[note]
+pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
+#[note]
+pub struct CallToFunctionWithRequiresUnsafe<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[note]
+pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub function: &'a str,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unused_unsafe)]
+pub struct UnusedUnsafe {
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub enclosing: Option<UnusedUnsafeEnclosing>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedUnsafeEnclosing {
+ #[label(mir_build_unused_unsafe_enclosing_block_label)]
+ Block {
+ #[primary_span]
+ span: Span,
+ },
+ #[label(mir_build_unused_unsafe_enclosing_fn_label)]
+ Function {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
+ pub cx: &'m MatchCheckCtxt<'p, 'tcx>,
+ pub expr_span: Span,
+ pub span: Span,
+ pub ty: Ty<'tcx>,
+}
+
+impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ self.span,
+ rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty,
+ error_code!(E0004),
+ );
+
+ let peeled_ty = self.ty.peel_refs();
+ diag.set_arg("ty", self.ty);
+ diag.set_arg("peeled_ty", peeled_ty);
+
+ if let ty::Adt(def, _) = peeled_ty.kind() {
+ let def_span = self
+ .cx
+ .tcx
+ .hir()
+ .get_if_local(def.did())
+ .and_then(|node| node.ident())
+ .map(|ident| ident.span)
+ .unwrap_or_else(|| self.cx.tcx.def_span(def.did()));
+
+ // workaround to make test pass
+ let mut span: MultiSpan = def_span.into();
+ span.push_span_label(def_span, "");
+
+ diag.span_note(span, rustc_errors::fluent::def_note);
+ }
+
+ let is_variant_list_non_exhaustive = match self.ty.kind() {
+ ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => {
+ true
+ }
+ _ => false,
+ };
+
+ if is_variant_list_non_exhaustive {
+ diag.note(rustc_errors::fluent::non_exhaustive_type_note);
+ } else {
+ diag.note(rustc_errors::fluent::type_note);
+ }
+
+ if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
+ if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
+ diag.note(rustc_errors::fluent::reference_note);
+ }
+ }
+
+ let mut suggestion = None;
+ let sm = self.cx.tcx.sess.source_map();
+ if self.span.eq_ctxt(self.expr_span) {
+ // Get the span for the empty match body `{}`.
+ let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) {
+ (format!("\n{}", snippet), " ")
+ } else {
+ (" ".to_string(), "")
+ };
+ suggestion = Some((
+ self.span.shrink_to_hi().with_hi(self.expr_span.hi()),
+ format!(
+ " {{{indentation}{more}_ => todo!(),{indentation}}}",
+ indentation = indentation,
+ more = more,
+ ),
+ ));
+ }
+
+ if let Some((span, sugg)) = suggestion {
+ diag.span_suggestion_verbose(
+ span,
+ rustc_errors::fluent::suggestion,
+ sugg,
+ Applicability::HasPlaceholders,
+ );
+ } else {
+ diag.help(rustc_errors::fluent::help);
+ }
+
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_static_in_pattern, code = "E0158")]
+pub struct StaticInPattern {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_assoc_const_in_pattern, code = "E0158")]
+pub struct AssocConstInPattern {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_const_param_in_pattern, code = "E0158")]
+pub struct ConstParamInPattern {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_non_const_path, code = "E0080")]
+pub struct NonConstPath {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_unreachable_pattern)]
+pub struct UnreachablePattern {
+ #[label]
+ pub span: Option<Span>,
+ #[label(catchall_label)]
+ pub catchall: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_const_pattern_depends_on_generic_parameter)]
+pub struct ConstPatternDependsOnGenericParameter {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_could_not_eval_const_pattern)]
+pub struct CouldNotEvalConstPattern {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")]
+pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[note(teach_note)]
+ pub teach: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
+pub struct LowerRangeBoundMustBeLessThanUpper {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_leading_irrefutable_let_patterns)]
+#[note]
+#[help]
+pub struct LeadingIrrefutableLetPatterns {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_trailing_irrefutable_let_patterns)]
+#[note]
+#[help]
+pub struct TrailingIrrefutableLetPatterns {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_bindings_with_variant_name, code = "E0170")]
+pub struct BindingsWithVariantName {
+ #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")]
+ pub suggestion: Option<Span>,
+ pub ty_path: String,
+ pub ident: Ident,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_generic_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsGenericLet {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_if_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsIfLet {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_if_let_guard)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsIfLetGuard {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_let_else)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsLetElse {
+ pub count: usize,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(mir_build_irrefutable_let_patterns_while_let)]
+#[note]
+#[help]
+pub struct IrrefutableLetPatternsWhileLet {
+ pub count: usize,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_borrow_of_moved_value)]
+pub struct BorrowOfMovedValue<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ #[label(occurs_because_label)]
+ pub binding_span: Span,
+ #[label(value_borrowed_label)]
+ pub conflicts_ref: Vec<Span>,
+ pub name: Ident,
+ pub ty: Ty<'tcx>,
+ #[suggestion(code = "ref ", applicability = "machine-applicable")]
+ pub suggest_borrowing: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_multiple_mut_borrows)]
+pub struct MultipleMutBorrows {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub binding_span: Span,
+ #[subdiagnostic]
+ pub occurences: Vec<MultipleMutBorrowOccurence>,
+ pub name: Ident,
+}
+
+#[derive(Subdiagnostic)]
+pub enum MultipleMutBorrowOccurence {
+ #[label(mutable_borrow)]
+ Mutable {
+ #[primary_span]
+ span: Span,
+ name_mut: Ident,
+ },
+ #[label(immutable_borrow)]
+ Immutable {
+ #[primary_span]
+ span: Span,
+ name_immut: Ident,
+ },
+ #[label(moved)]
+ Moved {
+ #[primary_span]
+ span: Span,
+ name_moved: Ident,
+ },
+}
mod build;
mod check_unsafety;
+mod errors;
mod lints;
pub mod thir;
+use crate::errors::UnconditionalRecursion;
use rustc_data_structures::graph::iterate::{
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
};
let sp = tcx.def_span(def_id);
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- tcx.struct_span_lint_hir(
+ tcx.emit_spanned_lint(
UNCONDITIONAL_RECURSION,
hir_id,
sp,
- "function cannot return without recursing",
- |lint| {
- lint.span_label(sp, "cannot return without recursing");
- // offer some help to the programmer.
- for call_span in vis.reachable_recursive_calls {
- lint.span_label(call_span, "recursive call site");
- }
- lint.help("a `loop` may express intention better if this is on purpose")
- },
+ UnconditionalRecursion { span: sp, call_sites: vis.reachable_recursive_calls },
);
}
}
let str_bytes = s.as_str().as_bytes();
ty::ValTree::from_raw_bytes(tcx, str_bytes)
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Slice(_)) =>
{
let bytes = data as &[u8];
ty::ValTree::from_raw_bytes(tcx, bytes)
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
let bytes = data as &[u8];
ty::ValTree::from_raw_bytes(tcx, bytes)
}
hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
lhs: self.mirror_expr(source),
variant_index: VariantIdx::new(0),
- name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
+ name: Field::new(self.typeck_results.field_index(expr.hir_id)),
},
hir::ExprKind::Cast(ref source, ref cast_ty) => {
// Check for a user-given type annotation on this `cast`
fields
.iter()
.map(|field| FieldExpr {
- name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+ name: Field::new(self.typeck_results.field_index(field.hir_id)),
expr: self.mirror_expr(field.expr),
})
.collect()
};
use super::{PatCtxt, PatternError};
+use crate::errors::*;
+
use rustc_arena::TypedArena;
use rustc_ast::Mutability;
use rustc_errors::{
- error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder,
- ErrorGuaranteed, MultiSpan,
+ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+ MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::*;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Pat};
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+
use rustc_session::lint::builtin::{
BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
};
for error in &self.errors {
match *error {
PatternError::StaticInPattern(span) => {
- self.span_e0158(span, "statics cannot be referenced in patterns")
+ self.tcx.sess.emit_err(StaticInPattern { span });
}
PatternError::AssocConstInPattern(span) => {
- self.span_e0158(span, "associated consts cannot be referenced in patterns")
+ self.tcx.sess.emit_err(AssocConstInPattern { span });
}
PatternError::ConstParamInPattern(span) => {
- self.span_e0158(span, "const parameters cannot be referenced in patterns")
+ self.tcx.sess.emit_err(ConstParamInPattern { span });
}
PatternError::NonConstPath(span) => {
- rustc_middle::mir::interpret::struct_error(
- self.tcx.at(span),
- "runtime values cannot be referenced in patterns",
- )
- .emit();
+ self.tcx.sess.emit_err(NonConstPath { span });
}
}
}
}
-
- fn span_e0158(&self, span: Span, text: &str) {
- struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit();
- }
}
impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
);
return true;
}
- let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| {
- let span_start = affix[0].unwrap().0;
- let span_end = affix.last().unwrap().unwrap().0;
- let span = span_start.to(span_end);
- let cnt = affix.len();
- let s = pluralize!(cnt);
- cx.tcx.struct_span_lint_hir(
- IRREFUTABLE_LET_PATTERNS,
- top,
- span,
- format!("{kind} irrefutable pattern{s} in let chain"),
- |lint| {
- lint.note(format!(
- "{these} pattern{s} will always match",
- these = pluralize!("this", cnt),
- ))
- .help(format!(
- "consider moving {} {suggestion}",
- if cnt > 1 { "them" } else { "it" }
- ))
- },
- );
- };
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
// The chain has a non-zero prefix of irrefutable `let` statements.
if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
// Emit the lint
let prefix = &chain_refutabilities[..until];
- lint_affix(prefix, "leading", "outside of the construct");
+ let span_start = prefix[0].unwrap().0;
+ let span_end = prefix.last().unwrap().unwrap().0;
+ let span = span_start.to(span_end);
+ let count = prefix.len();
+ cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count });
}
}
if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) {
// The chain has a non-empty suffix of irrefutable `let` statements
let suffix = &chain_refutabilities[from + 1..];
- lint_affix(suffix, "trailing", "into the body");
+ let span_start = suffix[0].unwrap().0;
+ let span_end = suffix.last().unwrap().unwrap().0;
+ let span = span_start.to(span_end);
+ let count = suffix.len();
+ cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count });
}
true
}
})
{
let variant_count = edef.variants().len();
- cx.tcx.struct_span_lint_hir(
+ let ty_path = with_no_trimmed_paths!({
+ cx.tcx.def_path_str(edef.did())
+ });
+ cx.tcx.emit_spanned_lint(
BINDINGS_WITH_VARIANT_NAME,
p.hir_id,
p.span,
- DelayDm(|| format!(
- "pattern binding `{}` is named the same as one \
- of the variants of the type `{}`",
- ident, cx.tcx.def_path_str(edef.did())
- )),
- |lint| {
- let ty_path = cx.tcx.def_path_str(edef.did());
- lint.code(error_code!(E0170));
-
+ BindingsWithVariantName {
// If this is an irrefutable pattern, and there's > 1 variant,
// then we can't actually match on this. Applying the below
// suggestion would produce code that breaks on `check_irrefutable`.
- if rf == Refutable || variant_count == 1 {
- lint.span_suggestion(
- p.span,
- "to match on the variant, qualify the path",
- format!("{}::{}", ty_path, ident),
- Applicability::MachineApplicable,
- );
- }
-
- lint
+ suggestion: if rf == Refutable || variant_count == 1 {
+ Some(p.span)
+ } else { None },
+ ty_path,
+ ident,
},
)
}
}
fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
- tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| {
- if let Some(catchall) = catchall {
- // We had a catchall pattern, hint at that.
- lint.span_label(span, "unreachable pattern");
- lint.span_label(catchall, "matches any value");
- }
- lint
- });
+ tcx.emit_spanned_lint(
+ UNREACHABLE_PATTERNS,
+ id,
+ span,
+ UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
+ );
}
fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
span: Span,
) {
macro_rules! emit_diag {
- (
- $lint:expr,
- $source_name:expr,
- $note_sufix:expr,
- $help_sufix:expr
- ) => {{
- let s = pluralize!(count);
- let these = pluralize!("this", count);
- tcx.struct_span_lint_hir(
- IRREFUTABLE_LET_PATTERNS,
- id,
- span,
- format!("irrefutable {} pattern{s}", $source_name),
- |lint| {
- lint.note(&format!(
- "{these} pattern{s} will always match, so the {}",
- $note_sufix
- ))
- .help(concat!("consider ", $help_sufix))
- },
- )
+ ($lint:tt) => {{
+ tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count });
}};
}
match source {
- LetSource::GenericLet => {
- emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
- }
- LetSource::IfLet => {
- emit_diag!(
- lint,
- "`if let`",
- "`if let` is useless",
- "replacing the `if let` with a `let`"
- );
- }
- LetSource::IfLetGuard => {
- emit_diag!(
- lint,
- "`if let` guard",
- "guard is useless",
- "removing the guard and adding a `let` inside the match arm"
- );
- }
- LetSource::LetElse => {
- emit_diag!(
- lint,
- "`let...else`",
- "`else` clause is useless",
- "removing the `else` clause"
- );
- }
- LetSource::WhileLet => {
- emit_diag!(
- lint,
- "`while let`",
- "loop will never exit",
- "instead using a `loop { ... }` with a `let` inside it"
- );
- }
- };
+ LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet),
+ LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
+ LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
+ LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
+ LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet),
+ }
}
fn is_let_irrefutable<'p, 'tcx>(
// informative.
let mut err;
let pattern;
- let mut patterns_len = 0;
+ let patterns_len;
if is_empty_match && !non_empty_enum {
- err = create_e0004(
- cx.tcx.sess,
- sp,
- format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
- );
- pattern = "_".to_string();
+ cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty {
+ cx,
+ expr_span,
+ span: sp,
+ ty: scrut_ty,
+ });
+ return;
} else {
+ // FIXME: migration of this diagnostic will require list support
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
err = create_e0004(
cx.tcx.sess,
}
});
if !conflicts_ref.is_empty() {
- let occurs_because = format!(
- "move occurs because `{}` has type `{}` which does not implement the `Copy` trait",
+ sess.emit_err(BorrowOfMovedValue {
+ span: pat.span,
+ binding_span,
+ conflicts_ref,
name,
- typeck_results.node_type(pat.hir_id),
- );
- let mut err = sess.struct_span_err(pat.span, "borrow of moved value");
- err.span_label(binding_span, format!("value moved into `{}` here", name))
- .span_label(binding_span, occurs_because)
- .span_labels(conflicts_ref, "value borrowed here after move");
- if pat.span.contains(binding_span) {
- err.span_suggestion_verbose(
- binding_span.shrink_to_lo(),
- "borrow this binding in the pattern to avoid moving the value",
- "ref ".to_string(),
- Applicability::MachineApplicable,
- );
- }
- err.emit();
+ ty: typeck_results.node_type(pat.hir_id),
+ suggest_borrowing: pat
+ .span
+ .contains(binding_span)
+ .then(|| binding_span.shrink_to_lo()),
+ });
}
return;
}
// Report errors if any.
if !conflicts_mut_mut.is_empty() {
// Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
- let mut err = sess
- .struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time");
- err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name));
- for (span, name) in conflicts_mut_mut {
- err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name));
+ let mut occurences = vec![];
+
+ for (span, name_mut) in conflicts_mut_mut {
+ occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut });
}
- for (span, name) in conflicts_mut_ref {
- err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name));
+ for (span, name_immut) in conflicts_mut_ref {
+ occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut });
}
- for (span, name) in conflicts_move {
- err.span_label(span, format!("also moved into `{}` here", name));
+ for (span, name_moved) in conflicts_move {
+ occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved });
}
- err.emit();
+ sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name });
} else if !conflicts_mut_ref.is_empty() {
// Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
let (primary, also) = match mut_outer {
ty::Dynamic(..) => {
"trait objects cannot be used in patterns".to_string()
}
- ty::Opaque(..) => {
+ ty::Alias(ty::Opaque, ..) => {
"opaque types cannot be used in patterns".to_string()
}
ty::Closure(..) => {
use std::cell::Cell;
use std::cmp::{self, max, min, Ordering};
use std::fmt;
-use std::iter::{once, IntoIterator};
+use std::iter::once;
use std::ops::RangeInclusive;
use smallvec::{smallvec, SmallVec};
mod usefulness;
pub(crate) use self::check_match::check_match;
+pub(crate) use self::usefulness::MatchCheckCtxt;
+use crate::errors::*;
use crate::thir::util::UserAnnotatedTyHelpers;
-use rustc_errors::struct_span_err;
+use rustc_errors::error_code;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
}
// `x..y` where `x >= y`. The range is empty => error.
(RangeEnd::Excluded, _) => {
- struct_span_err!(
- self.tcx.sess,
- span,
- E0579,
- "lower range bound must be less than upper"
- )
- .emit();
+ self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span });
PatKind::Wild
}
// `x..=y` where `x == y`.
}
// `x..=y` where `x > y` hence the range is empty => error.
(RangeEnd::Included, _) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
span,
- E0030,
- "lower range bound must be less than or equal to upper"
- );
- err.span_label(span, "lower bound larger than upper bound");
- if self.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note(
- "When matching against a range, the compiler \
- verifies that the range is non-empty. Range \
- patterns include both end-points, so this is \
- equivalent to requiring the start of the range \
- to be less than or equal to the end of the range.",
- );
- }
- err.emit();
+ teach: if self.tcx.sess.teach(&error_code!(E0030)) { Some(()) } else { None },
+ });
PatKind::Wild
}
}
let subpatterns = fields
.iter()
.map(|field| FieldPat {
- field: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+ field: Field::new(self.typeck_results.field_index(field.hir_id)),
pattern: self.lower_pattern(&field.pat),
})
.collect();
}
Err(_) => {
- self.tcx.sess.span_err(span, "could not evaluate constant pattern");
+ self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
return pat_from_kind(PatKind::Wild);
}
};
Err(ErrorHandled::TooGeneric) => {
// While `Reported | Linted` cases will have diagnostics emitted already
// it is not true for TooGeneric case, so we need to give user more information.
- self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+ self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
pat_from_kind(PatKind::Wild)
}
Err(_) => {
- self.tcx.sess.span_err(span, "could not evaluate constant pattern");
+ self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
pat_from_kind(PatKind::Wild)
}
}
mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
mir::ConstantKind::Unevaluated(..) => {
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
- self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
+ self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
return PatKind::Wild;
}
}
// Opaque types can't get destructured/split, but the patterns can
// actually hint at hidden types, so we use the patterns' types instead.
- if let ty::Opaque(..) = ty.kind() {
+ if let ty::Alias(ty::Opaque, ..) = ty.kind() {
if let Some(row) = rows.first() {
ty = row.head().ty();
}
None
}
-/// When enumerating the child fragments of a path, don't recurse into
-/// paths (1.) past arrays, slices, and pointers, nor (2.) into a type
-/// that implements `Drop`.
-///
-/// Places behind references or arrays are not tracked by elaboration
-/// and are always assumed to be initialized when accessible. As
-/// references and indexes can be reseated, trying to track them can
-/// only lead to trouble.
-///
-/// Places behind ADT's with a Drop impl are not tracked by
-/// elaboration since they can never have a drop-flag state that
-/// differs from that of the parent with the Drop impl.
-///
-/// In both cases, the contents can only be accessed if and only if
-/// their parents are initialized. This implies for example that there
-/// is no need to maintain separate drop flags to track such state.
-//
-// FIXME: we have to do something for moving slice patterns.
-fn place_contents_drop_state_cannot_differ<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
- place: mir::Place<'tcx>,
-) -> bool {
- let ty = place.ty(body, tcx).ty;
- match ty.kind() {
- ty::Array(..) => {
- debug!(
- "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
- place, ty
- );
- false
- }
- ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
- debug!(
- "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
- place, ty
- );
- true
- }
- ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
- debug!(
- "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
- place, ty
- );
- true
- }
- _ => false,
- }
-}
-
pub fn on_lookup_result_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
) where
F: FnMut(MovePathIndex),
{
+ #[inline]
fn is_terminal_path<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
path: MovePathIndex,
) -> bool {
- place_contents_drop_state_cannot_differ(tcx, body, move_data.move_paths[path].place)
+ let place = move_data.move_paths[path].place;
+
+ // When enumerating the child fragments of a path, don't recurse into
+ // paths (1.) past arrays, slices, and pointers, nor (2.) into a type
+ // that implements `Drop`.
+ //
+ // Places behind references or arrays are not tracked by elaboration
+ // and are always assumed to be initialized when accessible. As
+ // references and indexes can be reseated, trying to track them can
+ // only lead to trouble.
+ //
+ // Places behind ADT's with a Drop impl are not tracked by
+ // elaboration since they can never have a drop-flag state that
+ // differs from that of the parent with the Drop impl.
+ //
+ // In both cases, the contents can only be accessed if and only if
+ // their parents are initialized. This implies for example that there
+ // is no need to maintain separate drop flags to track such state.
+ //
+ // FIXME: we have to do something for moving slice patterns.
+ let ty = place.ty(body, tcx).ty;
+ match ty.kind() {
+ ty::Adt(def, _) if (def.has_dtor(tcx) && !def.is_box()) || def.is_union() => {
+ debug!(
+ "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} Drop => true",
+ place, ty
+ );
+ true
+ }
+ ty::Array(..) => {
+ debug!(
+ "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
+ place, ty
+ );
+ false
+ }
+ ty::Slice(..) | ty::Ref(..) | ty::RawPtr(..) => {
+ debug!(
+ "place_contents_drop_state_cannot_differ place: {:?} ty: {:?} refd => true",
+ place, ty
+ );
+ true
+ }
+ _ => false,
+ }
}
fn on_all_children_bits<'tcx, F>(
source_info: self.source_info,
kind: TerminatorKind::SwitchInt {
discr: Operand::Move(discr),
- switch_ty: discr_ty,
targets: SwitchTargets::new(
values.iter().copied().zip(blocks.iter().copied()),
*blocks.last().unwrap(),
let drop_trait = tcx.require_lang_item(LangItem::Drop, None);
let drop_fn = tcx.associated_item_def_ids(drop_trait)[0];
let ty = self.place_ty(self.place);
- let substs = tcx.mk_substs_trait(ty, []);
let ref_ty =
tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut });
)],
terminator: Some(Terminator {
kind: TerminatorKind::Call {
- func: Operand::function_handle(tcx, drop_fn, substs, self.source_info.span),
+ func: Operand::function_handle(
+ tcx,
+ drop_fn,
+ [ty.into()],
+ self.source_info.span,
+ ),
args: vec![Operand::Move(Place::from(ref_place))],
destination: unit_temp,
target: Some(succ),
is_cleanup: unwind.is_cleanup(),
terminator: Some(Terminator {
source_info: self.source_info,
- kind: TerminatorKind::if_(tcx, move_(can_go), succ, drop_block),
+ kind: TerminatorKind::if_(move_(can_go), succ, drop_block),
}),
};
let loop_block = self.elaborator.patch().new_block(loop_block);
source_info: self.source_info,
kind: TerminatorKind::SwitchInt {
discr: move_(elem_size),
- switch_ty: tcx.types.usize,
targets: SwitchTargets::static_if(
0,
self.drop_loop_pair(ety, false, len),
DropStyle::Static => on_set,
DropStyle::Conditional | DropStyle::Open => {
let flag = self.elaborator.get_drop_flag(self.path).unwrap();
- let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset);
+ let term = TerminatorKind::if_(flag, on_set, on_unset);
self.new_block(unwind, term)
}
}
propagate(pred, &tmp);
}
- mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
+ mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
let mut applier = BackwardSwitchIntEdgeEffectsApplier {
body,
pred,
}
}
- SwitchInt { ref targets, ref discr, switch_ty: _ } => {
+ SwitchInt { ref targets, ref discr } => {
let mut applier = ForwardSwitchIntEdgeEffectsApplier {
exit_state,
targets,
//! ## `PartialOrd`
//!
//! Given that they represent partially ordered sets, you may be surprised that [`JoinSemiLattice`]
-//! and [`MeetSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This
+//! and [`MeetSemiLattice`] do not have [`PartialOrd`] as a supertrait. This
//! is because most standard library types use lexicographic ordering instead of set inclusion for
//! their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a
//! dataflow analysis, there's no need for a newtype wrapper with a custom `PartialOrd` impl. The
use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
+use std::borrow::Cow;
use std::cell::RefCell;
#[derive(Clone)]
-pub struct MaybeStorageLive {
- always_live_locals: BitSet<Local>,
+pub struct MaybeStorageLive<'a> {
+ always_live_locals: Cow<'a, BitSet<Local>>,
}
-impl MaybeStorageLive {
- pub fn new(always_live_locals: BitSet<Local>) -> Self {
+impl<'a> MaybeStorageLive<'a> {
+ pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
MaybeStorageLive { always_live_locals }
}
}
-impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
type Domain = BitSet<Local>;
const NAME: &'static str = "maybe_storage_live";
}
}
-impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive {
+impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
type Idx = Local;
fn statement_effect(
pub struct AbstractOperand;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct AbstractType;
-pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
+pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType, AbstractType>;
pub trait Lift {
type Abstract;
Field(Field),
}
-impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
+impl<V, T1, T2> TryFrom<ProjectionElem<V, T1, T2>> for TrackElem {
type Error = ();
- fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
+ fn try_from(value: ProjectionElem<V, T1, T2>) -> Result<Self, Self::Error> {
match value {
ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
_ => Err(()),
pub struct AddRetag;
-/// Determines whether this place is "stable": Whether, if we evaluate it again
-/// after the assignment, we can be sure to obtain the same place value.
-/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
-/// copies. Data races are UB.)
-fn is_stable(place: PlaceRef<'_>) -> bool {
- // Which place this evaluates to can change with any memory write,
- // so cannot assume deref to be stable.
- !place.has_deref()
-}
-
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &body.local_decls;
let needs_retag = |place: &Place<'tcx>| {
- // FIXME: Instead of giving up for unstable places, we should introduce
- // a temporary and retag on that.
- is_stable(place.as_ref())
+ !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
&& !local_decls[place.local].is_deref_temp()
};
- let place_base_raw = |place: &Place<'tcx>| {
- // If this is a `Deref`, get the type of what we are deref'ing.
- if place.has_deref() {
- let ty = &local_decls[place.local].ty;
- ty.is_unsafe_ptr()
- } else {
- // Not a deref, and thus not raw.
- false
- }
- };
// PART 1
// Retag arguments at the beginning of the start block.
}
// PART 2
- // Retag return values of functions. Also escape-to-raw the argument of `drop`.
+ // Retag return values of functions.
// We collect the return destinations because we cannot mutate while iterating.
let returns = basic_blocks
.iter_mut()
}
// PART 3
- // Add retag after assignment.
+ // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
for block_data in basic_blocks {
// We want to insert statements as we iterate. To this end, we
// iterate backwards using indices.
for i in (0..block_data.statements.len()).rev() {
let (retag_kind, place) = match block_data.statements[i].kind {
- // Retag-as-raw after escaping to a raw pointer, if the referent
- // is not already a raw pointer.
- StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
- if !place_base_raw(rplace) =>
- {
- (RetagKind::Raw, lplace)
- }
// Retag after assignments of reference type.
StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
- let kind = match rvalue {
- Rvalue::Ref(_, borrow_kind, _)
- if borrow_kind.allows_two_phase_borrow() =>
- {
- RetagKind::TwoPhase
- }
- _ => RetagKind::Default,
+ let add_retag = match rvalue {
+ // Ptr-creating operations already do their own internal retagging, no
+ // need to also add a retag statement.
+ Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
+ _ => true,
};
- (kind, *place)
+ if add_retag {
+ (RetagKind::Default, *place)
+ } else {
+ continue;
+ }
}
// Do nothing for the rest
_ => continue,
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::HirId;
use rustc_hir::intravisit;
self.super_rvalue(rvalue, location);
}
+ fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+ if let Operand::Constant(constant) = op {
+ let maybe_uneval = match constant.literal {
+ ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
+ ConstantKind::Unevaluated(uv, _) => Some(uv),
+ };
+
+ if let Some(uv) = maybe_uneval {
+ if uv.promoted.is_none() {
+ let def_id = uv.def.def_id_for_type_of();
+ if self.tcx.def_kind(def_id) == DefKind::InlineConst {
+ let local_def_id = def_id.expect_local();
+ let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
+ self.tcx.unsafety_check_result(local_def_id);
+ self.register_violations(violations, used_unsafe_blocks.iter().copied());
+ }
+ }
+ }
+ }
+ self.super_operand(op, location);
+ }
+
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
// On types with `scalar_valid_range`, prevent
// * `&mut x.field`
intravisit::walk_block(self, block);
}
+ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+ if matches!(self.tcx.def_kind(c.def_id), DefKind::InlineConst) {
+ self.visit_body(self.tcx.hir().body(c.body))
+ }
+ }
+
fn visit_fn(
&mut self,
fk: intravisit::FnKind<'tcx>,
// `mir_built` force this.
let body = &tcx.mir_built(def).borrow();
- if body.should_skip() {
+ if body.is_custom_mir() {
return tcx.arena.alloc(UnsafetyCheckResult {
violations: Vec::new(),
used_unsafe_blocks: FxHashSet::default(),
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
checker.visit_body(&body);
- let unused_unsafes = (!tcx.is_closure(def.did.to_def_id()))
+ let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
.then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
tcx.arena.alloc(UnsafetyCheckResult {
pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
debug!("check_unsafety({:?})", def_id);
- // closures are handled by their parent fn.
- if tcx.is_closure(def_id.to_def_id()) {
+ // closures and inline consts are handled by their parent fn.
+ if tcx.is_typeck_child(def_id.to_def_id()) {
return;
}
}
let target_bb_terminator = target_bb.terminator();
- let (discr, switch_ty, targets) = target_bb_terminator.kind.as_switch()?;
+ let (discr, targets) = target_bb_terminator.kind.as_switch()?;
if discr.place() == Some(*place) {
+ let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty;
// We now know that the Switch matches on the const place, and it is statementless
// Now find which value in the Switch matches the const value.
let const_value =
use either::Right;
use rustc_ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
use rustc_target::spec::abi::Abi as CallAbi;
use rustc_trait_selection::traits;
type MemoryKind = !;
#[inline(always)]
- fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+ fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
// We do not check for alignment to avoid having to carry an `Align`
// in `ConstValue::ByRef`.
- false
+ CheckAlignment::No
}
#[inline(always)]
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
false // for now, we don't enforce validity
}
+ fn alignment_check_failed(
+ ecx: &InterpCx<'mir, 'tcx, Self>,
+ _has: Align,
+ _required: Align,
+ _check: CheckAlignment,
+ ) -> InterpResult<'tcx, ()> {
+ span_bug!(
+ ecx.cur_span(),
+ "`alignment_check_failed` called when no alignment check requested"
+ )
+ }
fn load_mir(
_ecx: &InterpCx<'mir, 'tcx, Self>,
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
let val = Immediate::ScalarPair(
- const_arg.to_scalar().into(),
- Scalar::from_bool(false).into(),
+ const_arg.to_scalar(),
+ Scalar::from_bool(false),
);
this.ecx.write_immediate(val, &dest)
} else {
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty;
use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
// All `TEMP_BLOCK` targets should be replaced before calling `to_body() -> mir::Body`.
blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
dummy_place: Place<'tcx>,
next_local: usize,
- bool_ty: Ty<'tcx>,
}
impl<'tcx> MockBlocks<'tcx> {
blocks: IndexVec::new(),
dummy_place: Place { local: RETURN_PLACE, projection: ty::List::empty() },
next_local: 0,
- bool_ty: TyCtxt::BOOL_TY_FOR_UNIT_TESTING,
}
}
fn switchint(&mut self, some_from_block: Option<BasicBlock>) -> BasicBlock {
let switchint_kind = TerminatorKind::SwitchInt {
discr: Operand::Move(Place::from(self.new_temp())),
- switch_ty: self.bool_ty, // just a dummy value
targets: SwitchTargets::static_if(0, TEMP_BLOCK, TEMP_BLOCK),
};
self.add_block_from(some_from_block, switchint_kind)
//!
//! Currently, this pass only propagates scalar values.
+use rustc_const_eval::const_eval::CheckAlignment;
use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::visit::{MutVisitor, Visitor};
use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
use rustc_span::DUMMY_SP;
+use rustc_target::abi::Align;
use crate::MirPass;
type MemoryKind = !;
const PANIC_ON_ALLOC_FAIL: bool = true;
- fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+ fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
unimplemented!()
}
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
unimplemented!()
}
+ fn alignment_check_failed(
+ _ecx: &InterpCx<'mir, 'tcx, Self>,
+ _has: Align,
+ _required: Align,
+ _check: CheckAlignment,
+ ) -> interpret::InterpResult<'tcx, ()> {
+ unimplemented!()
+ }
fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
use std::collections::hash_map::{Entry, OccupiedEntry};
+use crate::simplify::remove_dead_blocks;
use crate::MirPass;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::{dump_mir, PassWhere};
use rustc_middle::mir::{
traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
Rvalue, Statement, StatementKind, TerminatorKind,
};
-use rustc_middle::mir::{
- visit::{MutVisitor, PlaceContext, Visitor},
- ProjectionElem,
-};
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::MaybeLiveLocals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
apply_merges(body, tcx, &merges, &merged_locals);
}
+ if round_count != 0 {
+ // Merging can introduce overlap between moved arguments and/or call destination in an
+ // unreachable code, which validator considers to be ill-formed.
+ remove_dead_blocks(tcx, body);
+ }
+
trace!(round_count);
}
}
// through these methods, and not directly.
impl<'alloc> Candidates<'alloc> {
/// Just `Vec::retain`, but the condition is inverted and we add debugging output
- fn vec_remove_debug(
+ fn vec_filter_candidates(
src: Local,
v: &mut Vec<Local>,
- mut f: impl FnMut(Local) -> bool,
+ mut f: impl FnMut(Local) -> CandidateFilter,
at: Location,
) {
v.retain(|dest| {
let remove = f(*dest);
- if remove {
+ if remove == CandidateFilter::Remove {
trace!("eliminating {:?} => {:?} due to conflict at {:?}", src, dest, at);
}
- !remove
+ remove == CandidateFilter::Keep
});
}
- /// `vec_remove_debug` but for an `Entry`
- fn entry_remove(
+ /// `vec_filter_candidates` but for an `Entry`
+ fn entry_filter_candidates(
mut entry: OccupiedEntry<'_, Local, Vec<Local>>,
p: Local,
- f: impl FnMut(Local) -> bool,
+ f: impl FnMut(Local) -> CandidateFilter,
at: Location,
) {
let candidates = entry.get_mut();
- Self::vec_remove_debug(p, candidates, f, at);
+ Self::vec_filter_candidates(p, candidates, f, at);
if candidates.len() == 0 {
entry.remove();
}
}
- /// Removes all candidates `(p, q)` or `(q, p)` where `p` is the indicated local and `f(q)` is true.
- fn remove_candidates_if(&mut self, p: Local, mut f: impl FnMut(Local) -> bool, at: Location) {
+ /// For all candidates `(p, q)` or `(q, p)` removes the candidate if `f(q)` says to do so
+ fn filter_candidates_by(
+ &mut self,
+ p: Local,
+ mut f: impl FnMut(Local) -> CandidateFilter,
+ at: Location,
+ ) {
// Cover the cases where `p` appears as a `src`
if let Entry::Occupied(entry) = self.c.entry(p) {
- Self::entry_remove(entry, p, &mut f, at);
+ Self::entry_filter_candidates(entry, p, &mut f, at);
}
// And the cases where `p` appears as a `dest`
let Some(srcs) = self.reverse.get_mut(&p) else {
// We use `retain` here to remove the elements from the reverse set if we've removed the
// matching candidate in the forward set.
srcs.retain(|src| {
- if !f(*src) {
+ if f(*src) == CandidateFilter::Keep {
return true;
}
let Entry::Occupied(entry) = self.c.entry(*src) else {
return false;
};
- Self::entry_remove(entry, *src, |dest| dest == p, at);
+ Self::entry_filter_candidates(
+ entry,
+ *src,
+ |dest| {
+ if dest == p { CandidateFilter::Remove } else { CandidateFilter::Keep }
+ },
+ at,
+ );
false
});
}
}
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum CandidateFilter {
+ Keep,
+ Remove,
+}
+
impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
/// Filters the set of candidates to remove those that conflict.
///
for (i, statement) in data.statements.iter().enumerate().rev() {
self.at = Location { block, statement_index: i };
self.live.seek_after_primary_effect(self.at);
- self.get_statement_write_info(&statement.kind);
+ self.write_info.for_statement(&statement.kind, self.body);
self.apply_conflicts();
}
}
fn apply_conflicts(&mut self) {
let writes = &self.write_info.writes;
for p in writes {
- self.candidates.remove_candidates_if(
+ let other_skip = self.write_info.skip_pair.and_then(|(a, b)| {
+ if a == *p {
+ Some(b)
+ } else if b == *p {
+ Some(a)
+ } else {
+ None
+ }
+ });
+ self.candidates.filter_candidates_by(
*p,
- // It is possible that a local may be live for less than the
- // duration of a statement This happens in the case of function
- // calls or inline asm. Because of this, we also mark locals as
- // conflicting when both of them are written to in the same
- // statement.
- |q| self.live.contains(q) || writes.contains(&q),
+ |q| {
+ if Some(q) == other_skip {
+ return CandidateFilter::Keep;
+ }
+ // It is possible that a local may be live for less than the
+ // duration of a statement This happens in the case of function
+ // calls or inline asm. Because of this, we also mark locals as
+ // conflicting when both of them are written to in the same
+ // statement.
+ if self.live.contains(q) || writes.contains(&q) {
+ CandidateFilter::Remove
+ } else {
+ CandidateFilter::Keep
+ }
+ },
self.at,
);
}
}
-
- /// Gets the write info for the `statement`.
- fn get_statement_write_info(&mut self, statement: &StatementKind<'tcx>) {
- self.write_info.writes.clear();
- match statement {
- StatementKind::Assign(box (lhs, rhs)) => match rhs {
- Rvalue::Use(op) => {
- if !lhs.is_indirect() {
- self.get_assign_use_write_info(*lhs, op);
- return;
- }
- }
- _ => (),
- },
- _ => (),
- }
-
- self.write_info.for_statement(statement);
- }
-
- fn get_assign_use_write_info(&mut self, lhs: Place<'tcx>, rhs: &Operand<'tcx>) {
- // We register the writes for the operand unconditionally
- self.write_info.add_operand(rhs);
- // However, we cannot do the same thing for the `lhs` as that would always block the
- // optimization. Instead, we consider removing candidates manually.
- let Some(rhs) = rhs.place() else {
- self.write_info.add_place(lhs);
- return;
- };
- // Find out which candidate pair we should skip, if any
- let Some((src, dest)) = places_to_candidate_pair(lhs, rhs, self.body) else {
- self.write_info.add_place(lhs);
- return;
- };
- self.candidates.remove_candidates_if(
- lhs.local,
- |other| {
- // Check if this is the candidate pair that should not be removed
- if (lhs.local == src && other == dest) || (lhs.local == dest && other == src) {
- return false;
- }
- // Otherwise, do the "standard" thing
- self.live.contains(other)
- },
- self.at,
- )
- }
}
/// Describes where a statement/terminator writes to
#[derive(Default, Debug)]
struct WriteInfo {
writes: Vec<Local>,
+ /// If this pair of locals is a candidate pair, completely skip processing it during this
+ /// statement. All other candidates are unaffected.
+ skip_pair: Option<(Local, Local)>,
}
impl WriteInfo {
- fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>) {
+ fn for_statement<'tcx>(&mut self, statement: &StatementKind<'tcx>, body: &Body<'tcx>) {
+ self.reset();
match statement {
StatementKind::Assign(box (lhs, rhs)) => {
self.add_place(*lhs);
match rhs {
- Rvalue::Use(op) | Rvalue::Repeat(op, _) => {
+ Rvalue::Use(op) => {
+ self.add_operand(op);
+ self.consider_skipping_for_assign_use(*lhs, op, body);
+ }
+ Rvalue::Repeat(op, _) => {
self.add_operand(op);
}
Rvalue::Cast(_, op, _)
}
}
+ fn consider_skipping_for_assign_use<'tcx>(
+ &mut self,
+ lhs: Place<'tcx>,
+ rhs: &Operand<'tcx>,
+ body: &Body<'tcx>,
+ ) {
+ let Some(rhs) = rhs.place() else {
+ return
+ };
+ if let Some(pair) = places_to_candidate_pair(lhs, rhs, body) {
+ self.skip_pair = Some(pair);
+ }
+ }
+
fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) {
- self.writes.clear();
+ self.reset();
match terminator {
TerminatorKind::SwitchInt { discr: op, .. }
| TerminatorKind::Assert { cond: op, .. } => {
Operand::Copy(_) | Operand::Constant(_) => (),
}
}
+
+ fn reset(&mut self) {
+ self.writes.clear();
+ self.skip_pair = None;
+ }
}
/////////////////////////////////////////////////////
// Candidate accumulation
-fn is_constant<'tcx>(place: Place<'tcx>) -> bool {
- place.projection.iter().all(|p| !matches!(p, ProjectionElem::Deref | ProjectionElem::Index(_)))
-}
-
/// If the pair of places is being considered for merging, returns the candidate which would be
/// merged in order to accomplish this.
///
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
)) = &statement.kind
{
- if !is_constant(*lhs) || !is_constant(*rhs) {
- return;
- }
-
let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else {
return;
};
let TerminatorKind::SwitchInt {
discr: parent_op,
- switch_ty: parent_ty,
targets: parent_targets
} = &bbs[parent].terminator().kind else {
unreachable!()
Operand::Copy(x) => Operand::Copy(*x),
Operand::Constant(x) => Operand::Constant(x.clone()),
};
+ let parent_ty = parent_op.ty(body.local_decls(), tcx);
let statements_before = bbs[parent].statements.len();
let parent_end = Location { block: parent, statement_index: statements_before };
// create temp to store inequality comparison between the two discriminants, `_t` in
// example above
let nequal = BinOp::Ne;
- let comp_res_type = nequal.ty(tcx, *parent_ty, opt_data.child_ty);
+ let comp_res_type = nequal.ty(tcx, parent_ty, opt_data.child_ty);
let comp_temp = patch.new_temp(comp_res_type, opt_data.child_source.span);
patch.add_statement(parent_end, StatementKind::StorageLive(comp_temp));
kind: TerminatorKind::SwitchInt {
// switch on the first discriminant, so we can mark the second one as dead
discr: parent_op,
- switch_ty: opt_data.child_ty,
targets: eq_targets,
},
}));
let false_case = eq_bb;
patch.patch_terminator(
parent,
- TerminatorKind::if_(
- tcx,
- Operand::Move(Place::from(comp_temp)),
- true_case,
- false_case,
- ),
+ TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case),
);
// generate StorageDead for the second_discriminant_temp not in use anymore
let bbs = &body.basic_blocks;
let TerminatorKind::SwitchInt {
targets,
- switch_ty: parent_ty,
- ..
+ discr: parent_discr,
} = &bbs[parent].terminator().kind else {
return None
};
+ let parent_ty = parent_discr.ty(body.local_decls(), tcx);
let parent_dest = {
let poss = targets.otherwise();
// If the fallthrough on the parent is trivially unreachable, we can let the
let (_, child) = targets.iter().next()?;
let child_terminator = &bbs[child].terminator();
let TerminatorKind::SwitchInt {
- switch_ty: child_ty,
targets: child_targets,
- ..
+ discr: child_discr,
} = &child_terminator.kind else {
return None
};
+ let child_ty = child_discr.ty(body.local_decls(), tcx);
if child_ty != parent_ty {
return None;
}
Some(OptimizationData {
destination,
child_place: *child_place,
- child_ty: *child_ty,
+ child_ty,
child_source: child_terminator.source_info,
})
}
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
- let mut storage_live = MaybeStorageLive::new(always_live_locals.clone())
+ let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
.into_engine(tcx, body_ref)
.iterate_to_fixpoint()
.into_results_cursor(body_ref);
let (assign, discr) = transform.get_discr(body);
let switch_targets =
SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
- let switch = TerminatorKind::SwitchInt {
- discr: Operand::Move(discr),
- switch_ty: transform.discr_ty,
- targets: switch_targets,
- };
+ let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets };
let source_info = SourceInfo::outermost(body.span);
body.basic_blocks_mut().raw.insert(
tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
source_info,
);
- if tcx.sess.opts.unstable_opts.mir_emit_retag {
- // Alias tracking must know we changed the type
- body.basic_blocks_mut()[START_BLOCK].statements.insert(
- 0,
- Statement {
- source_info,
- kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))),
- },
- )
- }
// Make sure we remove dead blocks to remove
// unrelated code from the resume part of the function
};
let kind = match parent_ty.ty.kind() {
- &ty::Opaque(def_id, substs) => {
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
}
kind => kind,
continue;
}
- let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
+ let (discr, val, first, second) = match bbs[bb_idx].terminator().kind {
TerminatorKind::SwitchInt {
discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)),
- switch_ty,
ref targets,
..
} if targets.iter().len() == 1 => {
if target == targets.otherwise() {
continue;
}
- (discr, value, switch_ty, target, targets.otherwise())
+ (discr, value, target, targets.otherwise())
}
// Only optimize switch int statements
_ => continue,
}
// Take ownership of items now that we know we can optimize.
let discr = discr.clone();
+ let discr_ty = discr.ty(&body.local_decls, tcx);
// Introduce a temporary for the discriminant value.
let source_info = bbs[bb_idx].terminator().source_info;
- let discr_local = body.local_decls.push(LocalDecl::new(switch_ty, source_info.span));
+ let discr_local = body.local_decls.push(LocalDecl::new(discr_ty, source_info.span));
// We already checked that first and second are different blocks,
// and bb_idx has a different terminator from both of them.
(*f).clone()
} else {
// Different value between blocks. Make value conditional on switch condition.
- let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+ let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
let const_cmp = Operand::const_from_scalar(
tcx,
- switch_ty,
+ discr_ty,
rustc_const_eval::interpret::Scalar::from_uint(val, size),
rustc_span::DUMMY_SP,
);
fn maybe_zst(ty: Ty<'_>) -> bool {
match ty.kind() {
// maybe ZST (could be more precise)
- ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+ ty::Adt(..)
+ | ty::Array(..)
+ | ty::Closure(..)
+ | ty::Tuple(..)
+ | ty::Alias(ty::Opaque, ..) => true,
// definitely ZST
ty::FnDef(..) | ty::Never => true,
// unreachable or can't be ZST
if ty.is_some() {
// The first argument (index 0), but add 1 for the return value.
let dropee_ptr = Place::from(Local::new(1 + 0));
- if tcx.sess.opts.unstable_opts.mir_emit_retag {
- // Function arguments should be retagged, and we make this one raw.
- body.basic_blocks_mut()[START_BLOCK].statements.insert(
- 0,
- Statement {
- source_info,
- kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)),
- },
- );
- }
let patch = {
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let mut elaborator =
// we must subst the self_ty because it's
// otherwise going to be TySelf and we can't index
// or access fields of a Place of type TySelf.
- let substs = tcx.mk_substs_trait(self_ty, []);
- let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs);
+ let sig = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]);
let sig = tcx.erase_late_bound_regions(sig);
let span = tcx.def_span(def_id);
) {
let tcx = self.tcx;
- let substs = tcx.mk_substs_trait(ty, []);
-
// `func == Clone::clone(&ty) -> ty`
- let func_ty = tcx.mk_fn_def(self.def_id, substs);
+ let func_ty = tcx.mk_fn_def(self.def_id, [ty]);
let func = Operand::Constant(Box::new(Constant {
span: self.span,
user_ty: None,
statements.push(statement);
*kind = TerminatorKind::SwitchInt {
discr: Operand::Move(temp),
- switch_ty: discr_ty,
targets: SwitchTargets::new(cases.into_iter(), unreachable),
};
}
// Create substitutions for the `Self` and `Args` generic parameters of the shim body.
let arg_tup = tcx.mk_tup(untuple_args.iter());
- let sig_substs = tcx.mk_substs_trait(ty, [ty::subst::GenericArg::from(arg_tup)]);
- (Some(sig_substs), Some(untuple_args))
+ (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
} else {
(None, None)
};
assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
let mut sig =
- if let Some(sig_substs) = sig_substs { sig.subst(tcx, sig_substs) } else { sig.0 };
+ if let Some(sig_substs) = sig_substs { sig.subst(tcx, &sig_substs) } else { sig.0 };
if let CallKind::Indirect(fnty) = call_kind {
// `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use smallvec::SmallVec;
-use std::convert::TryInto;
pub struct SimplifyCfg {
label: String,
let terminator = block.terminator_mut();
terminator.kind = match terminator.kind {
TerminatorKind::SwitchInt {
- discr: Operand::Constant(ref c),
- switch_ty,
- ref targets,
- ..
+ discr: Operand::Constant(ref c), ref targets, ..
} => {
- let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty);
+ let constant = c.literal.try_eval_bits(tcx, param_env, c.ty());
if let Some(constant) = constant {
let target = targets.target_for_value(constant);
TerminatorKind::Goto { target }
let targets = SwitchTargets::new(iter::once((new_value, bb_cond)), bb_otherwise);
let terminator = bb.terminator_mut();
- terminator.kind = TerminatorKind::SwitchInt {
- discr: Operand::Move(opt.to_switch_on),
- switch_ty: opt.branch_value_ty,
- targets,
- };
+ terminator.kind =
+ TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), targets };
}
for (idx, bb_idx) in storage_deads_to_remove {
let terminator = match terminator_kind {
// This will unconditionally run into an unreachable and is therefore unreachable as well.
TerminatorKind::Goto { target } if is_unreachable(*target) => TerminatorKind::Unreachable,
- TerminatorKind::SwitchInt { targets, discr, switch_ty } => {
+ TerminatorKind::SwitchInt { targets, discr } => {
let otherwise = targets.otherwise();
// If all targets are unreachable, we can be unreachable as well.
return None;
}
- TerminatorKind::SwitchInt {
- discr: discr.clone(),
- switch_ty: *switch_ty,
- targets: new_targets,
- }
+ TerminatorKind::SwitchInt { discr: discr.clone(), targets: new_targets }
} else {
// If the otherwise branch is reachable, we don't want to delete any unreachable branches.
return None;
) {
if let ty::FnDef(def_id, substs) = *ty.kind() {
let instance = if is_direct_call {
- ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+ ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
} else {
- ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
- .unwrap()
+ match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
+ {
+ Some(instance) => instance,
+ _ => bug!("failed to resolve instance for {ty}"),
+ }
};
visit_instance_use(tcx, instance, is_direct_call, source, output);
}
trait_ref.substs[param.index as usize]
}
});
- let instance = ty::Instance::resolve(tcx, param_env, method.def_id, substs)
- .unwrap()
- .unwrap();
+ let instance =
+ ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
pub span: Option<Span>,
pub symbol: String,
}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_couldnt_dump_mono_stats)]
+pub struct CouldntDumpMonoStats {
+ pub error: String,
+}
mod default;
mod merging;
+use std::cmp;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+use std::path::{Path, PathBuf};
+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync;
use rustc_hir::def_id::DefIdSet;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
+use rustc_session::config::SwitchWithOptPath;
use rustc_span::symbol::Symbol;
use crate::collector::InliningMap;
use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
})
.collect();
+ // Output monomorphization stats per def_id
+ if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
+ if let Err(err) =
+ dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
+ {
+ tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
+ }
+ }
+
if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
(tcx.arena.alloc(mono_items), codegen_units)
}
+/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s
+/// def, to a file in the given output directory.
+fn dump_mono_items_stats<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ codegen_units: &[CodegenUnit<'tcx>],
+ output_directory: &Option<PathBuf>,
+ crate_name: Option<&str>,
+) -> Result<(), Box<dyn std::error::Error>> {
+ let output_directory = if let Some(ref directory) = output_directory {
+ fs::create_dir_all(directory)?;
+ directory
+ } else {
+ Path::new(".")
+ };
+
+ let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
+ let output_path = output_directory.join(&filename);
+ let file = File::create(output_path)?;
+ let mut file = BufWriter::new(file);
+
+ // Gather instantiated mono items grouped by def_id
+ let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
+ for cgu in codegen_units {
+ for (&mono_item, _) in cgu.items() {
+ // Avoid variable-sized compiler-generated shims
+ if mono_item.is_user_defined() {
+ items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
+ }
+ }
+ }
+
+ // Output stats sorted by total instantiated size, from heaviest to lightest
+ let mut stats: Vec<_> = items_per_def_id
+ .into_iter()
+ .map(|(def_id, items)| {
+ let instantiation_count = items.len();
+ let size_estimate = items[0].size_estimate(tcx);
+ let total_estimate = instantiation_count * size_estimate;
+ (def_id, instantiation_count, size_estimate, total_estimate)
+ })
+ .collect();
+ stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
+
+ if !stats.is_empty() {
+ writeln!(
+ file,
+ "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
+ )?;
+ writeln!(file, "| --- | ---: | ---: | ---: |")?;
+ for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
+ let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+ writeln!(
+ file,
+ "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
+ )?;
+ }
+ }
+
+ Ok(())
+}
+
fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet {
let (items, cgus) = tcx.collect_and_partition_mono_items(());
let mut visited = DefIdSet::default();
Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;
-use std::convert::TryInto;
use std::ops::ControlFlow;
use crate::errors::UnusedGenericParams;
#[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
pub Span,
);
+
+#[derive(Diagnostic)]
+#[diag(parse_maybe_fn_typo_with_impl)]
+pub(crate) struct FnTypoWithImpl {
+ #[primary_span]
+ #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
+ pub fn_span: Span,
+}
use rustc_ast::token::{self, Delimiter, Nonterminal};
use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult};
use rustc_span::{sym, BytePos, Span};
-use std::convert::TryInto;
// Public for rustfmt usage
#[derive(Debug)]
use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, DUMMY_SP};
-use std::convert::TryInto;
use std::ops::Range;
/// A wrapper type to ensure that the parser handles outer attributes correctly.
Standalone,
/// It's a subexpression, i.e., *not* standalone.
Subexpr,
- /// It's maybe standalone; we're not sure.
- Maybe,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
err.multipart_suggestion(&self.msg, self.patches, self.applicability);
}
- /// Overrides individual messages and applicabilities.
- fn emit_many(
- err: &mut Diagnostic,
- msg: &str,
- applicability: Applicability,
- suggestions: impl Iterator<Item = Self>,
- ) {
- err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
+ fn emit_verbose(self, err: &mut Diagnostic) {
+ err.multipart_suggestion_verbose(&self.msg, self.patches, self.applicability);
}
}
&mut self,
operand_expr: P<Expr>,
op_span: Span,
- prev_is_semi: bool,
+ start_stmt: bool,
) -> PResult<'a, P<Expr>> {
- let standalone =
- if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
+ let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
-
self.recover_from_inc_dec(operand_expr, kind, op_span)
}
&mut self,
operand_expr: P<Expr>,
op_span: Span,
+ start_stmt: bool,
) -> PResult<'a, P<Expr>> {
let kind = IncDecRecovery {
- standalone: IsStandalone::Maybe,
+ standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
op: IncOrDec::Inc,
fixity: UnaryFixity::Post,
};
-
self.recover_from_inc_dec(operand_expr, kind, op_span)
}
};
match kind.standalone {
- IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
+ IsStandalone::Standalone => {
+ self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err)
+ }
IsStandalone::Subexpr => {
let Ok(base_src) = self.span_to_snippet(base.span)
- else { return help_base_case(err, base) };
+ else { return help_base_case(err, base) };
match kind.fixity {
UnaryFixity::Pre => {
self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
}
UnaryFixity::Post => {
- self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+ // won't suggest since we can not handle the precedences
+ // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here
+ if !matches!(base.kind, ExprKind::Binary(_, _, _)) {
+ self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
+ }
}
}
}
- IsStandalone::Maybe => {
- let Ok(base_src) = self.span_to_snippet(base.span)
- else { return help_base_case(err, base) };
- let sugg1 = match kind.fixity {
- UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
- UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
- };
- let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
- MultiSugg::emit_many(
- &mut err,
- "use `+= 1` instead",
- Applicability::Unspecified,
- [sugg1, sugg2].into_iter(),
- )
- }
}
Err(err)
}
}
patches.push((post_span, format!(" {}= 1", kind.op.chr())));
-
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches,
pub(super) enum LhsExpr {
NotYetParsed,
AttributesParsed(AttrWrapper),
- AlreadyParsed(P<Expr>),
+ AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
}
impl From<Option<AttrWrapper>> for LhsExpr {
///
/// This conversion does not allocate.
fn from(expr: P<Expr>) -> Self {
- LhsExpr::AlreadyParsed(expr)
+ LhsExpr::AlreadyParsed(expr, false)
}
}
min_prec: usize,
lhs: LhsExpr,
) -> PResult<'a, P<Expr>> {
- let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
+ let mut starts_stmt = false;
+ let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+ starts_stmt = starts_statement;
expr
} else {
let attrs = match lhs {
let op_span = self.prev_token.span.to(self.token.span);
// Eat the second `+`
self.bump();
- lhs = self.recover_from_postfix_increment(lhs, op_span)?;
+ lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
continue;
}
token::BinOp(token::Plus)
if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
{
- let prev_is_semi = this.prev_token == token::Semi;
+ let starts_stmt = this.prev_token == token::Semi
+ || this.prev_token == token::CloseDelim(Delimiter::Brace);
let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
// Eat both `+`s.
this.bump();
this.bump();
let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
- this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi)
+ this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
}
token::Ident(..) if this.token.is_keyword(kw::Box) => {
make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
|| self.token.is_op())
{
- let lit = self.recover_unclosed_char(label_.ident, |self_| {
- self_.sess.create_err(UnexpectedTokenAfterLabel {
- span: self_.token.span,
- remove_label: None,
- enclose_in_block: None,
- })
- });
+ let (lit, _) =
+ self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
+ self_.sess.create_err(UnexpectedTokenAfterLabel {
+ span: self_.token.span,
+ remove_label: None,
+ enclose_in_block: None,
+ })
+ });
consume_colon = false;
- Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+ Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
} else if !ate_colon
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{
Ok(expr)
}
- /// Emit an error when a char is parsed as a lifetime because of a missing quote
- pub(super) fn recover_unclosed_char(
+ /// Emit an error when a char is parsed as a lifetime because of a missing quote.
+ pub(super) fn recover_unclosed_char<L>(
&self,
lifetime: Ident,
+ mk_lit_char: impl FnOnce(Symbol, Span) -> L,
err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
- ) -> ast::MetaItemLit {
+ ) -> L {
if let Some(mut diag) =
self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
{
.emit();
}
let name = lifetime.without_first_quote().name;
- ast::MetaItemLit {
- token_lit: token::Lit::new(token::LitKind::Char, name, None),
- kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
- span: lifetime.span,
- }
+ mk_lit_char(name, lifetime.span)
}
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
Some(lit) => match lit.kind {
ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
style,
- symbol: lit.token_lit.symbol,
- suffix: lit.token_lit.suffix,
+ symbol: lit.symbol,
+ suffix: lit.suffix,
span: lit.span,
symbol_unescaped,
}),
}
}
- fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
+ pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
+ (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
+ }
+
+ fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
+ ast::MetaItemLit {
+ symbol: name,
+ suffix: None,
+ kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
+ span,
+ }
+ }
+
+ fn handle_missing_lit<L>(
+ &mut self,
+ mk_lit_char: impl FnOnce(Symbol, Span) -> L,
+ ) -> PResult<'a, L> {
if let token::Interpolated(inner) = &self.token.kind {
let expr = match inner.as_ref() {
token::NtExpr(expr) => Some(expr),
// On an error path, eagerly consider a lifetime to be an unclosed character lit
if self.token.is_lifetime() {
let lt = self.expect_lifetime();
- Ok(self.recover_unclosed_char(lt.ident, err))
+ Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
} else {
Err(err(self))
}
pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
self.parse_opt_token_lit()
.ok_or(())
- .or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span)))
+ .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
}
pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
- self.parse_opt_meta_item_lit().ok_or(()).or_else(|()| self.handle_missing_lit())
+ self.parse_opt_meta_item_lit()
+ .ok_or(())
+ .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
}
fn recover_after_dot(&mut self) -> Option<Token> {
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
+use crate::errors::FnTypoWithImpl;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
-use std::convert::TryFrom;
use std::mem;
use thin_vec::ThinVec;
use tracing::debug;
}
match parse_item(self) {
Ok(None) => {
- let is_unnecessary_semicolon = !items.is_empty()
+ let mut is_unnecessary_semicolon = !items.is_empty()
// When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
- // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
+ // but the actual `token.kind` is `token::CloseDelim(Delimiter::Brace)`.
// This is because the `token.kind` of the close delim is treated as the same as
// that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
// Therefore, `token.kind` should not be compared here.
.span_to_snippet(self.prev_token.span)
.map_or(false, |snippet| snippet == "}")
&& self.token.kind == token::Semi;
- let semicolon_span = self.token.span;
+ let mut semicolon_span = self.token.span;
+ if !is_unnecessary_semicolon {
+ // #105369, Detect spurious `;` before assoc fn body
+ is_unnecessary_semicolon = self.token == token::OpenDelim(Delimiter::Brace)
+ && self.prev_token.kind == token::Semi;
+ semicolon_span = self.prev_token.span;
+ }
// We have to bail or we'll potentially never make progress.
let non_item_span = self.token.span;
let is_let = self.token.is_keyword(kw::Let);
vis: &Visibility,
case: Case,
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
+ let fn_span = self.token.span;
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
let ident = self.parse_ident()?; // `foo`
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
- let decl =
- self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
+ let decl = match self.parse_fn_decl(
+ fn_parse_mode.req_name,
+ AllowPlus::Yes,
+ RecoverReturnSign::Yes,
+ ) {
+ Ok(decl) => decl,
+ Err(old_err) => {
+ // If we see `for Ty ...` then user probably meant `impl` item.
+ if self.token.is_keyword(kw::For) {
+ old_err.cancel();
+ return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
+ } else {
+ return Err(old_err);
+ }
+ }
+ };
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
let mut sig_hi = self.prev_token.span;
use rustc_ast::util::case::Case;
use rustc_ast::AttrId;
use rustc_ast::DUMMY_NODE_ID;
-use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, DelimArgs, Extern};
+use rustc_ast::{self as ast, AnonConst, AttrStyle, Const, DelimArgs, Extern};
use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, MacDelimiter, Mutability, StrLit};
use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind};
use rustc_ast_pretty::pprust;
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
};
let blk_span = anon_const.value.span;
- Ok(self.mk_expr_with_attrs(
- span.to(blk_span),
- ExprKind::ConstBlock(anon_const),
- AttrVec::from(attrs),
- ))
+ Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs))
}
/// Parses mutability (`mut` or nothing).
{
// Recover a `'a` as a `'a'` literal
let lt = self.expect_lifetime();
- let lit = self.recover_unclosed_char(lt.ident, |self_| {
- let expected = expected.unwrap_or("pattern");
- let msg =
- format!("expected {}, found {}", expected, super::token_descr(&self_.token));
+ let (lit, _) =
+ self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
+ let expected = expected.unwrap_or("pattern");
+ let msg = format!(
+ "expected {}, found {}",
+ expected,
+ super::token_descr(&self_.token)
+ );
- let mut err = self_.struct_span_err(self_.token.span, &msg);
- err.span_label(self_.token.span, format!("expected {}", expected));
- err
- });
- PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
+ let mut err = self_.struct_span_err(self_.token.span, &msg);
+ err.span_label(self_.token.span, format!("expected {}", expected));
+ err
+ });
+ PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
} else {
// Try to parse everything else as literal with optional minus
match self.parse_literal_maybe_minus() {
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+ this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
})?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
- let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+ let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
StmtKind::Expr(e)
};
Ok(self.mk_stmt(lo.to(hi), kind))
[dependencies]
rustc_lexer = { path = "../rustc_lexer" }
+rustc_data_structures = { path = "../rustc_data_structures" }
/// A piece is a portion of the format string which represents the next part
/// to emit. These are emitted as a stream by the `Parser` class.
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub enum Piece<'a> {
/// A literal string which should directly be emitted
String(&'a str),
/// This describes that formatting should process the next argument (as
/// specified inside) for emission.
- NextArgument(Argument<'a>),
+ NextArgument(Box<Argument<'a>>),
}
/// Representation of an argument specification.
} else {
self.suggest_positional_arg_instead_of_captured_arg(arg);
}
- Some(NextArgument(arg))
+ Some(NextArgument(Box::new(arg)))
}
}
'}' => {
(skips, true)
}
+// Assert a reasonable size for `Piece`
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Piece<'_>, 16);
+
#[cfg(test)]
mod tests;
fn format_nothing() {
same(
"{}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: fmtdflt(),
- })],
+ }))],
);
}
#[test]
fn format_position() {
same(
"{3}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: fmtdflt(),
- })],
+ }))],
);
}
#[test]
fn format_position_nothing_else() {
same(
"{3:}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: fmtdflt(),
- })],
+ }))],
);
}
#[test]
fn format_named() {
same(
"{name}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentNamed("name"),
position_span: InnerSpan { start: 2, end: 6 },
format: fmtdflt(),
- })],
+ }))],
)
}
#[test]
fn format_type() {
same(
"{3:x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
}
#[test]
fn format_align_fill() {
same(
"{3:>}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: FormatSpec {
ty: "",
ty_span: None,
},
- })],
+ }))],
);
same(
"{3:0<}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: FormatSpec {
ty: "",
ty_span: None,
},
- })],
+ }))],
);
same(
"{3:*<abcd}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 2, end: 3 },
format: FormatSpec {
ty: "abcd",
ty_span: Some(InnerSpan::new(6, 10)),
},
- })],
+ }))],
);
}
#[test]
fn format_counts() {
same(
"{:10x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:10$.10x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
same(
"{1:0$.10x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentIs(1),
position_span: InnerSpan { start: 2, end: 3 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:.*x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(1),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:.10$x}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:a$.b$?}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "?",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:.4}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "",
ty_span: None,
},
- })],
+ }))],
)
}
#[test]
fn format_flags() {
same(
"{:-}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "",
ty_span: None,
},
- })],
+ }))],
);
same(
"{:+#}",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 2 },
format: FormatSpec {
ty: "",
ty_span: None,
},
- })],
+ }))],
);
}
#[test]
"abcd {3:x} efg",
&[
String("abcd "),
- NextArgument(Argument {
+ NextArgument(Box::new(Argument {
position: ArgumentIs(3),
position_span: InnerSpan { start: 7, end: 8 },
format: FormatSpec {
ty: "x",
ty_span: None,
},
- }),
+ })),
String(" efg"),
],
);
fn format_whitespace() {
same(
"{ }",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 3 },
format: fmtdflt(),
- })],
+ }))],
);
same(
"{ }",
- &[NextArgument(Argument {
+ &[NextArgument(Box::new(Argument {
position: ArgumentImplicitlyIs(0),
position_span: InnerSpan { start: 2, end: 4 },
format: fmtdflt(),
- })],
+ }))],
);
}
fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
match self.typeck_results().expr_ty_adjusted(lhs).kind() {
ty::Adt(def, _) => {
- let index = self.tcx.field_index(hir_id, self.typeck_results());
+ let index = self.typeck_results().field_index(hir_id);
self.insert_def_id(def.non_enum_variant().fields[index].did);
}
ty::Tuple(..) => {}
if let PatKind::Wild = pat.pat.kind {
continue;
}
- let index = self.tcx.field_index(pat.hir_id, self.typeck_results());
+ let index = self.typeck_results().field_index(pat.hir_id);
self.insert_def_id(variant.fields[index].did);
}
}
fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
for field in fields {
- let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+ let index = self.typeck_results().field_index(field.hir_id);
self.insert_def_id(adt.non_enum_variant().fields[index].did);
}
}
fn print(&self, title: &str, prefix: &str) {
let mut nodes: Vec<_> = self.nodes.iter().collect();
- nodes.sort_by_key(|&(_, ref node)| node.stats.count * node.stats.size);
+ nodes.sort_by_key(|(_, node)| node.stats.count * node.stats.size);
let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
);
if !node.subnodes.is_empty() {
let mut subnodes: Vec<_> = node.subnodes.iter().collect();
- subnodes.sort_by_key(|&(_, ref subnode)| subnode.count * subnode.size);
+ subnodes.sort_by_key(|(_, subnode)| subnode.count * subnode.size);
for (label, subnode) in subnodes {
let size = subnode.count * subnode.size;
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join(", ")
- .into()
};
let first_defined_span = self.tcx.hir().span_if_local(original_def_id);
let mut orig_crate_name = Empty;
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join(", ")
- .into()
};
if first_defined_span.is_none() {
orig_crate_name = self.tcx.crate_name(original_def_id.krate);
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
self.skeleton().visit_trait(trait_ref)
}
- fn visit_projection_ty(
- &mut self,
- projection: ty::ProjectionTy<'tcx>,
- ) -> ControlFlow<Self::BreakTy> {
+ fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<Self::BreakTy> {
self.skeleton().visit_projection_ty(projection)
}
fn visit_predicates(
V: DefIdVisitor<'tcx> + ?Sized,
{
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
- let TraitRef { def_id, substs } = trait_ref;
+ let TraitRef { def_id, substs, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
}
- fn visit_projection_ty(
- &mut self,
- projection: ty::ProjectionTy<'tcx>,
- ) -> ControlFlow<V::BreakTy> {
+ fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
let tcx = self.def_id_visitor.tcx();
- let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
- != DefKind::ImplTraitPlaceholder
- {
- projection.trait_ref_and_own_substs(tcx)
- } else {
- // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
- let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
- let trait_generics = tcx.generics_of(def_id);
- (
- ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
- &projection.substs[trait_generics.count()..],
- )
- };
+ let (trait_ref, assoc_substs) =
+ if tcx.def_kind(projection.def_id) != DefKind::ImplTraitPlaceholder {
+ projection.trait_ref_and_own_substs(tcx)
+ } else {
+ // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+ let def_id = tcx.impl_trait_in_trait_parent(projection.def_id);
+ let trait_generics = tcx.generics_of(def_id);
+ (
+ tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
+ &projection.substs[trait_generics.count()..],
+ )
+ };
self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() {
ControlFlow::CONTINUE
}
}
}
- ty::Projection(proj) => {
+ ty::Alias(ty::Projection, proj) => {
if self.def_id_visitor.skip_assoc_tys() {
// Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `<Type as Trait>::Alias`
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
}
}
- ty::Opaque(def_id, ..) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
// Skip repeated `Opaque`s to avoid infinite recursion.
if self.visited_opaque_tys.insert(def_id) {
// The intent is to treat `impl Trait1 + Trait2` identically to
// are checked for privacy (RFC 736). Rather than computing the set of
// unmentioned fields, just check them all.
for (vf_index, variant_field) in variant.fields.iter().enumerate() {
- let field = fields.iter().find(|f| {
- self.tcx.field_index(f.hir_id, self.typeck_results()) == vf_index
- });
+ let field = fields
+ .iter()
+ .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
let (use_ctxt, span) = match field {
Some(field) => (field.ident.span, field.span),
None => (base.span, base.span),
} else {
for field in fields {
let use_ctxt = field.ident.span;
- let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+ let index = self.typeck_results().field_index(field.hir_id);
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
}
}
let variant = adt.variant_of_res(res);
for field in fields {
let use_ctxt = field.ident.span;
- let index = self.tcx.field_index(field.hir_id, self.typeck_results());
+ let index = self.typeck_results().field_index(field.hir_id);
self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
}
}
let is_local_static =
if let DefKind::Static(_) = kind { def_id.is_local() } else { false };
if !self.item_is_accessible(def_id) && !is_local_static {
- let sess = self.tcx.sess;
- let sm = sess.source_map();
- let name = match qpath {
- hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => {
- sm.span_to_snippet(qpath.span()).ok()
+ let name = match *qpath {
+ hir::QPath::LangItem(it, ..) => {
+ self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
}
+ hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
};
let kind = kind.descr(def_id);
+ let sess = self.tcx.sess;
let _ = match name {
Some(name) => {
sess.emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1);
}
-impl std::convert::From<DepNodeIndex> for QueryInvocationId {
+impl From<DepNodeIndex> for QueryInvocationId {
#[inline]
fn from(dep_node_index: DepNodeIndex) -> Self {
QueryInvocationId(dep_node_index.as_u32())
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable};
use smallvec::SmallVec;
-use std::convert::TryInto;
// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
// unused so that we can store multiple index types in `CompressedHybridIndex`,
#[primary_span]
pub span: Span,
pub stack_bottom: String,
- #[subdiagnostic(eager)]
+ #[subdiagnostic]
pub cycle_stack: Vec<CycleStack>,
#[subdiagnostic]
pub stack_count: StackCount,
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::definitions::{DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
-use rustc_session::cstore::CrateStore;
+use rustc_hir::definitions::DefPathHash;
+use rustc_session::cstore::Untracked;
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol;
/// things (e.g., each `DefId`/`DefPath` is only hashed once).
#[derive(Clone)]
pub struct StableHashingContext<'a> {
- definitions: &'a Definitions,
- cstore: &'a dyn CrateStore,
- source_span: &'a IndexVec<LocalDefId, Span>,
+ untracked: &'a Untracked,
// The value of `-Z incremental-ignore-spans`.
// This field should only be used by `unstable_opts_incremental_ignore_span`
incremental_ignore_spans: bool,
impl<'a> StableHashingContext<'a> {
#[inline]
- pub fn new(
- sess: &'a Session,
- definitions: &'a Definitions,
- cstore: &'a dyn CrateStore,
- source_span: &'a IndexVec<LocalDefId, Span>,
- ) -> Self {
+ pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self {
let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
StableHashingContext {
body_resolver: BodyResolver::Forbidden,
- definitions,
- cstore,
- source_span,
+ untracked,
incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
caching_source_map: None,
raw_source_map: sess.source_map(),
if let Some(def_id) = def_id.as_local() {
self.local_def_path_hash(def_id)
} else {
- self.cstore.def_path_hash(def_id)
+ self.untracked.cstore.def_path_hash(def_id)
}
}
#[inline]
pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
- self.definitions.def_path_hash(def_id)
+ self.untracked.definitions.read().def_path_hash(def_id)
}
#[inline]
#[inline]
fn def_span(&self, def_id: LocalDefId) -> Span {
- *self.source_span.get(def_id).unwrap_or(&DUMMY_SP)
+ *self.untracked.source_span.get(def_id).unwrap_or(&DUMMY_SP)
}
#[inline]
use rustc_data_structures::sync::Lock;
use rustc_data_structures::sync::WorkerLocal;
use rustc_index::vec::{Idx, IndexVec};
-use std::default::Default;
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
rustc_data_structures::{jobserver, OnDrop},
rustc_rayon_core as rayon_core,
rustc_span::DUMMY_SP,
- std::iter::{self, FromIterator},
- std::{mem, process},
+ std::iter,
+ std::process,
};
/// Represents a span and a query key.
jobserver::release_thread();
waiter.condvar.wait(&mut info);
// Release the lock before we potentially block in `acquire_thread`
- mem::drop(info);
+ drop(info);
jobserver::acquire_thread();
}
}
// Ensure there is at most one `self` in the list
let self_spans = items
.iter()
- .filter_map(|&(ref use_tree, _)| {
+ .filter_map(|(use_tree, _)| {
if let ast::UseTreeKind::Simple(..) = use_tree.kind {
if use_tree.ident().name == kw::SelfLower {
return Some(use_tree.span);
} else if orig_name == Some(kw::SelfLower) {
Some(self.r.graph_root)
} else {
- self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
- |crate_id| {
- self.r.extern_crate_map.insert(local_def_id, crate_id);
- self.r.expect_module(crate_id.as_def_id())
- },
- )
+ let crate_id = self.r.crate_loader().process_extern_crate(item, local_def_id);
+ crate_id.map(|crate_id| {
+ self.r.extern_crate_map.insert(local_def_id, crate_id);
+ self.r.expect_module(crate_id.as_def_id())
+ })
}
.map(|module| {
let used = self.process_macro_use_imports(item, module);
if !candidates.is_empty() {
show_candidates(
&self.session,
- &self.source_span,
+ &self.untracked.source_span,
&mut err,
span,
&candidates,
}
show_candidates(
&self.session,
- &self.source_span,
+ &self.untracked.source_span,
&mut err,
Some(span),
&import_suggestions,
// otherwise cause duplicate suggestions.
continue;
}
- if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) {
+ let crate_id = self.crate_loader().maybe_process_path_extern(ident.name);
+ if let Some(crate_id) = crate_id {
let crate_root = self.expect_module(crate_id.as_def_id());
suggestions.extend(self.lookup_import_candidates_from_module(
lookup_ident,
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
show_candidates(
&self.session,
- &self.source_span,
+ &self.untracked.source_span,
err,
None,
&import_suggestions,
r.effective_visibilities.update_eff_vis(
r.local_def_id(node_id),
eff_vis,
- ResolverTree(&r.definitions, &r.crate_loader),
+ ResolverTree(&r.untracked),
)
}
}
if let Some(candidate) = &err.candidate {
import_candidates(
self.r.session,
- &self.r.source_span,
+ &self.r.untracked.source_span,
&mut diag,
Some(err.span),
&candidate,
/// FIXME #4948: Reuse ribs to avoid allocation.
ribs: PerNS<Vec<Rib<'a>>>,
+ /// Previous poped `rib`, only used for diagnostic.
+ last_block_rib: Option<Rib<'a>>,
+
/// The current set of local scopes, for labels.
label_ribs: Vec<Rib<'a, NodeId>>,
// Ignore errors in function bodies if this is rustdoc
// Be sure not to set this until the function signature has been resolved.
let previous_state = replace(&mut this.in_func_body, true);
+ // We only care block in the same function
+ this.last_block_rib = None;
// Resolve the function body, potentially inside the body of an async closure
this.with_lifetime_rib(
LifetimeRibKind::Elided(LifetimeRes::Infer),
type_ns: vec![Rib::new(start_rib_kind)],
macro_ns: vec![Rib::new(start_rib_kind)],
},
+ last_block_rib: None,
label_ribs: Vec::new(),
lifetime_ribs: Vec::new(),
lifetime_elision_candidates: None,
self.ribs[ValueNS].pop();
self.label_ribs.pop();
}
- self.ribs[ValueNS].pop();
+ self.last_block_rib = self.ribs[ValueNS].pop();
if anonymous_module.is_some() {
self.ribs[TypeNS].pop();
}
return (true, candidates);
}
}
+
+ // Try to find in last block rib
+ if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind {
+ for (ident, &res) in &rib.bindings {
+ if let Res::Local(_) = res && path.len() == 1 &&
+ ident.span.eq_ctxt(path[0].ident.span) &&
+ ident.name == path[0].ident.name {
+ err.span_help(
+ ident.span,
+ &format!("the binding `{}` is available in a different scope in the same function", path_str),
+ );
+ return (true, candidates);
+ }
+ }
+ }
+
return (false, candidates);
}
if !module.no_implicit_prelude {
let extern_prelude = self.r.extern_prelude.clone();
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
- self.r.crate_loader.maybe_process_path_extern(ident.name).and_then(
- |crate_id| {
+ self.r
+ .crate_loader()
+ .maybe_process_path_extern(ident.name)
+ .and_then(|crate_id| {
let crate_mod =
Res::Def(DefKind::Mod, crate_id.as_def_id());
} else {
None
}
- },
- )
+ })
}));
if let Some(prelude) = self.r.prelude {
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
use rustc_hir::def::Namespace::*;
use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
use rustc_query_system::ich::StableHashingContext;
-use rustc_session::cstore::{CrateStore, MetadataLoaderDyn};
+use rustc_session::cstore::{CrateStore, MetadataLoaderDyn, Untracked};
use rustc_session::lint::LintBuffer;
use rustc_session::Session;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
pub struct Resolver<'a> {
session: &'a Session,
- definitions: Definitions,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
- /// Reference span for definitions.
- source_span: IndexVec<LocalDefId, Span>,
graph_root: Module<'a>,
arenas: &'a ResolverArenas<'a>,
dummy_binding: &'a NameBinding<'a>,
- crate_loader: CrateLoader<'a>,
+ local_crate_name: Symbol,
+ metadata_loader: Box<MetadataLoaderDyn>,
+ untracked: Untracked,
+ used_extern_options: FxHashSet<Symbol>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
/// A small map keeping true kinds of built-in macros that appear to be fn-like on
/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
/// required to satisfy borrow checker by avoiding borrowing the whole resolver.
#[derive(Clone, Copy)]
-struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>);
+struct ResolverTree<'a>(&'a Untracked);
-impl DefIdTree for ResolverTree<'_, '_> {
+impl DefIdTree for ResolverTree<'_> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
- let ResolverTree(definitions, crate_loader) = self;
+ let ResolverTree(Untracked { definitions, cstore, .. }) = self;
match id.as_local() {
- Some(id) => definitions.def_key(id).parent,
- None => crate_loader.cstore().def_key(id).parent,
+ Some(id) => definitions.read().def_key(id).parent,
+ None => cstore.as_any().downcast_ref::<CStore>().unwrap().def_key(id).parent,
}
.map(|index| DefId { index, ..id })
}
impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
- ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id)
+ ResolverTree(&self.untracked).opt_parent(id)
}
}
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
node_id,
data,
- self.definitions.def_key(self.node_id_to_def_id[&node_id]),
+ self.untracked.definitions.read().def_key(self.node_id_to_def_id[&node_id]),
);
- let def_id = self.definitions.create_def(parent, data);
+ let def_id = self.untracked.definitions.write().create_def(parent, data);
// Create the definition.
if expn_id != ExpnId::root() {
// A relative span's parent must be an absolute span.
debug_assert_eq!(span.data_untracked().parent, None);
- let _id = self.source_span.push(span);
+ let _id = self.untracked.source_span.push(span);
debug_assert_eq!(_id, def_id);
// Some things for which we allocate `LocalDefId`s don't correspond to
pub fn new(
session: &'a Session,
krate: &Crate,
- crate_name: &str,
+ crate_name: Symbol,
metadata_loader: Box<MetadataLoaderDyn>,
arenas: &'a ResolverArenas<'a>,
) -> Resolver<'a> {
let mut resolver = Resolver {
session,
- definitions,
expn_that_defined: Default::default(),
- source_span,
// The outermost module has def ID 0; this is not reflected in the
// AST.
vis: ty::Visibility::Public,
}),
- crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
+ metadata_loader,
+ local_crate_name: crate_name,
+ used_extern_options: Default::default(),
+ untracked: Untracked {
+ cstore: Box::new(CStore::new(session)),
+ source_span,
+ definitions: RwLock::new(definitions),
+ },
macro_names: FxHashSet::default(),
builtin_macros: Default::default(),
builtin_macro_kinds: Default::default(),
pub fn into_outputs(self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
- let definitions = self.definitions;
- let cstore = Box::new(self.crate_loader.into_cstore());
- let source_span = self.source_span;
let expn_that_defined = self.expn_that_defined;
let visibilities = self.visibilities;
let has_pub_restricted = self.has_pub_restricted;
let main_def = self.main_def;
let confused_type_with_std_module = self.confused_type_with_std_module;
let effective_visibilities = self.effective_visibilities;
+ let untracked = self.untracked;
let global_ctxt = ResolverGlobalCtxt {
- cstore,
- source_span,
expn_that_defined,
visibilities,
has_pub_restricted,
builtin_macro_kinds: self.builtin_macro_kinds,
lifetime_elision_allowed: self.lifetime_elision_allowed,
};
- ResolverOutputs { definitions, global_ctxt, ast_lowering }
+ ResolverOutputs { global_ctxt, ast_lowering, untracked }
}
pub fn clone_outputs(&self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
- let definitions = self.definitions.clone();
+ let definitions = self.untracked.definitions.clone();
let cstore = Box::new(self.cstore().clone());
+ let untracked =
+ Untracked { cstore, source_span: self.untracked.source_span.clone(), definitions };
let global_ctxt = ResolverGlobalCtxt {
- cstore,
- source_span: self.source_span.clone(),
expn_that_defined: self.expn_that_defined.clone(),
visibilities: self.visibilities.clone(),
has_pub_restricted: self.has_pub_restricted,
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
};
- ResolverOutputs { definitions, global_ctxt, ast_lowering }
+ ResolverOutputs { global_ctxt, ast_lowering, untracked }
}
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
- StableHashingContext::new(
- self.session,
- &self.definitions,
- self.crate_loader.cstore(),
- &self.source_span,
+ StableHashingContext::new(self.session, &self.untracked)
+ }
+
+ pub fn crate_loader(&mut self) -> CrateLoader<'_> {
+ CrateLoader::new(
+ &self.session,
+ &*self.metadata_loader,
+ self.local_crate_name,
+ &mut *self.untracked.cstore.untracked_as_any().downcast_mut().unwrap(),
+ self.untracked.definitions.read(),
+ &mut self.used_extern_options,
)
}
pub fn cstore(&self) -> &CStore {
- self.crate_loader.cstore()
+ self.untracked.cstore.as_any().downcast_ref().unwrap()
}
fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
self.session.time("resolve_main", || self.resolve_main());
self.session.time("resolve_check_unused", || self.check_unused(krate));
self.session.time("resolve_report_errors", || self.report_errors(krate));
- self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate));
+ self.session.time("resolve_postprocess", || self.crate_loader().postprocess(krate));
});
}
} else {
let crate_id = if finalize {
let Some(crate_id) =
- self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
+ self.crate_loader().process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
crate_id
} else {
- self.crate_loader.maybe_process_path_extern(ident.name)?
+ self.crate_loader().maybe_process_path_extern(ident.name)?
};
let crate_root = self.expect_module(crate_id.as_def_id());
let vis = ty::Visibility::<LocalDefId>::Public;
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
#[inline]
pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
- def_id.as_local().map(|def_id| self.source_span[def_id])
+ def_id.as_local().map(|def_id| self.untracked.source_span[def_id])
}
/// Retrieves the name of the given `DefId`.
#[inline]
pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
let def_key = match def_id.as_local() {
- Some(def_id) => self.definitions.def_key(def_id),
+ Some(def_id) => self.untracked.definitions.read().def_key(def_id),
None => self.cstore().def_key(def_id),
};
def_key.get_opt_name()
}
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
- self.crate_loader.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
+ self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
}
fn declare_proc_macro(&mut self, id: NodeId) {
self.save_ctxt.lookup_def_id(ref_id)
}
- pub fn dump_crate_info(&mut self, name: &str) {
+ pub fn dump_crate_info(&mut self, name: Symbol) {
let source_file = self.tcx.sess.local_crate_source_file.as_ref();
let crate_root = source_file.map(|source_file| {
let source_file = Path::new(source_file);
let data = CratePreludeData {
crate_id: GlobalCrateId {
- name: name.into(),
+ name: name.to_string(),
disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
},
crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
self.dumper.crate_prelude(data);
}
- pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
+ pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
// Apply possible `remap-path-prefix` remapping to the input source file
// (and don't include remapping args anymore)
let (program, arguments) = {
use rustc_span::*;
use std::cell::Cell;
-use std::default::Default;
use std::env;
use std::fs::File;
use std::io::BufWriter;
}
/// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
- pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
+ pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
let sess = &self.tcx.sess;
// Save-analysis is emitted per whole session, not per each crate type
let crate_type = sess.crate_types()[0];
}
impl<'a> DumpHandler<'a> {
- pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
- DumpHandler { odir, cratename: cratename.to_owned() }
+ pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
+ DumpHandler { odir, cratename: cratename.to_string() }
}
fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
pub fn process_crate<'l, 'tcx, H: SaveHandler>(
tcx: TyCtxt<'tcx>,
- cratename: &str,
+ cratename: Symbol,
input: &'l Input,
config: Option<Config>,
mut handler: H,
use crate::leb128::{self, largest_max_leb128_len};
use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::convert::TryInto;
use std::fs::File;
use std::io::{self, Write};
use std::mem::MaybeUninit;
rustc_target = { path = "../rustc_target" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_index = { path = "../rustc_index" }
rustc_span = { path = "../rustc_span" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_ast = { path = "../rustc_ast" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
smallvec = "1.8.1"
+termize = "0.1.1"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
Min,
}
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FieldInfo {
pub name: Symbol,
pub offset: u64,
Union,
Enum,
Closure,
+ Generator,
}
#[derive(PartialEq, Eq, Hash, Debug)]
let struct_like = match kind {
DataTypeKind::Struct | DataTypeKind::Closure => true,
- DataTypeKind::Enum | DataTypeKind::Union => false,
+ DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Generator => false,
};
for (i, variant_info) in variants.into_iter().enumerate() {
let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
use std::hash::Hash;
-use std::iter::{self, FromIterator};
+use std::iter;
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
pub key: PAuthKey,
}
-#[derive(Clone, Copy, Hash, Debug, PartialEq)]
+#[derive(Clone, Copy, Hash, Debug, PartialEq, Default)]
pub struct BranchProtection {
pub bti: bool,
pub pac_ret: Option<PacRet>,
}
-impl Default for BranchProtection {
- fn default() -> Self {
- BranchProtection { bti: false, pac_ret: None }
- }
-}
-
pub const fn default_lib_output() -> CrateType {
CrateType::Rlib
}
.into_iter()
.flat_map(|(i, s)| {
// NB: This can match a string without `=`.
- if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
+ if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
})
.max();
if max_o > max_c {
.into_iter()
.flat_map(|(i, s)| {
// NB: This can match a string without `=`.
- if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
+ if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
})
.max();
if max_g > max_c {
use crate::utils::NativeLibKind;
use crate::Session;
use rustc_ast as ast;
-use rustc_data_structures::sync::{self, MetadataRef};
-use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_data_structures::sync::{self, MetadataRef, RwLock};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
+use rustc_index::vec::IndexVec;
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
/// during resolve)
pub trait CrateStore: std::fmt::Debug {
fn as_any(&self) -> &dyn Any;
+ fn untracked_as_any(&mut self) -> &mut dyn Any;
// Foreign definitions.
// This information is safe to access, since it's hashed as part of the DefPathHash, which incr.
}
pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
+
+#[derive(Debug)]
+pub struct Untracked {
+ pub cstore: Box<CrateStoreDyn>,
+ /// Reference span for definitions.
+ pub source_span: IndexVec<LocalDefId, Span>,
+ pub definitions: RwLock<Definitions>,
+}
pub target_triple: &'a TargetTriple,
}
+#[derive(Diagnostic)]
+#[diag(session_branch_protection_requires_aarch64)]
+pub(crate) struct BranchProtectionRequiresAArch64;
+
#[derive(Diagnostic)]
#[diag(session_split_debuginfo_unstable_platform)]
pub struct SplitDebugInfoUnstablePlatform {
#[derive(Diagnostic)]
#[diag(session_crate_name_does_not_match)]
-pub struct CrateNameDoesNotMatch<'a> {
+pub struct CrateNameDoesNotMatch {
#[primary_span]
pub span: Span,
- pub s: &'a str,
+ pub s: Symbol,
pub name: Symbol,
}
#[derive(Diagnostic)]
#[diag(session_invalid_character_in_create_name)]
-pub struct InvalidCharacterInCrateName<'a> {
+pub struct InvalidCharacterInCrateName {
#[primary_span]
pub span: Option<Span>,
pub character: char,
- pub crate_name: &'a str,
+ pub crate_name: Symbol,
}
#[derive(Subdiagnostic)]
#[derive(Diagnostic)]
#[diag(session_skipping_const_checks)]
pub struct SkippingConstChecks {
- #[subdiagnostic(eager)]
+ #[subdiagnostic]
pub unleashed_features: Vec<UnleashedFeatureHelp>,
}
s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
}
- // Try to lowercase the prefix if it's a valid base prefix.
- fn fix_base_capitalisation(s: &str) -> Option<String> {
- if let Some(stripped) = s.strip_prefix('B') {
- Some(format!("0b{stripped}"))
- } else if let Some(stripped) = s.strip_prefix('O') {
- Some(format!("0o{stripped}"))
- } else if let Some(stripped) = s.strip_prefix('X') {
- Some(format!("0x{stripped}"))
+ // Try to lowercase the prefix if the prefix and suffix are valid.
+ fn fix_base_capitalisation(prefix: &str, suffix: &str) -> Option<String> {
+ let mut chars = suffix.chars();
+
+ let base_char = chars.next().unwrap();
+ let base = match base_char {
+ 'B' => 2,
+ 'O' => 8,
+ 'X' => 16,
+ _ => return None,
+ };
+
+ // check that the suffix contains only base-appropriate characters
+ let valid = prefix == "0"
+ && chars
+ .filter(|c| *c != '_')
+ .take_while(|c| *c != 'i' && *c != 'u')
+ .all(|c| c.to_digit(base).is_some());
+
+ if valid {
+ Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
} else {
None
}
}
- let token::Lit { kind, suffix, .. } = lit;
+ let token::Lit { kind, symbol, suffix, .. } = lit;
match err {
// `LexerError` is an error, but it was already reported
// by lexer, so here we don't report it the second time.
if looks_like_width_suffix(&['i', 'u'], suf) {
// If it looks like a width, try to be helpful.
sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
- } else if let Some(fixed) = fix_base_capitalisation(suf) {
+ } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) {
sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
} else {
sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
use smallvec::{smallvec, SmallVec};
use std::env;
use std::fs;
-use std::iter::FromIterator;
use std::path::{Path, PathBuf};
use crate::search_paths::{PathKind, SearchPath};
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
- pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+ pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
pub const parse_cfguard: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
*slot |= match s {
"address" => SanitizerSet::ADDRESS,
"cfi" => SanitizerSet::CFI,
+ "kcfi" => SanitizerSet::KCFI,
"leak" => SanitizerSet::LEAK,
"memory" => SanitizerSet::MEMORY,
"memtag" => SanitizerSet::MEMTAG,
computed `block` spans (one span encompassing a block's terminator and \
all statements). If `-Z instrument-coverage` is also enabled, create \
an additional `.html` file showing the computed coverage spans."),
+ dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+ parse_switch_with_opt_path, [UNTRACKED],
+ "output statistics about monomorphization collection (format: markdown)"),
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
dylib_lto: bool = (false, parse_bool, [UNTRACKED],
use crate::Session;
use rustc_ast as ast;
use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use std::path::{Path, PathBuf};
pub fn out_filename(
sess: &Session,
crate_type: CrateType,
outputs: &OutputFilenames,
- crate_name: &str,
+ crate_name: Symbol,
) -> PathBuf {
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
let out_filename = outputs
}
}
-pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
- let validate = |s: String, span: Option<Span>| {
- validate_crate_name(sess, &s, span);
+pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
+ let validate = |s: Symbol, span: Option<Span>| {
+ validate_crate_name(sess, s, span);
s
};
sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
if let Some(ref s) = sess.opts.crate_name {
+ let s = Symbol::intern(s);
if let Some((attr, name)) = attr_crate_name {
- if name.as_str() != s {
+ if name != s {
sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
}
}
- return validate(s.clone(), None);
+ return validate(s, None);
}
if let Some((attr, s)) = attr_crate_name {
- return validate(s.to_string(), Some(attr.span));
+ return validate(s, Some(attr.span));
}
if let Input::File(ref path) = *input {
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
if s.starts_with('-') {
sess.emit_err(CrateNameInvalid { s });
} else {
- return validate(s.replace('-', "_"), None);
+ return validate(Symbol::intern(&s.replace('-', "_")), None);
}
}
}
- "rust_out".to_string()
+ Symbol::intern("rust_out")
}
-pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
+pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
let mut err_count = 0;
{
if s.is_empty() {
err_count += 1;
sess.emit_err(CrateNameEmpty { span: sp });
}
- for c in s.chars() {
+ for c in s.as_str().chars() {
if c.is_alphanumeric() {
continue;
}
pub fn filename_for_metadata(
sess: &Session,
- crate_name: &str,
+ crate_name: Symbol,
outputs: &OutputFilenames,
) -> PathBuf {
// If the command-line specified the path, use that directly.
pub fn filename_for_input(
sess: &Session,
crate_type: CrateType,
- crate_name: &str,
+ crate_name: Symbol,
outputs: &OutputFilenames,
) -> PathBuf {
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
use crate::errors::{
- CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
- NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
- SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
- SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
+ BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
+ LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist,
+ ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
+ SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
UnsupportedDwarfVersion,
};
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
}
+ pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
+ self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
+ }
+
/// Check whether this compile session and crate type use static crt.
pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
if !self.target.crt_static_respected {
) -> Option<Symbol> {
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
}
+
+ pub fn diagnostic_width(&self) -> usize {
+ let default_column_width = 140;
+ if let Some(width) = self.opts.diagnostic_width {
+ width
+ } else if self.opts.unstable_opts.ui_testing {
+ default_column_width
+ } else {
+ termize::dimensions().map_or(default_column_width, |(w, _)| w)
+ }
+ }
}
// JUSTIFICATION: defn of the suggested wrapper fns
let warnings_allow = sopts
.lint_opts
.iter()
- .rfind(|&&(ref key, _)| *key == "warnings")
+ .rfind(|&(key, _)| *key == "warnings")
.map_or(false, |&(_, level)| level == lint::Allow);
let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
}
}
+ // LLVM CFI and KCFI are mutually exclusive
+ if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
+ sess.emit_err(CannotMixAndMatchSanitizers {
+ first: "cfi".to_string(),
+ second: "kcfi".to_string(),
+ });
+ }
+
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
sess.emit_warning(StackProtectorNotSupportedForTarget {
}
}
+ if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
+ sess.emit_err(BranchProtectionRequiresAArch64);
+ }
+
if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
if dwarf_version > 5 {
sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
// There might still be a tail left to analyze
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
if tail_start < src.len() {
- analyze_source_file_generic(&src[tail_start as usize ..],
+ analyze_source_file_generic(&src[tail_start ..],
src.len() - tail_start,
output_offset + BytePos::from_usize(tail_start),
lines,
while i < scan_len {
let byte = unsafe {
// We verified that i < scan_len <= src.len()
- *src_bytes.get_unchecked(i as usize)
+ *src_bytes.get_unchecked(i)
};
// How much to advance in order to get to the next UTF-8 char in the
-use crate::HashStableContext;
+use crate::{HashStableContext, Symbol};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_data_structures::AtomicRef;
/// Computes the stable ID for a crate with the given name and
/// `-Cmetadata` arguments.
- pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+ pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
let mut hasher = StableHasher::new();
- crate_name.hash(&mut hasher);
+ // We must hash the string text of the crate name, not the id, as the id is not stable
+ // across builds.
+ crate_name.as_str().hash(&mut hasher);
// We don't want the stable crate ID to depend on the order of
// -C metadata arguments, so sort them:
FileNameDisplayPreference::Remapped => {
self.remapped_path_if_available().to_string_lossy()
}
+ FileNameDisplayPreference::Short => self
+ .local_path_if_available()
+ .file_name()
+ .map_or_else(|| "".into(), |f| f.to_string_lossy()),
}
}
}
/// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
/// This is appropriate for use in user-facing output (such as diagnostics).
Local,
+ /// Display only the filename, as a way to reduce the verbosity of the output.
+ /// This is appropriate for use in user-facing output (such as diagnostics).
+ Short,
}
pub struct FileNameDisplay<'a> {
pub fn is_dummy(self) -> bool {
self.lo.0 == 0 && self.hi.0 == 0
}
+ #[inline]
+ pub fn is_visible(self, sm: &SourceMap) -> bool {
+ !self.is_dummy() && sm.is_span_accessible(self.span())
+ }
/// Returns `true` if `self` fully encloses `other`.
pub fn contains(self, other: Self) -> bool {
self.lo <= other.lo && other.hi <= self.hi
self.data_untracked().is_dummy()
}
+ #[inline]
+ pub fn is_visible(self, sm: &SourceMap) -> bool {
+ self.data_untracked().is_visible(sm)
+ }
+
/// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
#[inline]
pub fn from_expansion(self) -> bool {
4 => {
raw_diffs = Vec::with_capacity(bytes_per_diff * num_diffs);
for diff in diff_iter {
- raw_diffs.extend_from_slice(&(diff.0 as u32).to_le_bytes());
+ raw_diffs.extend_from_slice(&(diff.0).to_le_bytes());
}
}
_ => unreachable!(),
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock};
+use std::cmp;
use std::hash::Hash;
use std::path::{Path, PathBuf};
use std::sync::atomic::Ordering;
-use std::{clone::Clone, cmp};
-use std::{convert::TryFrom, unreachable};
use std::fs;
use std::io;
}
}
- fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
+ pub fn span_to_string(
+ &self,
+ sp: Span,
+ filename_display_pref: FileNameDisplayPreference,
+ ) -> String {
if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
return "no-location".to_string();
}
let lo = self.lookup_char_pos(sp.lo());
let hi = self.lookup_char_pos(sp.hi());
format!(
- "{}:{}:{}: {}:{}",
+ "{}:{}:{}{}",
lo.file.name.display(filename_display_pref),
lo.line,
lo.col.to_usize() + 1,
- hi.line,
- hi.col.to_usize() + 1,
+ if let FileNameDisplayPreference::Short = filename_display_pref {
+ String::new()
+ } else {
+ format!(": {}:{}", hi.line, hi.col.to_usize() + 1)
+ }
)
}
/// Otherwise, the span reached to limit is returned.
pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
let mut sp = span;
- for _ in 0..limit.unwrap_or(100 as usize) {
+ for _ in 0..limit.unwrap_or(100_usize) {
sp = self.next_point(sp);
if let Ok(ref snippet) = self.span_to_snippet(sp) {
if expect.map_or(false, |es| snippet == es) {
// NOTE: We are iterating over the mapping entries from last to first
// because entries specified later on the command line should
// take precedence.
- for &(ref from, ref to) in mapping.iter().rev() {
+ for (from, to) in mapping.iter().rev() {
debug!("Trying to apply {from:?} => {to:?}");
if let Ok(rest) = path.strip_prefix(from) {
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::cmp::{Ord, PartialEq, PartialOrd};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::str;
item_like_imports,
iter,
iter_repeat,
+ iterator_collect_fn,
+ kcfi,
keyword,
kind,
kreg,
}
}
-/// This is the most general way to print identifiers.
+/// The most general type to print identifiers.
+///
/// AST pretty-printer is used as a fallback for turning AST structures into token streams for
/// proc macros. Additionally, proc macros may stringify their input and expect it survive the
/// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
/// For example `sym::rustfmt` or `sym::u8`.
pub mod sym {
use super::Symbol;
- use std::convert::TryInto;
#[doc(inline)]
pub use super::sym_generated::*;
tracing = "0.1"
punycode = "0.4.0"
rustc-demangle = "0.1.21"
+twox-hash = "1.6.3"
rustc_span = { path = "../rustc_span" }
rustc_middle = { path = "../rustc_middle" }
match *ty.kind() {
// Print all nominal types as paths (unlike `pretty_print_type`).
ty::FnDef(def_id, substs)
- | ty::Opaque(def_id, substs)
- | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+ | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
| ty::Closure(def_id, substs)
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
// Similar to `pretty_path_qualified`, but for the other
// types that are printed as paths (see `print_type` above).
match self_ty.kind() {
- ty::FnDef(..)
- | ty::Opaque(..)
- | ty::Projection(_)
- | ty::Closure(..)
- | ty::Generator(..)
+ ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Generator(..)
if trait_ref.is_none() =>
{
self.print_type(self_ty)
use rustc_middle::ty::{FnSig, Ty, TyCtxt};
use rustc_target::abi::call::FnAbi;
+use std::hash::Hasher;
+use twox_hash::XxHash64;
mod typeid_itanium_cxx_abi;
use typeid_itanium_cxx_abi::TypeIdOptions;
pub fn typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> String {
typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS)
}
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnAbi.
+pub fn kcfi_typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> u32 {
+ // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+ // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+ let mut hash: XxHash64 = Default::default();
+ hash.write(
+ typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, TypeIdOptions::NO_OPTIONS).as_bytes(),
+ );
+ hash.finish() as u32
+}
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnSig.
+pub fn kcfi_typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> u32 {
+ // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+ // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+ let mut hash: XxHash64 = Default::default();
+ hash.write(
+ typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS).as_bytes(),
+ );
+ hash.finish() as u32
+}
s.push_str(&encode_substs(tcx, trait_ref.substs, dict, options));
}
ty::ExistentialPredicate::Projection(projection) => {
- let name = encode_ty_name(tcx, projection.item_def_id);
+ let name = encode_ty_name(tcx, projection.def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
s.push_str(&encode_substs(tcx, projection.substs, dict, options));
match projection.term.unpack() {
| ty::Error(..)
| ty::GeneratorWitness(..)
| ty::Infer(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(..)
- | ty::Placeholder(..)
- | ty::Projection(..) => {
+ | ty::Placeholder(..) => {
bug!("encode_ty: unexpected `{:?}`", ty.kind());
}
};
| ty::Error(..)
| ty::GeneratorWitness(..)
| ty::Infer(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(..)
- | ty::Placeholder(..)
- | ty::Projection(..) => {
+ | ty::Placeholder(..) => {
bug!("transform_ty: unexpected `{:?}`", ty.kind());
}
}
// Mangle all nominal types as paths.
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
| ty::FnDef(def_id, substs)
- | ty::Opaque(def_id, substs)
- | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
+ | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
| ty::Closure(def_id, substs)
| ty::Generator(def_id, substs, _) => {
self = self.print_def_path(def_id, substs)?;
cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
}
ty::ExistentialPredicate::Projection(projection) => {
- let name = cx.tcx.associated_item(projection.item_def_id).name;
+ let name = cx.tcx.associated_item(projection.def_id).name;
cx.push("p");
cx.push_ident(name.as_str());
cx = match projection.term.unpack() {
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-use std::iter::FromIterator;
use std::path::{Path, PathBuf};
#[macro_use]
//
// For example, `-C target-cpu=cortex-a53`.
-use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{
+ Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target, TargetOptions,
+};
pub fn target() -> Target {
let opts = TargetOptions {
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+strict-align,+neon,+fp-armv8".into(),
+ supported_sanitizers: SanitizerSet::KCFI,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
_ => os.into(),
};
- let platform_version: StaticCow<str> = match os.as_ref() {
+ let platform_version: StaticCow<str> = match os {
"ios" => ios_lld_platform_version(),
"tvos" => tvos_lld_platform_version(),
"watchos" => watchos_lld_platform_version(),
fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> {
// Apple platforms only officially support macOS as a host for any compilation.
//
- // If building for macOS, we go ahead and remove any erronous environment state
+ // If building for macOS, we go ahead and remove any erroneous environment state
// that's only applicable to cross-OS compilation. Always leave anything for the
// host OS alone though.
if os == "macos" {
use serde_json::Value;
use std::borrow::Cow;
use std::collections::BTreeMap;
-use std::convert::TryFrom;
use std::hash::{Hash, Hasher};
-use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::str::FromStr;
bitflags::bitflags! {
#[derive(Default, Encodable, Decodable)]
- pub struct SanitizerSet: u8 {
+ pub struct SanitizerSet: u16 {
const ADDRESS = 1 << 0;
const LEAK = 1 << 1;
const MEMORY = 1 << 2;
const CFI = 1 << 5;
const MEMTAG = 1 << 6;
const SHADOWCALLSTACK = 1 << 7;
+ const KCFI = 1 << 8;
}
}
Some(match self {
SanitizerSet::ADDRESS => "address",
SanitizerSet::CFI => "cfi",
+ SanitizerSet::KCFI => "kcfi",
SanitizerSet::LEAK => "leak",
SanitizerSet::MEMORY => "memory",
SanitizerSet::MEMTAG => "memtag",
[
SanitizerSet::ADDRESS,
SanitizerSet::CFI,
+ SanitizerSet::KCFI,
SanitizerSet::LEAK,
SanitizerSet::MEMORY,
SanitizerSet::MEMTAG,
base.$key_name |= match s.as_str() {
Some("address") => SanitizerSet::ADDRESS,
Some("cfi") => SanitizerSet::CFI,
+ Some("kcfi") => SanitizerSet::KCFI,
Some("leak") => SanitizerSet::LEAK,
Some("memory") => SanitizerSet::MEMORY,
Some("memtag") => SanitizerSet::MEMTAG,
base.max_atomic_width = Some(64);
base.add_pre_link_args(
LinkerFlavor::Unix(Cc::No),
- &[
- "-b64".into(),
- "-bpT:0x100000000".into(),
- "-bpD:0x110000000".into(),
- "-bcdtors:all:0:s".into(),
- ],
+ &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"],
);
Target {
// For now this target just never has an entry symbol no matter the output
// type, so unconditionally pass this.
"--no-entry",
- // Rust really needs a way for users to specify exports and imports in
- // the source code. --export-dynamic isn't the right tool for this job,
- // however it does have the side effect of automatically exporting a lot
- // of symbols, which approximates what people want when compiling for
- // wasm32-unknown-unknown expect, so use it for now.
- "--export-dynamic",
],
);
options.add_pre_link_args(
// otherwise
"--target=wasm32-unknown-unknown",
"-Wl,--no-entry",
- "-Wl,--export-dynamic",
],
);
// `args::args()` makes the WASI API calls itself.
options.main_needs_argc_argv = false;
+ // And, WASI mangles the name of "main" to distinguish between different
+ // signatures.
+ options.entry_name = "__main_void".into();
+
Target {
llvm_target: "wasm32-wasi".into(),
pointer_width: 32,
// features.
use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use super::{RelroLevel, StackProbeType, Target, TargetOptions};
+use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
features:
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
.into(),
+ supported_sanitizers: SanitizerSet::KCFI,
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
code_model: Some(CodeModel::Kernel),
pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Param(_) => true,
- ty::Projection(p) => self.is_of_param(p.self_ty()),
+ ty::Alias(ty::Projection, p) => self.is_of_param(p.self_ty()),
_ => false,
}
}
fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
if let Some(ty) = p.term().skip_binder().ty() {
- matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty)
+ matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_ty)
} else {
false
}
+++ /dev/null
-// This file contains various trait resolution methods used by codegen.
-// They all assume regions can be erased and monomorphic types. It
-// seems likely that they should eventually be merged into more
-// general routines.
-
-use crate::infer::{DefiningAnchor, TyCtxtInferExt};
-use crate::traits::error_reporting::TypeErrCtxtExt;
-use crate::traits::{
- ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
- Unimplemented,
-};
-use rustc_infer::traits::FulfillmentErrorCode;
-use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, TyCtxt};
-
-/// Attempts to resolve an obligation to an `ImplSource`. The result is
-/// a shallow `ImplSource` resolution, meaning that we do not
-/// (necessarily) resolve all nested obligations on the impl. Note
-/// that type check should guarantee to us that all nested
-/// obligations *could be* resolved if we wanted to.
-///
-/// This also expects that `trait_ref` is fully normalized.
-pub fn codegen_select_candidate<'tcx>(
- tcx: TyCtxt<'tcx>,
- (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
-) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
- // We expect the input to be fully normalized.
- debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
-
- // Do the initial selection for the obligation. This yields the
- // shallow result we are looking for -- that is, what specific impl.
- let infcx = tcx
- .infer_ctxt()
- .ignoring_regions()
- .with_opaque_type_inference(DefiningAnchor::Bubble)
- .build();
- //~^ HACK `Bubble` is required for
- // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
- let mut selcx = SelectionContext::new(&infcx);
-
- let obligation_cause = ObligationCause::dummy();
- let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
-
- let selection = match selcx.select(&obligation) {
- Ok(Some(selection)) => selection,
- Ok(None) => return Err(CodegenObligationError::Ambiguity),
- Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
- Err(e) => {
- bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
- }
- };
-
- debug!(?selection);
-
- // Currently, we use a fulfillment context to completely resolve
- // all nested obligations. This is because they can inform the
- // inference of the impl's type parameters.
- let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
- let impl_source = selection.map(|predicate| {
- fulfill_cx.register_predicate_obligation(&infcx, predicate);
- });
-
- // In principle, we only need to do this so long as `impl_source`
- // contains unbound type parameters. It could be a slight
- // optimization to stop iterating early.
- let errors = fulfill_cx.select_all_or_error(&infcx);
- if !errors.is_empty() {
- // `rustc_monomorphize::collector` assumes there are no type errors.
- // Cycle errors are the only post-monomorphization errors possible; emit them now so
- // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
- for err in errors {
- if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
- infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
- }
- }
- return Err(CodegenObligationError::FulfillmentError);
- }
-
- let impl_source = infcx.resolve_vars_if_possible(impl_source);
- let impl_source = infcx.tcx.erase_regions(impl_source);
-
- // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
- // as they will get constrained elsewhere, too.
- // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
-
- Ok(&*tcx.arena.alloc(impl_source))
-}
| ty::RawPtr(..)
| ty::Never
| ty::Tuple(..)
- | ty::Projection(..) => self.found_non_local_ty(ty),
+ | ty::Alias(ty::Projection, ..) => self.found_non_local_ty(ty),
ty::Param(..) => self.found_param_ty(ty),
);
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
}
- ty::Opaque(..) => {
+ ty::Alias(ty::Opaque, ..) => {
// This merits some explanation.
// Normally, opaque types are not involved when performing
// coherence checking, since it is illegal to directly
span: Span,
) -> Result<(), NotConstEvaluatable> {
let tcx = infcx.tcx;
- match unexpanded_ct.kind() {
+ match tcx.expand_abstract_consts(unexpanded_ct).kind() {
ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (),
ty::ConstKind::Param(_)
| ty::ConstKind::Bound(_, _)
use rustc_hir::def_id::DefId;
-use rustc_infer::infer::InferCtxt;
+use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime};
+use rustc_infer::traits::util::elaborate_predicates_with_span;
use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty;
+use rustc_span::{Span, DUMMY_SP};
use crate::traits::ObligationCtxt;
+pub enum Ambiguity {
+ DefId(DefId),
+ ParamEnv(Span),
+}
+
pub fn recompute_applicable_impls<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &TraitObligation<'tcx>,
-) -> Vec<DefId> {
+) -> Vec<Ambiguity> {
let tcx = infcx.tcx;
let param_env = obligation.param_env;
- let dummy_cause = ObligationCause::dummy();
+
let impl_may_apply = |impl_def_id| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
let obligation_trait_ref =
- ocx.normalize(&dummy_cause, param_env, placeholder_obligation.trait_ref);
+ ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
- if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+ if let Err(_) =
+ ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
+ {
return false;
}
let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
- ocx.register_obligations(
- impl_predicates
- .predicates
- .iter()
- .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)),
+ ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
+ Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
+ }));
+
+ ocx.select_where_possible().is_empty()
+ };
+
+ let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
+ let placeholder_obligation =
+ infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ let obligation_trait_ref =
+ ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
+
+ let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+ DUMMY_SP,
+ LateBoundRegionConversionTime::HigherRankedType,
+ poly_trait_predicate,
);
+ let param_env_trait_ref =
+ ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
+
+ if let Err(_) =
+ ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
+ {
+ return false;
+ }
ocx.select_where_possible().is_empty()
};
- let mut impls = Vec::new();
+ let mut ambiguities = Vec::new();
+
tcx.for_each_relevant_impl(
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
|impl_def_id| {
- if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
- impls.push(impl_def_id)
+ if infcx.probe(|_| impl_may_apply(impl_def_id)) {
+ ambiguities.push(Ambiguity::DefId(impl_def_id))
}
},
);
- impls
+
+ let predicates =
+ tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+ for obligation in
+ elaborate_predicates_with_span(tcx, std::iter::zip(predicates.predicates, predicates.spans))
+ {
+ let kind = obligation.predicate.kind();
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
+ && param_env_candidate_may_apply(kind.rebind(trait_pred))
+ {
+ if kind.rebind(trait_pred.trait_ref) == ty::TraitRef::identity(tcx, trait_pred.def_id()) {
+ ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id())))
+ } else {
+ ambiguities.push(Ambiguity::ParamEnv(obligation.cause.span))
+ }
+ }
+ }
+
+ ambiguities
}
--- /dev/null
+use crate::infer::InferCtxt;
+
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct CollectAllMismatches<'a, 'tcx> {
+ pub infcx: &'a InferCtxt<'tcx>,
+ pub param_env: ty::ParamEnv<'tcx>,
+ pub errors: Vec<TypeError<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
+ fn tag(&self) -> &'static str {
+ "CollectAllMismatches"
+ }
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+ fn intercrate(&self) -> bool {
+ false
+ }
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.param_env
+ }
+ fn a_is_expected(&self) -> bool {
+ true
+ } // irrelevant
+ fn mark_ambiguous(&mut self) {
+ bug!()
+ }
+ fn relate_with_variance<T: Relate<'tcx>>(
+ &mut self,
+ _: ty::Variance,
+ _: ty::VarianceDiagInfo<'tcx>,
+ a: T,
+ b: T,
+ ) -> RelateResult<'tcx, T> {
+ self.relate(a, b)
+ }
+ fn regions(
+ &mut self,
+ a: ty::Region<'tcx>,
+ _b: ty::Region<'tcx>,
+ ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+ Ok(a)
+ }
+ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+ if a == b || matches!(a.kind(), ty::Infer(_)) || matches!(b.kind(), ty::Infer(_)) {
+ return Ok(a);
+ }
+ relate::super_relate_tys(self, a, b).or_else(|e| {
+ self.errors.push(e);
+ Ok(a)
+ })
+ }
+ fn consts(
+ &mut self,
+ a: ty::Const<'tcx>,
+ b: ty::Const<'tcx>,
+ ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+ if a == b {
+ return Ok(a);
+ }
+ relate::super_relate_consts(self, a, b) // could do something similar here for constants!
+ }
+ fn binders<T: Relate<'tcx>>(
+ &mut self,
+ a: ty::Binder<'tcx, T>,
+ b: ty::Binder<'tcx, T>,
+ ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
+ Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+ }
+}
mod ambiguity;
+pub mod method_chain;
pub mod on_unimplemented;
pub mod suggestions;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{FmtPrinter, Print};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
TypeVisitable,
};
use rustc_session::Limit;
use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::sym;
use rustc_span::{ExpnKind, Span, DUMMY_SP};
use std::fmt;
use std::iter;
let arg_length = arguments.len();
let distinct = matches!(other, &[ArgKind::Tuple(..)]);
match (arg_length, arguments.get(0)) {
- (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+ (1, Some(ArgKind::Tuple(_, fields))) => {
format!("a single {}-tuple as argument", fields.len())
}
_ => format!(
|err| {
self.note_obligation_cause_code(
err,
- &predicate,
+ predicate,
obligation.param_env,
obligation.cause.code(),
&mut vec![],
// can get a better error message by performing HIR-based well-formedness checking.
if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
root_obligation.cause.code().peel_derives()
+ && !obligation.predicate.has_non_region_infer()
{
if let Some(cause) = self
.tcx
trait_ref,
obligation.cause.body_id,
&mut err,
+ true,
) {
// This is *almost* equivalent to
// `obligation.cause.code().peel_derives()`, but it gives us the
trait_ref,
obligation.cause.body_id,
&mut err,
+ true,
);
}
}
&& self.fallback_has_occurred
{
let predicate = trait_predicate.map_bound(|trait_pred| {
- trait_pred.with_self_type(self.tcx, self.tcx.mk_unit())
+ trait_pred.with_self_ty(self.tcx, self.tcx.mk_unit())
});
let unit_obligation = obligation.with(tcx, predicate);
if self.predicate_may_hold(&unit_obligation) {
_ => None,
};
+ let found_node = found_did.and_then(|did| self.tcx.hir().get_if_local(did));
let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
found_trait_ref,
expected_trait_ref,
obligation.cause.code(),
+ found_node,
)
} else {
let (closure_span, closure_arg_span, found) = found_did
trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId,
err: &mut Diagnostic,
+ other: bool,
) -> bool;
/// Gets the parent trait chain start
fn annotate_source_of_ambiguity(
&self,
err: &mut Diagnostic,
- impls: &[DefId],
+ impls: &[ambiguity::Ambiguity],
predicate: ty::Predicate<'tcx>,
);
{
self.note_obligation_cause_code(
&mut diag,
- &error.obligation.predicate,
+ error.obligation.predicate,
error.obligation.param_env,
code,
&mut vec![],
infer::LateBoundRegionConversionTime::HigherRankedType,
bound_predicate.rebind(data),
);
- let normalized_ty = ocx.normalize(
- &obligation.cause,
- obligation.param_env,
- self.tcx
- .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs),
- );
+ let unnormalized_term = match data.term.unpack() {
+ ty::TermKind::Ty(_) => self
+ .tcx
+ .mk_projection(data.projection_ty.def_id, data.projection_ty.substs)
+ .into(),
+ ty::TermKind::Const(ct) => self
+ .tcx
+ .mk_const(
+ ty::UnevaluatedConst {
+ def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
+ substs: data.projection_ty.substs,
+ },
+ ct.ty(),
+ )
+ .into(),
+ };
+ let normalized_term =
+ ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
debug!(?obligation.cause, ?obligation.param_env);
- debug!(?normalized_ty, data.ty = ?data.term);
+ debug!(?normalized_term, data.ty = ?data.term);
- let is_normalized_ty_expected = !matches!(
+ let is_normalized_term_expected = !matches!(
obligation.cause.code().peel_derives(),
ObligationCauseCode::ItemObligation(_)
| ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::OpaqueType
);
- let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error());
// constrain inference variables a bit more to nested obligations from normalize so
// we can have more helpful errors.
if let Err(new_err) = ocx.eq_exp(
&obligation.cause,
obligation.param_env,
- is_normalized_ty_expected,
- normalized_ty,
- expected_ty,
+ is_normalized_term_expected,
+ normalized_term,
+ data.term,
) {
- (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err)
+ (Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
} else {
(None, error.err)
}
};
let msg = values
- .and_then(|(predicate, _, normalized_ty, expected_ty)| {
- self.maybe_detailed_projection_msg(
- predicate,
- normalized_ty.into(),
- expected_ty.into(),
- )
+ .and_then(|(predicate, _, normalized_term, expected_term)| {
+ self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
})
.unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
let secondary_span = match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
.tcx
- .opt_associated_item(proj.projection_ty.item_def_id)
+ .opt_associated_item(proj.projection_ty.def_id)
.and_then(|trait_assoc_item| {
self.tcx
- .trait_of_item(proj.projection_ty.item_def_id)
+ .trait_of_item(proj.projection_ty.def_id)
.map(|id| (trait_assoc_item, id))
})
.and_then(|(trait_assoc_item, id)| {
values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
infer::ValuePairs::Terms(ExpectedFound::new(
is_normalized_ty_expected,
- normalized_ty.into(),
- expected_ty.into(),
+ normalized_ty,
+ expected_ty,
))
}),
err,
let trait_def_id = pred.projection_ty.trait_def_id(self.tcx);
let self_ty = pred.projection_ty.self_ty();
- if Some(pred.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() {
- Some(format!(
- "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it returns `{normalized_ty}`",
- fn_kind = self_ty.prefix_string(self.tcx)
- ))
- } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
- Some(format!(
- "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it resolves to `{normalized_ty}`"
- ))
- } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
- Some(format!(
- "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it yields `{normalized_ty}`"
- ))
- } else {
- None
+ with_forced_trimmed_paths! {
+ if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+ Some(format!(
+ "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+ returns `{normalized_ty}`",
+ fn_kind = self_ty.prefix_string(self.tcx)
+ ))
+ } else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
+ Some(format!(
+ "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
+ resolves to `{normalized_ty}`"
+ ))
+ } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+ Some(format!(
+ "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
+ yields `{normalized_ty}`"
+ ))
+ } else {
+ None
+ }
}
}
ty::Closure(..) => Some(9),
ty::Tuple(..) => Some(10),
ty::Param(..) => Some(11),
- ty::Projection(..) => Some(12),
- ty::Opaque(..) => Some(13),
+ ty::Alias(ty::Projection, ..) => Some(12),
+ ty::Alias(ty::Opaque, ..) => Some(13),
ty::Never => Some(14),
ty::Adt(..) => Some(15),
ty::Generator(..) => Some(16),
trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId,
err: &mut Diagnostic,
+ other: bool,
) -> bool {
+ let other = if other { "other " } else { "" };
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
candidates.sort();
candidates.dedup();
candidates.dedup();
let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
err.help(&format!(
- "the following other types implement trait `{}`:{}{}",
+ "the following {other}types implement trait `{}`:{}{}",
trait_ref.print_only_trait_path(),
candidates[..end].join(""),
if len > 9 { format!("\nand {} others", len - 8) } else { String::new() }
param_env: ty::ParamEnv<'tcx>,
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
) -> PredicateObligation<'tcx> {
- let trait_pred = trait_ref_and_ty
- .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty));
+ let trait_pred =
+ trait_ref_and_ty.map_bound(|(tr, new_self_ty)| tr.with_self_ty(self.tcx, new_self_ty));
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred)
}
let mut selcx = SelectionContext::new(&self);
match selcx.select_from_obligation(&obligation) {
Ok(None) => {
- let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+ let ambiguities =
+ ambiguity::recompute_applicable_impls(self.infcx, &obligation);
let has_non_region_infer =
trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
// It doesn't make sense to talk about applicable impls if there are more
// than a handful of them.
- if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
- self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+ if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
+ if self.tainted_by_errors().is_some() && subst.is_none() {
+ // If `subst.is_none()`, then this is probably two param-env
+ // candidates or impl candidates that are equal modulo lifetimes.
+ // Therefore, if we've already emitted an error, just skip this
+ // one, since it's not particularly actionable.
+ err.cancel();
+ return;
+ }
+ self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
} else {
if self.tainted_by_errors().is_some() {
err.cancel();
return;
}
err.note(&format!("cannot satisfy `{}`", predicate));
+ let impl_candidates = self.find_similar_impl_candidates(
+ predicate.to_opt_poly_trait_pred().unwrap(),
+ );
+ if impl_candidates.len() < 10 {
+ self.report_similar_impl_candidates(
+ impl_candidates,
+ trait_ref,
+ body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+ &mut err,
+ false,
+ );
+ }
}
}
_ => {
}
}
- if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
- self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
- } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
- && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
- = *obligation.cause.code()
+ if let ObligationCauseCode::ItemObligation(def_id)
+ | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
{
- let generics = self.tcx.generics_of(def_id);
- if generics.params.iter().any(|p| p.name != kw::SelfUpper)
- && !snippet.ends_with('>')
- && !generics.has_impl_trait()
- && !self.tcx.is_fn_trait(def_id)
- {
- // FIXME: To avoid spurious suggestions in functions where type arguments
- // where already supplied, we check the snippet to make sure it doesn't
- // end with a turbofish. Ideally we would have access to a `PathSegment`
- // instead. Otherwise we would produce the following output:
- //
- // error[E0283]: type annotations needed
- // --> $DIR/issue-54954.rs:3:24
- // |
- // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
- // | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- // | |
- // | cannot infer type
- // | help: consider specifying the type argument
- // | in the function call:
- // | `Tt::const_val::<[i8; 123]>::<T>`
- // ...
- // LL | const fn const_val<T: Sized>() -> usize {
- // | - required by this bound in `Tt::const_val`
- // |
- // = note: cannot satisfy `_: Tt`
-
- // Clear any more general suggestions in favor of our specific one
- err.clear_suggestions();
-
- err.span_suggestion_verbose(
- span.shrink_to_hi(),
- &format!(
- "consider specifying the type argument{} in the function call",
- pluralize!(generics.params.len()),
- ),
- format!(
- "::<{}>",
- generics
- .params
- .iter()
- .map(|p| p.name.to_string())
- .collect::<Vec<String>>()
- .join(", ")
- ),
- Applicability::HasPlaceholders,
- );
- }
+ self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
}
if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
if trait_impls.blanket_impls().is_empty()
- && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
- && let Some(impl_def_id) = impl_ty.def() {
- let message = if trait_impls.non_blanket_impls().len() == 1 {
+ && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next()
+ {
+ let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count();
+ let message = if non_blanket_impl_count == 1 {
"use the fully-qualified path to the only available implementation".to_string()
} else {
format!(
"use a fully-qualified path to a specific available implementation ({} found)",
- trait_impls.non_blanket_impls().len()
+ non_blanket_impl_count
)
};
let mut suggestions = vec![(
- trait_path_segment.ident.span.shrink_to_lo(),
+ path.span.shrink_to_lo(),
format!("<{} as ", self.tcx.type_of(impl_def_id))
)];
if let Some(generic_arg) = trait_path_segment.args {
fn annotate_source_of_ambiguity(
&self,
err: &mut Diagnostic,
- impls: &[DefId],
+ ambiguities: &[ambiguity::Ambiguity],
predicate: ty::Predicate<'tcx>,
) {
let mut spans = vec![];
let mut crates = vec![];
let mut post = vec![];
- for def_id in impls {
- match self.tcx.span_of_impl(*def_id) {
- Ok(span) => spans.push(span),
- Err(name) => {
- crates.push(name);
- if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
- post.push(header);
+ let mut has_param_env = false;
+ for ambiguity in ambiguities {
+ match ambiguity {
+ ambiguity::Ambiguity::DefId(impl_def_id) => {
+ match self.tcx.span_of_impl(*impl_def_id) {
+ Ok(span) => spans.push(span),
+ Err(name) => {
+ crates.push(name);
+ if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
+ post.push(header);
+ }
+ }
}
}
+ ambiguity::Ambiguity::ParamEnv(span) => {
+ has_param_env = true;
+ spans.push(*span);
+ }
}
}
let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
return;
}
- let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+ let msg = format!(
+ "multiple `impl`s{} satisfying `{}` found",
+ if has_param_env { " or `where` clauses" } else { "" },
+ predicate
+ );
let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
} else if post.len() == 1 {
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
self.note_obligation_cause_code(
err,
- &obligation.predicate,
+ obligation.predicate,
obligation.param_env,
obligation.cause.code(),
&mut vec![],
+// ignore-tidy-filelength
+
use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation};
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt;
-use crate::traits::NormalizeExt;
+use crate::traits::{NormalizeExt, ObligationCtxt};
use hir::def::CtorOf;
use hir::HirId;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
use rustc_middle::hir::map;
+use rustc_middle::ty::error::TypeError::{self, Sorts};
+use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
- GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, IsSuggestable,
- ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+ GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
+ IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+ TypeSuperFoldable, TypeVisitable, TypeckResults,
};
-use rustc_middle::ty::{TypeAndMut, TypeckResults};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
-use std::fmt;
+use std::ops::Deref;
+use super::method_chain::CollectAllMismatches;
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;
+use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
#[derive(Debug)]
pub enum GeneratorInteriorOrUpvar {
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
+ found_node: Option<Node<'_>>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
fn note_conflicting_closure_bounds(
fn note_obligation_cause_code<T>(
&self,
err: &mut Diagnostic,
- predicate: &T,
+ predicate: T,
param_env: ty::ParamEnv<'tcx>,
cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
- T: fmt::Display + ToPredicate<'tcx>;
+ T: ToPredicate<'tcx>;
/// Suggest to await before try: future? => future.await?
fn suggest_await_before_try(
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
);
+ fn function_argument_obligation(
+ &self,
+ arg_hir_id: HirId,
+ err: &mut Diagnostic,
+ parent_code: &ObligationCauseCode<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ predicate: ty::Predicate<'tcx>,
+ call_hir_id: HirId,
+ );
+ fn point_at_chain(
+ &self,
+ expr: &hir::Expr<'_>,
+ typeck_results: &TypeckResults<'tcx>,
+ type_diffs: Vec<TypeError<'tcx>>,
+ param_env: ty::ParamEnv<'tcx>,
+ err: &mut Diagnostic,
+ );
+ fn probe_assoc_types_at_expr(
+ &self,
+ type_diffs: &[TypeError<'tcx>],
+ span: Span,
+ prev_ty: Ty<'tcx>,
+ body_id: hir::HirId,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
}
fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
msg: &str,
err: &mut Diagnostic,
fn_sig: Option<&hir::FnSig<'_>>,
- projection: Option<&ty::ProjectionTy<'_>>,
+ projection: Option<&ty::AliasTy<'_>>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
// When we are dealing with a trait, `super_traits` will be `Some`:
// Given `trait T: A + B + C {}`
let self_ty = trait_pred.skip_binder().self_ty();
let (param_ty, projection) = match self_ty.kind() {
ty::Param(_) => (true, None),
- ty::Projection(projection) => (false, Some(projection)),
+ ty::Alias(ty::Projection, projection) => (false, Some(projection)),
_ => (false, None),
};
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
// It only make sense when suggesting dereferences for arguments
- let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+ let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
else { return false; };
let Some(typeck_results) = &self.typeck_results
else { return false; };
real_trait_pred_and_base_ty,
);
if self.predicate_may_hold(&obligation) {
- err.span_suggestion_verbose(
- span.shrink_to_lo(),
- "consider dereferencing here",
- "*",
- Applicability::MachineApplicable,
+ let call_node = self.tcx.hir().get(*call_hir_id);
+ let msg = "consider dereferencing here";
+ let is_receiver = matches!(
+ call_node,
+ Node::Expr(hir::Expr {
+ kind: hir::ExprKind::MethodCall(_, receiver_expr, ..),
+ ..
+ })
+ if receiver_expr.hir_id == *arg_hir_id
);
+ if is_receiver {
+ err.multipart_suggestion_verbose(
+ msg,
+ vec![
+ (span.shrink_to_lo(), "(*".to_string()),
+ (span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
+ } else {
+ err.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ msg,
+ '*',
+ Applicability::MachineApplicable,
+ )
+ };
return true;
}
}
fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
))
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
- && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
// args tuple will always be substs[1]
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
{
ty::Dynamic(data, _, ty::Dyn) => {
data.iter().find_map(|pred| {
if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
- && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
// for existential projection, substs are shifted over by 1
&& let ty::Tuple(args) = proj.substs.type_at(0).kind()
{
ty::Param(_) => {
obligation.param_env.caller_bounds().iter().find_map(|pred| {
if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder()
- && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
&& proj.projection_ty.self_ty() == found
// args tuple will always be substs[1]
&& let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
if only_never_return {
// No return paths, probably using `panic!()` or similar.
- // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
+ // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
suggest_trait_object_return_type_alternatives(
err,
ret_ty.span,
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
cause: &ObligationCauseCode<'tcx>,
+ found_node: Option<Node<'_>>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_ty<'tcx>(
infcx: &InferCtxt<'tcx>,
self.note_conflicting_closure_bounds(cause, &mut err);
+ if let Some(found_node) = found_node {
+ hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
+ }
+
err
}
&& self.tcx.is_fn_trait(trait_pred.def_id())
{
let expected_self =
- self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
+ self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
let expected_substs = self
.tcx
- .anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));
+ .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.substs));
// Find another predicate whose self-type is equal to the expected self type,
// but whose substs don't match.
// Make sure that the self type matches
// (i.e. constraining this closure)
&& expected_self
- == self.tcx.anonymize_late_bound_regions(
+ == self.tcx.anonymize_bound_vars(
pred.kind().rebind(trait_pred.self_ty()),
)
// But the substs don't match (i.e. incompatible args)
&& expected_substs
- != self.tcx.anonymize_late_bound_regions(
+ != self.tcx.anonymize_bound_vars(
pred.kind().rebind(trait_pred.trait_ref.substs),
) =>
{
format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
};
- let mut explain_yield = |interior_span: Span,
- yield_span: Span,
- scope_span: Option<Span>| {
- let mut span = MultiSpan::from_span(yield_span);
- if let Ok(snippet) = source_map.span_to_snippet(interior_span) {
- // #70935: If snippet contains newlines, display "the value" instead
- // so that we do not emit complex diagnostics.
- let snippet = &format!("`{}`", snippet);
- let snippet = if snippet.contains('\n') { "the value" } else { snippet };
+ let mut explain_yield =
+ |interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
+ let mut span = MultiSpan::from_span(yield_span);
+ let snippet = match source_map.span_to_snippet(interior_span) {
+ // #70935: If snippet contains newlines, display "the value" instead
+ // so that we do not emit complex diagnostics.
+ Ok(snippet) if !snippet.contains('\n') => format!("`{}`", snippet),
+ _ => "the value".to_string(),
+ };
// note: future is not `Send` as this value is used across an await
// --> $DIR/issue-70935-complex-spans.rs:13:9
// |
interior_span,
format!("has type `{}` which {}", target_ty, trait_explanation),
);
- // If available, use the scope span to annotate the drop location.
- let mut scope_note = None;
if let Some(scope_span) = scope_span {
let scope_span = source_map.end_point(scope_span);
let msg = format!("{} is later dropped here", snippet);
- if source_map.is_multiline(yield_span.between(scope_span)) {
- span.push_span_label(scope_span, msg);
- } else {
- scope_note = Some((scope_span, msg));
- }
+ span.push_span_label(scope_span, msg);
}
err.span_note(
span,
future_or_generator, trait_explanation, an_await_or_yield
),
);
- if let Some((span, msg)) = scope_note {
- err.span_note(span, &msg);
- }
- }
- };
+ };
match interior_or_upvar_span {
GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
debug!(?next_code);
self.note_obligation_cause_code(
err,
- &obligation.predicate,
+ obligation.predicate,
obligation.param_env,
next_code.unwrap(),
&mut Vec::new(),
fn note_obligation_cause_code<T>(
&self,
err: &mut Diagnostic,
- predicate: &T,
+ predicate: T,
param_env: ty::ParamEnv<'tcx>,
cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
- T: fmt::Display + ToPredicate<'tcx>,
+ T: ToPredicate<'tcx>,
{
let tcx = self.tcx;
+ let predicate = predicate.to_predicate(tcx);
match *cause_code {
ObligationCauseCode::ExprAssignable
| ObligationCauseCode::MatchExpressionArm { .. }
err.note("only the last element of a tuple may have a dynamically sized type");
}
ObligationCauseCode::ProjectionWf(data) => {
- err.note(&format!("required so that the projection `{}` is well-formed", data,));
+ err.note(&format!("required so that the projection `{data}` is well-formed"));
}
ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
err.note(&format!(
- "required so that reference `{}` does not outlive its referent",
- ref_ty,
+ "required so that reference `{ref_ty}` does not outlive its referent"
));
}
ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
ObligationCauseCode::BindingObligation(item_def_id, span)
| ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
let item_name = tcx.def_path_str(item_def_id);
+ let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
let mut multispan = MultiSpan::from(span);
+ let sm = tcx.sess.source_map();
if let Some(ident) = tcx.opt_item_ident(item_def_id) {
- let sm = tcx.sess.source_map();
let same_line =
match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
(Ok(l), Ok(r)) => l.line == r.line,
_ => true,
};
- if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
+ if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
multispan.push_span_label(ident.span, "required by a bound in this");
}
}
- let descr = format!("required by a bound in `{}`", item_name);
- if !span.is_dummy() {
- let msg = format!("required by this bound in `{}`", item_name);
+ let descr = format!("required by a bound in `{item_name}`");
+ if span.is_visible(sm) {
+ let msg = format!("required by this bound in `{short_item_name}`");
multispan.push_span_label(span, msg);
err.span_note(multispan, &descr);
} else {
}
ObligationCauseCode::SizedArgumentType(sp) => {
if let Some(span) = sp {
+ if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
+ && let ty::Clause::Trait(trait_pred) = clause
+ && let ty::Dynamic(..) = trait_pred.self_ty().kind()
+ {
+ let span = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ && snippet.starts_with("dyn ")
+ {
+ let pos = snippet.len() - snippet[3..].trim_start().len();
+ span.with_hi(span.lo() + BytePos(pos as u32))
+ } else {
+ span.shrink_to_lo()
+ };
+ err.span_suggestion_verbose(
+ span,
+ "you can use `impl Trait` as the argument type",
+ "impl ".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
err.span_suggestion_verbose(
span.shrink_to_lo(),
"function arguments must have a statically known size, borrowed types \
Some(ident) => err.span_note(ident.span, &msg),
None => err.note(&msg),
},
- ty::Opaque(def_id, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
// Avoid printing the future from `core::future::identity_future`, it's not helpful
if tcx.parent(*def_id) == identity_future {
break 'print;
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
err,
- &parent_predicate,
+ parent_predicate,
param_env,
&data.parent_code,
obligated_types,
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
err,
- &parent_predicate,
+ parent_predicate,
param_env,
cause_code.peel_derives(),
obligated_types,
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
err,
- &parent_predicate,
+ parent_predicate,
param_env,
&data.parent_code,
obligated_types,
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
err,
- &parent_predicate,
+ parent_predicate,
param_env,
&data.parent_code,
obligated_types,
arg_hir_id,
call_hir_id,
ref parent_code,
+ ..
} => {
- let hir = self.tcx.hir();
- if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
- hir.find(arg_hir_id)
- {
- let parent_id = hir.get_parent_item(arg_hir_id);
- let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
- Some(t) if t.hir_owner == parent_id => t,
- _ => self.tcx.typeck(parent_id.def_id),
- };
- let expr = expr.peel_blocks();
- let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
- let span = expr.span;
- if Some(span) != err.span.primary_span() {
- err.span_label(
- span,
- if ty.references_error() {
- String::new()
- } else {
- format!("this tail expression is of type `{:?}`", ty)
- },
- );
- }
- }
- if let Some(Node::Expr(hir::Expr {
- kind:
- hir::ExprKind::Call(hir::Expr { span, .. }, _)
- | hir::ExprKind::MethodCall(
- hir::PathSegment { ident: Ident { span, .. }, .. },
- ..,
- ),
- ..
- })) = hir.find(call_hir_id)
- {
- if Some(*span) != err.span.primary_span() {
- err.span_label(*span, "required by a bound introduced by this call");
- }
- }
+ self.function_argument_obligation(
+ arg_hir_id,
+ err,
+ parent_code,
+ param_env,
+ predicate,
+ call_hir_id,
+ );
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
err,
ObligationCauseCode::CompareImplItemObligation { trait_item_def_id, kind, .. } => {
let item_name = self.tcx.item_name(trait_item_def_id);
let msg = format!(
- "the requirement `{}` appears on the `impl`'s {kind} `{}` but not on the \
- corresponding trait's {kind}",
- predicate, item_name,
+ "the requirement `{predicate}` appears on the `impl`'s {kind} \
+ `{item_name}` but not on the corresponding trait's {kind}",
);
let sp = self
.tcx
let mut assoc_span: MultiSpan = sp.into();
assoc_span.push_span_label(
sp,
- format!("this trait's {kind} doesn't have the requirement `{}`", predicate),
+ format!("this trait's {kind} doesn't have the requirement `{predicate}`"),
);
if let Some(ident) = self
.tcx
}
ObligationCauseCode::OpaqueReturnType(expr_info) => {
if let Some((expr_ty, expr_span)) = expr_info {
- let expr_ty = self.resolve_vars_if_possible(expr_ty);
+ let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty));
err.span_label(
expr_span,
format!("return type was inferred to be `{expr_ty}` here"),
self.tcx.mk_projection(
item_def_id,
// Future::Output has no substs
- self.tcx.mk_substs_trait(trait_pred.self_ty(), []),
+ [trait_pred.self_ty()],
)
});
let InferOk { value: projection_ty, .. } =
);
}
}
+ fn function_argument_obligation(
+ &self,
+ arg_hir_id: HirId,
+ err: &mut Diagnostic,
+ parent_code: &ObligationCauseCode<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ predicate: ty::Predicate<'tcx>,
+ call_hir_id: HirId,
+ ) {
+ let tcx = self.tcx;
+ let hir = tcx.hir();
+ if let Some(Node::Expr(expr)) = hir.find(arg_hir_id) {
+ let parent_id = hir.get_parent_item(arg_hir_id);
+ let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
+ Some(t) if t.hir_owner == parent_id => t,
+ _ => self.tcx.typeck(parent_id.def_id),
+ };
+ if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
+ let expr = expr.peel_blocks();
+ let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+ let span = expr.span;
+ if Some(span) != err.span.primary_span() {
+ err.span_label(
+ span,
+ if ty.references_error() {
+ String::new()
+ } else {
+ let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+ format!("this tail expression is of type `{ty}`")
+ },
+ );
+ }
+ }
+
+ // FIXME: visit the ty to see if there's any closure involved, and if there is,
+ // check whether its evaluated return type is the same as the one corresponding
+ // to an associated type (as seen from `trait_pred`) in the predicate. Like in
+ // trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
+ let mut type_diffs = vec![];
+
+ if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
+ && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+ && let Some(pred) = predicates.predicates.get(*idx)
+ {
+ if let Ok(trait_pred) = pred.kind().try_map_bound(|pred| match pred {
+ ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+ _ => Err(()),
+ })
+ && let Ok(trait_predicate) = predicate.kind().try_map_bound(|pred| match pred {
+ ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => Ok(trait_pred),
+ _ => Err(()),
+ })
+ {
+ let mut c = CollectAllMismatches {
+ infcx: self.infcx,
+ param_env,
+ errors: vec![],
+ };
+ if let Ok(_) = c.relate(trait_pred, trait_predicate) {
+ type_diffs = c.errors;
+ }
+ } else if let ty::PredicateKind::Clause(
+ ty::Clause::Projection(proj)
+ ) = pred.kind().skip_binder()
+ && let ty::PredicateKind::Clause(
+ ty::Clause::Projection(projection)
+ ) = predicate.kind().skip_binder()
+ {
+ type_diffs = vec![
+ Sorts(ty::error::ExpectedFound {
+ expected: self.tcx.mk_ty(ty::Alias(ty::Projection, proj.projection_ty)),
+ found: projection.term.ty().unwrap(),
+ }),
+ ];
+ }
+ }
+ if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+ && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+ && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+ && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+ && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id)
+ && let Some(binding_expr) = local.init
+ {
+ // If the expression we're calling on is a binding, we want to point at the
+ // `let` when talking about the type. Otherwise we'll point at every part
+ // of the method chain with the type.
+ self.point_at_chain(binding_expr, typeck_results, type_diffs, param_env, err);
+ } else {
+ self.point_at_chain(expr, typeck_results, type_diffs, param_env, err);
+ }
+ }
+ let call_node = hir.find(call_hir_id);
+ if let Some(Node::Expr(hir::Expr {
+ kind: hir::ExprKind::MethodCall(path, rcvr, ..), ..
+ })) = call_node
+ {
+ if Some(rcvr.span) == err.span.primary_span() {
+ err.replace_span_with(path.ident.span);
+ }
+ }
+ if let Some(Node::Expr(hir::Expr {
+ kind:
+ hir::ExprKind::Call(hir::Expr { span, .. }, _)
+ | hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
+ ..
+ })) = hir.find(call_hir_id)
+ {
+ if Some(*span) != err.span.primary_span() {
+ err.span_label(*span, "required by a bound introduced by this call");
+ }
+ }
+ }
+
+ fn point_at_chain(
+ &self,
+ expr: &hir::Expr<'_>,
+ typeck_results: &TypeckResults<'tcx>,
+ type_diffs: Vec<TypeError<'tcx>>,
+ param_env: ty::ParamEnv<'tcx>,
+ err: &mut Diagnostic,
+ ) {
+ let mut primary_spans = vec![];
+ let mut span_labels = vec![];
+
+ let tcx = self.tcx;
+
+ let mut print_root_expr = true;
+ let mut assocs = vec![];
+ let mut expr = expr;
+ let mut prev_ty = self.resolve_vars_if_possible(
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ );
+ while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
+ // Point at every method call in the chain with the resulting type.
+ // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+ // ^^^^^^ ^^^^^^^^^^^
+ expr = rcvr_expr;
+ let assocs_in_this_method =
+ self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
+ assocs.push(assocs_in_this_method);
+ prev_ty = self.resolve_vars_if_possible(
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ );
+
+ if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
+ && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path
+ && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id)
+ && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id)
+ && let Some(parent) = self.tcx.hir().find(parent_hir_id)
+ {
+ // We've reached the root of the method call chain...
+ if let hir::Node::Local(local) = parent
+ && let Some(binding_expr) = local.init
+ {
+ // ...and it is a binding. Get the binding creation and continue the chain.
+ expr = binding_expr;
+ }
+ if let hir::Node::Param(param) = parent {
+ // ...and it is a an fn argument.
+ let prev_ty = self.resolve_vars_if_possible(
+ typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+ );
+ let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
+ if assocs_in_this_method.iter().any(|a| a.is_some()) {
+ assocs.push(assocs_in_this_method);
+ print_root_expr = false;
+ }
+ break;
+ }
+ }
+ }
+ // We want the type before deref coercions, otherwise we talk about `&[_]`
+ // instead of `Vec<_>`.
+ if let Some(ty) = typeck_results.expr_ty_opt(expr) && print_root_expr {
+ let ty = with_forced_trimmed_paths!(self.ty_to_string(ty));
+ // Point at the root expression
+ // vec![1, 2, 3].iter().map(mapper).sum<i32>()
+ // ^^^^^^^^^^^^^
+ span_labels.push((expr.span, format!("this expression has type `{ty}`")));
+ };
+ // Only show this if it is not a "trivial" expression (not a method
+ // chain) and there are associated types to talk about.
+ let mut assocs = assocs.into_iter().peekable();
+ while let Some(assocs_in_method) = assocs.next() {
+ let Some(prev_assoc_in_method) = assocs.peek() else {
+ for entry in assocs_in_method {
+ let Some((span, (assoc, ty))) = entry else { continue; };
+ if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
+ let Sorts(expected_found) = diff else { return false; };
+ self.can_eq(param_env, expected_found.found, ty).is_ok()
+ }) {
+ // FIXME: this doesn't quite work for `Iterator::collect`
+ // because we have `Vec<i32>` and `()`, but we'd want `i32`
+ // to point at the `.into_iter()` call, but as long as we
+ // still point at the other method calls that might have
+ // introduced the issue, this is fine for now.
+ primary_spans.push(span);
+ }
+ span_labels.push((
+ span,
+ with_forced_trimmed_paths!(format!(
+ "`{}` is `{ty}` here",
+ self.tcx.def_path_str(assoc),
+ )),
+ ));
+ }
+ break;
+ };
+ for (entry, prev_entry) in
+ assocs_in_method.into_iter().zip(prev_assoc_in_method.into_iter())
+ {
+ match (entry, prev_entry) {
+ (Some((span, (assoc, ty))), Some((_, (_, prev_ty)))) => {
+ let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
+
+ let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
+ if self.can_eq(param_env, ty, *prev_ty).is_err() {
+ if type_diffs.iter().any(|diff| {
+ let Sorts(expected_found) = diff else { return false; };
+ self.can_eq(param_env, expected_found.found, ty).is_ok()
+ }) {
+ primary_spans.push(span);
+ }
+ span_labels
+ .push((span, format!("`{assoc}` changed to `{ty_str}` here")));
+ } else {
+ span_labels.push((span, format!("`{assoc}` remains `{ty_str}` here")));
+ }
+ }
+ (Some((span, (assoc, ty))), None) => {
+ span_labels.push((
+ span,
+ with_forced_trimmed_paths!(format!(
+ "`{}` is `{}` here",
+ self.tcx.def_path_str(assoc),
+ self.ty_to_string(ty),
+ )),
+ ));
+ }
+ (None, Some(_)) | (None, None) => {}
+ }
+ }
+ }
+ if !primary_spans.is_empty() {
+ let mut multi_span: MultiSpan = primary_spans.into();
+ for (span, label) in span_labels {
+ multi_span.push_span_label(span, label);
+ }
+ err.span_note(
+ multi_span,
+ format!("the method call chain might not have had the expected associated types"),
+ );
+ }
+ }
+
+ fn probe_assoc_types_at_expr(
+ &self,
+ type_diffs: &[TypeError<'tcx>],
+ span: Span,
+ prev_ty: Ty<'tcx>,
+ body_id: hir::HirId,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>> {
+ let ocx = ObligationCtxt::new_in_snapshot(self.infcx);
+ let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
+ for diff in type_diffs {
+ let Sorts(expected_found) = diff else { continue; };
+ let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+
+ let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
+ let trait_def_id = proj.trait_def_id(self.tcx);
+ // Make `Self` be equivalent to the type of the call chain
+ // expression we're looking at now, so that we can tell what
+ // for example `Iterator::Item` is at this point in the chain.
+ let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+ match param.kind {
+ ty::GenericParamDefKind::Type { .. } => {
+ if param.index == 0 {
+ return prev_ty.into();
+ }
+ }
+ ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Const { .. } => {}
+ }
+ self.var_for_def(span, param)
+ });
+ // This will hold the resolved type of the associated type, if the
+ // current expression implements the trait that associated type is
+ // in. For example, this would be what `Iterator::Item` is here.
+ let ty_var = self.infcx.next_ty_var(origin);
+ // This corresponds to `<ExprTy as Iterator>::Item = _`.
+ let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
+ ty::ProjectionPredicate {
+ projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+ term: ty_var.into(),
+ },
+ )));
+ // Add `<ExprTy as Iterator>::Item = _` obligation.
+ ocx.register_obligation(Obligation::misc(
+ self.tcx, span, body_id, param_env, projection,
+ ));
+ if ocx.select_where_possible().is_empty() {
+ // `ty_var` now holds the type that `Item` is for `ExprTy`.
+ let ty_var = self.resolve_vars_if_possible(ty_var);
+ assocs_in_this_method.push(Some((span, (proj.def_id, ty_var))));
+ } else {
+ // `<ExprTy as Iterator>` didn't select, so likely we've
+ // reached the end of the iterator chain, like the originating
+ // `Vec<_>`.
+ // Keep the space consistent for later zipping.
+ assocs_in_this_method.push(None);
+ }
+ }
+ assocs_in_this_method
+ }
+}
+
+/// Add a hint to add a missing borrow or remove an unnecessary one.
+fn hint_missing_borrow<'tcx>(
+ span: Span,
+ found_span: Span,
+ found: Ty<'tcx>,
+ expected: Ty<'tcx>,
+ found_node: Node<'_>,
+ err: &mut Diagnostic,
+) {
+ let found_args = match found.kind() {
+ ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ kind => {
+ span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
+ }
+ };
+ let expected_args = match expected.kind() {
+ ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ kind => {
+ span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
+ }
+ };
+
+ let fn_decl = found_node
+ .fn_decl()
+ .unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
+
+ let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
+
+ fn get_deref_type_and_refs<'tcx>(mut ty: Ty<'tcx>) -> (Ty<'tcx>, usize) {
+ let mut refs = 0;
+
+ while let ty::Ref(_, new_ty, _) = ty.kind() {
+ ty = *new_ty;
+ refs += 1;
+ }
+
+ (ty, refs)
+ }
+
+ let mut to_borrow = Vec::new();
+ let mut remove_borrow = Vec::new();
+
+ for ((found_arg, expected_arg), arg_span) in found_args.zip(expected_args).zip(arg_spans) {
+ let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
+ let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
+
+ if found_ty == expected_ty {
+ if found_refs < expected_refs {
+ to_borrow.push((arg_span, expected_arg.to_string()));
+ } else if found_refs > expected_refs {
+ remove_borrow.push((arg_span, expected_arg.to_string()));
+ }
+ }
+ }
+
+ if !to_borrow.is_empty() {
+ err.multipart_suggestion(
+ "consider borrowing the argument",
+ to_borrow,
+ Applicability::MaybeIncorrect,
+ );
+ }
+
+ if !remove_borrow.is_empty() {
+ err.multipart_suggestion(
+ "do not borrow the argument",
+ remove_borrow,
+ Applicability::MaybeIncorrect,
+ );
+ }
}
/// Collect all the returned expressions within the input expression.
trait_obj: &str,
is_object_safe: bool,
) {
- err.span_suggestion(
- ret_ty,
- "use some type `T` that is `T: Sized` as the return type if all return paths have the \
- same type",
- "T",
- Applicability::MaybeIncorrect,
- );
err.span_suggestion(
ret_ty,
&format!(
pub mod auto_trait;
mod chalk_fulfill;
-pub mod codegen;
mod coherence;
pub mod const_evaluatable;
mod engine;
mod specialize;
mod structural_match;
mod util;
+mod vtable;
pub mod wf;
-use crate::errors::DumpVTableEntries;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
- self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, VtblEntry,
-};
+use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
-use rustc_span::{sym, Span};
-use smallvec::SmallVec;
+use rustc_span::Span;
use std::fmt::Debug;
use std::ops::ControlFlow;
bound: DefId,
) -> Vec<FulfillmentError<'tcx>> {
let tcx = infcx.tcx;
- let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) };
- let obligation = Obligation {
- cause,
- recursion_depth: 0,
- param_env,
- predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
- };
+ let trait_ref = tcx.mk_trait_ref(bound, [ty]);
+ let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref));
fully_solve_obligation(infcx, obligation)
}
false
}
-#[derive(Clone, Debug)]
-enum VtblSegment<'tcx> {
- MetadataDSA,
- TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
-}
-
-/// Prepare the segments for a vtable
-fn prepare_vtable_segments<'tcx, T>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
- mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
-) -> Option<T> {
- // The following constraints holds for the final arrangement.
- // 1. The whole virtual table of the first direct super trait is included as the
- // the prefix. If this trait doesn't have any super traits, then this step
- // consists of the dsa metadata.
- // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
- // other super traits except those already included as part of the first
- // direct super trait virtual table.
- // 3. finally, the own methods of this trait.
-
- // This has the advantage that trait upcasting to the first direct super trait on each level
- // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
- // while not using too much extra memory.
-
- // For a single inheritance relationship like this,
- // D --> C --> B --> A
- // The resulting vtable will consists of these segments:
- // DSA, A, B, C, D
-
- // For a multiple inheritance relationship like this,
- // D --> C --> A
- // \-> B
- // The resulting vtable will consists of these segments:
- // DSA, A, B, B-vptr, C, D
-
- // For a diamond inheritance relationship like this,
- // D --> B --> A
- // \-> C -/
- // The resulting vtable will consists of these segments:
- // DSA, A, B, C, C-vptr, D
-
- // For a more complex inheritance relationship like this:
- // O --> G --> C --> A
- // \ \ \-> B
- // | |-> F --> D
- // | \-> E
- // |-> N --> J --> H
- // \ \-> I
- // |-> M --> K
- // \-> L
- // The resulting vtable will consists of these segments:
- // DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
- // H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
- // N, N-vptr, O
-
- // emit dsa segment first.
- if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
- return Some(v);
- }
-
- let mut emit_vptr_on_new_entry = false;
- let mut visited = util::PredicateSet::new(tcx);
- let predicate = trait_ref.without_const().to_predicate(tcx);
- let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
- smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
- visited.insert(predicate);
-
- // the main traversal loop:
- // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
- // that each node is emitted after all its descendents have been emitted.
- // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
- // this is done on the fly.
- // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
- // stops after it finds a node that has a next-sibling node.
- // This next-sibling node will used as the starting point of next slice.
-
- // Example:
- // For a diamond inheritance relationship like this,
- // D#1 --> B#0 --> A#0
- // \-> C#1 -/
-
- // Starting point 0 stack [D]
- // Loop run #0: Stack after diving in is [D B A], A is "childless"
- // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
- // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
- // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
- // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
- // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
- // Loop run #1: Stack after exiting out is []. Now the function exits.
-
- loop {
- // dive deeper into the stack, recording the path
- 'diving_in: loop {
- if let Some((inner_most_trait_ref, _, _)) = stack.last() {
- let inner_most_trait_ref = *inner_most_trait_ref;
- let mut direct_super_traits_iter = tcx
- .super_predicates_of(inner_most_trait_ref.def_id())
- .predicates
- .into_iter()
- .filter_map(move |(pred, _)| {
- pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
- });
-
- 'diving_in_skip_visited_traits: loop {
- if let Some(next_super_trait) = direct_super_traits_iter.next() {
- if visited.insert(next_super_trait.to_predicate(tcx)) {
- // We're throwing away potential constness of super traits here.
- // FIXME: handle ~const super traits
- let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
- stack.push((
- next_super_trait,
- emit_vptr_on_new_entry,
- Some(direct_super_traits_iter),
- ));
- break 'diving_in_skip_visited_traits;
- } else {
- continue 'diving_in_skip_visited_traits;
- }
- } else {
- break 'diving_in;
- }
- }
- }
- }
-
- // Other than the left-most path, vptr should be emitted for each trait.
- emit_vptr_on_new_entry = true;
-
- // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
- 'exiting_out: loop {
- if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
- if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
- trait_ref: *inner_most_trait_ref,
- emit_vptr: *emit_vptr,
- }) {
- return Some(v);
- }
-
- 'exiting_out_skip_visited_traits: loop {
- if let Some(siblings) = siblings_opt {
- if let Some(next_inner_most_trait_ref) = siblings.next() {
- if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
- // We're throwing away potential constness of super traits here.
- // FIXME: handle ~const super traits
- let next_inner_most_trait_ref =
- next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
- *inner_most_trait_ref = next_inner_most_trait_ref;
- *emit_vptr = emit_vptr_on_new_entry;
- break 'exiting_out;
- } else {
- continue 'exiting_out_skip_visited_traits;
- }
- }
- }
- stack.pop();
- continue 'exiting_out;
- }
- }
- // all done
- return None;
- }
- }
-}
-
-fn dump_vtable_entries<'tcx>(
- tcx: TyCtxt<'tcx>,
- sp: Span,
- trait_ref: ty::PolyTraitRef<'tcx>,
- entries: &[VtblEntry<'tcx>],
-) {
- tcx.sess.emit_err(DumpVTableEntries {
- span: sp,
- trait_ref,
- entries: format!("{:#?}", entries),
- });
-}
-
-fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
- let trait_methods = tcx
- .associated_items(trait_def_id)
- .in_definition_order()
- .filter(|item| item.kind == ty::AssocKind::Fn);
- // Now list each method's DefId (for within its trait).
- let own_entries = trait_methods.filter_map(move |trait_method| {
- debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
- let def_id = trait_method.def_id;
-
- // Some methods cannot be called on an object; skip those.
- if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
- debug!("own_existential_vtable_entry: not vtable safe");
- return None;
- }
-
- Some(def_id)
- });
-
- tcx.arena.alloc_from_iter(own_entries.into_iter())
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-fn vtable_entries<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [VtblEntry<'tcx>] {
- debug!("vtable_entries({:?})", trait_ref);
-
- let mut entries = vec![];
-
- let vtable_segment_callback = |segment| -> ControlFlow<()> {
- match segment {
- VtblSegment::MetadataDSA => {
- entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
- }
- VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- let existential_trait_ref = trait_ref
- .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
-
- // Lookup the shape of vtable for the trait.
- let own_existential_entries =
- tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
-
- let own_entries = own_existential_entries.iter().copied().map(|def_id| {
- debug!("vtable_entries: trait_method={:?}", def_id);
-
- // The method may have some early-bound lifetimes; add regions for those.
- let substs = trait_ref.map_bound(|trait_ref| {
- InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
- GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
- GenericParamDefKind::Type { .. }
- | GenericParamDefKind::Const { .. } => {
- trait_ref.substs[param.index as usize]
- }
- })
- });
-
- // The trait type may have higher-ranked lifetimes in it;
- // erase them if they appear, so that we get the type
- // at some particular call site.
- let substs = tcx
- .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
-
- // It's possible that the method relies on where-clauses that
- // do not hold for this particular set of type parameters.
- // Note that this method could then never be called, so we
- // do not want to try and codegen it, in that case (see #23435).
- let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
- if impossible_predicates(tcx, predicates.predicates) {
- debug!("vtable_entries: predicates do not hold");
- return VtblEntry::Vacant;
- }
-
- let instance = ty::Instance::resolve_for_vtable(
- tcx,
- ty::ParamEnv::reveal_all(),
- def_id,
- substs,
- )
- .expect("resolution failed during building vtable representation");
- VtblEntry::Method(instance)
- });
-
- entries.extend(own_entries);
-
- if emit_vptr {
- entries.push(VtblEntry::TraitVPtr(trait_ref));
- }
- }
- }
-
- ControlFlow::Continue(())
- };
-
- let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
-
- if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
- let sp = tcx.def_span(trait_ref.def_id());
- dump_vtable_entries(tcx, sp, trait_ref, &entries);
- }
-
- tcx.arena.alloc_from_iter(entries.into_iter())
-}
-
-/// Find slot base for trait methods within vtable entries of another trait
-fn vtable_trait_first_method_offset<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: (
- ty::PolyTraitRef<'tcx>, // trait_to_be_found
- ty::PolyTraitRef<'tcx>, // trait_owning_vtable
- ),
-) -> usize {
- let (trait_to_be_found, trait_owning_vtable) = key;
-
- // #90177
- let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
-
- let vtable_segment_callback = {
- let mut vtable_base = 0;
-
- move |segment| {
- match segment {
- VtblSegment::MetadataDSA => {
- vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
- }
- VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
- return ControlFlow::Break(vtable_base);
- }
- vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
- if emit_vptr {
- vtable_base += 1;
- }
- }
- }
- ControlFlow::Continue(())
- }
- };
-
- if let Some(vtable_base) =
- prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
- {
- vtable_base
- } else {
- bug!("Failed to find info for expected trait in vtable");
- }
-}
-
-/// Find slot offset for trait vptr within vtable entries of another trait
-pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: (
- Ty<'tcx>, // trait object type whose trait owning vtable
- Ty<'tcx>, // trait object for supertrait
- ),
-) -> Option<usize> {
- let (source, target) = key;
- assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
- assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
-
- // this has been typecked-before, so diagnostics is not really needed.
- let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
-
- let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
-
- match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
- Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
- implsrc_traitcasting.vtable_vptr_slot
- }
- otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
- }
-}
-
pub fn provide(providers: &mut ty::query::Providers) {
object_safety::provide(providers);
- structural_match::provide(providers);
+ vtable::provide(providers);
*providers = ty::query::Providers {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
- codegen_select_candidate: codegen::codegen_select_candidate,
- own_existential_vtable_entries,
- vtable_entries,
- vtable_trait_upcasting_coercion_new_vptr_slot,
subst_and_check_impossible_predicates,
is_impossible_method,
..*providers
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
Some(pred.map_bound(|p| {
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
- item_def_id: p.projection_ty.item_def_id,
+ def_id: p.projection_ty.def_id,
substs: p.projection_ty.substs,
term: p.term,
})
// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
- let substs =
- InternalSubsts::for_item(tcx, method.trait_container(tcx).unwrap(), |param, _| {
- if param.index == 0 {
- unsized_self_ty.into()
- } else {
- tcx.mk_param_from_def(param)
- }
- });
+ let trait_def_id = method.trait_container(tcx).unwrap();
+ let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+ if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
+ });
- ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
- .without_const()
- .to_predicate(tcx)
+ ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
};
let caller_bounds: Vec<Predicate<'tcx>> =
ControlFlow::CONTINUE
}
}
- ty::Projection(ref data)
- if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ ty::Alias(ty::Projection, ref data)
+ if self.tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder =>
{
// We'll deny these later in their own pass
ControlFlow::CONTINUE
}
- ty::Projection(ref data) => {
+ ty::Alias(ty::Projection, ref data) => {
// This is a projected type `<Foo as SomeTrait>::X`.
// Compute supertraits of current trait lazily.
// FIXME(RPITIT): Perhaps we should use a visitor here?
ty.skip_binder().walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Projection(proj) = ty.kind()
- && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+ && let ty::Alias(ty::Projection, proj) = ty.kind()
+ && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
{
- Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id)))
+ Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.def_id)))
} else {
None
}
pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
pub(super) struct InProgress;
// This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark.
- ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+ if !substs.has_escaping_bound_vars() =>
+ {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.super_fold_with(self),
}
}
- ty::Projection(data) if !data.has_escaping_bound_vars() => {
+ ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
// This branch is *mostly* just an optimization: when we don't
// have escaping bound vars, we don't need to replace them with
// placeholders (see branch below). *Also*, we know that we can
normalized_ty.ty().unwrap()
}
- ty::Projection(data) => {
+ ty::Alias(ty::Projection, data) => {
// If there are escaping bound vars, we temporarily replace the
// bound vars with placeholders. Note though, that in the case
// that we still can't project for whatever reason (e.g. self
pub fn normalize_projection_type<'a, 'b, 'tcx>(
selcx: &'a mut SelectionContext<'b, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
fn opt_normalize_projection_type<'a, 'b, 'tcx>(
selcx: &'a mut SelectionContext<'b, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
fn normalize_to_error<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
- projection_ty: ty::ProjectionTy<'tcx>,
+ projection_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
) -> NormalizedTy<'tcx> {
predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
};
let tcx = selcx.infcx.tcx;
- let def_id = projection_ty.item_def_id;
let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType,
- span: tcx.def_span(def_id),
+ span: tcx.def_span(projection_ty.def_id),
});
Normalized { value: new_value, obligations: vec![trait_obligation] }
}
// need to investigate whether or not this is fine.
selcx
.tcx()
- .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs)
+ .mk_projection(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
)),
// Error occurred while trying to processing impls.
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
let tcx = selcx.tcx();
- if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+ if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
+ let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
// If we are trying to project an RPITIT with trait's default `Self` parameter,
// then we must be within a default trait body.
if obligation.predicate.self_ty()
- == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
- .type_at(0)
+ == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
&& tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
{
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
let trait_substs =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
// FIXME(named-returns): Binders
- let trait_predicate =
- ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs });
+ let trait_predicate = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, trait_substs));
let _ = selcx.infcx.commit_if_ok(|_| {
match selcx.select(&obligation.with(tcx, trait_predicate)) {
// Check whether the self-type is itself a projection.
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match *obligation.predicate.self_ty().kind() {
- ty::Projection(ref data) => tcx.bound_item_bounds(data.item_def_id).subst(tcx, data.substs),
- ty::Opaque(def_id, substs) => tcx.bound_item_bounds(def_id).subst(tcx, substs),
+ ty::Alias(_, ref data) => tcx.bound_item_bounds(data.def_id).subst(tcx, data.substs),
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
};
let env_predicates = data
.projection_bounds()
- .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
+ .filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
.map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
assemble_candidates_from_predicates(
predicate.kind().skip_binder()
{
let data = bound_predicate.rebind(data);
- if data.projection_def_id() != obligation.predicate.item_def_id {
+ if data.projection_def_id() != obligation.predicate.def_id {
continue;
}
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
// Can't assemble candidate from impl for RPITIT
- if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+ if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
return;
}
// NOTE: This should be kept in sync with the similar code in
// `rustc_ty_utils::instance::resolve_associated_item()`.
let node_item =
- assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
+ assoc_def(selcx, impl_data.impl_def_id, obligation.predicate.def_id)
.map_err(|ErrorGuaranteed { .. }| ())?;
if node_item.is_final() {
// type parameters, opaques, and unnormalized projections have pointer
// metadata if they're known (e.g. by the param_env) to be sized
ty::Param(_)
- | ty::Projection(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..)
// type parameters, opaques, and unnormalized projections have pointer
// metadata if they're known (e.g. by the param_env) to be sized
- ty::Param(_) | ty::Projection(..) | ty::Opaque(..)
+ ty::Param(_) | ty::Alias(..)
if selcx.infcx.predicate_must_hold_modulo_regions(
&obligation.with(
selcx.tcx(),
// FIXME(compiler-errors): are Bound and Placeholder types ever known sized?
ty::Param(_)
- | ty::Projection(..)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(..)
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
term: selcx
.tcx()
- .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+ .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
.into(),
obligations: vec![],
},
gen_sig,
)
.map_bound(|(trait_ref, yield_ty, return_ty)| {
- let name = tcx.associated_item(obligation.predicate.item_def_id).name;
+ let name = tcx.associated_item(obligation.predicate.def_id).name;
let ty = if name == sym::Return {
return_ty
} else if name == sym::Yield {
};
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: obligation.predicate.item_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
term: ty.into(),
}
});
gen_sig,
)
.map_bound(|(trait_ref, return_ty)| {
- debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+ debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: obligation.predicate.item_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
term: return_ty.into(),
}
});
let self_ty = obligation.predicate.self_ty();
let substs = tcx.mk_substs([self_ty.into()].iter());
let lang_items = tcx.lang_items();
- let item_def_id = obligation.predicate.item_def_id;
+ let item_def_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
let (term, obligations) = if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
};
let predicate =
- ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id }, term };
+ ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
.with_addl_obligations(obligations)
flag,
)
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- substs: trait_ref.substs,
- item_def_id: fn_once_output_def_id,
- },
+ projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
term: ret_type.into(),
});
let tcx = selcx.tcx();
let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
- let assoc_item_id = obligation.predicate.item_def_id;
+ let assoc_item_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let param_env = obligation.param_env;
let tcx = selcx.tcx();
let mut obligations = data.nested;
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
+ let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
return Progress { term: tcx.ty_error().into(), obligations };
};
// Use the default `impl Trait` for the trait, e.g., for a default trait body
if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
return Progress {
- term: tcx
- .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
- .into(),
+ term: tcx.mk_opaque(obligation.predicate.def_id, obligation.predicate.substs).into(),
obligations,
};
}
obligation.recursion_depth + 1,
tcx.bound_trait_impl_trait_tys(impl_fn_def_id)
.map_bound(|tys| {
- tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.item_def_id])
+ tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
})
.subst(tcx, impl_fn_substs),
&mut obligations,
) {
let tcx = selcx.tcx();
let own = tcx
- .predicates_of(obligation.predicate.item_def_id)
+ .predicates_of(obligation.predicate.def_id)
.instantiate_own(tcx, obligation.predicate.substs);
for (predicate, span) in std::iter::zip(own.predicates, own.spans) {
let normalized = normalize_with_depth_to(
ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- super::ItemObligation(obligation.predicate.item_def_id),
+ super::ItemObligation(obligation.predicate.def_id),
)
} else {
ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
- super::BindingObligation(obligation.predicate.item_def_id, span),
+ super::BindingObligation(obligation.predicate.def_id, span),
)
};
nested.push(Obligation::with_depth(
// The following *might* require a destructor: needs deeper inspection.
ty::Dynamic(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Param(_)
- | ty::Opaque(..)
| ty::Placeholder(..)
| ty::Infer(_)
| ty::Bound(..)
// This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark.
- ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
+ if !substs.has_escaping_bound_vars() =>
+ {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.try_super_fold_with(self),
}
}
- ty::Projection(data) if !data.has_escaping_bound_vars() => {
+ ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
// This branch is just an optimization: when we don't have escaping bound vars,
// we don't need to replace them with placeholders (see branch below).
}
}
- ty::Projection(data) => {
+ ty::Alias(ty::Projection, data) => {
// See note in `rustc_trait_selection::traits::project`
let tcx = self.infcx.tcx;
.kind()
.rebind(
// (*) binder moved here
- ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_type(infcx.tcx, new_self_ty)))
+ ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
),
);
// Don't report overflow errors. Otherwise equivalent to may_hold.
// Before we go into the whole placeholder thing, just
// quickly check if the self-type is a projection at all.
match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
- ty::Projection(_) | ty::Opaque(..) => {}
+ ty::Alias(..) => {}
ty::Infer(ty::TyVar(_)) => {
span_bug!(
obligation.cause.span,
// still be provided by a manual implementation for
// this trait and type.
}
- ty::Param(..) | ty::Projection(..) => {
+ ty::Param(..) | ty::Alias(ty::Projection, ..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
let ty = traits::normalize_projection_type(
self,
param_env,
- ty::ProjectionTy {
- item_def_id: tcx.lang_items().deref_target()?,
- substs: trait_ref.substs,
- },
+ tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
cause.clone(),
0,
// We're *intentionally* throwing these away,
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
match self_ty.skip_binder().kind() {
- ty::Opaque(..)
+ ty::Alias(..)
| ty::Dynamic(..)
| ty::Error(_)
| ty::Bound(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => {
+ | ty::Placeholder(_) => {
// We don't know if these are `~const Destruct`, at least
// not structurally... so don't push a candidate.
}
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
| ty::Never
- | ty::Projection(_)
- | ty::Opaque(_, _)
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(_, _)
| ty::Error(_)
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
+use crate::traits::vtable::{
+ count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
+ VtblSegment,
+};
use crate::traits::{
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
- SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+ SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
};
use super::BuiltinImplConditions;
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() {
- ty::Projection(proj) => (proj.item_def_id, proj.substs),
- ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
};
.map_err(|_| Unimplemented)
})?);
- if let ty::Projection(..) = placeholder_self_ty.kind() {
+ if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
debug!(?predicates, "projection predicates");
for predicate in predicates {
debug!(?nested, "object nested obligations");
- let vtable_base = super::super::vtable_trait_first_method_offset(
+ let vtable_base = vtable_trait_first_method_offset(
tcx,
(unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
);
vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
}
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- vptr_offset += util::count_own_vtable_entries(tcx, trait_ref);
+ vptr_offset += count_own_vtable_entries(tcx, trait_ref);
if trait_ref == upcast_trait_ref {
if emit_vptr {
return ControlFlow::Break(Some(vptr_offset));
};
let vtable_vptr_slot =
- super::super::prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback)
- .unwrap();
+ prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
}
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
- ty::Projection(..) => {
+ ty::Alias(ty::Projection, ..) => {
let predicate = normalize_with_depth_to(
self,
obligation.param_env,
let tcx = self.infcx.tcx;
let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
- ty::Projection(ref data) => (data.item_def_id, data.substs),
- ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
_ => {
span_bug!(
obligation.cause.span,
});
if is_match {
- let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
+ let generics = self.tcx().generics_of(obligation.predicate.def_id);
// FIXME(generic-associated-types): Addresses aggressive inference in #92917.
// If this type is a GAT, and of the GAT substs resolve to something new,
// that means that we must have newly inferred something about the GAT.
}))
}
- ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+ ty::Alias(..) | ty::Param(_) => None,
ty::Infer(ty::TyVar(_)) => Ambiguous,
ty::Placeholder(..)
}
}
- ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+ ty::Adt(..) | ty::Alias(..) | ty::Param(..) => {
// Fallback to whatever user-defined impls exist in this case.
None
}
| ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
- | ty::Projection(..)
+ | ty::Alias(ty::Projection, ..)
| ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("asked to assemble constituent types of unexpected type: {:?}", t);
t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::{ObligationCause, ObligationCtxt};
-
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
-use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
.break_value()
}
-/// This method returns true if and only if `adt_ty` itself has been marked as
-/// eligible for structural-match: namely, if it implements both
-/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
-/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
-///
-/// Note that this does *not* recursively check if the substructure of `adt_ty`
-/// implements the traits.
-fn type_marked_structural<'tcx>(
- infcx: &InferCtxt<'tcx>,
- adt_ty: Ty<'tcx>,
- cause: ObligationCause<'tcx>,
-) -> bool {
- let ocx = ObligationCtxt::new(infcx);
- // require `#[derive(PartialEq)]`
- let structural_peq_def_id =
- infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
- ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
- // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
- // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
- let structural_teq_def_id =
- infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
- ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
-
- // We deliberately skip *reporting* fulfillment errors (via
- // `report_fulfillment_errors`), for two reasons:
- //
- // 1. The error messages would mention `std::marker::StructuralPartialEq`
- // (a trait which is solely meant as an implementation detail
- // for now), and
- //
- // 2. We are sometimes doing future-incompatibility lints for
- // now, so we do not want unconditional errors here.
- ocx.select_all_or_error().is_empty()
-}
-
/// This implements the traversal over the structure of a given type to try to
/// find instances of ADTs (specifically structs or enums) that do not implement
/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
ty::Foreign(_) => {
return ControlFlow::Break(ty);
}
- ty::Opaque(..) => {
- return ControlFlow::Break(ty);
- }
- ty::Projection(..) => {
+ ty::Alias(..) => {
return ControlFlow::Break(ty);
}
ty::Closure(..) => {
})
}
}
-
-pub fn provide(providers: &mut Providers) {
- providers.has_structural_eq_impls = |tcx, ty| {
- let infcx = tcx.infer_ctxt().build();
- let cause = ObligationCause::dummy();
- type_marked_structural(&infcx, ty, cause)
- };
-}
supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
}
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
-) -> usize {
- tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
-}
-
/// Given an upcast trait object described by `object`, returns the
/// index of the method `method_def_id` (which should be part of
/// `object.upcast_trait_ref`) within the vtable for `object`.
--- /dev/null
+use crate::errors::DumpVTableEntries;
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
+use rustc_hir::def_id::DefId;
+use rustc_hir::lang_items::LangItem;
+use rustc_infer::traits::util::PredicateSet;
+use rustc_infer::traits::ImplSource;
+use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
+use rustc_span::{sym, Span};
+use smallvec::SmallVec;
+
+use std::fmt::Debug;
+use std::ops::ControlFlow;
+
+#[derive(Clone, Debug)]
+pub(super) enum VtblSegment<'tcx> {
+ MetadataDSA,
+ TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
+}
+
+/// Prepare the segments for a vtable
+pub(super) fn prepare_vtable_segments<'tcx, T>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+ mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+) -> Option<T> {
+ // The following constraints holds for the final arrangement.
+ // 1. The whole virtual table of the first direct super trait is included as the
+ // the prefix. If this trait doesn't have any super traits, then this step
+ // consists of the dsa metadata.
+ // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
+ // other super traits except those already included as part of the first
+ // direct super trait virtual table.
+ // 3. finally, the own methods of this trait.
+
+ // This has the advantage that trait upcasting to the first direct super trait on each level
+ // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
+ // while not using too much extra memory.
+
+ // For a single inheritance relationship like this,
+ // D --> C --> B --> A
+ // The resulting vtable will consists of these segments:
+ // DSA, A, B, C, D
+
+ // For a multiple inheritance relationship like this,
+ // D --> C --> A
+ // \-> B
+ // The resulting vtable will consists of these segments:
+ // DSA, A, B, B-vptr, C, D
+
+ // For a diamond inheritance relationship like this,
+ // D --> B --> A
+ // \-> C -/
+ // The resulting vtable will consists of these segments:
+ // DSA, A, B, C, C-vptr, D
+
+ // For a more complex inheritance relationship like this:
+ // O --> G --> C --> A
+ // \ \ \-> B
+ // | |-> F --> D
+ // | \-> E
+ // |-> N --> J --> H
+ // \ \-> I
+ // |-> M --> K
+ // \-> L
+ // The resulting vtable will consists of these segments:
+ // DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
+ // H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
+ // N, N-vptr, O
+
+ // emit dsa segment first.
+ if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
+ return Some(v);
+ }
+
+ let mut emit_vptr_on_new_entry = false;
+ let mut visited = PredicateSet::new(tcx);
+ let predicate = trait_ref.without_const().to_predicate(tcx);
+ let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
+ smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
+ visited.insert(predicate);
+
+ // the main traversal loop:
+ // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
+ // that each node is emitted after all its descendents have been emitted.
+ // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
+ // this is done on the fly.
+ // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
+ // stops after it finds a node that has a next-sibling node.
+ // This next-sibling node will used as the starting point of next slice.
+
+ // Example:
+ // For a diamond inheritance relationship like this,
+ // D#1 --> B#0 --> A#0
+ // \-> C#1 -/
+
+ // Starting point 0 stack [D]
+ // Loop run #0: Stack after diving in is [D B A], A is "childless"
+ // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
+ // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
+ // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
+ // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
+ // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
+ // Loop run #1: Stack after exiting out is []. Now the function exits.
+
+ loop {
+ // dive deeper into the stack, recording the path
+ 'diving_in: loop {
+ if let Some((inner_most_trait_ref, _, _)) = stack.last() {
+ let inner_most_trait_ref = *inner_most_trait_ref;
+ let mut direct_super_traits_iter = tcx
+ .super_predicates_of(inner_most_trait_ref.def_id())
+ .predicates
+ .into_iter()
+ .filter_map(move |(pred, _)| {
+ pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
+ });
+
+ 'diving_in_skip_visited_traits: loop {
+ if let Some(next_super_trait) = direct_super_traits_iter.next() {
+ if visited.insert(next_super_trait.to_predicate(tcx)) {
+ // We're throwing away potential constness of super traits here.
+ // FIXME: handle ~const super traits
+ let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
+ stack.push((
+ next_super_trait,
+ emit_vptr_on_new_entry,
+ Some(direct_super_traits_iter),
+ ));
+ break 'diving_in_skip_visited_traits;
+ } else {
+ continue 'diving_in_skip_visited_traits;
+ }
+ } else {
+ break 'diving_in;
+ }
+ }
+ }
+ }
+
+ // Other than the left-most path, vptr should be emitted for each trait.
+ emit_vptr_on_new_entry = true;
+
+ // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
+ 'exiting_out: loop {
+ if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
+ if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
+ trait_ref: *inner_most_trait_ref,
+ emit_vptr: *emit_vptr,
+ }) {
+ return Some(v);
+ }
+
+ 'exiting_out_skip_visited_traits: loop {
+ if let Some(siblings) = siblings_opt {
+ if let Some(next_inner_most_trait_ref) = siblings.next() {
+ if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
+ // We're throwing away potential constness of super traits here.
+ // FIXME: handle ~const super traits
+ let next_inner_most_trait_ref =
+ next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
+ *inner_most_trait_ref = next_inner_most_trait_ref;
+ *emit_vptr = emit_vptr_on_new_entry;
+ break 'exiting_out;
+ } else {
+ continue 'exiting_out_skip_visited_traits;
+ }
+ }
+ }
+ stack.pop();
+ continue 'exiting_out;
+ }
+ }
+ // all done
+ return None;
+ }
+ }
+}
+
+fn dump_vtable_entries<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ sp: Span,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+ entries: &[VtblEntry<'tcx>],
+) {
+ tcx.sess.emit_err(DumpVTableEntries {
+ span: sp,
+ trait_ref,
+ entries: format!("{:#?}", entries),
+ });
+}
+
+fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
+ let trait_methods = tcx
+ .associated_items(trait_def_id)
+ .in_definition_order()
+ .filter(|item| item.kind == ty::AssocKind::Fn);
+ // Now list each method's DefId (for within its trait).
+ let own_entries = trait_methods.filter_map(move |trait_method| {
+ debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+ let def_id = trait_method.def_id;
+
+ // Some methods cannot be called on an object; skip those.
+ if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
+ debug!("own_existential_vtable_entry: not vtable safe");
+ return None;
+ }
+
+ Some(def_id)
+ });
+
+ tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
+/// Given a trait `trait_ref`, iterates the vtable entries
+/// that come from `trait_ref`, including its supertraits.
+fn vtable_entries<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+) -> &'tcx [VtblEntry<'tcx>] {
+ debug!("vtable_entries({:?})", trait_ref);
+
+ let mut entries = vec![];
+
+ let vtable_segment_callback = |segment| -> ControlFlow<()> {
+ match segment {
+ VtblSegment::MetadataDSA => {
+ entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
+ }
+ VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+ let existential_trait_ref = trait_ref
+ .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+ // Lookup the shape of vtable for the trait.
+ let own_existential_entries =
+ tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
+
+ let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+ debug!("vtable_entries: trait_method={:?}", def_id);
+
+ // The method may have some early-bound lifetimes; add regions for those.
+ let substs = trait_ref.map_bound(|trait_ref| {
+ InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+ GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+ GenericParamDefKind::Type { .. }
+ | GenericParamDefKind::Const { .. } => {
+ trait_ref.substs[param.index as usize]
+ }
+ })
+ });
+
+ // The trait type may have higher-ranked lifetimes in it;
+ // erase them if they appear, so that we get the type
+ // at some particular call site.
+ let substs = tcx
+ .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+
+ // It's possible that the method relies on where-clauses that
+ // do not hold for this particular set of type parameters.
+ // Note that this method could then never be called, so we
+ // do not want to try and codegen it, in that case (see #23435).
+ let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+ if impossible_predicates(tcx, predicates.predicates) {
+ debug!("vtable_entries: predicates do not hold");
+ return VtblEntry::Vacant;
+ }
+
+ let instance = ty::Instance::resolve_for_vtable(
+ tcx,
+ ty::ParamEnv::reveal_all(),
+ def_id,
+ substs,
+ )
+ .expect("resolution failed during building vtable representation");
+ VtblEntry::Method(instance)
+ });
+
+ entries.extend(own_entries);
+
+ if emit_vptr {
+ entries.push(VtblEntry::TraitVPtr(trait_ref));
+ }
+ }
+ }
+
+ ControlFlow::Continue(())
+ };
+
+ let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
+
+ if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
+ let sp = tcx.def_span(trait_ref.def_id());
+ dump_vtable_entries(tcx, sp, trait_ref, &entries);
+ }
+
+ tcx.arena.alloc_from_iter(entries.into_iter())
+}
+
+/// Find slot base for trait methods within vtable entries of another trait
+pub(super) fn vtable_trait_first_method_offset<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ key: (
+ ty::PolyTraitRef<'tcx>, // trait_to_be_found
+ ty::PolyTraitRef<'tcx>, // trait_owning_vtable
+ ),
+) -> usize {
+ let (trait_to_be_found, trait_owning_vtable) = key;
+
+ // #90177
+ let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
+ let vtable_segment_callback = {
+ let mut vtable_base = 0;
+
+ move |segment| {
+ match segment {
+ VtblSegment::MetadataDSA => {
+ vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
+ }
+ VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+ if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
+ return ControlFlow::Break(vtable_base);
+ }
+ vtable_base += count_own_vtable_entries(tcx, trait_ref);
+ if emit_vptr {
+ vtable_base += 1;
+ }
+ }
+ }
+ ControlFlow::Continue(())
+ }
+ };
+
+ if let Some(vtable_base) =
+ prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
+ {
+ vtable_base
+ } else {
+ bug!("Failed to find info for expected trait in vtable");
+ }
+}
+
+/// Find slot offset for trait vptr within vtable entries of another trait
+pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ key: (
+ Ty<'tcx>, // trait object type whose trait owning vtable
+ Ty<'tcx>, // trait object for supertrait
+ ),
+) -> Option<usize> {
+ let (source, target) = key;
+ assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
+ assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
+
+ // this has been typecked-before, so diagnostics is not really needed.
+ let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
+
+ let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
+
+ match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
+ Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
+ implsrc_traitcasting.vtable_vptr_slot
+ }
+ otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
+ }
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub(crate) fn count_own_vtable_entries<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+) -> usize {
+ tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
+}
+
+pub(super) fn provide(providers: &mut ty::query::Providers) {
+ *providers = ty::query::Providers {
+ own_existential_vtable_entries,
+ vtable_entries,
+ vtable_trait_upcasting_coercion_new_vptr_slot,
+ ..*providers
+ };
+}
// projection coming from another associated type. See
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
// `traits-assoc-type-in-supertrait-bad.rs`.
- if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+ if let Some(ty::Alias(ty::Projection, projection_ty)) = proj.term.ty().map(|ty| ty.kind())
&& let Some(&impl_item_id) =
- tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
+ tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
&& let Some(impl_item_span) = items
.iter()
.find(|item| item.id.owner_id.to_def_id() == impl_item_id)
// An associated item obligation born out of the `trait` failed to be met. An example
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
- if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+ if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
&& let Some(&impl_item_id) =
- tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
+ tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
&& let Some(impl_item_span) = items
.iter()
.find(|item| item.id.owner_id.to_def_id() == impl_item_id)
/// Pushes the obligations required for `trait_ref::Item` to be WF
/// into `self.out`.
- fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
+ fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {
// A projection is well-formed if
//
// (a) its predicates hold (*)
// `i32: Copy`
// ]
// Projection types do not require const predicates.
- let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs);
+ let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
self.out.extend(obligations);
let tcx = self.tcx();
GenericArgKind::Const(ct) => {
match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
- let obligations = self.nominal_obligations(uv.def.did, uv.substs);
- self.out.extend(obligations);
-
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
- let cause = self.cause(traits::WellFormed(None));
- self.out.push(traits::Obligation::with_depth(
- self.tcx(),
- cause,
- self.recursion_depth,
- self.param_env,
- predicate,
- ));
+ if !ct.has_escaping_bound_vars() {
+ let obligations = self.nominal_obligations(uv.def.did, uv.substs);
+ self.out.extend(obligations);
+
+ let predicate =
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct));
+ let cause = self.cause(traits::WellFormed(None));
+ self.out.push(traits::Obligation::with_depth(
+ self.tcx(),
+ cause,
+ self.recursion_depth,
+ self.param_env,
+ predicate,
+ ));
+ }
}
ty::ConstKind::Infer(_) => {
let cause = self.cause(traits::WellFormed(None));
// Simple cases that are WF if their type args are WF.
}
- ty::Projection(data) => {
+ ty::Alias(ty::Projection, data) => {
walker.skip_current_subtree(); // Subtree handled by compute_projection.
self.compute_projection(data);
}
// types appearing in the fn signature
}
- ty::Opaque(did, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// All of the requirements on type parameters
// have already been checked for `impl Trait` in
// return position. We do need to check type-alias-impl-trait though.
- if ty::is_impl_trait_defn(self.tcx, did).is_none() {
- let obligations = self.nominal_obligations(did, substs);
+ if ty::is_impl_trait_defn(self.tcx, def_id).is_none() {
+ let obligations = self.nominal_obligations(def_id, substs);
self.out.extend(obligations);
}
}
(ast::Mutability::Not, chalk_ir::Mutability::Not) => true,
}
}
- (&ty::Opaque(def_id, ..), OpaqueType(opaque_ty_id, ..)) => def_id == opaque_ty_id.0,
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }),
+ OpaqueType(opaque_ty_id, ..),
+ ) => def_id == opaque_ty_id.0,
(&ty::FnDef(def_id, ..), FnDef(fn_def_id, ..)) => def_id == fn_def_id.0,
(&ty::Str, Str) => true,
(&ty::Never, Never) => true,
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Opaque(def_id, substs) = *ty.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind() {
if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
return self.tcx.mk_ty(ty::Bound(
self.binder_index,
}
}
-impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy<RustInterner<'tcx>>> for ty::ProjectionTy<'tcx> {
- fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy<RustInterner<'tcx>> {
- chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
- associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id),
- substitution: self.substs.lower_into(interner),
- })
- }
-}
-
impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'tcx>>>>
for ChalkEnvironmentAndGoal<'tcx>
{
// FIXME(associated_const_equality): teach chalk about terms for alias eq.
chalk_ir::AliasEq {
ty: self.term.ty().unwrap().lower_into(interner),
- alias: self.projection_ty.lower_into(interner),
+ alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+ associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
+ substitution: self.projection_ty.substs.lower_into(interner),
+ }),
}
}
}
ty::Tuple(types) => {
chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
}
- ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)),
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }) => {
+ chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
+ associated_ty_id: chalk_ir::AssocTypeId(def_id),
+ substitution: substs.lower_into(interner),
+ }))
+ }
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
opaque_ty_id: chalk_ir::OpaqueTyId(def_id),
substitution: substs.lower_into(interner),
mutbl.lower_into(interner),
),
TyKind::Str => ty::Str,
- TyKind::OpaqueType(opaque_ty, substitution) => {
- ty::Opaque(opaque_ty.0, substitution.lower_into(interner))
- }
- TyKind::AssociatedType(assoc_ty, substitution) => ty::Projection(ty::ProjectionTy {
- substs: substitution.lower_into(interner),
- item_def_id: assoc_ty.0,
- }),
+ TyKind::OpaqueType(opaque_ty, substitution) => ty::Alias(
+ ty::Opaque,
+ interner.tcx.mk_alias_ty(opaque_ty.0, substitution.lower_into(interner)),
+ ),
+ TyKind::AssociatedType(assoc_ty, substitution) => ty::Alias(
+ ty::Projection,
+ interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
+ ),
TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
TyKind::Error => return interner.tcx.ty_error(),
TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
name: ty::BoundVar::from_usize(placeholder.idx),
}),
TyKind::Alias(alias_ty) => match alias_ty {
- chalk_ir::AliasTy::Projection(projection) => ty::Projection(ty::ProjectionTy {
- item_def_id: projection.associated_ty_id.0,
- substs: projection.substitution.lower_into(interner),
- }),
- chalk_ir::AliasTy::Opaque(opaque) => {
- ty::Opaque(opaque.opaque_ty_id.0, opaque.substitution.lower_into(interner))
- }
+ chalk_ir::AliasTy::Projection(projection) => ty::Alias(
+ ty::Projection,
+ interner.tcx.mk_alias_ty(
+ projection.associated_ty_id.0,
+ projection.substitution.lower_into(interner),
+ ),
+ ),
+ chalk_ir::AliasTy::Opaque(opaque) => ty::Alias(
+ ty::Opaque,
+ interner.tcx.mk_alias_ty(
+ opaque.opaque_ty_id.0,
+ opaque.substitution.lower_into(interner),
+ ),
+ ),
},
TyKind::Function(_quantified_ty) => unimplemented!(),
TyKind::BoundVar(_bound) => ty::Bound(
binders.clone(),
chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq {
alias: chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
- associated_ty_id: chalk_ir::AssocTypeId(predicate.item_def_id),
+ associated_ty_id: chalk_ir::AssocTypeId(predicate.def_id),
substitution: interner
.tcx
.mk_substs_trait(self_ty, predicate.substs)
let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx);
chalk_solve::rust_ir::AliasEqBound {
trait_bound: trait_ref.lower_into(interner),
- associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id),
+ associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.def_id),
parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(),
value: self.term.ty().unwrap().lower_into(interner),
}
--- /dev/null
+// This file contains various trait resolution methods used by codegen.
+// They all assume regions can be erased and monomorphic types. It
+// seems likely that they should eventually be merged into more
+// general routines.
+
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::traits::FulfillmentErrorCode;
+use rustc_middle::traits::CodegenObligationError;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::{
+ ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
+ Unimplemented,
+};
+
+/// Attempts to resolve an obligation to an `ImplSource`. The result is
+/// a shallow `ImplSource` resolution, meaning that we do not
+/// (necessarily) resolve all nested obligations on the impl. Note
+/// that type check should guarantee to us that all nested
+/// obligations *could be* resolved if we wanted to.
+///
+/// This also expects that `trait_ref` is fully normalized.
+pub fn codegen_select_candidate<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
+) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
+ // We expect the input to be fully normalized.
+ debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
+
+ // Do the initial selection for the obligation. This yields the
+ // shallow result we are looking for -- that is, what specific impl.
+ let infcx = tcx
+ .infer_ctxt()
+ .ignoring_regions()
+ .with_opaque_type_inference(DefiningAnchor::Bubble)
+ .build();
+ //~^ HACK `Bubble` is required for
+ // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+ let mut selcx = SelectionContext::new(&infcx);
+
+ let obligation_cause = ObligationCause::dummy();
+ let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
+
+ let selection = match selcx.select(&obligation) {
+ Ok(Some(selection)) => selection,
+ Ok(None) => return Err(CodegenObligationError::Ambiguity),
+ Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
+ Err(e) => {
+ bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
+ }
+ };
+
+ debug!(?selection);
+
+ // Currently, we use a fulfillment context to completely resolve
+ // all nested obligations. This is because they can inform the
+ // inference of the impl's type parameters.
+ let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
+ let impl_source = selection.map(|predicate| {
+ fulfill_cx.register_predicate_obligation(&infcx, predicate);
+ });
+
+ // In principle, we only need to do this so long as `impl_source`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ // `rustc_monomorphize::collector` assumes there are no type errors.
+ // Cycle errors are the only post-monomorphization errors possible; emit them now so
+ // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
+ for err in errors {
+ if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+ infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
+ }
+ }
+ return Err(CodegenObligationError::FulfillmentError);
+ }
+
+ let impl_source = infcx.resolve_vars_if_possible(impl_source);
+ let impl_source = infcx.tcx.erase_regions(impl_source);
+
+ // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
+ // as they will get constrained elsewhere, too.
+ // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+
+ Ok(&*tcx.arena.alloc(impl_source))
+}
// A projection that we couldn't resolve - it
// might have a destructor.
- ty::Projection(..) | ty::Opaque(..) => {
+ ty::Alias(..) => {
result.kinds.push(ty.into());
}
}
// Types that can't be resolved. Pass them forward.
- ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => {
+ ty::Alias(..) | ty::Param(..) => {
constraints.dtorck_types.push(ty);
}
extern crate rustc_middle;
mod chalk;
+mod codegen;
mod dropck_outlives;
mod evaluate_obligation;
mod implied_outlives_bounds;
normalize_projection_ty::provide(p);
normalize_erasing_regions::provide(p);
type_op::provide(p);
+ p.codegen_select_candidate = codegen::codegen_select_candidate;
}
bound_vars,
)
}
- ty::Generator(_, substs, _) => {
+ ty::Generator(did, substs, _) => {
let sig = substs.as_generator().poly_sig();
let bound_vars = tcx.mk_bound_variable_kinds(
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
let sig = sig.skip_binder();
- let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
- let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+ // The `FnSig` and the `ret_ty` here is for a generators main
+ // `Generator::resume(...) -> GeneratorState` function in case we
+ // have an ordinary generator, or the `Future::poll(...) -> Poll`
+ // function in case this is a special generator backing an async construct.
+ let ret_ty = if tcx.generator_is_async(did) {
+ let state_did = tcx.require_lang_item(LangItem::Poll, None);
+ let state_adt_ref = tcx.adt_def(state_did);
+ let state_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+ tcx.mk_adt(state_adt_ref, state_substs)
+ } else {
+ let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+ let state_adt_ref = tcx.adt_def(state_did);
+ let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+ tcx.mk_adt(state_adt_ref, state_substs)
+ };
+
ty::Binder::bind_with_vars(
tcx.mk_fn_sig(
[env_ty, sig.resume_ty].iter(),
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
- resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs)
+ resolve_associated_item(
+ tcx,
+ def.did,
+ param_env,
+ trait_def_id,
+ tcx.normalize_erasing_regions(param_env, substs),
+ )
} else {
let ty = tcx.type_of(def.def_id_for_type_of());
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
+use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
};
use rustc_middle::ty::{
- self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+ self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
};
use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
use rustc_span::symbol::Symbol;
}
// Types with no meaningful known layout.
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
// NOTE(eddyb) `layout_of` query should've normalized these away,
// if that was possible, so there's no reason to try again here.
return Err(LayoutError::Unknown(ty));
);
};
- let adt_def = match *layout.ty.kind() {
- ty::Adt(ref adt_def, _) => {
+ match *layout.ty.kind() {
+ ty::Adt(adt_def, _) => {
debug!("print-type-size t: `{:?}` process adt", layout.ty);
- adt_def
+ let adt_kind = adt_def.adt_kind();
+ let adt_packed = adt_def.repr().pack.is_some();
+ let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
+ record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
+ }
+
+ ty::Generator(def_id, substs, _) => {
+ debug!("print-type-size t: `{:?}` record generator", layout.ty);
+ // Generators always have a begin/poisoned/end state with additional suspend points
+ let (variant_infos, opt_discr_size) =
+ variant_info_for_generator(cx, layout, def_id, substs);
+ record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
}
ty::Closure(..) => {
debug!("print-type-size t: `{:?}` record closure", layout.ty);
record(DataTypeKind::Closure, false, None, vec![]);
- return;
}
_ => {
debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
- return;
}
};
+}
- let adt_kind = adt_def.adt_kind();
- let adt_packed = adt_def.repr().pack.is_some();
-
+fn variant_info_for_adt<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+ adt_def: AdtDef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
let mut min_size = Size::ZERO;
let field_info: Vec<_> = flds
.map(|(i, &name)| {
let field_layout = layout.field(cx, i);
let offset = layout.fields.offset(i);
- let field_end = offset + field_layout.size;
- if min_size < field_end {
- min_size = field_end;
- }
+ min_size = min_size.max(offset + field_layout.size);
FieldInfo {
name,
offset: offset.bytes(),
debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
let variant_def = &adt_def.variant(index);
let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
- record(
- adt_kind.into(),
- adt_packed,
- None,
- vec![build_variant_info(Some(variant_def.name), &fields, layout)],
- );
+ (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
} else {
- // (This case arises for *empty* enums; so give it
- // zero variants.)
- record(adt_kind.into(), adt_packed, None, vec![]);
+ (vec![], None)
}
}
build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
})
.collect();
- record(
- adt_kind.into(),
- adt_packed,
+
+ (
+ variant_infos,
match tag_encoding {
TagEncoding::Direct => Some(tag.size(cx)),
_ => None,
},
- variant_infos,
- );
+ )
}
}
}
+
+fn variant_info_for_generator<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+ let Variants::Multiple { tag, ref tag_encoding, tag_field, .. } = layout.variants else {
+ return (vec![], None);
+ };
+
+ let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+ let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
+
+ let mut upvars_size = Size::ZERO;
+ let upvar_fields: Vec<_> = substs
+ .as_generator()
+ .upvar_tys()
+ .zip(upvar_names)
+ .enumerate()
+ .map(|(field_idx, (_, name))| {
+ let field_layout = layout.field(cx, field_idx);
+ let offset = layout.fields.offset(field_idx);
+ upvars_size = upvars_size.max(offset + field_layout.size);
+ FieldInfo {
+ name: Symbol::intern(&name),
+ offset: offset.bytes(),
+ size: field_layout.size.bytes(),
+ align: field_layout.align.abi.bytes(),
+ }
+ })
+ .collect();
+
+ let variant_infos: Vec<_> = generator
+ .variant_fields
+ .iter_enumerated()
+ .map(|(variant_idx, variant_def)| {
+ let variant_layout = layout.for_variant(cx, variant_idx);
+ let mut variant_size = Size::ZERO;
+ let fields = variant_def
+ .iter()
+ .enumerate()
+ .map(|(field_idx, local)| {
+ let field_layout = variant_layout.field(cx, field_idx);
+ let offset = variant_layout.fields.offset(field_idx);
+ // The struct is as large as the last field's end
+ variant_size = variant_size.max(offset + field_layout.size);
+ FieldInfo {
+ name: state_specific_names.get(*local).copied().flatten().unwrap_or(
+ Symbol::intern(&format!(".generator_field{}", local.as_usize())),
+ ),
+ offset: offset.bytes(),
+ size: field_layout.size.bytes(),
+ align: field_layout.align.abi.bytes(),
+ }
+ })
+ .chain(upvar_fields.iter().copied())
+ .collect();
+
+ // If the variant has no state-specific fields, then it's the size of the upvars.
+ if variant_size == Size::ZERO {
+ variant_size = upvars_size;
+ }
+
+ // This `if` deserves some explanation.
+ //
+ // The layout code has a choice of where to place the discriminant of this generator.
+ // If the discriminant of the generator is placed early in the layout (before the
+ // variant's own fields), then it'll implicitly be counted towards the size of the
+ // variant, since we use the maximum offset to calculate size.
+ // (side-note: I know this is a bit problematic given upvars placement, etc).
+ //
+ // This is important, since the layout printing code always subtracts this discriminant
+ // size from the variant size if the struct is "enum"-like, so failing to account for it
+ // will either lead to numerical underflow, or an underreported variant size...
+ //
+ // However, if the discriminant is placed past the end of the variant, then we need
+ // to factor in the size of the discriminant manually. This really should be refactored
+ // better, but this "works" for now.
+ if layout.fields.offset(tag_field) >= variant_size {
+ variant_size += match tag_encoding {
+ TagEncoding::Direct => tag.size(cx),
+ _ => Size::ZERO,
+ };
+ }
+
+ VariantInfo {
+ name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+ kind: SizeKind::Exact,
+ size: variant_size.bytes(),
+ align: variant_layout.align.abi.bytes(),
+ fields,
+ }
+ })
+ .collect();
+ (
+ variant_infos,
+ match tag_encoding {
+ TagEncoding::Direct => Some(tag.size(cx)),
+ _ => None,
+ },
+ )
+}
mod layout_sanity_check;
mod needs_drop;
pub mod representability;
+mod structural_match;
mod ty;
pub fn provide(providers: &mut Providers) {
representability::provide(providers);
ty::provide(providers);
instance::provide(providers);
+ structural_match::provide(providers);
}
queue_type(self, required);
}
}
- ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+ ty::Array(..) | ty::Alias(..) | ty::Param(_) => {
if ty == component {
// Return the type to the caller: they may be able
// to normalize further than we can.
--- /dev/null
+use rustc_hir::lang_items::LangItem;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+
+/// This method returns true if and only if `adt_ty` itself has been marked as
+/// eligible for structural-match: namely, if it implements both
+/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
+/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
+///
+/// Note that this does *not* recursively check if the substructure of `adt_ty`
+/// implements the traits.
+fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
+ let ref infcx = tcx.infer_ctxt().build();
+ let cause = ObligationCause::dummy();
+
+ let ocx = ObligationCtxt::new(infcx);
+ // require `#[derive(PartialEq)]`
+ let structural_peq_def_id =
+ infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
+ ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
+ // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
+ // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
+ let structural_teq_def_id =
+ infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
+ ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
+
+ // We deliberately skip *reporting* fulfillment errors (via
+ // `report_fulfillment_errors`), for two reasons:
+ //
+ // 1. The error messages would mention `std::marker::StructuralPartialEq`
+ // (a trait which is solely meant as an implementation detail
+ // for now), and
+ //
+ // 2. We are sometimes doing future-incompatibility lints for
+ // now, so we do not want unconditional errors here.
+ ocx.select_all_or_error().is_empty()
+}
+
+pub fn provide(providers: &mut Providers) {
+ providers.has_structural_eq_impls = has_structural_eq_impls;
+}
.collect()
}
- Projection(..) | Opaque(..) => {
+ Alias(..) => {
// must calculate explicitly.
// FIXME: consider special-casing always-Sized projections
vec![ty]
type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type ProjectionTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type AliasTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
#![allow(rustc::usage_of_ty_tykind)]
-use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use std::cmp::Ordering;
use std::{fmt, hash};
use crate::DebruijnIndex;
use rustc_serialize::{Decodable, Decoder, Encodable};
/// Specifies how a trait object is represented.
-#[derive(
- Clone,
- Copy,
- PartialEq,
- Eq,
- PartialOrd,
- Ord,
- Hash,
- Debug,
- Encodable,
- Decodable,
- HashStable_Generic
-)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum DynKind {
/// An unsized `dyn Trait` object
Dyn,
DynStar,
}
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum AliasKind {
+ Projection,
+ Opaque,
+}
+
/// Defines the kinds of types used by the type system.
///
/// Types written by the user start out as `hir::TyKind` and get
/// A tuple type. For example, `(i32, bool)`.
Tuple(I::ListTy),
- /// The projection of an associated type. For example,
- /// `<T as Trait<..>>::N`.
- Projection(I::ProjectionTy),
-
- /// Opaque (`impl Trait`) type found in a return type.
- ///
- /// The `DefId` comes either from
- /// * the `impl Trait` ast::Ty node,
- /// * or the `type Foo = impl Trait` declaration
- ///
- /// For RPIT the substitutions are for the generics of the function,
- /// while for TAIT it is used for the generic parameters of the alias.
- ///
- /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type.
- Opaque(I::DefId, I::SubstsRef),
+ /// A projection or opaque type. Both of these types
+ Alias(AliasKind, I::AliasTy),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}`.
Param(I::ParamTy),
GeneratorWitness(_) => 17,
Never => 18,
Tuple(_) => 19,
- Projection(_) => 20,
- Opaque(_, _) => 21,
- Param(_) => 22,
- Bound(_, _) => 23,
- Placeholder(_) => 24,
- Infer(_) => 25,
- Error(_) => 26,
+ Alias(_, _) => 20,
+ Param(_) => 21,
+ Bound(_, _) => 22,
+ Placeholder(_) => 23,
+ Infer(_) => 24,
+ Error(_) => 25,
}
}
match self {
Bool => Bool,
Char => Char,
- Int(i) => Int(i.clone()),
- Uint(u) => Uint(u.clone()),
- Float(f) => Float(f.clone()),
+ Int(i) => Int(*i),
+ Uint(u) => Uint(*u),
+ Float(f) => Float(*f),
Adt(d, s) => Adt(d.clone(), s.clone()),
Foreign(d) => Foreign(d.clone()),
Str => Str,
Ref(r, t, m) => Ref(r.clone(), t.clone(), m.clone()),
FnDef(d, s) => FnDef(d.clone(), s.clone()),
FnPtr(s) => FnPtr(s.clone()),
- Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), repr.clone()),
+ Dynamic(p, r, repr) => Dynamic(p.clone(), r.clone(), *repr),
Closure(d, s) => Closure(d.clone(), s.clone()),
Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
GeneratorWitness(g) => GeneratorWitness(g.clone()),
Never => Never,
Tuple(t) => Tuple(t.clone()),
- Projection(p) => Projection(p.clone()),
- Opaque(d, s) => Opaque(d.clone(), s.clone()),
+ Alias(k, p) => Alias(*k, p.clone()),
Param(p) => Param(p.clone()),
- Bound(d, b) => Bound(d.clone(), b.clone()),
+ Bound(d, b) => Bound(*d, b.clone()),
Placeholder(p) => Placeholder(p.clone()),
Infer(t) => Infer(t.clone()),
Error(e) => Error(e.clone()),
}
(GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
(Tuple(a_t), Tuple(b_t)) => a_t == b_t,
- (Projection(a_p), Projection(b_p)) => a_p == b_p,
- (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
(Param(a_p), Param(b_p)) => a_p == b_p,
(Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
(Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
}
(GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
(Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
- (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
- (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
+ (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
(Param(a_p), Param(b_p)) => a_p.cmp(b_p),
(Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
(Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
}
GeneratorWitness(g) => g.hash(state),
Tuple(t) => t.hash(state),
- Projection(p) => p.hash(state),
- Opaque(d, s) => {
- d.hash(state);
- s.hash(state)
+ Alias(i, p) => {
+ i.hash(state);
+ p.hash(state);
}
Param(p) => p.hash(state),
Bound(d, b) => {
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
Never => f.write_str("Never"),
Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
- Projection(p) => f.debug_tuple_field1_finish("Projection", p),
- Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
+ Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
Param(p) => f.debug_tuple_field1_finish("Param", p),
Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
I::ListBinderExistentialPredicate: Encodable<E>,
I::BinderListTy: Encodable<E>,
I::ListTy: Encodable<E>,
- I::ProjectionTy: Encodable<E>,
+ I::AliasTy: Encodable<E>,
I::ParamTy: Encodable<E>,
I::BoundTy: Encodable<E>,
I::PlaceholderType: Encodable<E>,
Tuple(substs) => e.emit_enum_variant(disc, |e| {
substs.encode(e);
}),
- Projection(p) => e.emit_enum_variant(disc, |e| {
+ Alias(k, p) => e.emit_enum_variant(disc, |e| {
+ k.encode(e);
p.encode(e);
}),
- Opaque(def_id, substs) => e.emit_enum_variant(disc, |e| {
- def_id.encode(e);
- substs.encode(e);
- }),
Param(p) => e.emit_enum_variant(disc, |e| {
p.encode(e);
}),
I::ListBinderExistentialPredicate: Decodable<D>,
I::BinderListTy: Decodable<D>,
I::ListTy: Decodable<D>,
- I::ProjectionTy: Decodable<D>,
+ I::AliasTy: Decodable<D>,
I::ParamTy: Decodable<D>,
+ I::AliasTy: Decodable<D>,
I::BoundTy: Decodable<D>,
I::PlaceholderType: Decodable<D>,
I::InferTy: Decodable<D>,
17 => GeneratorWitness(Decodable::decode(d)),
18 => Never,
19 => Tuple(Decodable::decode(d)),
- 20 => Projection(Decodable::decode(d)),
- 21 => Opaque(Decodable::decode(d), Decodable::decode(d)),
- 22 => Param(Decodable::decode(d)),
- 23 => Bound(Decodable::decode(d), Decodable::decode(d)),
- 24 => Placeholder(Decodable::decode(d)),
- 25 => Infer(Decodable::decode(d)),
- 26 => Error(Decodable::decode(d)),
+ 20 => Alias(Decodable::decode(d), Decodable::decode(d)),
+ 21 => Param(Decodable::decode(d)),
+ 22 => Bound(Decodable::decode(d), Decodable::decode(d)),
+ 23 => Placeholder(Decodable::decode(d)),
+ 24 => Infer(Decodable::decode(d)),
+ 25 => Error(Decodable::decode(d)),
_ => panic!(
"{}",
format!(
I::Mutability: HashStable<CTX>,
I::BinderListTy: HashStable<CTX>,
I::ListTy: HashStable<CTX>,
- I::ProjectionTy: HashStable<CTX>,
+ I::AliasTy: HashStable<CTX>,
I::BoundTy: HashStable<CTX>,
I::ParamTy: HashStable<CTX>,
I::PlaceholderType: HashStable<CTX>,
Tuple(substs) => {
substs.hash_stable(__hcx, __hasher);
}
- Projection(p) => {
+ Alias(k, p) => {
+ k.hash_stable(__hcx, __hasher);
p.hash_stable(__hcx, __hasher);
}
- Opaque(def_id, substs) => {
- def_id.hash_stable(__hcx, __hasher);
- substs.hash_stable(__hcx, __hasher);
- }
Param(p) => {
p.hash_stable(__hcx, __hasher);
}
fn clone(&self) -> Self {
match self {
ReEarlyBound(r) => ReEarlyBound(r.clone()),
- ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
+ ReLateBound(d, r) => ReLateBound(*d, r.clone()),
ReFree(r) => ReFree(r.clone()),
ReStatic => ReStatic,
ReVar(r) => ReVar(r.clone()),
# Unless you're developing for a target where Rust CI doesn't build a compiler
# toolchain or changing LLVM locally, you probably want to set this to true.
#
-# This is false by default so that distributions don't unexpectedly download
-# LLVM from the internet.
-#
# All tier 1 targets are currently supported; set this to `"if-available"` if
# you are not sure whether you're on a tier 1 target.
#
#
# Note that many of the LLVM options are not currently supported for
# downloading. Currently only the "assertions" option can be toggled.
-#download-ci-llvm = false
+#
+# Defaults to "if-available" when `channel = "dev"` and "false" otherwise.
+#download-ci-llvm = "if-available"
# Indicates whether LLVM rebuild should be skipped when running bootstrap. If
# this is `false` then the compiler's LLVM will be rebuilt whenever the built
pub(super) fn new(inner: VecDeque<T, A>) -> Self {
IntoIter { inner }
}
+
+ pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
+ self.inner
+ }
}
#[stable(feature = "collection_debug", since = "1.17.0")]
mod spec_extend;
+use self::spec_from_iter::SpecFromIter;
+
+mod spec_from_iter;
+
#[cfg(test)]
mod tests;
VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) }
}
+ /// Creates a `VecDeque` from a raw allocation, when the initialized
+ /// part of that allocation forms a *contiguous* subslice thereof.
+ ///
+ /// For use by `vec::IntoIter::into_vecdeque`
+ ///
+ /// # Safety
+ ///
+ /// All the usual requirements on the allocated memory like in
+ /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are
+ /// initialized rather than only supporting `0..len`. Requires that
+ /// `initialized.start` ≤ `initialized.end` ≤ `capacity`.
+ #[inline]
+ pub(crate) unsafe fn from_contiguous_raw_parts_in(
+ ptr: *mut T,
+ initialized: Range<usize>,
+ capacity: usize,
+ alloc: A,
+ ) -> Self {
+ debug_assert!(initialized.start <= initialized.end);
+ debug_assert!(initialized.end <= capacity);
+
+ // SAFETY: Our safety precondition guarantees the range length won't wrap,
+ // and that the allocation is valid for use in `RawVec`.
+ unsafe {
+ VecDeque {
+ head: initialized.start,
+ len: initialized.end.unchecked_sub(initialized.start),
+ buf: RawVec::from_raw_parts_in(ptr, capacity, alloc),
+ }
+ }
+ }
+
/// Provides a reference to the element at the given index.
///
/// Element at index 0 is the front of the queue.
/// The deque is assumed to be partitioned according to the given predicate.
/// This means that all elements for which the predicate returns true are at the start of the deque
/// and all elements for which the predicate returns false are at the end.
- /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
+ /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0`
/// (all odd numbers are at the start, all even at the end).
///
/// If the deque is not partitioned, the returned result is unspecified and meaningless,
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> FromIterator<T> for VecDeque<T> {
- #[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
- // Since converting is O(1) now, might as well re-use that logic
- // (including things like the `vec::IntoIter`→`Vec` specialization)
- // especially as that could save us some monomorphiziation work
- // if one uses the same iterators (like slice ones) with both.
- return from_iter_via_vec(iter.into_iter());
-
- #[inline]
- fn from_iter_via_vec<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
- Vec::from_iter(iter).into()
- }
+ SpecFromIter::spec_from_iter(iter.into_iter())
}
}
--- /dev/null
+use super::{IntoIter, VecDeque};
+
+/// Specialization trait used for `VecDeque::from_iter`
+pub(super) trait SpecFromIter<T, I> {
+ fn spec_from_iter(iter: I) -> Self;
+}
+
+impl<T, I> SpecFromIter<T, I> for VecDeque<T>
+where
+ I: Iterator<Item = T>,
+{
+ default fn spec_from_iter(iterator: I) -> Self {
+ // Since converting is O(1) now, just re-use the `Vec` logic for
+ // anything where we can't do something extra-special for `VecDeque`,
+ // especially as that could save us some monomorphiziation work
+ // if one uses the same iterators (like slice ones) with both.
+ crate::vec::Vec::from_iter(iterator).into()
+ }
+}
+
+impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
+ #[inline]
+ fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
+ iterator.into_vecdeque()
+ }
+}
+
+impl<T> SpecFromIter<T, IntoIter<T>> for VecDeque<T> {
+ #[inline]
+ fn spec_from_iter(iterator: IntoIter<T>) -> Self {
+ iterator.into_vecdeque()
+ }
+}
//! // documentation for details, and the function `pad` can be used
//! // to pad strings.
//! let decimals = f.precision().unwrap_or(3);
-//! let string = format!("{:.*}", decimals, magnitude);
+//! let string = format!("{magnitude:.decimals$}");
//! f.pad_integral(true, "", &string)
//! }
//! }
//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro"));
//!
//! fn my_fmt_fn(args: fmt::Arguments) {
-//! write!(&mut io::stdout(), "{}", args);
+//! write!(&mut io::stdout(), "{args}");
//! }
//! my_fmt_fn(format_args!(", or a {} too", "function"));
//! ```
#[cfg(not(no_global_oom_handling))]
use super::AsVecIntoIter;
use crate::alloc::{Allocator, Global};
+#[cfg(not(no_global_oom_handling))]
+use crate::collections::VecDeque;
use crate::raw_vec::RawVec;
use core::array;
use core::fmt;
pub(crate) fn forget_remaining_elements(&mut self) {
self.ptr = self.end;
}
+
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ pub(crate) fn into_vecdeque(self) -> VecDeque<T, A> {
+ // Keep our `Drop` impl from dropping the elements and the allocator
+ let mut this = ManuallyDrop::new(self);
+
+ // SAFETY: This allocation originally came from a `Vec`, so it passes
+ // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
+ // so the `sub_ptr`s below cannot wrap, and will produce a well-formed
+ // range. `end` ≤ `buf + cap`, so the range will be in-bounds.
+ // Taking `alloc` is ok because nothing else is going to look at it,
+ // since our `Drop` impl isn't going to run so there's no more code.
+ unsafe {
+ let buf = this.buf.as_ptr();
+ let initialized = if T::IS_ZST {
+ // All the pointers are the same for ZSTs, so it's fine to
+ // say that they're all at the beginning of the "allocation".
+ 0..this.len()
+ } else {
+ this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf)
+ };
+ let cap = this.cap;
+ let alloc = ManuallyDrop::take(&mut this.alloc);
+ VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc)
+ }
+ }
}
#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
d.resize(1, v);
assert_eq!(d[0].capacity(), 1234);
}
+
+#[test]
+fn test_collect_from_into_iter_keeps_allocation() {
+ let mut v = Vec::with_capacity(13);
+ v.extend(0..7);
+ check(v.as_ptr(), v.last().unwrap(), v.into_iter());
+
+ let mut v = VecDeque::with_capacity(13);
+ v.extend(0..7);
+ check(&v[0], &v[v.len() - 1], v.into_iter());
+
+ fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) {
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.next(), Some(1));
+
+ let mut v: VecDeque<i32> = it.collect();
+ assert_eq!(v.capacity(), 13);
+ assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2));
+ assert_eq!(&v[v.len() - 1] as *const _, last);
+
+ assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+ v.push_front(7);
+ assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+ v.push_front(8);
+ assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+
+ // Now that we've adding thing in place of the two that we removed from
+ // the front of the iterator, we're back to matching the buffer pointer.
+ assert_eq!(v.as_slices().0.as_ptr(), buf);
+ assert_eq!(&v[v.len() - 1] as *const _, last);
+
+ v.push_front(9);
+ assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice()));
+ assert_eq!(v.capacity(), 13);
+ }
+}
/// if any element creation was unsuccessful.
///
/// The return type of this function depends on the return type of the closure.
-/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
///
/// # Arguments
/// return an array the same size as `self` or the first error encountered.
///
/// The return type of this function depends on the return type of the closure.
- /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N]; E>`.
+ /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
///
/// # Examples
/// to be modified, it can additionally implement [`BorrowMut<T>`].
///
/// Further, when providing implementations for additional traits, it needs
-/// to be considered whether they should behave identical to those of the
+/// to be considered whether they should behave identically to those of the
/// underlying type as a consequence of acting as a representation of that
/// underlying type. Generic code typically uses `Borrow<T>` when it relies
/// on the identical behavior of these additional trait implementations.
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
/// in `rustc_trait_selection`.
mod impls {
-
use super::Clone;
macro_rules! impl_clone {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
impl const Clone for $t {
- #[inline]
+ #[inline(always)]
fn clone(&self) -> Self {
*self
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
impl<T: ?Sized> const Clone for *const T {
- #[inline]
+ #[inline(always)]
fn clone(&self) -> Self {
*self
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
impl<T: ?Sized> const Clone for *mut T {
- #[inline]
+ #[inline(always)]
fn clone(&self) -> Self {
*self
}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
impl<T: ?Sized> const Clone for &T {
- #[inline]
+ #[inline(always)]
#[rustc_diagnostic_item = "noop_method_clone"]
fn clone(&self) -> Self {
*self
/// ```
#[stable(feature = "convert_id", since = "1.33.0")]
#[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
-#[inline]
+#[inline(always)]
pub const fn identity<T>(x: T) -> T {
x
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsRef<[T]> for [T] {
+ #[inline(always)]
fn as_ref(&self) -> &[T] {
self
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> AsMut<[T]> for [T] {
+ #[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
self
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<str> for str {
- #[inline]
+ #[inline(always)]
fn as_ref(&self) -> &str {
self
}
#[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
impl AsMut<str> for str {
- #[inline]
+ #[inline(always)]
fn as_mut(&mut self) -> &mut str {
self
}
/// 1. The `pieces` slice must be at least as long as `fmt`.
/// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be a
/// valid index of `args`.
- /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of
+ /// 3. Every [`rt::v1::Count::Param`] within `fmt` must contain a valid index of
/// `args`.
#[doc(hidden)]
#[inline]
/// ```
///
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
-#[inline]
+#[inline(always)]
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
#[cfg(target_arch = "x86")]
#[unstable(feature = "hint_must_use", issue = "94745")]
#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
#[must_use] // <-- :)
+#[inline(always)]
pub const fn must_use<T>(value: T) -> T {
value
}
//! #[custom_mir(dialect = "built")]
//! pub fn simple(x: i32) -> i32 {
//! mir!(
-//! let temp1: i32;
-//! let temp2: _;
+//! let temp2: i32;
//!
//! {
-//! temp1 = x;
-//! Goto(exit)
+//! let temp1 = x;
+//! Goto(my_second_block)
//! }
//!
-//! exit = {
+//! my_second_block = {
//! temp2 = Move(temp1);
//! RET = temp2;
//! Return()
//! }
//! ```
//!
-//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
+//! The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
+//! attribute only works on functions - there is no way to insert custom MIR into the middle of
+//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
+//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
+//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
+//! "runtime", phase = "optimized")] if you don't.
//!
-//! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
-//! attribute only works on functions - there is no way to insert custom MIR into the middle of
-//! another function.
-//! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
-//! This will normally be the phase that corresponds to the thing you are trying to test. The
-//! phase can be omitted for dialects that have just one.
-//! - You should define your function signature like you normally would. Externally, this function
-//! can be called like any other function.
-//! - Type inference works - you don't have to spell out the type of all of your locals.
+//! [dialect docs]:
+//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
//!
-//! For now, all statements and terminators are parsed from nested invocations of the special
-//! functions provided in this module. We additionally want to (but do not yet) support more
-//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
-//! supported yet.
+//! The input to the [`mir!`] macro is:
+//!
+//! - A possibly empty list of local declarations. Locals can also be declared inline on
+//! assignments via `let`. Type inference generally works. Shadowing does not.
+//! - A list of basic blocks. The first of these is the start block and is where execution begins.
+//! All blocks other than the start block need to be given a name, so that they can be referred
+//! to later.
+//! - Each block is a list of semicolon terminated statements, followed by a terminator. The
+//! syntax for the various statements and terminators is designed to be as similar as possible
+//! to the syntax for analogous concepts in native Rust. See below for a list.
+//!
+//! # Examples
+//!
+//! ```rust
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 {
+//! mir!(
+//! {
+//! match c {
+//! true => t,
+//! _ => f,
+//! }
+//! }
+//!
+//! t = {
+//! let temp = a;
+//! Goto(load_and_exit)
+//! }
+//!
+//! f = {
+//! temp = b;
+//! Goto(load_and_exit)
+//! }
+//!
+//! load_and_exit = {
+//! RET = *temp;
+//! Return()
+//! }
+//! )
+//! }
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn unwrap_unchecked<T>(opt: Option<T>) -> T {
+//! mir!({
+//! RET = Move(Field(Variant(opt, 1), 0));
+//! Return()
+//! })
+//! }
+//!
+//! #[custom_mir(dialect = "runtime", phase = "optimized")]
+//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
+//! mir!(
+//! let unused;
+//! let popped;
+//!
+//! {
+//! Call(unused, pop, Vec::push(v, value))
+//! }
+//!
+//! pop = {
+//! Call(popped, drop, Vec::pop(v))
+//! }
+//!
+//! drop = {
+//! Drop(popped, ret)
+//! }
+//!
+//! ret = {
+//! Return()
+//! }
+//! )
+//! }
+//! ```
+//!
+//! We can also set off compilation failures that happen in sufficiently late stages of the
+//! compiler:
+//!
+//! ```rust,compile_fail
+//! #![feature(core_intrinsics, custom_mir)]
+//!
+//! extern crate core;
+//! use core::intrinsics::mir::*;
+//!
+//! #[custom_mir(dialect = "built")]
+//! fn borrow_error(should_init: bool) -> i32 {
+//! mir!(
+//! let temp: i32;
+//!
+//! {
+//! match should_init {
+//! true => init,
+//! _ => use_temp,
+//! }
+//! }
+//!
+//! init = {
+//! temp = 0;
+//! Goto(use_temp)
+//! }
+//!
+//! use_temp = {
+//! RET = temp;
+//! Return()
+//! }
+//! )
+//! }
+//! ```
+//!
+//! ```text
+//! error[E0381]: used binding is possibly-uninitialized
+//! --> test.rs:24:13
+//! |
+//! 8 | / mir!(
+//! 9 | | let temp: i32;
+//! 10 | |
+//! 11 | | {
+//! ... |
+//! 19 | | temp = 0;
+//! | | -------- binding initialized here in some conditions
+//! ... |
+//! 24 | | RET = temp;
+//! | | ^^^^^^^^^^ value used here but it is possibly-uninitialized
+//! 25 | | Return()
+//! 26 | | }
+//! 27 | | )
+//! | |_____- binding declared here but left uninitialized
+//!
+//! error: aborting due to previous error
+//!
+//! For more information about this error, try `rustc --explain E0381`.
+//! ```
+//!
+//! # Syntax
+//!
+//! The lists below are an exhaustive description of how various MIR constructs can be created.
+//! Anything missing from the list should be assumed to not be supported, PRs welcome.
+//!
+//! #### Locals
+//!
+//! - The `_0` return local can always be accessed via `RET`.
+//! - Arguments can be accessed via their regular name.
+//! - All other locals need to be declared with `let` somewhere and then can be accessed by name.
+//!
+//! #### Places
+//! - Locals implicit convert to places.
+//! - Field accesses, derefs, and indexing work normally.
+//! - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions,
+//! see their documentation for details.
+//!
+//! #### Operands
+//! - Places implicitly convert to `Copy` operands.
+//! - `Move` operands can be created via [`Move`].
+//! - Const blocks, literals, named constants, and const params all just work.
+//! - [`Static`] and [`StaticMut`] can be used to create `&T` and `*mut T`s to statics. These are
+//! constants in MIR and the only way to access statics.
+//!
+//! #### Statements
+//! - Assign statements work via normal Rust assignment.
+//! - [`Retag`] statements have an associated function.
+//!
+//! #### Rvalues
+//!
+//! - Operands implicitly convert to `Use` rvalues.
+//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
+//! - [`Discriminant`] has an associated function.
+//!
+//! #### Terminators
+//!
+//! Custom MIR does not currently support cleanup blocks or non-trivial unwind paths. As such, there
+//! are no resume and abort terminators, and terminators that might unwind do not have any way to
+//! indicate the unwind block.
+//!
+//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions.
+//! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block`
+//! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the
+//! otherwise branch.
+//! - [`Call`] has an associated function as well. The third argument of this function is a normal
+//! function call expresion, for example `my_other_function(a, 5)`.
//!
#![unstable(
pub struct BasicBlock;
macro_rules! define {
- ($name:literal, $($sig:tt)*) => {
+ ($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
#[rustc_diagnostic_item = $name]
- pub $($sig)* { panic!() }
+ $( #[ $meta ] )*
+ pub fn $($sig)* { panic!() }
}
}
define!("mir_return", fn Return() -> BasicBlock);
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
+define!("mir_unreachable", fn Unreachable() -> BasicBlock);
+define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
+define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: BasicBlock));
+define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_retag_raw", fn RetagRaw<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
define!("mir_static", fn Static<T>(s: T) -> &'static T);
define!("mir_static_mut", fn StaticMut<T>(s: T) -> *mut T);
+define!(
+ "mir_discriminant",
+ /// Gets the discriminant of a place.
+ fn Discriminant<T>(place: T) -> <T as ::core::marker::DiscriminantKind>::Discriminant
+);
+define!("mir_set_discriminant", fn SetDiscriminant<T>(place: T, index: u32));
+define!(
+ "mir_field",
+ /// Access the field with the given index of some place.
+ ///
+ /// This only makes sense to use in conjunction with [`Variant`]. If the type you are looking to
+ /// access the field of does not have variants, you can use normal field projection syntax.
+ ///
+ /// There is no proper way to do a place projection to a variant in Rust, and so these two
+ /// functions are a workaround. You can access a field of a variant via `Field(Variant(place,
+ /// var_idx), field_idx)`, where `var_idx` and `field_idx` are appropriate literals. Some
+ /// caveats:
+ ///
+ /// - The return type of `Variant` is always `()`. Don't worry about that, the correct MIR will
+ /// still be generated.
+ /// - In some situations, the return type of `Field` cannot be inferred. You may need to
+ /// annotate it on the function in these cases.
+ /// - Since `Field` is a function call which is not a place expression, using this on the left
+ /// hand side of an expression is rejected by the compiler. [`place!`] is a macro provided to
+ /// work around that issue. Wrap the left hand side of an assignment in the macro to convince
+ /// the compiler that it's ok.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(custom_mir, core_intrinsics)]
+ ///
+ /// extern crate core;
+ /// use core::intrinsics::mir::*;
+ ///
+ /// #[custom_mir(dialect = "built")]
+ /// fn unwrap_deref(opt: Option<&i32>) -> i32 {
+ /// mir!({
+ /// RET = *Field::<&i32>(Variant(opt, 1), 0);
+ /// Return()
+ /// })
+ /// }
+ ///
+ /// #[custom_mir(dialect = "built")]
+ /// fn set(opt: &mut Option<i32>) {
+ /// mir!({
+ /// place!(Field(Variant(*opt, 1), 0)) = 5;
+ /// Return()
+ /// })
+ /// }
+ /// ```
+ fn Field<F>(place: (), field: u32) -> F
+);
+define!(
+ "mir_variant",
+ /// Adds a variant projection with the given index to the place.
+ ///
+ /// See [`Field`] for documentation.
+ fn Variant<T>(place: T, index: u32) -> ()
+);
+define!(
+ "mir_make_place",
+ #[doc(hidden)]
+ fn __internal_make_place<T>(place: T) -> *mut T
+);
-/// Convenience macro for generating custom MIR.
+/// Macro for generating custom MIR.
///
/// See the module documentation for syntax details. This macro is not magic - it only transforms
/// your MIR into something that is easier to parse in the compiler.
}}
}
+/// Helper macro that allows you to treat a value expression like a place expression.
+///
+/// See the documentation on [`Variant`] for why this is necessary and how to use it.
+pub macro place($e:expr) {
+ (*::core::intrinsics::mir::__internal_make_place($e))
+}
+
/// Helper macro that extracts the `let` declarations out of a bunch of statements.
///
/// This macro is written using the "statement muncher" strategy. Each invocation parses the first
/// [`sum()`]: Iterator::sum
/// [`FromIterator`]: iter::FromIterator
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+ message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
+ label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
+)]
pub trait Sum<A = Self>: Sized {
/// Method which takes an iterator and generates `Self` from the elements by
/// "summing up" the items.
/// [`product()`]: Iterator::product
/// [`FromIterator`]: iter::FromIterator
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+ message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
+ label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
+)]
pub trait Product<A = Self>: Sized {
/// Method which takes an iterator and generates `Self` from the elements by
/// multiplying the items.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
+ #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
fn collect<B: FromIterator<Self::Item>>(self) -> B
where
Self: Sized,
/// the first true result or the first error.
///
/// The return type of this method depends on the return type of the closure.
- /// If you return `Result<bool, E>` from the closure, you'll get a `Result<Option<Self::Item>; E>`.
+ /// If you return `Result<bool, E>` from the closure, you'll get a `Result<Option<Self::Item>, E>`.
/// If you return `Option<bool>` from the closure, you'll get an `Option<Option<Self::Item>>`.
///
/// # Examples
use crate::ascii;
use crate::convert::TryInto;
-use crate::error::Error;
use crate::intrinsics;
use crate::mem;
use crate::ops::{Add, Mul, Sub};
use crate::str::FromStr;
+#[cfg(not(no_fp_fmt_parse))]
+use crate::error::Error;
+
// Used because the `?` operator is not allowed in a const context.
macro_rules! try_opt {
($e:expr) => {
//! should have some resemblance to multiplication (and share expected
//! properties like associativity).
//!
-//! Note that the `&&` and `||` operators short-circuit, i.e., they only
-//! evaluate their second operand if it contributes to the result. Since this
-//! behavior is not enforceable by traits, `&&` and `||` are not supported as
-//! overloadable operators.
+//! Note that the `&&` and `||` operators are currently not supported for
+//! overloading. Due to their short circuiting nature, they require a different
+//! design from traits for other operators like [`BitAnd`]. Designs for them are
+//! under discussion.
//!
//! Many of the operators take their operands by value. In non-generic
//! contexts involving built-in types, this is usually not a problem.
//! }
//! ```
//!
+//! # The question mark operator, `?`
+//!
+//! Similar to the [`Result`] type, when writing code that calls many functions that return the
+//! [`Option`] type, handling `Some`/`None` can be tedious. The question mark
+//! operator, [`?`], hides some of the boilerplate of propagating values
+//! up the call stack.
+//!
+//! It replaces this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//! let a = stack.pop();
+//! let b = stack.pop();
+//!
+//! match (a, b) {
+//! (Some(x), Some(y)) => Some(x + y),
+//! _ => None,
+//! }
+//! }
+//!
+//! ```
+//!
+//! With this:
+//!
+//! ```
+//! # #![allow(dead_code)]
+//! fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> {
+//! Some(stack.pop()? + stack.pop()?)
+//! }
+//! ```
+//!
+//! *It's much nicer!*
+//!
+//! Ending the expression with [`?`] will result in the [`Some`]'s unwrapped value, unless the
+//! result is [`None`], in which case [`None`] is returned early from the enclosing function.
+//!
+//! [`?`] can be used in functions that return [`Option`] because of the
+//! early return of [`None`] that it provides.
+//!
+//! [`?`]: crate::ops::Try
+//! [`Some`]: Some
+//! [`None`]: None
+//!
//! # Representation
//!
//! Rust guarantees to optimize the following types `T` such that
/// Casts to a pointer of another type.
#[stable(feature = "ptr_cast", since = "1.38.0")]
#[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
- #[inline]
+ #[inline(always)]
pub const fn cast<U>(self) -> *const U {
self as _
}
/// refactored.
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+ #[inline(always)]
pub const fn cast_mut(self) -> *mut T {
self as _
}
note = "replaced by the `exposed_addr` method, or update your code \
to follow the strict provenance rules using its APIs"
)]
+ #[inline(always)]
pub fn to_bits(self) -> usize
where
T: Sized,
your code to follow the strict provenance rules using its APIs"
)]
#[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+ #[inline(always)]
pub fn from_bits(bits: usize) -> Self
where
T: Sized,
/// might change in the future (including possibly weakening this so it becomes wholly
/// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
#[must_use]
- #[inline]
+ #[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
pub fn addr(self) -> usize
where
///
/// [`from_exposed_addr`]: from_exposed_addr
#[must_use]
- #[inline]
+ #[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
pub fn expose_addr(self) -> usize
where
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
- #[inline]
+ #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn sub(self, count: usize) -> Self
where
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_sub(self, count: usize) -> Self
where
T: Sized,
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
/// [module documentation][crate::ptr] for details.
#[must_use]
-#[inline]
+#[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
/// This API and its claimed semantics are part of the Strict Provenance experiment, see the
/// [module documentation][crate::ptr] for details.
#[must_use]
-#[inline]
+#[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
/// (which is what the `PartialEq for &T` implementation does).
///
/// When comparing wide pointers, both the address and the metadata are tested for equality.
-/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
+/// However, note that comparing trait object pointers (`*const dyn Trait`) is unreliable: pointers
/// to values of the same underlying type can compare inequal (because vtables are duplicated in
/// multiple codegen units), and pointers to values of *different* underlying type can compare equal
/// (since identical vtables can be deduplicated within a codegen unit).
/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
/// ```
#[stable(feature = "ptr_eq", since = "1.17.0")]
-#[inline]
+#[inline(always)]
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
a == b
}
/// [`cast_mut`]: #method.cast_mut
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+ #[inline(always)]
pub const fn cast_const(self) -> *const T {
self as _
}
note = "replaced by the `exposed_addr` method, or update your code \
to follow the strict provenance rules using its APIs"
)]
+ #[inline(always)]
pub fn to_bits(self) -> usize
where
T: Sized,
update your code to follow the strict provenance rules using its APIs"
)]
#[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+ #[inline(always)]
pub fn from_bits(bits: usize) -> Self
where
T: Sized,
/// might change in the future (including possibly weakening this so it becomes wholly
/// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
#[must_use]
- #[inline]
+ #[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
pub fn addr(self) -> usize
where
///
/// [`from_exposed_addr_mut`]: from_exposed_addr_mut
#[must_use]
- #[inline]
+ #[inline(always)]
#[unstable(feature = "strict_provenance", issue = "95228")]
pub fn expose_addr(self) -> usize
where
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
- #[inline]
+ #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn sub(self, count: usize) -> Self
where
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_sub(self, count: usize) -> Self
where
T: Sized,
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
#[must_use]
- #[inline]
+ #[inline(always)]
pub const fn as_ptr(self) -> *mut T {
self.pointer as *mut T
}
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[must_use]
- #[inline]
+ #[inline(always)]
pub const unsafe fn as_ref<'a>(&self) -> &'a T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
#[must_use]
- #[inline]
+ #[inline(always)]
pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
impl<T: ?Sized> const Clone for NonNull<T> {
- #[inline]
+ #[inline(always)]
fn clone(&self) -> Self {
*self
}
//!
//! *It's much nicer!*
//!
-//! Ending the expression with [`?`] will result in the unwrapped
-//! success ([`Ok`]) value, unless the result is [`Err`], in which case
-//! [`Err`] is returned early from the enclosing function.
+//! Ending the expression with [`?`] will result in the [`Ok`]'s unwrapped value, unless the result
+//! is [`Err`], in which case [`Err`] is returned early from the enclosing function.
//!
-//! [`?`] can only be used in functions that return [`Result`] because of the
+//! [`?`] can be used in functions that return [`Result`] because of the
//! early return of [`Err`] that it provides.
//!
//! [`expect`]: Result::expect
/// [`as_mut_ptr`]: slice::as_mut_ptr
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
#[must_use]
pub const fn as_ptr(&self) -> *const T {
self as *const [T] as *const T
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
#[rustc_allow_const_fn_unstable(const_mut_refs)]
- #[inline]
+ #[inline(always)]
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut T {
self as *mut [T] as *mut T
/// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
/// assert_eq!(remainder, &['m']);
/// ```
+ ///
+ /// If you expect the slice to be an exact multiple, you can combine
+ /// `let`-`else` with an empty slice pattern:
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let slice = ['R', 'u', 's', 't'];
+ /// let (chunks, []) = slice.as_chunks::<2>() else {
+ /// panic!("slice didn't have even length")
+ /// };
+ /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
+ /// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
#[must_use]
/// maintained.
///
/// This method splits the slice into three distinct slices: prefix, correctly aligned middle
- /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
- /// length possible for a given type and input slice, but only your algorithm's performance
- /// should depend on that, not its correctness. It is permissible for all of the input data to
- /// be returned as the prefix or suffix slice.
+ /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+ /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+ /// maximal middle part, that is because code is running in a context where performance does not
+ /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+ /// in a default (debug or release) execution *will* return a maximal middle part.
///
/// This method has no purpose when either input element `T` or output element `U` are
/// zero-sized and will return the original slice without splitting anything.
/// types is maintained.
///
/// This method splits the slice into three distinct slices: prefix, correctly aligned middle
- /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
- /// length possible for a given type and input slice, but only your algorithm's performance
- /// should depend on that, not its correctness. It is permissible for all of the input data to
- /// be returned as the prefix or suffix slice.
+ /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+ /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+ /// maximal middle part, that is because code is running in a context where performance does not
+ /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+ /// in a default (debug or release) execution *will* return a maximal middle part.
///
/// This method has no purpose when either input element `T` or output element `U` are
/// zero-sized and will return the original slice without splitting anything.
/// The slice is assumed to be partitioned according to the given predicate.
/// This means that all elements for which the predicate returns true are at the start of the slice
/// and all elements for which the predicate returns false are at the end.
- /// For example, [7, 15, 3, 5, 4, 12, 6] is a partitioned under the predicate x % 2 != 0
+ /// For example, `[7, 15, 3, 5, 4, 12, 6]` is partitioned under the predicate `x % 2 != 0`
/// (all odd numbers are at the start, all even at the end).
///
/// If this slice is not partitioned, the returned result is unspecified and meaningless,
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
#[must_use]
- #[inline]
+ #[inline(always)]
pub const fn as_ptr(&self) -> *const u8 {
self as *const str as *const u8
}
/// modified in a way that it remains valid UTF-8.
#[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
#[must_use]
- #[inline]
+ #[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self as *mut str as *mut u8
}
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
}
- /// Build a _mutable_ references to an `Exclusive<T>` from
+ /// Build a _mutable_ reference to an `Exclusive<T>` from
/// a _mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
}
- /// Build a _pinned mutable_ references to an `Exclusive<T>` from
+ /// Build a _pinned mutable_ reference to an `Exclusive<T>` from
/// a _pinned mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
use std::ffi::OsStr;
/// Retrieve an environment variable and add it to build dependency info.
- /// Build system executing the compiler will know that the variable was accessed during
+ /// The build system executing the compiler will know that the variable was accessed during
/// compilation, and will be able to rerun the build when the value of that variable changes.
/// Besides the dependency tracking this function should be equivalent to `env::var` from the
/// standard library, except that the argument must be UTF-8.
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.82" }
+compiler_builtins = { version = "0.1.85" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
///
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya
///
+/// # Deprecation
+///
+/// This function is deprecated because the behaviour on Windows is not correct.
+/// The 'HOME' environment variable is not standard on Windows, and may not produce
+/// desired results; for instance, under Cygwin or Mingw it will return `/home/you`
+/// when it should return `C:\Users\you`.
+///
/// # Examples
///
/// ```
/// ```
#[deprecated(
since = "1.29.0",
- note = "This function's behavior is unexpected and probably not what you want. \
+ note = "This function's behavior may be unexpected on Windows. \
Consider using a crate from crates.io instead."
)]
#[must_use]
fs::metadata(hiberfil).unwrap();
assert_eq!(true, hiberfil.exists());
}
+
+/// Test that two different ways of obtaining the FileType give the same result.
+/// Cf. https://github.com/rust-lang/rust/issues/104900
+#[test]
+fn test_eq_direntry_metadata() {
+ let tmpdir = tmpdir();
+ let file_path = tmpdir.join("file");
+ File::create(file_path).unwrap();
+ for e in fs::read_dir(tmpdir.path()).unwrap() {
+ let e = e.unwrap();
+ let p = e.path();
+ let ft1 = e.file_type().unwrap();
+ let ft2 = p.metadata().unwrap().file_type();
+ assert_eq!(ft1, ft2);
+ }
+}
+
+/// Regression test for https://github.com/rust-lang/rust/issues/50619.
+#[test]
+#[cfg(target_os = "linux")]
+fn test_read_dir_infinite_loop() {
+ use crate::io::ErrorKind;
+ use crate::process::Command;
+
+ // Create a zombie child process
+ let Ok(mut child) = Command::new("echo").spawn() else { return };
+
+ // Make sure the process is (un)dead
+ match child.kill() {
+ // InvalidInput means the child already exited
+ Err(e) if e.kind() != ErrorKind::InvalidInput => return,
+ _ => {}
+ }
+
+ // open() on this path will succeed, but readdir() will fail
+ let id = child.id();
+ let path = format!("/proc/{id}/net");
+
+ // Skip the test if we can't open the directory in the first place
+ let Ok(dir) = fs::read_dir(path) else { return };
+
+ // Check for duplicate errors
+ assert!(dir.filter(|e| e.is_err()).take(2).count() < 2);
+}
}
}
+#[stable(feature = "path_buf_deref_mut", since = "CURRENT_RUSTC_VERSION")]
+impl ops::DerefMut for PathBuf {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut Path {
+ Path::from_inner_mut(&mut self.inner)
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<Path> for PathBuf {
#[inline]
unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
}
+ fn from_inner_mut(inner: &mut OsStr) -> &mut Path {
+ // SAFETY: Path is just a wrapper around OsStr,
+ // therefore converting &mut OsStr to &mut Path is safe.
+ unsafe { &mut *(inner as *mut OsStr as *mut Path) }
+ }
+
/// Yields the underlying [`OsStr`] slice.
///
/// # Examples
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
+
+ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.inner.read_to_end(buf)
+ }
}
impl AsInner<AnonPipe> for ChildStdout {
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> {
- self.inner
- .spawn(imp::Stdio::MakePipe, false)
- .map(Child::from_inner)
- .and_then(|p| p.wait_with_output())
+ let (status, stdout, stderr) = self.inner.output()?;
+ Ok(Output { status: ExitStatus(status), stdout, stderr })
}
/// Executes a command as a child process, waiting for it to finish and
}
}
- unsafe { mutex.lock() };
+ mutex.lock();
}
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
// we woke up because of `notify_*`.
let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
- unsafe { mutex.lock() };
+ mutex.lock();
success
}
}
impl<'a> MutexGuard<'a> {
#[inline]
pub(super) fn lock(x: &'a Mutex) -> Self {
- unsafe { x.lock() };
+ x.lock();
Self(x)
}
}
ffi::CStr,
hint, io,
mem::ManuallyDrop,
+ ptr::NonNull,
sync::atomic::{AtomicUsize, Ordering},
sys::thread_local_dtor::run_dtors,
time::Duration,
};
pub struct Thread {
- inner: ManuallyDrop<Box<ThreadInner>>,
+ p_inner: NonNull<ThreadInner>,
/// The ID of the underlying task.
task: abi::ID,
}
+// Safety: There's nothing in `Thread` that ties it to the original creator. It
+// can be dropped by any threads.
+unsafe impl Send for Thread {}
+// Safety: `Thread` provides no methods that take `&self`.
+unsafe impl Sync for Thread {}
+
/// State data shared between a parent thread and child thread. It's dropped on
/// a transition to one of the final states.
struct ThreadInner {
});
unsafe extern "C" fn trampoline(exinf: isize) {
+ let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
// Safety: `ThreadInner` is alive at this point
- let inner = unsafe { &*(exinf as *const ThreadInner) };
+ let inner = unsafe { &*p_inner };
// Safety: Since `trampoline` is called only once for each
// `ThreadInner` and only `trampoline` touches `start`,
// No one will ever join, so we'll ask the collector task to
// delete the task.
- // In this case, `inner`'s ownership has been moved to us,
- // And we are responsible for dropping it. The acquire
+ // In this case, `*p_inner`'s ownership has been moved to
+ // us, and we are responsible for dropping it. The acquire
// ordering is not necessary because the parent thread made
// no memory access needing synchronization since the call
// to `acre_tsk`.
// Safety: See above.
- let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
+ let _ = unsafe { Box::from_raw(p_inner) };
// Safety: There are no pinned references to the stack
unsafe { terminate_and_delete_current_task() };
}
}
- let inner_ptr = (&*inner) as *const ThreadInner;
+ // Safety: `Box::into_raw` returns a non-null pointer
+ let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
let new_task = ItronError::err_if_negative(unsafe {
abi::acre_tsk(&abi::T_CTSK {
// Activate this task immediately
tskatr: abi::TA_ACT,
- exinf: inner_ptr as abi::EXINF,
+ exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
// The entry point
task: Some(trampoline),
// Inherit the calling task's base priority
})
.map_err(|e| e.as_io_error())?;
- Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
+ Ok(Self { p_inner, task: new_task })
}
pub fn yield_now() {
}
}
- pub fn join(mut self) {
- let inner = &*self.inner;
+ pub fn join(self) {
+ // Safety: `ThreadInner` is alive at this point
+ let inner = unsafe { self.p_inner.as_ref() };
// Get the current task ID. Panicking here would cause a resource leak,
// so just abort on failure.
let current_task = task::current_task_id_aborting();
unsafe { terminate_and_delete_task(self.task) };
// In either case, we are responsible for dropping `inner`.
- // Safety: The contents of `self.inner` will not be accessed hereafter
- let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+ // Safety: The contents of `*p_inner` will not be accessed hereafter
+ let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
// Skip the destructor (because it would attempt to detach the thread)
crate::mem::forget(self);
impl Drop for Thread {
fn drop(&mut self) {
+ // Safety: `ThreadInner` is alive at this point
+ let inner = unsafe { self.p_inner.as_ref() };
+
// Detach the thread.
- match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
+ match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
LIFECYCLE_INIT => {
// [INIT → DETACHED]
// When the time comes, the child will figure out that no
// one will ever join it.
- // The ownership of `self.inner` is moved to the child thread.
+ // The ownership of `*p_inner` is moved to the child thread.
// However, the release ordering is not necessary because we
// made no memory access needing synchronization since the call
// to `acre_tsk`.
// delete by entering the `FINISHED` state.
unsafe { terminate_and_delete_task(self.task) };
- // Wwe are responsible for dropping `inner`.
- // Safety: The contents of `self.inner` will not be accessed
- // hereafter
- unsafe { ManuallyDrop::drop(&mut self.inner) };
+ // Wwe are responsible for dropping `*p_inner`.
+ // Safety: The contents of `*p_inner` will not be accessed hereafter
+ let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
}
_ => unsafe { hint::unreachable_unchecked() },
}
pub mod stdio;
pub mod thread;
pub mod thread_local_key;
+pub mod thread_parker;
pub mod time;
mod condvar;
/// execution. The signal is sent once all TLS destructors have finished at
/// which point no new thread locals should be created.
pub mod wait_notify {
- use super::super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
+ use super::super::thread_parker::Parker;
+ use crate::pin::Pin;
use crate::sync::Arc;
- pub struct Notifier(Arc<SpinMutex<WaitVariable<bool>>>);
+ pub struct Notifier(Arc<Parker>);
impl Notifier {
/// Notify the waiter. The waiter is either notified right away (if
/// currently blocked in `Waiter::wait()`) or later when it calls the
/// `Waiter::wait()` method.
pub fn notify(self) {
- let mut guard = self.0.lock();
- *guard.lock_var_mut() = true;
- let _ = WaitQueue::notify_one(guard);
+ Pin::new(&*self.0).unpark()
}
}
- pub struct Waiter(Arc<SpinMutex<WaitVariable<bool>>>);
+ pub struct Waiter(Arc<Parker>);
impl Waiter {
/// Wait for a notification. If `Notifier::notify()` has already been
/// called, this will return immediately, otherwise the current thread
/// is blocked until notified.
pub fn wait(self) {
- let guard = self.0.lock();
- if *guard.lock_var() {
- return;
- }
- WaitQueue::wait(guard, || {});
+ // This is not actually `unsafe`, but it uses the `Parker` API,
+ // which needs `unsafe` on some platforms.
+ unsafe { Pin::new(&*self.0).park() }
}
}
pub fn new() -> (Notifier, Waiter) {
- let inner = Arc::new(SpinMutex::new(WaitVariable::new(false)));
+ let inner = Arc::new(Parker::new_internal());
(Notifier(inner.clone()), Waiter(inner))
}
}
--- /dev/null
+//! Thread parking based on SGX events.
+
+use super::abi::{thread, usercalls};
+use crate::io::ErrorKind;
+use crate::pin::Pin;
+use crate::ptr::{self, NonNull};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::time::Duration;
+use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE};
+
+// The TCS structure must be page-aligned (this is checked by EENTER), so these cannot
+// be valid pointers
+const EMPTY: *mut u8 = ptr::invalid_mut(1);
+const NOTIFIED: *mut u8 = ptr::invalid_mut(2);
+
+pub struct Parker {
+ /// The park state. One of EMPTY, NOTIFIED or a TCS address.
+ /// A state change to NOTIFIED must be done with release ordering
+ /// and be observed with acquire ordering so that operations after
+ /// `thread::park` returns will not occur before the unpark message
+ /// was sent.
+ state: AtomicPtr<u8>,
+}
+
+impl Parker {
+ /// Construct the thread parker. The UNIX parker implementation
+ /// requires this to happen in-place.
+ pub unsafe fn new(parker: *mut Parker) {
+ unsafe { parker.write(Parker::new_internal()) }
+ }
+
+ pub(super) fn new_internal() -> Parker {
+ Parker { state: AtomicPtr::new(EMPTY) }
+ }
+
+ // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+ pub unsafe fn park(self: Pin<&Self>) {
+ if self.state.load(Acquire) != NOTIFIED {
+ let mut prev = EMPTY;
+ loop {
+ // Guard against changing TCS addresses by always setting the state to
+ // the current value.
+ let tcs = thread::current().as_ptr();
+ if self.state.compare_exchange(prev, tcs, Relaxed, Acquire).is_ok() {
+ let event = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap();
+ assert!(event & EV_UNPARK == EV_UNPARK);
+ prev = tcs;
+ } else {
+ // The state was definitely changed by another thread at this point.
+ // The only time this occurs is when the state is changed to NOTIFIED.
+ // We observed this change with acquire ordering, so we can simply
+ // change the state to EMPTY with a relaxed store.
+ break;
+ }
+ }
+ }
+
+ // At this point, the token was definately read with acquire ordering,
+ // so this can be a relaxed store.
+ self.state.store(EMPTY, Relaxed);
+ }
+
+ // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+ pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+ let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64;
+ let tcs = thread::current().as_ptr();
+
+ if self.state.load(Acquire) != NOTIFIED {
+ if self.state.compare_exchange(EMPTY, tcs, Relaxed, Acquire).is_ok() {
+ match usercalls::wait(EV_UNPARK, timeout) {
+ Ok(event) => assert!(event & EV_UNPARK == EV_UNPARK),
+ Err(e) => {
+ assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock))
+ }
+ }
+
+ // Swap to provide acquire ordering even if the timeout occurred
+ // before the token was set. This situation can result in spurious
+ // wakeups on the next call to `park_timeout`, but it is better to let
+ // those be handled by the user than do some perhaps unnecessary, but
+ // always expensive guarding.
+ self.state.swap(EMPTY, Acquire);
+ return;
+ }
+ }
+
+ // The token was already read with `acquire` ordering, this can be a store.
+ self.state.store(EMPTY, Relaxed);
+ }
+
+ // This implementation doesn't require `Pin`, but other implementations do.
+ pub fn unpark(self: Pin<&Self>) {
+ let state = self.state.swap(NOTIFIED, Release);
+
+ if !matches!(state, EMPTY | NOTIFIED) {
+ // There is a thread waiting, wake it up.
+ let tcs = NonNull::new(state).unwrap();
+ // This will fail if the thread has already terminated or its TCS is destroyed
+ // by the time the signal is sent, but that is fine. If another thread receives
+ // the same TCS, it will receive this notification as a spurious wakeup, but
+ // all users of `wait` should and (internally) do guard against those where
+ // necessary.
+ let _ = usercalls::send(EV_UNPARK, Some(tcs));
+ }
+ }
+}
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}
+
+pub fn is_terminal<T>(_: &T) -> bool {
+ false
+}
use super::unsupported;
-use crate::convert::TryFrom;
use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::os::{
pub struct ReadDir {
inner: Arc<InnerReadDir>,
- #[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "solaris",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "redox",
- )))]
end_of_stream: bool,
}
+impl ReadDir {
+ fn new(inner: InnerReadDir) -> Self {
+ Self { inner: Arc::new(inner), end_of_stream: false }
+ }
+}
+
struct Dir(*mut libc::DIR);
unsafe impl Send for Dir {}
modified: Option<SystemTime>,
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, Eq, Debug)]
pub struct FileType {
mode: mode_t,
}
+impl PartialEq for FileType {
+ fn eq(&self, other: &Self) -> bool {
+ self.masked() == other.masked()
+ }
+}
+
+impl core::hash::Hash for FileType {
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ self.masked().hash(state);
+ }
+}
+
#[derive(Debug)]
pub struct DirBuilder {
mode: mode_t,
}
pub fn is(&self, mode: mode_t) -> bool {
- self.mode & libc::S_IFMT == mode
+ self.masked() == mode
+ }
+
+ fn masked(&self) -> mode_t {
+ self.mode & libc::S_IFMT
}
}
target_os = "illumos"
))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ if self.end_of_stream {
+ return None;
+ }
+
unsafe {
loop {
// As of POSIX.1-2017, readdir() is not required to be thread safe; only
super::os::set_errno(0);
let entry_ptr = readdir64(self.inner.dirp.0);
if entry_ptr.is_null() {
- // null can mean either the end is reached or an error occurred.
- // So we had to clear errno beforehand to check for an error now.
+ // We either encountered an error, or reached the end. Either way,
+ // the next call to next() should return None.
+ self.end_of_stream = true;
+
+ // To distinguish between errors and end-of-directory, we had to clear
+ // errno beforehand to check for an error now.
return match super::os::errno() {
0 => None,
e => Some(Err(Error::from_raw_os_error(e))),
} else {
let root = path.to_path_buf();
let inner = InnerReadDir { dirp: Dir(ptr), root };
- Ok(ReadDir {
- inner: Arc::new(inner),
- #[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "solaris",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "redox",
- )))]
- end_of_stream: false,
- })
+ Ok(ReadDir::new(inner))
}
}
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use crate::os::unix::prelude::{OwnedFd, RawFd};
use crate::path::{Path, PathBuf};
- use crate::sync::Arc;
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::{cvt, cvt_r};
- #[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
+ #[cfg(not(any(
+ target_os = "linux",
+ all(target_os = "macos", not(target_arch = "aarch64"))
+ )))]
use libc::{fdopendir, openat, unlinkat};
+ #[cfg(target_os = "linux")]
+ use libc::{fdopendir, openat64 as openat, unlinkat};
#[cfg(all(target_os = "macos", not(target_arch = "aarch64")))]
use macos_weak::{fdopendir, openat, unlinkat};
// a valid root is not needed because we do not call any functions involving the full path
// of the DirEntrys.
let dummy_root = PathBuf::new();
- Ok((
- ReadDir {
- inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
- #[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "solaris",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "redox",
- )))]
- end_of_stream: false,
- },
- new_parent_fd,
- ))
+ let inner = InnerReadDir { dirp, root: dummy_root };
+ Ok((ReadDir::new(inner), new_parent_fd))
}
#[cfg(any(
use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use crate::sys::cvt;
use crate::sys::weak::syscall;
+#[cfg(not(target_os = "linux"))]
+use libc::sendfile as sendfile64;
+#[cfg(target_os = "linux")]
+use libc::sendfile64;
use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
#[cfg(test)]
let result = match mode {
SpliceMode::Sendfile => {
- cvt(unsafe { libc::sendfile(writer, reader, ptr::null_mut(), chunk_size) })
+ cvt(unsafe { sendfile64(writer, reader, ptr::null_mut(), chunk_size) })
}
SpliceMode::Splice => cvt(unsafe {
splice(reader, ptr::null_mut(), writer, ptr::null_mut(), chunk_size, 0)
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
use crate::sys::locks::{pthread_mutex, Mutex};
+use crate::sys::time::TIMESPEC_MAX;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;
mutex: AtomicPtr<libc::pthread_mutex_t>,
}
-const TIMESPEC_MAX: libc::timespec =
- libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
-fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
- if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
-}
-
#[inline]
fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
c.inner.0.get()
target_os = "horizon"
)))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- use crate::mem;
+ use crate::sys::time::Timespec;
let mutex = pthread_mutex::raw(mutex);
self.verify(mutex);
- let mut now: libc::timespec = mem::zeroed();
- let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
- assert_eq!(r, 0);
-
- // Nanosecond calculations can't overflow because both values are below 1e9.
- let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
-
- let sec = saturating_cast_to_time_t(dur.as_secs())
- .checked_add((nsec / 1_000_000_000) as libc::time_t)
- .and_then(|s| s.checked_add(now.tv_sec));
- let nsec = nsec % 1_000_000_000;
-
- let timeout =
- sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX);
-
+ let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+ .checked_add_duration(&dur)
+ .and_then(|t| t.to_timespec())
+ .unwrap_or(TIMESPEC_MAX);
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
assert!(r == libc::ETIMEDOUT || r == 0);
r == 0
target_os = "espidf",
target_os = "horizon"
))]
- pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
+ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+ use crate::sys::time::SystemTime;
use crate::time::Instant;
let mutex = pthread_mutex::raw(mutex);
self.verify(mutex);
- // 1000 years
- let max_dur = Duration::from_secs(1000 * 365 * 86400);
-
- if dur > max_dur {
- // OSX implementation of `pthread_cond_timedwait` is buggy
- // with super long durations. When duration is greater than
- // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
- // in macOS Sierra return error 316.
- //
- // This program demonstrates the issue:
- // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
- //
- // To work around this issue, and possible bugs of other OSes, timeout
- // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
- // because of spurious wakeups.
-
- dur = max_dur;
- }
-
- // First, figure out what time it currently is, in both system and
- // stable time. pthread_cond_timedwait uses system time, but we want to
- // report timeout based on stable time.
- let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
- let stable_now = Instant::now();
- let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
- assert_eq!(r, 0, "unexpected error: {:?}", crate::io::Error::last_os_error());
-
- let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;
- let extra = (nsec / 1_000_000_000) as libc::time_t;
- let nsec = nsec % 1_000_000_000;
- let seconds = saturating_cast_to_time_t(dur.as_secs());
-
- let timeout = sys_now
- .tv_sec
- .checked_add(extra)
- .and_then(|s| s.checked_add(seconds))
- .map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec })
+ // OSX implementation of `pthread_cond_timedwait` is buggy
+ // with super long durations. When duration is greater than
+ // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
+ // in macOS Sierra returns error 316.
+ //
+ // This program demonstrates the issue:
+ // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
+ //
+ // To work around this issue, and possible bugs of other OSes, timeout
+ // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
+ // because of spurious wakeups.
+ let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
+
+ // pthread_cond_timedwait uses system time, but we want to report timeout
+ // based on stable time.
+ let now = Instant::now();
+
+ let timeout = SystemTime::now()
+ .t
+ .checked_add_duration(&dur)
+ .and_then(|t| t.to_timespec())
.unwrap_or(TIMESPEC_MAX);
- // And wait!
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
debug_assert!(r == libc::ETIMEDOUT || r == 0);
// ETIMEDOUT is not a totally reliable method of determining timeout due
// to clock shifts, so do the check ourselves
- stable_now.elapsed() < dur
+ now.elapsed() < dur
}
}
)))]
'poll: {
use crate::sys::os::errno;
+ #[cfg(not(target_os = "linux"))]
+ use libc::open as open64;
+ #[cfg(target_os = "linux")]
+ use libc::open64;
let pfds: &mut [_] = &mut [
libc::pollfd { fd: 0, events: 0, revents: 0 },
libc::pollfd { fd: 1, events: 0, revents: 0 },
if pfd.revents & libc::POLLNVAL == 0 {
continue;
}
- if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+ if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
)))]
{
use crate::sys::os::errno;
+ #[cfg(not(target_os = "linux"))]
+ use libc::open as open64;
+ #[cfg(target_os = "linux")]
+ use libc::open64;
for fd in 0..3 {
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
- if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
+ if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
self.0.is_read_vectored()
}
+ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.0.read_to_end(buf)
+ }
+
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
Ok((Process { handle: Handle::new(process_handle) }, ours))
}
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+ crate::sys_common::process::wait_with_output(proc, pipes)
+ }
+
pub fn exec(&mut self, default: Stdio) -> io::Error {
if self.saw_nul() {
return io::const_io_error!(
//
// Note that as soon as we're done with the fork there's no need to hold
// a lock any more because the parent won't do anything and the child is
- // in its own process. Thus the parent drops the lock guard while the child
- // forgets it to avoid unlocking it on a new thread, which would be invalid.
+ // in its own process. Thus the parent drops the lock guard immediately.
+ // The child calls `mem::forget` to leak the lock, which is crucial because
+ // releasing a lock is not async-signal-safe.
let env_lock = sys::os::env_read_lock();
let (pid, pidfd) = unsafe { self.do_fork()? };
if pid == 0 {
crate::panic::always_abort();
- mem::forget(env_lock);
+ mem::forget(env_lock); // avoid non-async-signal-safe unlocking
drop(input);
let Err(err) = unsafe { self.do_exec(theirs, envp.as_ref()) };
let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
}
}
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+ crate::sys_common::process::wait_with_output(proc, pipes)
+ }
+
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
#[cfg(not(target_os = "linux"))]
unsupported()
}
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ unsupported()
+ }
+
pub fn exec(&mut self, _default: Stdio) -> io::Error {
unsupported_err()
}
}
}
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+ crate::sys_common::process::wait_with_output(proc, pipes)
+ }
+
pub fn exec(&mut self, default: Stdio) -> io::Error {
let ret = Command::spawn(self, default, false);
match ret {
use crate::thread;
use libc::MAP_FAILED;
- use libc::{mmap, munmap};
+ #[cfg(not(target_os = "linux"))]
+ use libc::{mmap as mmap64, munmap};
+ #[cfg(target_os = "linux")]
+ use libc::{mmap64, munmap};
use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
#[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))]
let flags = MAP_PRIVATE | MAP_ANON;
let stackp =
- mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
+ mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
if stackp == MAP_FAILED {
panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
}
unsafe {
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
- let name = truncate_cstr(name, TASK_COMM_LEN);
+ let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
// We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
debug_assert_eq!(res, 0);
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
pub fn set_name(name: &CStr) {
unsafe {
- let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
+ let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
let res = libc::pthread_setname_np(name.as_ptr());
// We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
debug_assert_eq!(res, 0);
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
-fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
- use crate::{borrow::Cow, ffi::CString};
-
- if cstr.to_bytes_with_nul().len() > max_with_nul {
- let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
- // SAFETY: the non-nul bytes came straight from a CStr.
- // (CString will add the terminating nul.)
- Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
- } else {
- Cow::Borrowed(cstr)
+fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
+ let mut result = [0; MAX_WITH_NUL];
+ for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
+ *dst = *src as libc::c_char;
}
+ result
}
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
))]
#[cfg_attr(test, allow(dead_code))]
pub mod guard {
- use libc::{mmap, mprotect};
+ #[cfg(not(target_os = "linux"))]
+ use libc::{mmap as mmap64, mprotect};
+ #[cfg(target_os = "linux")]
+ use libc::{mmap64, mprotect};
use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
use crate::io;
// read/write permissions and only then mprotect() it to
// no permissions at all. See issue #50313.
let stackptr = get_stack_start_aligned()?;
- let result = mmap(
+ let result = mmap64(
stackptr,
page_size,
PROT_READ | PROT_WRITE,
use crate::ptr::addr_of_mut;
use crate::sync::atomic::AtomicUsize;
use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::time::TIMESPEC_MAX;
use crate::time::Duration;
const EMPTY: usize = 0;
debug_assert_eq!(r, 0);
}
-const TIMESPEC_MAX: libc::timespec =
- libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
unsafe fn wait_timeout(
cond: *mut libc::pthread_cond_t,
lock: *mut libc::pthread_mutex_t,
const NSEC_PER_SEC: u64 = 1_000_000_000;
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
+#[allow(dead_code)] // Used for pthread condvar timeouts
+pub const TIMESPEC_MAX: libc::timespec =
+ libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
use crate::sync::atomic::{self, AtomicPtr, Ordering};
// We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))]
+pub(crate) macro weak {
+ (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+ extern "C" {
+ #[linkage = "extern_weak"]
+ static $name: Option<unsafe extern "C" fn($($t),*) -> $ret>;
+ }
+ #[allow(unused_unsafe)]
+ ExternWeak::new(unsafe { $name })
+ };
+ )
+}
+
+#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub(crate) use self::dlsym as weak;
+#[cfg(not(bootstrap))]
+pub(crate) struct ExternWeak<F: Copy> {
+ weak_ptr: Option<F>,
+}
+
+#[cfg(not(bootstrap))]
+impl<F: Copy> ExternWeak<F> {
+ #[inline]
+ pub(crate) fn new(weak_ptr: Option<F>) -> Self {
+ ExternWeak { weak_ptr }
+ }
+
+ #[inline]
+ pub(crate) fn get(&self) -> Option<F> {
+ self.weak_ptr
+ }
+}
+
+#[cfg(bootstrap)]
pub(crate) struct ExternWeak<F> {
weak_ptr: *const libc::c_void,
_marker: PhantomData<F>,
}
+#[cfg(bootstrap)]
impl<F> ExternWeak<F> {
#[inline]
pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self {
}
}
+#[cfg(bootstrap)]
impl<F> ExternWeak<F> {
#[inline]
pub(crate) fn get(&self) -> Option<F> {
self.0
}
+ pub fn read_to_end(&self, _buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.0
+ }
+
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
self.0
}
) -> io::Result<(Process, StdioPipes)> {
unsupported()
}
+
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ unsupported()
+ }
}
impl From<AnonPipe> for Stdio {
use crate::os::windows::prelude::*;
use crate::ffi::OsStr;
-use crate::io::{self, IoSlice, IoSliceMut};
+use crate::io::{self, IoSlice, IoSliceMut, Read};
use crate::mem;
use crate::path::Path;
use crate::ptr;
self.inner.is_read_vectored()
}
+ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ self.handle().read_to_end(buf)
+ }
+
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
unsafe {
let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
) -> io::Result<(Process, StdioPipes)> {
let maybe_env = self.env.capture_if_changed();
- let mut si = zeroed_startupinfo();
- si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
- si.dwFlags = c::STARTF_USESTDHANDLES;
-
let child_paths = if let Some(env) = maybe_env.as_ref() {
env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str())
} else {
let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?;
let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?;
let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
- si.hStdInput = stdin.as_raw_handle();
- si.hStdOutput = stdout.as_raw_handle();
- si.hStdError = stderr.as_raw_handle();
+
+ let mut si = zeroed_startupinfo();
+ si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
+
+ // If at least one of stdin, stdout or stderr are set (i.e. are non null)
+ // then set the `hStd` fields in `STARTUPINFO`.
+ // Otherwise skip this and allow the OS to apply its default behaviour.
+ // This provides more consistent behaviour between Win7 and Win8+.
+ let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null();
+ if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) {
+ si.dwFlags |= c::STARTF_USESTDHANDLES;
+ si.hStdInput = stdin.as_raw_handle();
+ si.hStdOutput = stdout.as_raw_handle();
+ si.hStdError = stderr.as_raw_handle();
+ }
unsafe {
cvt(c::CreateProcessW(
))
}
}
+
+ pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+ crate::sys_common::process::wait_with_output(proc, pipes)
+ }
}
impl fmt::Debug for Command {
impl Stdio {
fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> {
match *self {
- // If no stdio handle is available, then inherit means that it
- // should still be unavailable so propagate the
- // INVALID_HANDLE_VALUE.
Stdio::Inherit => match stdio::get_handle(stdio_id) {
Ok(io) => unsafe {
let io = Handle::from_raw_handle(io);
io.into_raw_handle();
ret
},
- Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) },
+ // If no stdio handle is available, then propagate the null value.
+ Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) },
},
Stdio::MakePipe => {
wShowWindow: 0,
cbReserved2: 0,
lpReserved2: ptr::null_mut(),
- hStdInput: c::INVALID_HANDLE_VALUE,
- hStdOutput: c::INVALID_HANDLE_VALUE,
- hStdError: c::INVALID_HANDLE_VALUE,
+ hStdInput: ptr::null_mut(),
+ hStdOutput: ptr::null_mut(),
+ hStdError: ptr::null_mut(),
}
}
use crate::collections::BTreeMap;
use crate::env;
use crate::ffi::{OsStr, OsString};
-use crate::sys::process::EnvKey;
+use crate::io;
+use crate::sys::pipe::read2;
+use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
// Stores a set of changes to an environment
#[derive(Clone, Debug)]
self.iter.is_empty()
}
}
+
+pub fn wait_with_output(
+ mut process: Process,
+ mut pipes: StdioPipes,
+) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+ drop(pipes.stdin.take());
+
+ let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
+ match (pipes.stdout.take(), pipes.stderr.take()) {
+ (None, None) => {}
+ (Some(out), None) => {
+ let res = out.read_to_end(&mut stdout);
+ res.unwrap();
+ }
+ (None, Some(err)) => {
+ let res = err.read_to_end(&mut stderr);
+ res.unwrap();
+ }
+ (Some(out), Some(err)) => {
+ let res = read2(out, &mut stdout, err, &mut stderr);
+ res.unwrap();
+ }
+ }
+
+ let status = process.wait()?;
+ Ok((status, stdout, stderr))
+}
pub use wait_flag::Parker;
} else if #[cfg(any(windows, target_family = "unix"))] {
pub use crate::sys::thread_parker::Parker;
+ } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
+ pub use crate::sys::thread_parker::Parker;
} else {
mod generic;
pub use generic::Parker;
use crate::install;
use crate::native;
use crate::run;
+use crate::setup;
use crate::test;
use crate::tool::{self, SourceType};
use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
// single alias, which does not correspond to any on-disk path
pub fn alias(mut self, alias: &str) -> Self {
+ // exceptional case for `Kind::Setup` because its `library`
+ // and `compiler` options would otherwise naively match with
+ // `compiler` and `library` folders respectively.
assert!(
- !self.builder.src.join(alias).exists(),
+ self.kind == Kind::Setup || !self.builder.src.join(alias).exists(),
"use `builder.path()` for real paths: {}",
alias
);
install::RustDemangler,
install::Clippy,
install::Miri,
+ install::LlvmTools,
install::Analysis,
install::Src,
install::Rustc
run::CollectLicenseMetadata,
run::GenerateCopyright,
),
+ Kind::Setup => describe!(setup::Profile),
// These commands either don't use paths, or they're special-cased in Build::build()
- Kind::Clean | Kind::Format | Kind::Setup => vec![],
+ Kind::Clean | Kind::Format => vec![],
}
}
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
Subcommand::Format { .. } => (Kind::Format, &[][..]),
- Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
+ Subcommand::Setup { profile: ref path } => (
+ Kind::Setup,
+ path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)),
+ ),
+ Subcommand::Clean { .. } => {
panic!()
}
};
impl<T: Internable + Deref> Deref for Interned<T> {
type Target = T::Target;
- fn deref(&self) -> &'static Self::Target {
+ fn deref(&self) -> &Self::Target {
let l = T::intern_cache().lock().unwrap();
- unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) }
+ unsafe { mem::transmute::<&Self::Target, &Self::Target>(l.get(*self)) }
}
}
impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> {
- fn as_ref(&self) -> &'static U {
+ fn as_ref(&self) -> &U {
let l = T::intern_cache().lock().unwrap();
- unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) }
+ unsafe { mem::transmute::<&U, &U>(l.get(*self).as_ref()) }
}
}
//! This module implements parsing `config.toml` configuration files to tweak
//! how the build runs.
+#[cfg(test)]
+mod tests;
+
use std::cell::{Cell, RefCell};
use std::cmp;
use std::collections::{HashMap, HashSet};
dist_stage: Option<u32> = "dist-stage",
bench_stage: Option<u32> = "bench-stage",
patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix",
+ // NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
metrics: Option<bool> = "metrics",
}
}
}
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum StringOrBool {
String(String),
}
pub fn parse(args: &[String]) -> Config {
+ #[cfg(test)]
+ let get_toml = |_: &_| TomlConfig::default();
+ #[cfg(not(test))]
+ let get_toml = |file: &Path| {
+ let contents =
+ t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
+ // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
+ // TomlConfig and sub types to be monomorphized 5x by toml.
+ match toml::from_str(&contents)
+ .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+ {
+ Ok(table) => table,
+ Err(err) => {
+ eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+ crate::detail_exit(2);
+ }
+ }
+ };
+
+ Self::parse_inner(args, get_toml)
+ }
+
+ fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
let flags = Flags::parse(&args);
let mut config = Config::default_opts();
config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
- #[cfg(test)]
- let get_toml = |_| TomlConfig::default();
- #[cfg(not(test))]
- let get_toml = |file: &Path| {
- let contents =
- t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
- // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
- // TomlConfig and sub types to be monomorphized 5x by toml.
- match toml::from_str(&contents)
- .and_then(|table: toml::Value| TomlConfig::deserialize(table))
- {
- Ok(table) => table,
- Err(err) => {
- eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
- crate::detail_exit(2);
- }
- }
- };
-
// Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
let toml_path = flags
.config
let mut optimize = None;
let mut ignore_git = None;
+ if let Some(rust) = toml.rust {
+ debug = rust.debug;
+ debug_assertions = rust.debug_assertions;
+ debug_assertions_std = rust.debug_assertions_std;
+ overflow_checks = rust.overflow_checks;
+ overflow_checks_std = rust.overflow_checks_std;
+ debug_logging = rust.debug_logging;
+ debuginfo_level = rust.debuginfo_level;
+ debuginfo_level_rustc = rust.debuginfo_level_rustc;
+ debuginfo_level_std = rust.debuginfo_level_std;
+ debuginfo_level_tools = rust.debuginfo_level_tools;
+ debuginfo_level_tests = rust.debuginfo_level_tests;
+ config.rust_split_debuginfo = rust
+ .split_debuginfo
+ .as_deref()
+ .map(SplitDebuginfo::from_str)
+ .map(|v| v.expect("invalid value for rust.split_debuginfo"))
+ .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
+ optimize = rust.optimize;
+ ignore_git = rust.ignore_git;
+ config.rust_new_symbol_mangling = rust.new_symbol_mangling;
+ set(&mut config.rust_optimize_tests, rust.optimize_tests);
+ set(&mut config.codegen_tests, rust.codegen_tests);
+ set(&mut config.rust_rpath, rust.rpath);
+ set(&mut config.jemalloc, rust.jemalloc);
+ set(&mut config.test_compare_mode, rust.test_compare_mode);
+ set(&mut config.backtrace, rust.backtrace);
+ set(&mut config.channel, rust.channel);
+ config.description = rust.description;
+ set(&mut config.rust_dist_src, rust.dist_src);
+ set(&mut config.verbose_tests, rust.verbose_tests);
+ // in the case "false" is set explicitly, do not overwrite the command line args
+ if let Some(true) = rust.incremental {
+ config.incremental = true;
+ }
+ set(&mut config.use_lld, rust.use_lld);
+ set(&mut config.lld_enabled, rust.lld);
+ set(&mut config.llvm_tools_enabled, rust.llvm_tools);
+ config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
+ config.rustc_default_linker = rust.default_linker;
+ config.musl_root = rust.musl_root.map(PathBuf::from);
+ config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
+ set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
+ set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
+ set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
+ config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
+ set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
+ set(&mut config.control_flow_guard, rust.control_flow_guard);
+ config.llvm_libunwind_default = rust
+ .llvm_libunwind
+ .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
+
+ if let Some(ref backends) = rust.codegen_backends {
+ config.rust_codegen_backends =
+ backends.iter().map(|s| INTERNER.intern_str(s)).collect();
+ }
+
+ config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
+ config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
+ config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
+ config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
+ config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
+
+ config.rust_lto = rust
+ .lto
+ .as_deref()
+ .map(|value| RustcLto::from_str(value).unwrap())
+ .unwrap_or_default();
+ } else {
+ config.rust_profile_use = flags.rust_profile_use;
+ config.rust_profile_generate = flags.rust_profile_generate;
+ }
+
if let Some(llvm) = toml.llvm {
match llvm.ccache {
Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
config.llvm_polly = llvm.polly.unwrap_or(false);
config.llvm_clang = llvm.clang.unwrap_or(false);
config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
+
+ let asserts = llvm_assertions.unwrap_or(false);
config.llvm_from_ci = match llvm.download_ci_llvm {
Some(StringOrBool::String(s)) => {
assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
- crate::native::is_ci_llvm_available(&config, llvm_assertions.unwrap_or(false))
+ crate::native::is_ci_llvm_available(&config, asserts)
}
Some(StringOrBool::Bool(b)) => b,
- None => false,
+ None => {
+ config.channel == "dev" && crate::native::is_ci_llvm_available(&config, asserts)
+ }
};
if config.llvm_from_ci {
// the link step) with each stage.
config.llvm_link_shared.set(Some(true));
}
- }
-
- if let Some(rust) = toml.rust {
- debug = rust.debug;
- debug_assertions = rust.debug_assertions;
- debug_assertions_std = rust.debug_assertions_std;
- overflow_checks = rust.overflow_checks;
- overflow_checks_std = rust.overflow_checks_std;
- debug_logging = rust.debug_logging;
- debuginfo_level = rust.debuginfo_level;
- debuginfo_level_rustc = rust.debuginfo_level_rustc;
- debuginfo_level_std = rust.debuginfo_level_std;
- debuginfo_level_tools = rust.debuginfo_level_tools;
- debuginfo_level_tests = rust.debuginfo_level_tests;
- config.rust_split_debuginfo = rust
- .split_debuginfo
- .as_deref()
- .map(SplitDebuginfo::from_str)
- .map(|v| v.expect("invalid value for rust.split_debuginfo"))
- .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
- optimize = rust.optimize;
- ignore_git = rust.ignore_git;
- config.rust_new_symbol_mangling = rust.new_symbol_mangling;
- set(&mut config.rust_optimize_tests, rust.optimize_tests);
- set(&mut config.codegen_tests, rust.codegen_tests);
- set(&mut config.rust_rpath, rust.rpath);
- set(&mut config.jemalloc, rust.jemalloc);
- set(&mut config.test_compare_mode, rust.test_compare_mode);
- set(&mut config.backtrace, rust.backtrace);
- set(&mut config.channel, rust.channel);
- config.description = rust.description;
- set(&mut config.rust_dist_src, rust.dist_src);
- set(&mut config.verbose_tests, rust.verbose_tests);
- // in the case "false" is set explicitly, do not overwrite the command line args
- if let Some(true) = rust.incremental {
- config.incremental = true;
- }
- set(&mut config.use_lld, rust.use_lld);
- set(&mut config.lld_enabled, rust.lld);
- set(&mut config.llvm_tools_enabled, rust.llvm_tools);
- config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
- config.rustc_default_linker = rust.default_linker;
- config.musl_root = rust.musl_root.map(PathBuf::from);
- config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
- set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
- set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
- set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
- config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
- set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
- set(&mut config.control_flow_guard, rust.control_flow_guard);
- config.llvm_libunwind_default = rust
- .llvm_libunwind
- .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
-
- if let Some(ref backends) = rust.codegen_backends {
- config.rust_codegen_backends =
- backends.iter().map(|s| INTERNER.intern_str(s)).collect();
- }
-
- config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
- config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
- config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
- config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
- config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
-
- config.rust_lto = rust
- .lto
- .as_deref()
- .map(|value| RustcLto::from_str(value).unwrap())
- .unwrap_or_default();
} else {
- config.rust_profile_use = flags.rust_profile_use;
- config.rust_profile_generate = flags.rust_profile_generate;
+ config.llvm_from_ci =
+ config.channel == "dev" && crate::native::is_ci_llvm_available(&config, false);
}
if let Some(t) = toml.target {
--- /dev/null
+use super::{Config, TomlConfig};
+use std::path::Path;
+
+fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
+ |&_| toml::from_str(config).unwrap()
+}
+
+fn parse(config: &str) -> Config {
+ Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+}
+
+#[test]
+fn download_ci_llvm() {
+ let parse_llvm = |s| parse(s).llvm_from_ci;
+ let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\"");
+
+ assert!(parse_llvm("llvm.download-ci-llvm = true"));
+ assert!(!parse_llvm("llvm.download-ci-llvm = false"));
+ assert_eq!(parse_llvm(""), if_available);
+ assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available);
+ assert!(!parse_llvm("rust.channel = \"stable\""));
+}
+
+// FIXME: add test for detecting `src` and `out`
doc-stage = 2
# When compiling from source, you usually want all tools.
extended = true
+
+[llvm]
+# Most users installing from source want to build all parts of the project from source, not just rustc itself.
+download-ci-llvm = false
let xform = |p: &Path| {
let mut contents = t!(fs::read_to_string(p));
- for tool in &["rust-demangler"] {
+ for tool in &["rust-demangler", "miri"] {
if !built_tools.contains(tool) {
contents = filter(&contents, tool);
}
prepare("rust-std");
prepare("rust-analysis");
prepare("clippy");
- prepare("miri");
prepare("rust-analyzer");
- for tool in &["rust-docs", "rust-demangler"] {
+ for tool in &["rust-docs", "rust-demangler", "miri"] {
if built_tools.contains(tool) {
prepare(tool);
}
prepare("rust-docs");
prepare("rust-std");
prepare("clippy");
- prepare("miri");
prepare("rust-analyzer");
- for tool in &["rust-demangler"] {
+ for tool in &["rust-demangler", "miri"] {
if built_tools.contains(tool) {
prepare(tool);
}
.arg(etc.join("msi/remove-duplicates.xsl")),
);
}
- builder.run(
- Command::new(&heat)
- .current_dir(&exe)
- .arg("dir")
- .arg("miri")
- .args(&heat_flags)
- .arg("-cg")
- .arg("MiriGroup")
- .arg("-dr")
- .arg("Miri")
- .arg("-var")
- .arg("var.MiriDir")
- .arg("-out")
- .arg(exe.join("MiriGroup.wxs"))
- .arg("-t")
- .arg(etc.join("msi/remove-duplicates.xsl")),
- );
+ if built_tools.contains("miri") {
+ builder.run(
+ Command::new(&heat)
+ .current_dir(&exe)
+ .arg("dir")
+ .arg("miri")
+ .args(&heat_flags)
+ .arg("-cg")
+ .arg("MiriGroup")
+ .arg("-dr")
+ .arg("Miri")
+ .arg("-var")
+ .arg("var.MiriDir")
+ .arg("-out")
+ .arg(exe.join("MiriGroup.wxs"))
+ .arg("-t")
+ .arg(etc.join("msi/remove-duplicates.xsl")),
+ );
+ }
builder.run(
Command::new(&heat)
.current_dir(&exe)
.arg("-dStdDir=rust-std")
.arg("-dAnalysisDir=rust-analysis")
.arg("-dClippyDir=clippy")
- .arg("-dMiriDir=miri")
.arg("-arch")
.arg(&arch)
.arg("-out")
if built_tools.contains("rust-analyzer") {
cmd.arg("-dRustAnalyzerDir=rust-analyzer");
}
+ if built_tools.contains("miri") {
+ cmd.arg("-dMiriDir=miri");
+ }
if target.ends_with("windows-gnu") {
cmd.arg("-dGccDir=rust-mingw");
}
candle("CargoGroup.wxs".as_ref());
candle("StdGroup.wxs".as_ref());
candle("ClippyGroup.wxs".as_ref());
- candle("MiriGroup.wxs".as_ref());
+ if built_tools.contains("miri") {
+ candle("MiriGroup.wxs".as_ref());
+ }
if built_tools.contains("rust-demangler") {
candle("RustDemanglerGroup.wxs".as_ref());
}
.arg("StdGroup.wixobj")
.arg("AnalysisGroup.wixobj")
.arg("ClippyGroup.wixobj")
- .arg("MiriGroup.wixobj")
.current_dir(&exe);
+ if built_tools.contains("miri") {
+ cmd.arg("MiriGroup.wixobj");
+ }
if built_tools.contains("rust-analyzer") {
cmd.arg("RustAnalyzerGroup.wixobj");
}
args: Vec<String>,
},
Setup {
- profile: Option<Profile>,
+ profile: Option<PathBuf>,
},
}
// fn usage()
let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
- let config = Config::parse(&["build".to_string()]);
+ let config = Config::parse(&["setup".to_string()]);
let build = Build::new(config);
let paths = Builder::get_help(&build, subcommand);
}
Kind::Setup => {
let profile = if paths.len() > 1 {
- println!("\nat most one profile can be passed to setup\n");
+ eprintln!("\nerror: At most one profile can be passed to setup\n");
usage(1, &opts, verbose, &subcommand_help)
} else if let Some(path) = paths.pop() {
let profile_string = t!(path.into_os_string().into_string().map_err(
use std::process::{Command, Stdio};
use std::sync::mpsc::SyncSender;
-fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut() {
+fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool {
let mut cmd = Command::new(&rustfmt);
// avoid the submodule config paths from coming into play,
// we only allow a single global config for the workspace for now
let cmd_debug = format!("{:?}", cmd);
let mut cmd = cmd.spawn().expect("running rustfmt");
// poor man's async: return a closure that'll wait for rustfmt's completion
- move || {
+ move |block: bool| -> bool {
+ if !block {
+ match cmd.try_wait() {
+ Ok(Some(_)) => {}
+ _ => return false,
+ }
+ }
let status = cmd.wait().unwrap();
if !status.success() {
eprintln!(
);
crate::detail_exit(1);
}
+ true
}
}
let child = rustfmt(&src, &rustfmt_path, paths.as_slice(), check);
children.push_back(child);
+ // poll completion before waiting
+ for i in (0..children.len()).rev() {
+ if children[i](false) {
+ children.swap_remove_back(i);
+ break;
+ }
+ }
+
if children.len() >= max_processes {
// await oldest child
- children.pop_front().unwrap()();
+ children.pop_front().unwrap()(true);
}
}
// await remaining children
for mut child in children {
- child();
+ child(true);
}
});
.expect("missing miri");
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
};
+ LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
+ let tarball = builder
+ .ensure(dist::LlvmTools { target: self.target })
+ .expect("missing llvm-tools");
+ install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+ };
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
compiler: self.compiler,
use std::env;
use std::fs::{self, File};
use std::io;
+use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use crate::builder::Kind;
use crate::config::{LlvmLibunwind, TargetSelection};
-use crate::util::{exe, libdir, mtime, output, run, run_suppressed, try_run_suppressed, CiEnv};
+use crate::util::{
+ exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, CiEnv,
+};
mod bolt;
mod builder;
metadata::build(&mut build);
}
+ // Make a symbolic link so we can use a consistent directory in the documentation.
+ let build_triple = build.out.join(&build.build.triple);
+ let host = build.out.join("host");
+ if let Err(e) = symlink_dir(&build.config, &build_triple, &host) {
+ if e.kind() != ErrorKind::AlreadyExists {
+ panic!(
+ "symlink_dir({} => {}) failed with {}",
+ host.display(),
+ build_triple.display(),
+ e
+ );
+ }
+ }
+
build
}
return clean::clean(self, all);
}
- if let Subcommand::Setup { profile } = &self.config.cmd {
- return setup::setup(&self.config, *profile);
- }
-
// Download rustfmt early so that it can be used in rust-analyzer configs.
let _ = &builder::Builder::new(&self).initial_rustfmt();
/// If the test is running and code is an error code, it will cause a panic.
fn detail_exit(code: i32) -> ! {
// if in test and code is an error code, panic with status code provided
- if cfg!(test) && code != 0 {
+ if cfg!(test) {
panic!("status code: {}", code);
} else {
- //otherwise,exit with provided status code
+ // otherwise,exit with provided status code
std::process::exit(code);
}
}
+use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::Config;
use crate::{t, VERSION};
use std::env::consts::EXE_SUFFIX;
use std::str::FromStr;
use std::{fmt, fs, io};
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Profile {
Compiler,
Codegen,
}
out
}
+
+ pub fn as_str(&self) -> &'static str {
+ match self {
+ Profile::Compiler => "compiler",
+ Profile::Codegen => "codegen",
+ Profile::Library => "library",
+ Profile::Tools => "tools",
+ Profile::User => "user",
+ }
+ }
}
impl FromStr for Profile {
impl fmt::Display for Profile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Profile::Compiler => write!(f, "compiler"),
- Profile::Codegen => write!(f, "codegen"),
- Profile::Library => write!(f, "library"),
- Profile::User => write!(f, "user"),
- Profile::Tools => write!(f, "tools"),
+ f.write_str(self.as_str())
+ }
+}
+
+impl Step for Profile {
+ type Output = ();
+ const DEFAULT: bool = true;
+
+ fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
+ for choice in Profile::all() {
+ run = run.alias(choice.as_str());
}
+ run
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ // for Profile, `run.paths` will have 1 and only 1 element
+ // this is because we only accept at most 1 path from user input.
+ // If user calls `x.py setup` without arguments, the interactive TUI
+ // will guide user to provide one.
+ let profile = if run.paths.len() > 1 {
+ // HACK: `builder` runs this step with all paths if no path was passed.
+ t!(interactive_path())
+ } else {
+ run.paths
+ .first()
+ .unwrap()
+ .assert_single_path()
+ .path
+ .as_path()
+ .as_os_str()
+ .to_str()
+ .unwrap()
+ .parse()
+ .unwrap()
+ };
+
+ run.builder.ensure(profile);
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ setup(&builder.build.config, self)
}
}
-pub fn setup(config: &Config, profile: Option<Profile>) {
- let profile = profile.unwrap_or_else(|| t!(interactive_path()));
+pub fn setup(config: &Config, profile: Profile) {
let stage_path =
["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
if !rustup_installed() && profile != Profile::User {
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
- } else if stage_dir_exists(&stage_path[..]) {
+ } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
attempt_toolchain_link(&stage_path[..]);
}
Profile::User => &["dist", "build"],
};
- t!(install_git_hook_maybe(&config));
+ if !config.dry_run() {
+ t!(install_git_hook_maybe(&config));
+ }
println!();
changelog-seen = {}\n",
profile, VERSION
);
+
t!(fs::write(path, settings));
let include_path = profile.include_path(&config.src);
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- let builder = run.builder;
-
// Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
run.path("src/tools/rust-analyzer")
.path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
- .default_condition(
- builder.config.extended
- && builder.config.tools.as_ref().map_or(true, |tools| {
- tools.iter().any(|tool| {
- tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
- })
- }),
- )
}
fn make_run(run: RunConfig<'_>) {
ENV HOSTS=powerpc64le-unknown-linux-gnu
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
+ python3 ../x.py test --stage 0 src/tools/tidy && \
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
python3 ../x.py build --stage 0 src/tools/build-manifest && \
python3 ../x.py test --stage 0 src/tools/compiletest && \
- python3 ../x.py test --stage 2 src/tools/tidy && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \
# Build both public and internal documentation.
- RUSTDOCFLAGS="--document-private-items" python3 ../x.py doc --stage 0 library/test && \
+ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \
/scripts/validate-toolstate.sh && \
/scripts/validate-error-codes.sh && \
reuse lint && \
zlib1g-dev \
xz-utils \
nodejs \
-
+ \
# Install powershell so we can test x.ps1 on Linux
apt-transport-https software-properties-common && \
curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
sudo \
xz-utils \
tidy \
-
+ \
# Install dependencies for chromium browser
gconf-service \
libasound2 \
"-f",
self.ssh_keyfile_path(),
"-C",
- "Generated by test_toolchain.py",
+ "Generated by fuchsia-test-runner.py",
],
stdout=self.subprocess_output(),
stderr=self.subprocess_output(),
--target=x86_64-pc-windows-msvc
--enable-full-tools
--enable-profiler
+ --set rust.lto=thin
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-windows-xl
if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
+ HAS_METRICS=1
fi
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-sccache"
# sccache server at the start of the build, but no need to worry if this fails.
SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true
-if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
- $SRC/configure --set rust.parallel-compiler
- CARGO_INCREMENTAL=0 $PYTHON ../x.py check
- rm -f config.toml
- rm -rf build
-fi
-
$SRC/configure $RUST_CONFIGURE_ARGS
retry make prepare
do_make "$RUST_CHECK_TARGET"
fi
+if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
+ rm -f config.toml
+ $SRC/configure --set rust.parallel-compiler
+
+ # Save the build metrics before we wipe the directory
+ if [ $HAS_METRICS = 1 ]; then
+ mv build/metrics.json .
+ fi
+ rm -rf build
+ if [ $HAS_METRICS = 1 ]; then
+ mkdir build
+ mv metrics.json build
+ fi
+
+ CARGO_INCREMENTAL=0 $PYTHON ../x.py check
+fi
+
sccache --show-stats || true
pathname syntax. For example `--remap-path-prefix foo=bar` will match
`foo/lib.rs` but not `./foo/lib.rs`.
+When multiple remappings are given and several of them match, the **last**
+matching one is applied.
+
<a id="option-json"></a>
## `--json`: configure json messages printed by the compiler
used when wrapping semantics are intended, and that explicit checking and
wrapping methods always be used when using Unsafe Rust.
-<small id="fn:2">2\. See <https://doc.rust-lang.org/std/primitive.u32.html>
+<small id="fn:2">2\. See [the `u32` docs](../std/primitive.u32.html)
for more information on the checked, overflowing, saturating, and wrapping
methods (using u32 as an example). <a href="#fnref:2"
class="reversefootnote" role="doc-backlink">↩</a></small>
<https://hacks.mozilla.org/2019/02/fearless-security-thread-safety/>.
3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming
- Language. <https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html>.
+ Language. [https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html](../book/ch04-01-what-is-ownership.html).
4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust
Programming Language.
- <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html>.
+ [https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html](../book/ch04-02-references-and-borrowing.html).
5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming
- Language. <https://doc.rust-lang.org/book/ch04-03-slices.html>.
+ Language. [https://doc.rust-lang.org/book/ch04-03-slices.html](../book/ch04-03-slices.html).
6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language.
- <https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html>.
+ [https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html](../book/ch19-01-unsafe-rust.html).
7. S. Davidoff. “How Rust’s standard library was vulnerable for years and
nobody noticed.” Medium.
for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
41. “ControlFlowIntegrity.” The Rust Unstable Book.
- <https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity>.
+ [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
This is fixed if you explicitly set the target, for example
`cargo build --target x86_64-pc-windows-msvc`
Without an explicit --target the flags will be passed to all compiler invocations (including build
-scripts and proc macros), see [cargo docs on rustflags](https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags)
+scripts and proc macros), see [cargo docs on rustflags](../cargo/reference/config.html#buildrustflags)
If you have dependencies using the `cc` crate, you will need to set these
environment variables:
[Android NDK]: https://developer.android.com/ndk/downloads
A list of all supported targets can be found
-[here](https://doc.rust-lang.org/rustc/platform-support.html)
+[here](../platform-support.html)
The `cargo-3ds` tool mentioned in [Building Rust programs](#building-rust-programs)
supports the use of `3dslink` with `cargo 3ds run`. The default Rust test runner
is not supported, but
-[custom test frameworks](https://doc.rust-lang.org/beta/unstable-book/language-features/custom-test-frameworks.html)
+[custom test frameworks](../../unstable-book/language-features/custom-test-frameworks.html)
can be used with `cargo 3ds test` to run unit tests on a device.
The Rust test suite for `library/std` is not yet supported.
After installing our Fuchsia targets, we can now compile a Rust binary that targets
Fuchsia.
-To create our Rust project, we can issue a standard `cargo` command as follows:
+To create our Rust project, we can use [`cargo`][cargo] as follows:
**From base working directory**
```sh
[Fuchsia]: https://fuchsia.dev/
[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
[rustup]: https://rustup.rs/
-[cargo]: https://doc.rust-lang.org/cargo/
+[cargo]: ../../cargo/index.html
[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
[reference for the file format]: https://fuchsia.dev/reference/cml
rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json
```
-To use a custom target, see the (unstable) [`build-std` feature](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) of `cargo`.
+To use a custom target, see the (unstable) [`build-std` feature](../../cargo/reference/unstable.html#build-std) of `cargo`.
# `branch-protection`
This option lets you enable branch authentication instructions on AArch64.
-This option is ignored for non-AArch64 architectures.
+This option is only accepted when targeting AArch64 architectures.
It takes some combination of the following values, separated by a `,`.
- `pac-ret` - Enable pointer authentication for non-leaf functions.
Rust's standard library does not ship with BTI or pointer authentication enabled by default.
In Cargo projects the standard library can be recompiled with pointer authentication using the nightly
-[build-std](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature.
+[build-std](../../cargo/reference/unstable.html#build-std) feature.
To enable CFG in the standard library, use the [cargo `-Z build-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
For example:
```cmd
forward-edge control flow protection.
* [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to
AddressSanitizer, but based on partial hardware assistance.
+* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel Control
+ Flow Integrity (KCFI) provides forward-edge control flow protection for
+ operating systems kernels.
* [LeakSanitizer](#leaksanitizer) a run-time memory leak detector.
* [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
* [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on
parameter types than the return type expected and arguments intended/passed in
the call/branch site, the execution is also terminated (see Fig. 9).
-[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: https://doc.rust-lang.org/book/title-page.html
+[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
+[rust-book]: ../../book/title-page.html
# HWAddressSanitizer
SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
```
+# KernelControlFlowIntegrity
+
+The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler
+initially provides forward-edge control flow protection for operating systems
+kernels for Rust-compiled code only by aggregating function pointers in groups
+identified by their return and parameter types. (See [LLVM commit cff5bef "KCFI
+sanitizer"](https://github.com/llvm/llvm-project/commit/cff5bef948c91e4919de8a5fb9765e0edc13f3de).)
+
+Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
+binaries" (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space) will be provided in later work by defining and using
+compatible type identifiers (see Type metadata in the design document in the
+tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+LLVM KCFI can be enabled with `-Zsanitizer=kcfi`.
+
+LLVM KCFI is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-linux-android`
+* `x86_64-unknown-linux-gnu`
+
+See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
+details.
+
# LeakSanitizer
LeakSanitizer is run-time memory leak detector.
instrumented standard library, for example using [cargo `-Zbuild-std`
functionality][build-std].
-[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+[build-std]: ../../cargo/reference/unstable.html#build-std
# Build scripts and procedural macros
[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
[clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
+[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
to inlining of `f`, `Foo::foo` can then be called from a foreign crate. This can
lead to miscompilations.
-[Clto]: https://doc.rust-lang.org/rustc/codegen-options/index.html#lto
+[Clto]: ../../rustc/codegen-options/index.html#lto
has explicitly opted out via a negative impl. (Negative impls are separately controlled
by the `negative_impls` feature.)
-[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
-[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+[`Send`]: ../../std/marker/trait.Send.html
+[`Sync`]: ../../std/marker/trait.Sync.html
```rust,ignore (partial-example)
impl !Trait for Type {}
required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have
exactly one (non self) argument, a tuple representing the argument list.
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
```rust
#![feature(unboxed_closures)]
just forwards to [`Default::default()`], but may remove repetition of the word
"default" from the call site.
-[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default
+[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default
Here is an example:
The `fn_traits` feature allows for implementation of the [`Fn*`] traits
for creating custom closure-like types.
-[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+[`Fn*`]: ../../std/ops/trait.Fn.html
```rust
#![feature(unboxed_closures)]
discard_positive_impl: bool,
) -> Option<Item> {
let tcx = self.cx.tcx;
- let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]);
+ let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty]));
if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
return None;
unsafety: hir::Unsafety::Normal,
generics: new_generics,
trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())),
- for_: clean_middle_ty(ty, self.cx, None),
+ for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None),
items: Vec::new(),
polarity,
kind: ImplKind::Auto,
// the post-inference `trait_ref`, as it's more accurate.
trait_: Some(clean_trait_ref_with_bindings(
cx,
- trait_ref.0,
+ ty::Binder::dummy(trait_ref.0),
ThinVec::new(),
)),
- for_: clean_middle_ty(ty.0, cx, None),
+ for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None),
items: cx
.tcx
.associated_items(impl_def_id)
.collect::<Vec<_>>(),
polarity: ty::ImplPolarity::Positive,
kind: ImplKind::Blanket(Box::new(clean_middle_ty(
- trait_ref.0.self_ty(),
+ ty::Binder::dummy(trait_ref.0.self_ty()),
cx,
None,
))),
use super::*;
-use rustc_ast::attr;
-use rustc_ast::Path;
+use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::DUMMY_SP;
fn word_cfg(s: &str) -> Cfg {
}
}
+fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
+ let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
+ MetaItem {
+ path: Path::from_ident(Ident::from_str(name)),
+ kind: MetaItemKind::NameValue(lit),
+ span: DUMMY_SP,
+ }
+}
+
macro_rules! dummy_meta_item_list {
($name:ident, [$($list:ident),* $(,)?]) => {
MetaItem {
let mi = dummy_meta_item_word("all");
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
- let mi =
- attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP);
+ let done = Symbol::intern("done");
+ let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
let mi = dummy_meta_item_list!(all, [a, b]);
#[test]
fn test_parse_err() {
create_default_session_globals_then(|| {
- let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP);
+ let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
assert!(Cfg::parse(&mi).is_err());
let mi = dummy_meta_item_list!(not, [a, b]);
fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
let predicates = cx.tcx.explicit_predicates_of(did);
- let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did));
+ let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
Box::new(clean::Typedef {
type_,
// * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
// * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
- use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*;
+ use rustc_middle::ty::fast_reject::SimplifiedType::*;
let type_ =
if tcx.is_trait(did) { TraitSimplifiedType(did) } else { AdtSimplifiedType(did) };
for &did in tcx.incoherent_impls(type_) {
let for_ = match &impl_item {
Some(impl_) => clean_ty(impl_.self_ty, cx),
- None => clean_middle_ty(tcx.type_of(did), cx, Some(did)),
+ None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
};
// Only inline impl if the implementing type is
),
};
let polarity = tcx.impl_polarity(did);
- let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new()));
+ let trait_ = associated_trait
+ .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new()));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
clean::Constant {
- type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
kind: clean::ConstantKind::Extern { def_id },
}
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
- type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
mutability: if mutable { Mutability::Mut } else { Mutability::Not },
expr: None,
}
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
- let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
+ let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
let generic_args = clean_generic_args(generic_args, cx);
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
- trait_ref: ty::TraitRef<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>,
) -> Path {
- let kind = cx.tcx.def_kind(trait_ref.def_id).into();
+ let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
- span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind);
+ span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
}
- inline::record_extern_fqn(cx, trait_ref.def_id, kind);
- let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs);
+ inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
+ let path =
+ external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs));
- debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
+ debug!(?trait_ref);
path
}
})
.collect();
- let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings);
+ let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
GenericBound::TraitBound(
PolyTrait { trait_, generic_params: late_bound_regions },
hir::TraitBoundModifier::None,
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
- type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)),
+ type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
}
pub(crate) fn clean_middle_const<'tcx>(
- constant: ty::Const<'tcx>,
+ constant: ty::Binder<'tcx, ty::Const<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> Constant {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
- type_: clean_middle_ty(constant.ty(), cx, None),
- kind: ConstantKind::TyConst { expr: constant.to_string().into() },
+ type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None),
+ kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
}
}
let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
Some(WherePredicate::BoundPredicate {
- ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None),
+ ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None),
bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())],
bound_params: Vec::new(),
})
let ty::OutlivesPredicate(ty, lt) = pred;
Some(WherePredicate::BoundPredicate {
- ty: clean_middle_ty(ty, cx, None),
+ ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None),
bounds: vec![GenericBound::Outlives(
clean_middle_region(lt).expect("failed to clean lifetimes"),
)],
})
}
-fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
- match term.unpack() {
- ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)),
- ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)),
+fn clean_middle_term<'tcx>(
+ term: ty::Binder<'tcx, ty::Term<'tcx>>,
+ cx: &mut DocContext<'tcx>,
+) -> Term {
+ match term.skip_binder().unpack() {
+ ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)),
+ ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
}
}
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
hir::Term::Const(c) => {
let def_id = cx.tcx.hir().local_def_id(c.hir_id);
- Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx))
+ Term::Constant(clean_middle_const(
+ ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
+ cx,
+ ))
}
}
}
})
.collect();
- let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
-
WherePredicate::EqPredicate {
- lhs: Box::new(clean_projection(projection_ty, cx, None)),
- rhs: Box::new(clean_middle_term(term, cx)),
+ lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
+ rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
bound_params: late_bound_regions,
}
}
fn clean_projection<'tcx>(
- ty: ty::ProjectionTy<'tcx>,
+ ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+ if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
let bounds = cx
.tcx
- .explicit_item_bounds(ty.item_def_id)
+ .explicit_item_bounds(ty.skip_binder().def_id)
.iter()
- .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+ .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs))
.collect::<Vec<_>>();
return clean_middle_opaque_bounds(cx, bounds);
}
- let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
- let self_type = clean_middle_ty(ty.self_ty(), cx, None);
+ let trait_ =
+ clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new());
+ let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
} else {
}
fn projection_to_path_segment<'tcx>(
- ty: ty::ProjectionTy<'tcx>,
+ ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> PathSegment {
- let item = cx.tcx.associated_item(ty.item_def_id);
- let generics = cx.tcx.generics_of(ty.item_def_id);
+ let item = cx.tcx.associated_item(ty.skip_binder().def_id);
+ let generics = cx.tcx.generics_of(ty.skip_binder().def_id);
PathSegment {
name: item.name,
args: GenericArgs::AngleBracketed {
- args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(),
+ args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false)
+ .into(),
bindings: Default::default(),
},
}
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
- Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id)))
+ Some(clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ cx,
+ Some(def.def_id),
+ ))
} else {
None
};
def.name,
GenericParamDefKind::Const {
did: def.def_id,
- ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))),
+ ty: Box::new(clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ cx,
+ Some(def.def_id),
+ )),
default: match has_default {
true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())),
false => None,
.collect::<ThinVec<GenericParamDef>>();
// param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
- let mut impl_trait_proj =
- FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
+ let mut impl_trait_proj = FxHashMap::<
+ u32,
+ Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>,
+ >::default();
let where_predicates = preds
.predicates
let proj = projection.map(|p| {
(
- clean_projection(p.skip_binder().projection_ty, cx, None),
- p.skip_binder().term,
+ clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+ p.map_bound(|p| p.term),
)
});
if let Some(((_, trait_did, name), rhs)) = proj
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name,
- rhs.ty().unwrap(),
+ rhs.map_bound(|rhs| rhs.ty().unwrap()),
p.get_bound_params()
.into_iter()
.flatten()
// We assume all empty tuples are default return type. This theoretically can discard `-> ()`,
// but shouldn't change any code meaning.
- let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) {
+ let output = match clean_middle_ty(sig.output(), cx, None) {
Type::Tuple(inner) if inner.is_empty() => DefaultReturn,
ty => Return(ty),
};
c_variadic: sig.skip_binder().c_variadic,
inputs: Arguments {
values: sig
- .skip_binder()
.inputs()
.iter()
.map(|t| Argument {
- type_: clean_middle_ty(*t, cx, None),
+ type_: clean_middle_ty(t.map_bound(|t| *t), cx, None),
name: names
.next()
.map(|i| i.name)
hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None);
+ let item_type =
+ clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None);
AssocTypeItem(
Box::new(Typedef {
type_: clean_ty(default, cx),
hir::ImplItemKind::Type(hir_ty) => {
let type_ = clean_ty(hir_ty, cx);
let generics = clean_generics(impl_.generics, cx);
- let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+ let item_type =
+ clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
AssocTypeItem(
Box::new(Typedef { type_, generics, item_type: Some(item_type) }),
Vec::new(),
let tcx = cx.tcx;
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
- let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
+ let ty = clean_middle_ty(
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+ cx,
+ Some(assoc_item.def_id),
+ );
let provided = match assoc_item.container {
ty::ImplContainer => true,
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- tcx.type_of(assoc_item.def_id),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
cx,
Some(assoc_item.def_id),
),
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- tcx.type_of(assoc_item.def_id),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
cx,
Some(assoc_item.def_id),
),
hir::QPath::Resolved(Some(qself), p) => {
// Try to normalize `<X as Y>::T` to a type
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
- if let Some(normalized_value) = normalize(cx, ty) {
- return clean_middle_ty(normalized_value, cx, None);
+ // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
+ if !ty.has_escaping_bound_vars() {
+ if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
+ return clean_middle_ty(normalized_value, cx, None);
+ }
}
let trait_segments = &p.segments[..p.segments.len() - 1];
hir::QPath::TypeRelative(qself, segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
let res = match ty.kind() {
- ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+ ty::Alias(ty::Projection, proj) => {
+ Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
+ }
// Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
ty::Error(_) => return Type::Infer,
// Otherwise, this is an inherent associated type.
- _ => return clean_middle_ty(ty, cx, None),
+ _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None),
};
let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
register_res(cx, trait_.res);
}
/// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(
+ cx: &mut DocContext<'tcx>,
+ ty: ty::Binder<'tcx, Ty<'tcx>>,
+) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
// HACK: low-churn fix for #79459 while we wait for a trait normalization fix
if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
return None;
}
}
+#[instrument(level = "trace", skip(cx), ret)]
pub(crate) fn clean_middle_ty<'tcx>(
- ty: Ty<'tcx>,
+ bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- trace!("cleaning type: {:?}", ty);
- let ty = normalize(cx, ty).unwrap_or(ty);
- match *ty.kind() {
+ let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
+ match *bound_ty.skip_binder().kind() {
ty::Never => Primitive(PrimitiveType::Never),
ty::Bool => Primitive(PrimitiveType::Bool),
ty::Char => Primitive(PrimitiveType::Char),
ty::Uint(uint_ty) => Primitive(uint_ty.into()),
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
- ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
+ ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))),
ty::Array(ty, mut n) => {
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
let n = print_const(cx, n);
- Array(Box::new(clean_middle_ty(ty, cx, None)), n.into())
+ Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into())
+ }
+ ty::RawPtr(mt) => {
+ RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None)))
}
- ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
ty::Ref(r, ty, mutbl) => BorrowedRef {
lifetime: clean_middle_region(r),
mutability: mutbl,
- type_: Box::new(clean_middle_ty(ty, cx, None)),
+ type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)),
},
ty::FnDef(..) | ty::FnPtr(_) => {
- let sig = ty.fn_sig(cx.tcx);
+ // FIXME: should we merge the outer and inner binders somehow?
+ let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
BareFunction(Box::new(BareFunctionDecl {
unsafety: sig.unsafety(),
AdtKind::Enum => ItemType::Enum,
};
inline::record_extern_fqn(cx, did, kind);
- let path = external_path(cx, did, false, ThinVec::new(), substs);
+ let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs));
Type::Path { path }
}
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
- let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty());
+ let path = external_path(
+ cx,
+ did,
+ false,
+ ThinVec::new(),
+ ty::Binder::dummy(InternalSubsts::empty()),
+ );
Type::Path { path }
}
ty::Dynamic(obj, ref reg, _) => {
let did = obj
.principal_def_id()
.or_else(|| dids.next())
- .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
+ .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
let substs = match obj.principal() {
- Some(principal) => principal.skip_binder().substs,
+ Some(principal) => principal.map_bound(|p| p.substs),
// marker traits have no substs.
- _ => cx.tcx.intern_substs(&[]),
+ _ => ty::Binder::dummy(InternalSubsts::empty()),
};
inline::record_extern_fqn(cx, did, ItemType::Trait);
let lifetime = clean_middle_region(*reg);
let mut bounds = dids
.map(|did| {
- let empty = cx.tcx.intern_substs(&[]);
+ let empty = ty::Binder::dummy(InternalSubsts::empty());
let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
PolyTrait { trait_: path, generic_params: Vec::new() }
.projection_bounds()
.map(|pb| TypeBinding {
assoc: projection_to_path_segment(
- pb.skip_binder()
- // HACK(compiler-errors): Doesn't actually matter what self
- // type we put here, because we're only using the GAT's substs.
- .with_self_ty(cx.tcx, cx.tcx.types.self_param)
- .projection_ty,
+ pb.map_bound(|pb| {
+ pb
+ // HACK(compiler-errors): Doesn't actually matter what self
+ // type we put here, because we're only using the GAT's substs.
+ .with_self_ty(cx.tcx, cx.tcx.types.self_param)
+ .projection_ty
+ }),
cx,
),
kind: TypeBindingKind::Equality {
- term: clean_middle_term(pb.skip_binder().term, cx),
+ term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
},
})
.collect();
DynTrait(bounds, lifetime)
}
- ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()),
+ ty::Tuple(t) => {
+ Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect())
+ }
- ty::Projection(ref data) => clean_projection(*data, cx, def_id),
+ ty::Alias(ty::Projection, ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id),
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
}
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the bounds associated with the def_id.
let bounds = cx
{
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
Some(TypeBinding {
- assoc: projection_to_path_segment(proj.projection_ty, cx),
+ assoc: projection_to_path_segment(
+ bound.kind().rebind(proj.projection_ty),
+ cx,
+ ),
kind: TypeBindingKind::Equality {
- term: clean_middle_term(proj.term, cx),
+ term: clean_middle_term(bound.kind().rebind(proj.term), cx),
},
})
} else {
clean_field_with_def_id(
field.did,
field.name,
- clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)),
+ clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
cx,
)
}
}),
ItemKind::TyAlias(hir_ty, generics) => {
let rustdoc_ty = clean_ty(hir_ty, cx);
- let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
+ let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None);
TypedefItem(Box::new(Typedef {
type_: rustdoc_ty,
generics: clean_generics(generics, cx),
let for_ = clean_ty(impl_.self_ty, cx);
let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
- DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))),
+ DefKind::TyAlias => {
+ Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
+ }
_ => None,
});
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
use arrayvec::ArrayVec;
use thin_vec::ThinVec;
-use rustc_ast::attr;
use rustc_ast::util::comments::beautify_doc_string;
use rustc_ast::{self as ast, AttrStyle};
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, FileName, Loc};
use rustc_target::abi::VariantIdx;
// #[doc(cfg(target_feature = "feat"))] attributes as well
for attr in self.lists(sym::target_feature) {
if attr.has_name(sym::enable) {
- if let Some(feat) = attr.value_str() {
- let meta = attr::mk_name_value_item_str(
- Ident::with_dummy_span(sym::target_feature),
- feat,
- DUMMY_SP,
- );
+ if attr.value_str().is_some() {
+ // Clone `enable = "feat"`, change to `target_feature = "feat"`.
+ // Unwrap is safe because `value_str` succeeded above.
+ let mut meta = attr.meta_item().unwrap().clone();
+ meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
+
if let Ok(feat_cfg) = Cfg::parse(&meta) {
cfg &= feat_cfg;
}
impl GenericBound {
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
- let empty = cx.tcx.intern_substs(&[]);
+ let empty = ty::Binder::dummy(ty::InternalSubsts::empty());
let path = external_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
}
pub(crate) fn simplified_types() -> &'static SimplifiedTypes {
- use ty::fast_reject::SimplifiedTypeGen::*;
+ use ty::fast_reject::SimplifiedType::*;
use ty::{FloatTy, IntTy, UintTy};
use PrimitiveType::*;
static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
pub(crate) fn substs_to_args<'tcx>(
cx: &mut DocContext<'tcx>,
- substs: &[ty::subst::GenericArg<'tcx>],
+ substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>,
mut skip_first: bool,
) -> Vec<GenericArg> {
let mut ret_val =
- Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
- ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
+ Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
+ 1
+ } else {
+ 0
+ }));
+ ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() {
GenericArgKind::Lifetime(lt) => {
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
}
skip_first = false;
None
}
- GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))),
- GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))),
+ GenericArgKind::Type(ty) => {
+ Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None)))
+ }
+ GenericArgKind::Const(ct) => {
+ Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx))))
+ }
}));
ret_val
}
did: DefId,
has_self: bool,
bindings: ThinVec<TypeBinding>,
- substs: SubstsRef<'tcx>,
+ substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> GenericArgs {
- let args = substs_to_args(cx, substs, has_self);
+ let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self);
if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+ let ty = substs
+ .iter()
+ .nth(if has_self { 1 } else { 0 })
+ .unwrap()
+ .map_bound(|arg| arg.expect_ty());
let inputs =
// The trait's first substitution is the one after self, if there is one.
- match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() {
- ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::<Vec<_>>().into(),
+ match ty.skip_binder().kind() {
+ ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().into(),
_ => return GenericArgs::AngleBracketed { args: args.into(), bindings },
};
let output = bindings.into_iter().next().and_then(|binding| match binding.kind {
did: DefId,
has_self: bool,
bindings: ThinVec<TypeBinding>,
- substs: SubstsRef<'tcx>,
+ substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> Path {
let def_kind = cx.tcx.def_kind(did);
let name = cx.tcx.item_name(did);
pub(crate) input: PathBuf,
/// The name of the crate being documented.
pub(crate) crate_name: Option<String>,
+ /// Whether or not this is a bin crate
+ pub(crate) bin_crate: bool,
/// Whether or not this is a proc-macro crate
pub(crate) proc_macro_crate: bool,
/// How to format errors and warnings.
f.debug_struct("Options")
.field("input", &self.input)
.field("crate_name", &self.crate_name)
+ .field("bin_crate", &self.bin_crate)
.field("proc_macro_crate", &self.proc_macro_crate)
.field("error_format", &self.error_format)
.field("libs", &self.libs)
None => OutputFormat::default(),
};
let crate_name = matches.opt_str("crate-name");
+ let bin_crate = crate_types.contains(&CrateType::Executable);
let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
let playground_url = matches.opt_str("playground-url");
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
let options = Options {
input,
+ bin_crate,
proc_macro_crate,
error_format,
diagnostic_width,
ItemType::TraitAlias => "traitalias",
}
}
+ pub(crate) fn is_method(&self) -> bool {
+ matches!(*self, ItemType::Method | ItemType::TyMethod)
+ }
}
impl fmt::Display for ItemType {
use super::format::{self, Buffer};
/// This type is needed in case we want to render links on items to allow to go to their definition.
-pub(crate) struct HrefContext<'a, 'b, 'c> {
- pub(crate) context: &'a Context<'b>,
+pub(crate) struct HrefContext<'a, 'tcx> {
+ pub(crate) context: &'a Context<'tcx>,
/// This span contains the current file we're going through.
pub(crate) file_span: Span,
/// This field is used to know "how far" from the top of the directory we are to link to either
/// documentation pages or other source pages.
- pub(crate) root_path: &'c str,
+ pub(crate) root_path: &'a str,
/// This field is used to calculate precise local URLs.
- pub(crate) current_href: &'c str,
+ pub(crate) current_href: String,
}
/// Decorations are represented as a map from CSS class to vector of character ranges.
src: &str,
out: &mut Buffer,
line_numbers: Buffer,
- href_context: HrefContext<'_, '_, '_>,
+ href_context: HrefContext<'_, '_>,
decoration_info: DecorationInfo,
extra: Option<&str>,
) {
/// This type is used as a conveniency to prevent having to pass all its fields as arguments into
/// the various functions (which became its methods).
-struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+struct TokenHandler<'a, 'tcx> {
out: &'a mut Buffer,
/// It contains the closing tag and the associated `Class`.
closing_tags: Vec<(&'static str, Class)>,
current_class: Option<Class>,
/// We need to keep the `Class` for each element because it could contain a `Span` which is
/// used to generate links.
- pending_elems: Vec<(&'b str, Option<Class>)>,
- href_context: Option<HrefContext<'c, 'd, 'e>>,
+ pending_elems: Vec<(&'a str, Option<Class>)>,
+ href_context: Option<HrefContext<'a, 'tcx>>,
}
-impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> TokenHandler<'a, 'tcx> {
fn handle_exit_span(&mut self) {
// We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
// being used in `write_pending_elems`.
}
}
-impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+impl<'a, 'tcx> Drop for TokenHandler<'a, 'tcx> {
/// When leaving, we need to flush all pending data to not have missing content.
fn drop(&mut self) {
if self.pending_exit_span.is_some() {
fn write_code(
out: &mut Buffer,
src: &str,
- href_context: Option<HrefContext<'_, '_, '_>>,
+ href_context: Option<HrefContext<'_, '_>>,
decoration_info: Option<DecorationInfo>,
) {
// This replace allows to fix how the code source with DOS backline characters is displayed.
/// Processes program tokens, classifying strings of text by highlighting
/// category (`Class`).
-struct Classifier<'a> {
- tokens: PeekIter<'a>,
+struct Classifier<'src> {
+ tokens: PeekIter<'src>,
in_attribute: bool,
in_macro: bool,
in_macro_nonterminal: bool,
byte_pos: u32,
file_span: Span,
- src: &'a str,
+ src: &'src str,
decorations: Option<Decorations>,
}
-impl<'a> Classifier<'a> {
+impl<'src> Classifier<'src> {
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
/// file span which will be used later on by the `span_correspondance_map`.
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
///
/// It returns the token's kind, the token as a string and its byte position in the source
/// string.
- fn next(&mut self) -> Option<(TokenKind, &'a str, u32)> {
+ fn next(&mut self) -> Option<(TokenKind, &'src str, u32)> {
if let Some((kind, text)) = self.tokens.next() {
let before = self.byte_pos;
self.byte_pos += text.len() as u32;
/// The general structure for this method is to iterate over each token,
/// possibly giving it an HTML span with a class specifying what flavor of
/// token is used.
- fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'a>)) {
+ fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
loop {
if let Some(decs) = self.decorations.as_mut() {
let byte_pos = self.byte_pos;
fn advance(
&mut self,
token: TokenKind,
- text: &'a str,
- sink: &mut dyn FnMut(Highlight<'a>),
+ text: &'src str,
+ sink: &mut dyn FnMut(Highlight<'src>),
before: u32,
) {
let lookahead = self.peek();
fn enter_span(
out: &mut Buffer,
klass: Class,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
) -> &'static str {
string_without_closing_tag(out, "", Some(klass), href_context, true).expect(
"internal error: enter_span was called with Some(klass) but did not return a \
out: &mut Buffer,
text: T,
klass: Option<Class>,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
open_tag: bool,
) {
if let Some(closing_tag) = string_without_closing_tag(out, text, klass, href_context, open_tag)
out: &mut Buffer,
text: T,
klass: Option<Class>,
- href_context: &Option<HrefContext<'_, '_, '_>>,
+ href_context: &Option<HrefContext<'_, '_>>,
open_tag: bool,
) -> Option<&'static str> {
let Some(klass) = klass
// https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
match href {
LinkFromSrc::Local(span) => {
- context.href_from_span_relative(*span, href_context.current_href)
+ context.href_from_span_relative(*span, &href_context.current_href)
}
LinkFromSrc::External(def_id) => {
format::href_with_root_path(*def_id, context, Some(href_context.root_path))
return event;
};
- let mut origtext = String::new();
+ let mut original_text = String::new();
for event in &mut self.inner {
match event {
Event::End(Tag::CodeBlock(..)) => break,
Event::Text(ref s) => {
- origtext.push_str(s);
+ original_text.push_str(s);
}
_ => {}
}
}
- let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
- let text = lines.intersperse("\n".into()).collect::<String>();
let parse_result = match kind {
CodeBlockKind::Fenced(ref lang) => {
<pre class=\"language-{}\"><code>{}</code></pre>\
</div>",
lang,
- Escape(&text),
+ Escape(&original_text),
)
.into(),
));
CodeBlockKind::Indented => Default::default(),
};
+ let lines = original_text.lines().filter_map(|l| map_line(l).for_html());
+ let text = lines.intersperse("\n".into()).collect::<String>();
+
compile_fail = parse_result.compile_fail;
should_panic = parse_result.should_panic;
ignore = parse_result.ignore;
if url.is_empty() {
return None;
}
- let test = origtext
+ let test = original_text
.lines()
.map(|l| map_line(l).for_code())
.intersperse("\n".into())
inner: I,
started: bool,
depth: u32,
+ skipped_tags: u32,
}
impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
fn new(iter: I) -> Self {
- SummaryLine { inner: iter, started: false, depth: 0 }
+ SummaryLine { inner: iter, started: false, depth: 0, skipped_tags: 0 }
}
}
let is_allowed_tag = match event {
Event::Start(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth += 1;
}
Event::End(ref c) => {
if is_forbidden_tag(c) {
+ self.skipped_tags += 1;
return None;
}
self.depth -= 1;
}
_ => true,
};
+ if !is_allowed_tag {
+ self.skipped_tags += 1;
+ }
return if !is_allowed_tag {
if is_start {
Some(Event::Start(Tag::Paragraph))
}
impl MarkdownSummaryLine<'_> {
- pub(crate) fn into_string(self) -> String {
+ pub(crate) fn into_string_with_has_more_content(self) -> (String, bool) {
let MarkdownSummaryLine(md, links) = self;
// This is actually common enough to special-case
if md.is_empty() {
- return String::new();
+ return (String::new(), false);
}
let mut replacer = |broken_link: BrokenLink<'_>| {
.map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
};
- let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
+ let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer))
+ .peekable();
+ let mut summary = SummaryLine::new(p);
let mut s = String::new();
- let without_paragraphs = LinkReplacer::new(SummaryLine::new(p), links).filter(|event| {
+ let without_paragraphs = LinkReplacer::new(&mut summary, links).filter(|event| {
!matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph))
});
html::push_html(&mut s, without_paragraphs);
- s
+ let has_more_content =
+ matches!(summary.inner.peek(), Some(Event::Start(_))) || summary.skipped_tags > 0;
+
+ (s, has_more_content)
+ }
+
+ pub(crate) fn into_string(self) -> String {
+ self.into_string_with_has_more_content().0
}
}
t("```rust\n```\n```rust\n```", &[1, 3]);
t("```rust\n```\n ```rust\n```", &[1, 3]);
}
+
+#[test]
+fn test_ascii_with_prepending_hashtag() {
+ fn t(input: &str, expect: &str) {
+ let mut map = IdMap::new();
+ let output = Markdown {
+ content: input,
+ links: &[],
+ ids: &mut map,
+ error_codes: ErrorCodes::Yes,
+ edition: DEFAULT_EDITION,
+ playground: &None,
+ heading_offset: HeadingOffset::H2,
+ }
+ .into_string();
+ assert_eq!(output, expect, "original: {}", input);
+ }
+
+ t(
+ r#"```ascii
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+```"#,
+ "<div class=\"example-wrap\"><pre class=\"language-ascii\"><code>\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+</code></pre></div>",
+ );
+ t(
+ r#"```markdown
+# hello
+```"#,
+ "<div class=\"example-wrap\"><pre class=\"language-markdown\"><code>\
+# hello
+</code></pre></div>",
+ );
+}
You need to enable Javascript be able to update your settings.\
</section>\
</noscript>\
- <link rel=\"stylesheet\" type=\"text/css\" \
+ <link rel=\"stylesheet\" \
href=\"{static_root_path}{settings_css}\">\
<script defer src=\"{static_root_path}{settings_js}\"></script>",
static_root_path = page.get_static_root_path(),
return;
}
if let Some(s) = item.doc_value() {
- let mut summary_html = MarkdownSummaryLine(&s, &item.links(cx)).into_string();
+ let (mut summary_html, has_more_content) =
+ MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
- if s.contains('\n') {
+ if has_more_content {
let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));
if let Some(idx) = summary_html.rfind("</p>") {
let toggled = !doc_buffer.is_empty();
if toggled {
- let method_toggle_class =
- if item_type == ItemType::Method { " method-toggle" } else { "" };
+ let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
}
match &*item.kind {
// The call locations are output in sequence, so that sequence needs to be determined.
// Ideally the most "relevant" examples would be shown first, but there's no general algorithm
- // for determining relevance. Instead, we prefer the smallest examples being likely the easiest to
- // understand at a glance.
+ // for determining relevance. We instead proxy relevance with the following heuristics:
+ // 1. Code written to be an example is better than code not written to be an example, e.g.
+ // a snippet from examples/foo.rs is better than src/lib.rs. We don't know the Cargo
+ // directory structure in Rustdoc, so we proxy this by prioritizing code that comes from
+ // a --crate-type bin.
+ // 2. Smaller examples are better than large examples. So we prioritize snippets that have
+ // the smallest number of lines in their enclosing item.
+ // 3. Finally we sort by the displayed file name, which is arbitrary but prevents the
+ // ordering of examples from randomly changing between Rustdoc invocations.
let ordered_locations = {
- let sort_criterion = |(_, call_data): &(_, &CallData)| {
+ fn sort_criterion<'a>(
+ (_, call_data): &(&PathBuf, &'a CallData),
+ ) -> (bool, u32, &'a String) {
// Use the first location because that's what the user will see initially
let (lo, hi) = call_data.locations[0].enclosing_item.byte_span;
- hi - lo
- };
+ (!call_data.is_bin, hi - lo, &call_data.display_name)
+ }
let mut locs = call_locations.iter().collect::<Vec<_>>();
locs.sort_by_key(sort_criterion);
document(&mut content, cx, m, Some(t), HeadingOffset::H5);
let toggled = !content.is_empty();
if toggled {
- write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
+ let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
+ write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>");
}
write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);
let mut line_numbers = Buffer::empty_from(buf);
let extra;
line_numbers.write_str("<pre class=\"src-line-numbers\">");
- let current_href = &context
+ let current_href = context
.href_from_span(clean::Span::new(file_span), false)
.expect("only local crates should have sources emitted");
match source_context {
.mobile-topbar h2 a,
h1 a,
.search-results a,
-.module-item .stab,
-.import-item .stab,
+.stab,
.result-name .primitive > i, .result-name .keyword > i {
color: var(--main-color);
}
overflow-y: hidden;
}
-.source .sidebar, #sidebar-toggle, #source-sidebar {
+.source .sidebar, #src-sidebar-toggle, #source-sidebar {
background-color: var(--sidebar-background-color);
}
-#sidebar-toggle > button:hover, #sidebar-toggle > button:focus {
+#src-sidebar-toggle > button:hover, #src-sidebar-toggle > button:focus {
background-color: var(--sidebar-background-color-hover);
}
-.source .sidebar > *:not(#sidebar-toggle) {
+.source .sidebar > *:not(#src-sidebar-toggle) {
visibility: hidden;
}
flex-basis: 300px;
}
-.source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) {
+.source-sidebar-expanded .source .sidebar > *:not(#src-sidebar-toggle) {
visibility: visible;
}
}
.source .content pre.rust {
- overflow: auto;
padding-left: 0;
}
text-overflow: ellipsis;
}
/* Wrap non-pre code blocks (`text`) but not (```text```). */
-.docblock > :not(pre) > code,
-.docblock-short > code {
+.docblock :not(pre) > code,
+.docblock-short code {
white-space: pre-wrap;
}
.docblock table {
margin: .5em 0;
- width: calc(100% - 2px);
- overflow-x: auto;
- display: block;
border-collapse: collapse;
}
-.docblock table td {
+.docblock table td, .docblock table th {
padding: .5em;
- border: 1px dashed var(--border-color);
- vertical-align: top;
+ border: 1px solid var(--border-color);
}
-.docblock table th {
- padding: .5em;
- text-align: left;
- border: 1px solid var(--border-color);
+.docblock table tbody tr:nth-child(2n) {
+ background: var(--table-alt-row-background-color);
}
/* Shift "where ..." part of method or fn definition down a line */
top: 100%;
right: 0;
z-index: 2;
- display: block;
margin-top: 7px;
border-radius: 3px;
border: 1px solid var(--border-color);
+ background-color: var(--main-background-color);
+ color: var(--main-color);
--popover-arrow-offset: 11px;
}
right: var(--popover-arrow-offset);
border: solid var(--border-color);
border-width: 1px 1px 0 0;
+ background-color: var(--main-background-color);
padding: 4px;
transform: rotate(-45deg);
top: -5px;
}
-.popover, .popover::before {
- background-color: var(--main-background-color);
- color: var(--main-color);
-}
-
/* use larger max-width for help popover, but not for help.html */
#help.popover {
max-width: 600px;
}
.item-info .stab {
- width: fit-content;
/* This min-height is needed to unify the height of the stab elements because some of them
have emojis.
*/
min-height: 36px;
display: flex;
- align-items: center;
- white-space: pre-wrap;
-}
-.stab {
padding: 3px;
margin-bottom: 5px;
+}
+.item-left .stab {
+ margin-left: 0.3125em;
+}
+.stab {
+ padding: 0 2px;
font-size: 0.875rem;
font-weight: normal;
color: var(--main-color);
background-color: var(--stab-background-color);
+ width: fit-content;
+ align-items: center;
+ white-space: pre-wrap;
+ border-radius: 3px;
+ display: inline-flex;
+ vertical-align: text-bottom;
}
.stab.portability > code {
margin-right: 0.3rem;
}
-/* This is to prevent the `.stab` elements to overflow the .docblock elements. */
-.docblock .stab {
- padding: 0 0.125em;
- margin-bottom: 0;
-}
-
/* Black one-pixel outline around emoji shapes */
.emoji {
text-shadow:
0 -1px 0 black;
}
-.module-item .stab,
-.import-item .stab {
- border-radius: 3px;
- display: inline-block;
- line-height: 1.2;
- margin-bottom: 0;
- margin-left: 0.3125em;
- padding: 2px;
- vertical-align: text-bottom;
-}
-
.module-item.unstable,
.import-item.unstable {
opacity: 0.65;
color: var(--code-highlight-doc-comment-color);
}
+.rustdoc.source .example-wrap pre.rust a {
+ background: var(--codeblock-link-background);
+}
+
.example-wrap.compile_fail,
.example-wrap.should_panic {
border-left: 2px solid var(--codeblock-error-color);
top: 5px;
}
-.example-wrap .tooltip::after {
- display: none;
+.example-wrap .tooltip:hover::after {
text-align: center;
padding: 5px 3px 3px 3px;
border-radius: 6px;
color: var(--tooltip-color);
}
-.example-wrap .tooltip::before {
+.example-wrap .tooltip:hover::before {
content: " ";
position: absolute;
top: 50%;
left: 16px;
margin-top: -5px;
- display: none;
z-index: 1;
border: 5px solid transparent;
border-right-color: var(--tooltip-background-color);
}
-.example-wrap.ignore .tooltip::after {
+.example-wrap.ignore .tooltip:hover::after {
content: "This example is not tested";
}
-.example-wrap.compile_fail .tooltip::after {
+.example-wrap.compile_fail .tooltip:hover::after {
content: "This example deliberately fails to compile";
}
-.example-wrap.should_panic .tooltip::after {
+.example-wrap.should_panic .tooltip:hover::after {
content: "This example panics";
}
-.example-wrap.edition .tooltip::after {
+.example-wrap.edition .tooltip:hover::after {
content: "This code runs with edition " attr(data-edition);
}
-.example-wrap .tooltip:hover::before, .example-wrap .tooltip:hover::after {
- display: inline;
-}
-
.example-wrap.compile_fail .tooltip,
.example-wrap.should_panic .tooltip,
.example-wrap.ignore .tooltip {
font-size: 1rem;
}
-#sidebar-toggle {
+#src-sidebar-toggle {
position: sticky;
top: 0;
left: 0;
#source-sidebar div.files > a.selected {
background-color: var(--source-sidebar-background-selected);
}
-#sidebar-toggle > button {
+#src-sidebar-toggle > button {
font-size: inherit;
font-weight: bold;
background: none;
vertical-align: middle;
border: solid 1px var(--border-color);
border-radius: 3px;
- cursor: default;
color: var(--kbd--color);
background-color: var(--kbd-background);
box-shadow: inset 0 -1px 0 var(--kbd-box-shadow-color);
left: -11px;
}
- #sidebar-toggle {
+ #src-sidebar-toggle {
position: fixed;
left: 1px;
top: 100px;
width: 30px;
font-size: 1.5rem;
- text-align: center;
padding: 0;
z-index: 10;
border-top-right-radius: 3px;
border-left: 0;
}
- .source-sidebar-expanded #sidebar-toggle {
+ .source-sidebar-expanded #src-sidebar-toggle {
left: unset;
top: unset;
width: unset;
}
}
+/* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
+@media (min-width: 701px) {
+ /* Places file-link for a scraped example on top of the example to save space.
+ We only do this on large screens so the file-link doesn't overlap too much
+ with the example's content. */
+ .scraped-example-title {
+ position: absolute;
+ z-index: 10;
+ background: var(--main-background-color);
+ bottom: 8px;
+ right: 5px;
+ padding: 2px 4px;
+ box-shadow: 0 0 4px var(--main-background-color);
+ }
+}
+
@media print {
nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
width: 35px;
}
- #sidebar-toggle {
+ #src-sidebar-toggle {
top: 10px;
}
- .source-sidebar-expanded #sidebar-toggle {
+ .source-sidebar-expanded #src-sidebar-toggle {
top: unset;
}
}
}
.variants > .docblock,
+.implementors-toggle > .docblock,
.impl-items > .rustdoc-toggle[open]:not(:last-child),
.methods > .rustdoc-toggle[open]:not(:last-child),
.implementors-toggle[open]:not(:last-child) {
border-radius: 50px;
}
+.scraped-example {
+ /* So .scraped-example-title can be positioned absolutely */
+ position: relative;
+}
+
.scraped-example .code-wrapper {
position: relative;
display: flex;
}
.scraped-example:not(.expanded) .code-wrapper {
- max-height: 240px;
+ /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
+ * of lines shown in the un-expanded example code viewer. This pre needs to have
+ * a max-height equal to line-height * N. The line-height is currently 1.5em,
+ * and we include additional 10px for padding. */
+ max-height: calc(1.5em * 5 + 10px);
}
.scraped-example:not(.expanded) .code-wrapper pre {
overflow-y: hidden;
- max-height: 240px;
padding-bottom: 0;
+ /* See above comment, should be the same max-height. */
+ max-height: calc(1.5em * 5 + 10px);
+}
+
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
+ /* See above comment, except this height is based on HIDDEN_MAX_LINES. */
+ max-height: calc(1.5em * 10 + 10px);
}
.scraped-example .code-wrapper .next,
.scraped-example .code-wrapper .prev,
.scraped-example .code-wrapper .expand {
+ color: var(--main-color);
position: absolute;
top: 0.25em;
z-index: 1;
}
.scraped-example .code-wrapper .src-line-numbers {
- margin: 0;
padding: 14px 0;
}
.more-examples-toggle .hide-more {
margin-left: 25px;
- margin-bottom: 5px;
cursor: pointer;
}
height: 100%;
}
-.more-scraped-examples .scraped-example {
- margin-bottom: 20px;
-}
-
-.more-scraped-examples .scraped-example:last-child {
- margin-bottom: 0;
+.more-scraped-examples .scraped-example, .example-links {
+ margin-top: 20px;
}
-.example-links a {
- margin-top: 20px;
+.more-scraped-examples .scraped-example:first-child {
+ margin-top: 5px;
}
.example-links ul {
cursor: pointer;
}
-.setting-line > .sub-settings {
- padding-left: 42px;
- width: 100%;
- display: block;
-}
-
#settings .setting-line {
margin: 1.2em 0.6em;
}
--crate-search-hover-border: #e0e0e0;
--source-sidebar-background-selected: #14191f;
--source-sidebar-background-hover: #14191f;
+ --table-alt-row-background-color: #191f26;
+ --codeblock-link-background: #333;
}
h1, h2, h3, h4 {
color: #c5c5c5;
}
-.content .item-info::before { color: #ccc; }
-
.sidebar h2 a,
.sidebar h3 a {
color: white;
}
-body.source .example-wrap pre.rust a {
- background: #333;
-}
-
-.module-item .stab,
-.import-item .stab {
- color: #000;
-}
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
--crate-search-hover-border: #2196f3;
--source-sidebar-background-selected: #333;
--source-sidebar-background-hover: #444;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
- background: #333;
+ --table-alt-row-background-color: #2A2A2A;
+ --codeblock-link-background: #333;
}
#titles > button:not(.selected) {
--crate-search-hover-border: #717171;
--source-sidebar-background-selected: #fff;
--source-sidebar-background-hover: #e0e0e0;
-}
-
-.content .item-info::before { color: #ccc; }
-
-body.source .example-wrap pre.rust a {
- background: #eee;
+ --table-alt-row-background-color: #F5F5F5;
+ --codeblock-link-background: #eee;
}
#titles > button:not(.selected) {
function loadCss(cssUrl) {
const link = document.createElement("link");
link.href = cssUrl;
- link.type = "text/css";
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild(link);
}
const innerToggle = document.getElementById(toggleAllDocsId);
removeClass(innerToggle, "will-expand");
onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
- if (!hasClass(e, "type-contents-toggle")) {
+ if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
e.open = true;
}
});
"use strict";
(function() {
- // Number of lines shown when code viewer is not expanded
- const MAX_LINES = 10;
+ // Number of lines shown when code viewer is not expanded.
+ // DEFAULT is the first example shown by default, while HIDDEN is
+ // the examples hidden beneath the "More examples" toggle.
+ //
+ // NOTE: these values MUST be synchronized with certain rules in rustdoc.css!
+ const DEFAULT_MAX_LINES = 5;
+ const HIDDEN_MAX_LINES = 10;
// Scroll code block to the given code location
- function scrollToLoc(elt, loc) {
+ function scrollToLoc(elt, loc, isHidden) {
const lines = elt.querySelector(".src-line-numbers");
let scrollOffset;
// If the block is greater than the size of the viewer,
// then scroll to the top of the block. Otherwise scroll
// to the middle of the block.
- if (loc[1] - loc[0] > MAX_LINES) {
+ const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
+ if (loc[1] - loc[0] > maxLines) {
const line = Math.max(0, loc[0] - 1);
scrollOffset = lines.children[line].offsetTop;
} else {
const wrapper = elt.querySelector(".code-wrapper");
const halfHeight = wrapper.offsetHeight / 2;
- const offsetMid = (lines.children[loc[0]].offsetTop
- + lines.children[loc[1]].offsetTop) / 2;
+ const offsetTop = lines.children[loc[0]].offsetTop;
+ const lastLine = lines.children[loc[1]];
+ const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
+ const offsetMid = (offsetTop + offsetBot) / 2;
scrollOffset = offsetMid - halfHeight;
}
elt.querySelector(".rust").scrollTo(0, scrollOffset);
}
- function updateScrapedExample(example) {
+ function updateScrapedExample(example, isHidden) {
const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
let locIndex = 0;
const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
const onChangeLoc = changeIndex => {
removeClass(highlights[locIndex], "focus");
changeIndex();
- scrollToLoc(example, locs[locIndex][0]);
+ scrollToLoc(example, locs[locIndex][0], isHidden);
addClass(highlights[locIndex], "focus");
const url = locs[locIndex][1];
expandButton.addEventListener("click", () => {
if (hasClass(example, "expanded")) {
removeClass(example, "expanded");
- scrollToLoc(example, locs[0][0]);
+ scrollToLoc(example, locs[0][0], isHidden);
} else {
addClass(example, "expanded");
}
}
// Start with the first example in view
- scrollToLoc(example, locs[0][0]);
+ scrollToLoc(example, locs[0][0], isHidden);
}
const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
- onEachLazy(firstExamples, updateScrapedExample);
+ onEachLazy(firstExamples, el => updateScrapedExample(el, false));
onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
// Allow users to click the left border of the <details> section to close it,
// since the section can be large and finding the [+] button is annoying.
// depends on offsetHeight, a property that requires an element to be visible to
// compute correctly.
setTimeout(() => {
- onEachLazy(moreExamples, updateScrapedExample);
+ onEachLazy(moreExamples, el => updateScrapedExample(el, true));
});
}, {once: true});
});
function createSidebarToggle() {
const sidebarToggle = document.createElement("div");
- sidebarToggle.id = "sidebar-toggle";
+ sidebarToggle.id = "src-sidebar-toggle";
const inner = document.createElement("button");
-Rustdoc will automatically scrape examples of documented items from the `examples/` directory of a project. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
+Rustdoc will automatically scrape examples of documented items from a project's source code. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
```rust
// src/lib.rs
Then this code snippet will be included in the documentation for `a_func`.
+
## How to read scraped examples
Scraped examples are shown as blocks of code from a given file. The relevant item will be highlighted. If the file is larger than a couple lines, only a small window will be shown which you can expand by clicking ↕ in the top-right. If a file contains multiple instances of an item, you can use the ≺ and ≻ buttons to toggle through each instance.
## How Rustdoc scrapes examples
-When you run `cargo doc`, Rustdoc will analyze all the crates that match Cargo's `--examples` filter for instances of items that occur in the crates being documented. Then Rustdoc will include the source code of these instances in the generated documentation.
+When you run `cargo doc -Zunstable-options -Zrustdoc-scrape-examples`, Rustdoc will analyze all the documented crates for uses of documented items. Then Rustdoc will include the source code of these instances in the generated documentation.
Rustdoc has a few techniques to ensure this doesn't overwhelm documentation readers, and that it doesn't blow up the page size:
fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
match res {
- Ok(()) => Ok(()),
+ Ok(()) => diag.has_errors().map_or(Ok(()), Err),
Err(err) => {
let reported = diag.struct_err(&err).emit();
Err(reported)
tcx: TyCtxt<'tcx>,
) -> MainResult {
match formats::run_format::<T>(krate, renderopts, cache, tcx) {
- Ok(_) => Ok(()),
+ Ok(_) => tcx.sess.has_errors().map_or(Ok(()), Err),
Err(e) => {
let mut msg =
tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error));
let output_format = options.output_format;
let externs = options.externs.clone();
let scrape_examples_options = options.scrape_examples_options.clone();
+ let bin_crate = options.bin_crate;
let config = core::create_config(options);
info!("finished with rustc");
if let Some(options) = scrape_examples_options {
- return scrape_examples::run(krate, render_opts, cache, tcx, options);
+ return scrape_examples::run(
+ krate,
+ render_opts,
+ cache,
+ tcx,
+ options,
+ bin_crate,
+ );
}
cache.crate_version = crate_version;
let mut css = String::new();
for name in &options.markdown_css {
- write!(css, r#"<link rel="stylesheet" type="text/css" href="{name}">"#)
+ write!(css, r#"<link rel="stylesheet" href="{name}">"#)
.expect("Writing to a String can't fail");
}
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
Res::from_def_id(self.cx.tcx, did)
}
- ty::Projection(_)
+ ty::Alias(..)
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(_)
- | ty::Opaque(..)
| ty::Dynamic(..)
| ty::Param(_)
| ty::Bound(..)
};
pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+ // We need to check if there are errors before running this pass because it would crash when
+ // we try to get auto and blanket implementations.
+ if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() {
+ return krate;
+ }
+
let synth_impls = cx.sess().time("collect_synthetic_impls", || {
let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
synth.visit_crate(&krate);
pub(crate) url: String,
pub(crate) display_name: String,
pub(crate) edition: Edition,
+ pub(crate) is_bin: bool,
}
pub(crate) type FnCallLocations = FxHashMap<PathBuf, CallData>;
cx: Context<'tcx>,
target_crates: Vec<CrateNum>,
calls: &'a mut AllCallLocations,
+ bin_crate: bool,
}
impl<'a, 'tcx> Visitor<'tcx> for FindCalls<'a, 'tcx>
let mk_call_data = || {
let display_name = file_path.display().to_string();
let edition = call_span.edition();
- CallData { locations: Vec::new(), url, display_name, edition }
+ let is_bin = self.bin_crate;
+
+ CallData { locations: Vec::new(), url, display_name, edition, is_bin }
};
let fn_key = tcx.def_path_hash(*def_id);
cache: formats::cache::Cache,
tcx: TyCtxt<'_>,
options: ScrapeExamplesOptions,
+ bin_crate: bool,
) -> interface::Result<()> {
let inner = move || -> Result<(), String> {
// Generates source files for examples
// Run call-finder on all items
let mut calls = FxHashMap::default();
- let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
+ let mut finder =
+ FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate };
tcx.hir().visit_all_item_likes_in_crate(&mut finder);
// The visitor might have found a type error, which we need to
-Subproject commit a1232c451fc27173f8718e05d174b2503ca0b607
+Subproject commit 3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6ec
// It also validates that functions can be called through function pointers
// through traits.
-#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
+#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
#![crate_type = "lib"]
#![no_core]
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
+extern "rust-intrinsic" {
+ pub fn transmute<Src, Dst>(src: Src) -> Dst;
+}
+
pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
pub static mut STORAGE_BAR: u32 = 12;
STORAGE_FOO(&1, &mut buf);
}
}
+
+// Validate that we can codegen transmutes between data ptrs and fn ptrs.
+
+// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
+ // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+ // as long as it doesn't cause a verifier error by using `bitcast`.
+ transmute(x)
+}
+
+// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
+#[no_mangle]
+pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
+ // It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
+ // as long as it doesn't cause a verifier error by using `bitcast`.
+ transmute(x)
+}
// On riscv the closure is another function, placed before fn foo so CHECK can't
// find it
// ignore-riscv64 FIXME
+// On s390x the closure is also in another function
+// ignore-s390x FIXME
#![crate_type = "lib"]
#![feature(c_unwind)]
// CHECK: define i8 @match1{{.*}}
// CHECK-NEXT: start:
-// CHECK-NEXT: %1 = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
-// CHECK-NEXT: switch i8 %1, label {{.*}} [
+// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
+// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
#[no_mangle]
pub fn match1(e: Enum1) -> u8 {
use Enum1::*;
--- /dev/null
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
+// min-llvm-version: 15.0 # this test uses opaque pointer notation
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+#[no_mangle]
+pub fn outer_function(x: S, y: S) -> usize {
+ (#[inline(always)]|| {
+ let _z = x;
+ y.0[0]
+ })()
+}
+
+// Check that we do not attempt to load from the spilled arg before it is assigned to
+// when generating debuginfo.
+// CHECK-LABEL: @outer_function
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
+// CHECK-NOT: [[load:%.*]] = load ptr, ptr
+// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
--- /dev/null
+// Test that __llvm_profile_counter_bias does not get internalized by lto.
+
+// ignore-macos -runtime-counter-relocation not honored on Mach-O
+// compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
+// needs-profiler-support
+// no-prefer-dynamic
+
+// CHECK: @__llvm_profile_counter_bias = {{.*}}global
+
+pub fn main() {}
include!("aux_mod.rs");
// Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
pub static FILE_PATH: &'static str = file!();
fn main() {
// ignore-powerpc
// ignore-powerpc64
// ignore-riscv64 see codegen/riscv-abi
+// ignore-s390x
// ignore-windows
// See repr-transparent.rs
// ignore-riscv64 riscv64 has an i128 type used with test_Vector
// see codegen/riscv-abi for riscv functiona call tests
+// ignore-s390x s390x with default march passes vector types per reference
#![crate_type="lib"]
#![feature(repr_simd, transparent_unions)]
--- /dev/null
+// Verifies that "kcfi" module flag is added.
+//
+// needs-sanitizer-kcfi
+// compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi", i32 1}
--- /dev/null
+// Verifies that KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}foo
+ // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+ // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE1:[0-9]+]]
+ // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
+ f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}bar
+ // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+ // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE2:[0-9]+]]
+ // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
+ f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+ // CHECK-LABEL: define{{.*}}baz
+ // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+ // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE3:[0-9]+]]
+ // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+ f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 653723426}
+// CHECK: ![[TYPE2]] = !{i32 412174924}
+// CHECK: ![[TYPE3]] = !{i32 -636668840}
// CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
-// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"\EF\BE\AD\DE", [12 x i8] undef }>, align 4
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
// This shouldn't contain undef, since it contains more chunks
// than the default value of uninit_const_chunk_threshold.
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail6")]
pub fn change_break_label() {
let mut _x = 0;
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
#[rustc_clean(cfg="cfail6")]
pub fn change_continue_label() {
let mut _x = 0;
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/76803_regression.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
}
bb1: {
- _2 = Ne(move _3, const true); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
}
bb1: {
- _2 = Ne(const true, move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
}
bb1: {
- _2 = Eq(move _3, const false); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
}
bb1: {
- _2 = Eq(const false, move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+ _2 = Not(move _3); // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
StorageDead(_3); // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
}
bb1: {
--- /dev/null
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR enums.switch_bool.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_bool(b: bool) -> u32 {
+ mir!(
+ {
+ match b {
+ true => t,
+ false => f,
+ _ => f,
+ }
+ }
+
+ t = {
+ RET = 5;
+ Return()
+ }
+
+ f = {
+ RET = 10;
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR enums.switch_option.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn switch_option(option: Option<()>) -> bool {
+ mir!(
+ {
+ let discr = Discriminant(option);
+ match discr {
+ 0 => n,
+ 1 => s,
+ _ => s,
+ }
+ }
+
+ n = {
+ RET = false;
+ Return()
+ }
+
+ s = {
+ RET = true;
+ Return()
+ }
+ )
+}
+
+#[repr(u8)]
+enum Bool {
+ False = 0,
+ True = 1,
+}
+
+// EMIT_MIR enums.switch_option_repr.built.after.mir
+#[custom_mir(dialect = "built")]
+fn switch_option_repr(option: Bool) -> bool {
+ mir!(
+ {
+ let discr = Discriminant(option);
+ match discr {
+ 0 => f,
+ _ => t,
+ }
+ }
+
+ t = {
+ RET = true;
+ Return()
+ }
+
+ f = {
+ RET = false;
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR enums.set_discr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr(option: &mut Option<()>) {
+ mir!({
+ SetDiscriminant(*option, 0);
+ Return()
+ })
+}
+
+// EMIT_MIR enums.set_discr_repr.built.after.mir
+#[custom_mir(dialect = "runtime", phase = "initial")]
+fn set_discr_repr(b: &mut Bool) {
+ mir!({
+ SetDiscriminant(*b, 0);
+ Return()
+ })
+}
+
+fn main() {
+ assert_eq!(switch_bool(true), 5);
+ assert_eq!(switch_bool(false), 10);
+
+ assert_eq!(switch_option(Some(())), true);
+ assert_eq!(switch_option(None), false);
+
+ assert_eq!(switch_option_repr(Bool::True), true);
+ assert_eq!(switch_option_repr(Bool::False), false);
+
+ let mut opt = Some(());
+ set_discr(&mut opt);
+ assert_eq!(opt, None);
+
+ let mut b = Bool::True;
+ set_discr_repr(&mut b);
+ assert!(matches!(b, Bool::False));
+}
--- /dev/null
+// MIR for `set_discr` after built
+
+fn set_discr(_1: &mut Option<()>) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
+
+ bb0: {
+ discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+2:9: +2:36
+ return; // scope 0 at $DIR/enums.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `set_discr_repr` after built
+
+fn set_discr_repr(_1: &mut Bool) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/enums.rs:+0:33: +0:33
+
+ bb0: {
+ discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+2:9: +2:31
+ return; // scope 0 at $DIR/enums.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `switch_bool` after built
+
+fn switch_bool(_1: bool) -> u32 {
+ let mut _0: u32; // return place in scope 0 at $DIR/enums.rs:+0:32: +0:35
+
+ bb0: {
+ switchInt(_1) -> [1: bb1, 0: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+3:13: +7:14
+ }
+
+ bb1: {
+ _0 = const 5_u32; // scope 0 at $DIR/enums.rs:+11:13: +11:20
+ return; // scope 0 at $DIR/enums.rs:+12:13: +12:21
+ }
+
+ bb2: {
+ _0 = const 10_u32; // scope 0 at $DIR/enums.rs:+16:13: +16:21
+ return; // scope 0 at $DIR/enums.rs:+17:13: +17:21
+ }
+}
--- /dev/null
+// MIR for `switch_option` after built
+
+fn switch_option(_1: Option<()>) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/enums.rs:+0:45: +0:49
+ let mut _2: isize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ switchInt(_2) -> [0: bb1, 1: bb2, otherwise: bb2]; // scope 0 at $DIR/enums.rs:+4:13: +8:14
+ }
+
+ bb1: {
+ _0 = const false; // scope 0 at $DIR/enums.rs:+12:13: +12:24
+ return; // scope 0 at $DIR/enums.rs:+13:13: +13:21
+ }
+
+ bb2: {
+ _0 = const true; // scope 0 at $DIR/enums.rs:+17:13: +17:23
+ return; // scope 0 at $DIR/enums.rs:+18:13: +18:21
+ }
+}
--- /dev/null
+// MIR for `switch_option_repr` after built
+
+fn switch_option_repr(_1: Bool) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/enums.rs:+0:40: +0:44
+ let mut _2: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/enums.rs:+4:13: +7:14
+ }
+
+ bb1: {
+ _0 = const true; // scope 0 at $DIR/enums.rs:+11:13: +11:23
+ return; // scope 0 at $DIR/enums.rs:+12:13: +12:21
+ }
+
+ bb2: {
+ _0 = const false; // scope 0 at $DIR/enums.rs:+16:13: +16:24
+ return; // scope 0 at $DIR/enums.rs:+17:13: +17:21
+ }
+}
--- /dev/null
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+union U {
+ a: i32,
+ b: u32,
+}
+
+// EMIT_MIR projections.unions.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unions(u: U) -> i32 {
+ mir!({
+ RET = u.a;
+ Return()
+ })
+}
+
+// EMIT_MIR projections.tuples.built.after.mir
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn tuples(i: (u32, i32)) -> (u32, i32) {
+ mir!(
+ // FIXME(JakobDegen): This is necessary because we can't give type hints for `RET`
+ let temp: (u32, i32);
+ {
+ temp.0 = i.0;
+ temp.1 = i.1;
+
+ RET = temp;
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR projections.unwrap.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap(opt: Option<i32>) -> i32 {
+ mir!({
+ RET = Field(Variant(opt, 1), 0);
+ Return()
+ })
+}
+
+// EMIT_MIR projections.unwrap_deref.built.after.mir
+#[custom_mir(dialect = "built")]
+fn unwrap_deref(opt: Option<&i32>) -> i32 {
+ mir!({
+ RET = *Field::<&i32>(Variant(opt, 1), 0);
+ Return()
+ })
+}
+
+// EMIT_MIR projections.set.built.after.mir
+#[custom_mir(dialect = "built")]
+fn set(opt: &mut Option<i32>) {
+ mir!({
+ place!(Field(Variant(*opt, 1), 0)) = 10;
+ Return()
+ })
+}
+
+// EMIT_MIR projections.simple_index.built.after.mir
+#[custom_mir(dialect = "built")]
+fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
+ mir!({
+ let temp = 3;
+ RET = a[temp];
+ RET = (*b)[temp];
+ Return()
+ })
+}
+
+fn main() {
+ assert_eq!(unions(U { a: 5 }), 5);
+ assert_eq!(tuples((5, 6)), (5, 6));
+
+ assert_eq!(unwrap(Some(5)), 5);
+ assert_eq!(unwrap_deref(Some(&5)), 5);
+ let mut o = Some(5);
+ set(&mut o);
+ assert_eq!(o, Some(10));
+
+ assert_eq!(simple_index([0; 10], &[0; 10]), 0);
+}
--- /dev/null
+// MIR for `set` after built
+
+fn set(_1: &mut Option<i32>) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/projections.rs:+0:31: +0:31
+
+ bb0: {
+ (((*_1) as variant#1).0: i32) = const 10_i32; // scope 0 at $DIR/projections.rs:+2:9: +2:48
+ return; // scope 0 at $DIR/projections.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `simple_index` after built
+
+fn simple_index(_1: [i32; 10], _2: &[i32]) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/projections.rs:+0:45: +0:48
+ let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _3 = const 3_usize; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _0 = _1[_3]; // scope 0 at $DIR/projections.rs:+3:9: +3:22
+ _0 = (*_2)[_3]; // scope 0 at $DIR/projections.rs:+4:9: +4:25
+ return; // scope 0 at $DIR/projections.rs:+5:9: +5:17
+ }
+}
--- /dev/null
+// MIR for `tuples` after built
+
+fn tuples(_1: (u32, i32)) -> (u32, i32) {
+ let mut _0: (u32, i32); // return place in scope 0 at $DIR/projections.rs:+0:29: +0:39
+ let mut _2: (u32, i32); // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ (_2.0: u32) = (_1.0: u32); // scope 0 at $DIR/projections.rs:+5:13: +5:25
+ (_2.1: i32) = (_1.1: i32); // scope 0 at $DIR/projections.rs:+6:13: +6:25
+ _0 = _2; // scope 0 at $DIR/projections.rs:+8:13: +8:23
+ return; // scope 0 at $DIR/projections.rs:+9:13: +9:21
+ }
+}
--- /dev/null
+// MIR for `unions` after built
+
+fn unions(_1: U) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/projections.rs:+0:20: +0:23
+
+ bb0: {
+ _0 = (_1.0: i32); // scope 0 at $DIR/projections.rs:+2:9: +2:18
+ return; // scope 0 at $DIR/projections.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `unwrap` after built
+
+fn unwrap(_1: Option<i32>) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/projections.rs:+0:32: +0:35
+
+ bb0: {
+ _0 = ((_1 as variant#1).0: i32); // scope 0 at $DIR/projections.rs:+2:9: +2:40
+ return; // scope 0 at $DIR/projections.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `unwrap_deref` after built
+
+fn unwrap_deref(_1: Option<&i32>) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/projections.rs:+0:39: +0:42
+
+ bb0: {
+ _0 = (*((_1 as variant#1).0: &i32)); // scope 0 at $DIR/projections.rs:+2:9: +2:49
+ return; // scope 0 at $DIR/projections.rs:+3:9: +3:17
+ }
+}
--- /dev/null
+// MIR for `raw_pointer` after built
+
+fn raw_pointer(_1: *const i32) -> *const i32 {
+ let mut _0: *const i32; // return place in scope 0 at $DIR/references.rs:+0:38: +0:48
+
+ bb0: {
+ _0 = &raw const (*_1); // scope 0 at $DIR/references.rs:+4:9: +4:27
+ return; // scope 0 at $DIR/references.rs:+5:9: +5:17
+ }
+}
)
}
+// EMIT_MIR references.raw_pointer.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn raw_pointer(x: *const i32) -> *const i32 {
+ // Regression test for a bug in which unsafetyck was not correctly turned off for
+ // `dialect = "built"`
+ mir!({
+ RET = addr_of!(*x);
+ Return()
+ })
+}
+
fn main() {
let mut x = 5;
assert_eq!(*mut_ref(&mut x), 5);
assert_eq!(*immut_ref(&x), 5);
+ unsafe {
+ assert_eq!(*raw_pointer(addr_of!(x)), 5);
+ }
}
--- /dev/null
+// MIR for `assert_nonzero` after built
+
+fn assert_nonzero(_1: i32) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:27: +0:27
+
+ bb0: {
+ switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/terminators.rs:+3:13: +6:14
+ }
+
+ bb1: {
+ unreachable; // scope 0 at $DIR/terminators.rs:+10:13: +10:26
+ }
+
+ bb2: {
+ return; // scope 0 at $DIR/terminators.rs:+14:13: +14:21
+ }
+}
--- /dev/null
+// MIR for `direct_call` after built
+
+fn direct_call(_1: i32) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/terminators.rs:+0:27: +0:30
+
+ bb0: {
+ _0 = ident::<i32>(_1) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:42
+ // mir::Constant
+ // + span: $DIR/terminators.rs:15:33: 15:38
+ // + literal: Const { ty: fn(i32) -> i32 {ident::<i32>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+ }
+}
--- /dev/null
+// MIR for `drop_first` after built
+
+fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59
+
+ bb0: {
+ replace(_1 <- move _2) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:49
+ }
+
+ bb1: {
+ return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+ }
+}
--- /dev/null
+// MIR for `drop_second` after built
+
+fn drop_second(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:60: +0:60
+
+ bb0: {
+ drop(_2) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:30
+ }
+
+ bb1: {
+ return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+ }
+}
--- /dev/null
+// MIR for `indirect_call` after built
+
+fn indirect_call(_1: i32, _2: fn(i32) -> i32) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/terminators.rs:+0:48: +0:51
+
+ bb0: {
+ _0 = _2(_1) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:38
+ }
+
+ bb1: {
+ return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21
+ }
+}
--- /dev/null
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+fn ident<T>(t: T) -> T {
+ t
+}
+
+// EMIT_MIR terminators.direct_call.built.after.mir
+#[custom_mir(dialect = "built")]
+fn direct_call(x: i32) -> i32 {
+ mir!(
+ {
+ Call(RET, retblock, ident(x))
+ }
+
+ retblock = {
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR terminators.indirect_call.built.after.mir
+#[custom_mir(dialect = "built")]
+fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
+ mir!(
+ {
+ Call(RET, retblock, f(x))
+ }
+
+ retblock = {
+ Return()
+ }
+ )
+}
+
+struct WriteOnDrop<'a>(&'a mut i32, i32);
+
+impl<'a> Drop for WriteOnDrop<'a> {
+ fn drop(&mut self) {
+ *self.0 = self.1;
+ }
+}
+
+// EMIT_MIR terminators.drop_first.built.after.mir
+#[custom_mir(dialect = "built")]
+fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
+ mir!(
+ {
+ DropAndReplace(a, Move(b), retblock)
+ }
+
+ retblock = {
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR terminators.drop_second.built.after.mir
+#[custom_mir(dialect = "built")]
+fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) {
+ mir!(
+ {
+ Drop(b, retblock)
+ }
+
+ retblock = {
+ Return()
+ }
+ )
+}
+
+// EMIT_MIR terminators.assert_nonzero.built.after.mir
+#[custom_mir(dialect = "built")]
+fn assert_nonzero(a: i32) {
+ mir!(
+ {
+ match a {
+ 0 => unreachable,
+ _ => retblock
+ }
+ }
+
+ unreachable = {
+ Unreachable()
+ }
+
+ retblock = {
+ Return()
+ }
+ )
+}
+
+fn main() {
+ assert_eq!(direct_call(5), 5);
+ assert_eq!(indirect_call(5, ident), 5);
+
+ let mut a = 0;
+ let mut b = 0;
+ drop_first(WriteOnDrop(&mut a, 1), WriteOnDrop(&mut b, 1));
+ assert_eq!((a, b), (1, 0));
+
+ let mut a = 0;
+ let mut b = 0;
+ drop_second(WriteOnDrop(&mut a, 1), WriteOnDrop(&mut b, 1));
+ assert_eq!((a, b), (0, 1));
+}
StorageLive(_5); // scope 1 at $DIR/issue_101867.rs:+2:14: +2:15
FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
_6 = discriminant(_1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
- switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
+ switchInt(move _6) -> [1: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
}
bb1: {
StorageLive(_3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
_3 = const true; // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
- switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
+ switchInt(_3) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
}
bb3: {
_2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
_3 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
- switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+ switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
}
bb1: {
}
bb6: {
- switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+ switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
}
bb7: {
_2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
_3 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
- switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+ switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
}
bb1: {
}
bb6: {
- switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+ switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
}
bb7: {
_2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
_4 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
- switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+ switchInt(move _4) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
}
bb1: {
bb4: {
_3 = discriminant(_2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
- switchInt(move _3) -> [1_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+ switchInt(move _3) -> [1: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
}
bb5: {
}
bb9: {
- switchInt(move _8) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
+ switchInt(move _8) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
}
bb10: {
}
bb15: {
- switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
+ switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
}
bb16: {
bb0: {
FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple_match.rs:+1:11: +1:12
- switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
+ switchInt(_1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
}
bb1: {
bb0: {
- StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _3 = discriminant(_1); // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
-- switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _2 = discriminant(_1); // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
-+ switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb1: {
- }
-
- bb3: {
-- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb4: {
StorageLive(_1); // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:11: +6:6
StorageLive(_2); // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
_2 = const A; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
- switchInt(_2) -> [1_i32: bb2, 2_i32: bb2, 3_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
+ switchInt(_2) -> [1: bb2, 2: bb2, 3: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
}
bb1: {
bb2: {
_1 = const B; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
- goto -> bb3; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
-+ switchInt(_1) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
++ switchInt(_1) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
}
bb3: {
-- switchInt(_1) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
+- switchInt(_1) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
- }
-
- bb4: {
- StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
- StorageLive(_6); // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
- _6 = const true; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
-- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
+- switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
+ StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
+ _2 = const true; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
-+ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
++ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
}
bb1: {
-
- bb3: {
- StorageDead(_6); // scope 0 at $DIR/const_goto_storage.rs:+2:51: +2:52
-- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
+- switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
- }
-
- bb4: {
-
- bb6: {
- StorageDead(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:75: +2:76
-- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
+- switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
- }
-
- bb7: {
- }
-
- bb9: {
-- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
+- switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
- }
-
- bb10: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
_1 = const _; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
-- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
-+ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
+- switchInt(move _1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
++ switchInt(const false) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
}
bb1: {
((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
_1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
-- switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
-+ switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+- switchInt(_1) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
++ switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
}
bb1: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
_1 = const 1_i32; // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
-- switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+- switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+ goto -> bb2; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
}
bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br align="left"/> 11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br align="left"/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br align="left"/> </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
- bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
+ bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<0>];
bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
}
discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21
StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10
_3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20
- switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
+ switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
}
bb1: {
+ _4 = const 1_i32; // scope 1 at $DIR/if.rs:+2:16: +2:17
+ _3 = const true; // scope 1 at $DIR/if.rs:+2:16: +2:22
StorageDead(_4); // scope 1 at $DIR/if.rs:+2:21: +2:22
-- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
-+ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
+- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
++ switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
}
bb1: {
+ _9 = const 1_i32; // scope 3 at $DIR/if.rs:+5:16: +5:17
+ _8 = const true; // scope 3 at $DIR/if.rs:+5:16: +5:22
StorageDead(_9); // scope 3 at $DIR/if.rs:+5:21: +5:22
-- switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
-+ switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
+- switchInt(move _8) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
++ switchInt(const true) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
}
bb4: {
StorageLive(_1); // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33
StorageLive(_2); // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
_2 = const true; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
-+ switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
++ switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
}
bb1: {
}
bb2: {
-- switchInt(move _5) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
-+ switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
+- switchInt(move _5) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
++ switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
}
bb3: {
bb0: {
StorageLive(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
_3 = _1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
+ switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
}
bb1: {
_7 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
_8 = const 4_usize; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
_9 = Ge(move _7, move _8); // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
- switchInt(move _9) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
+ switchInt(move _9) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
}
bb2: {
- switchInt((*_2)[0 of 4]) -> [47_u8: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+ switchInt((*_2)[0 of 4]) -> [47: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb3: {
- switchInt((*_2)[1 of 4]) -> [47_u8: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+ switchInt((*_2)[1 of 4]) -> [47: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb4: {
- switchInt((*_2)[2 of 4]) -> [47_u8: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+ switchInt((*_2)[2 of 4]) -> [47: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb5: {
-- switchInt((*_2)[3 of 4]) -> [47_u8: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+ switchInt((*_2)[3 of 4]) -> [47_u8: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb6: {
_4 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
_5 = const 3_usize; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
_6 = Ge(move _4, move _5); // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
- switchInt(move _6) -> [false: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
+ switchInt(move _6) -> [0: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
}
bb7: {
- switchInt((*_2)[0 of 3]) -> [47_u8: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb8: {
- switchInt((*_2)[1 of 3]) -> [47_u8: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb9: {
-- switchInt((*_2)[2 of 3]) -> [47_u8: bb12, 33_u8: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+ switchInt((*_2)[2 of 3]) -> [47_u8: bb11, 33_u8: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
}
bb10: {
_7 = const false; // scope 0 at $DIR/string.rs:+1:11: +1:12
_7 = const true; // scope 0 at $DIR/string.rs:+1:11: +1:12
_5 = discriminant(_1); // scope 0 at $DIR/string.rs:+1:11: +1:12
- switchInt(move _5) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
+ switchInt(move _5) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
}
bb1: {
}
bb4: {
- switchInt(move _4) -> [false: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+ switchInt(move _4) -> [0: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
}
bb5: {
}
bb9: {
- switchInt(_7) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
+ switchInt(_7) -> [0: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
}
}
bb3: {
StorageDead(_8); // scope 1 at $DIR/derefer_complex_case.rs:+1:25: +1:26
_10 = discriminant(_7); // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
- switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
}
bb4: {
_6 = &_7; // scope 2 at $DIR/derefer_terminator_test.rs:+3:18: +3:21
_5 = &_6; // scope 2 at $DIR/derefer_terminator_test.rs:+3:17: +3:21
_4 = &_5; // scope 2 at $DIR/derefer_terminator_test.rs:+3:15: +3:22
-- switchInt((*(*(*(*_4))))) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+- switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _10 = deref_copy (*_4); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _11 = deref_copy (*_10); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+ _12 = deref_copy (*_11); // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
-+ switchInt((*_12)) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
++ switchInt((*_12)) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
}
bb3: {
}
bb2: {
- switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
+ switchInt(move _3) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
}
bb3: {
--- /dev/null
+- // MIR for `f` before DestinationPropagation
++ // MIR for `f` after DestinationPropagation
+
+ fn f(_1: T) -> () {
+ debug a => _1; // in scope 0 at $DIR/unreachable.rs:+0:19: +0:20
+ let mut _0: (); // return place in scope 0 at $DIR/unreachable.rs:+0:25: +0:25
+ let _2: T; // in scope 0 at $DIR/unreachable.rs:+1:9: +1:10
+ let mut _3: bool; // in scope 0 at $DIR/unreachable.rs:+2:8: +2:13
+ let _4: (); // in scope 0 at $DIR/unreachable.rs:+3:9: +3:16
+ let mut _5: T; // in scope 0 at $DIR/unreachable.rs:+3:11: +3:12
+ let mut _6: T; // in scope 0 at $DIR/unreachable.rs:+3:14: +3:15
+ let _7: (); // in scope 0 at $DIR/unreachable.rs:+5:9: +5:16
+ let mut _8: T; // in scope 0 at $DIR/unreachable.rs:+5:11: +5:12
+ let mut _9: T; // in scope 0 at $DIR/unreachable.rs:+5:14: +5:15
+ scope 1 {
+- debug b => _2; // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10
++ debug b => _1; // in scope 1 at $DIR/unreachable.rs:+1:9: +1:10
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/unreachable.rs:+1:9: +1:10
+- _2 = _1; // scope 0 at $DIR/unreachable.rs:+1:13: +1:14
++ nop; // scope 0 at $DIR/unreachable.rs:+1:9: +1:10
++ nop; // scope 0 at $DIR/unreachable.rs:+1:13: +1:14
+ StorageLive(_3); // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+ _3 = const false; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+- goto -> bb3; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
++ goto -> bb1; // scope 1 at $DIR/unreachable.rs:+2:8: +2:13
+ }
+
+ bb1: {
+- StorageLive(_4); // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
+- StorageLive(_5); // scope 1 at $DIR/unreachable.rs:+3:11: +3:12
+- _5 = _1; // scope 1 at $DIR/unreachable.rs:+3:11: +3:12
+- StorageLive(_6); // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
+- _6 = _2; // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
+- _4 = g::<T>(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
+- // mir::Constant
+- // + span: $DIR/unreachable.rs:11:9: 11:10
+- // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+- }
+-
+- bb2: {
+- StorageDead(_6); // scope 1 at $DIR/unreachable.rs:+3:15: +3:16
+- StorageDead(_5); // scope 1 at $DIR/unreachable.rs:+3:15: +3:16
+- StorageDead(_4); // scope 1 at $DIR/unreachable.rs:+3:16: +3:17
+- _0 = const (); // scope 1 at $DIR/unreachable.rs:+2:14: +4:6
+- goto -> bb5; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
+- }
+-
+- bb3: {
+ StorageLive(_7); // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
+- StorageLive(_8); // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
+- _8 = _2; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
++ nop; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
++ nop; // scope 1 at $DIR/unreachable.rs:+5:11: +5:12
+ StorageLive(_9); // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
+- _9 = _2; // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
+- _7 = g::<T>(move _8, move _9) -> bb4; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
++ _9 = _1; // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
++ _7 = g::<T>(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
+ // mir::Constant
+ // + span: $DIR/unreachable.rs:13:9: 13:10
+ // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+ }
+
+- bb4: {
++ bb2: {
+ StorageDead(_9); // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
+- StorageDead(_8); // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
++ nop; // scope 1 at $DIR/unreachable.rs:+5:15: +5:16
+ StorageDead(_7); // scope 1 at $DIR/unreachable.rs:+5:16: +5:17
+ _0 = const (); // scope 1 at $DIR/unreachable.rs:+4:12: +6:6
+- goto -> bb5; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
++ goto -> bb3; // scope 1 at $DIR/unreachable.rs:+2:5: +6:6
+ }
+
+- bb5: {
++ bb3: {
+ StorageDead(_3); // scope 1 at $DIR/unreachable.rs:+6:5: +6:6
+- StorageDead(_2); // scope 0 at $DIR/unreachable.rs:+7:1: +7:2
++ nop; // scope 0 at $DIR/unreachable.rs:+7:1: +7:2
+ return; // scope 0 at $DIR/unreachable.rs:+7:2: +7:2
+ }
+ }
+
--- /dev/null
+// Check that unreachable code is removed after the destination propagation.
+// Regression test for issue #105428.
+//
+// compile-flags: --crate-type=lib -Zmir-opt-level=0
+// compile-flags: -Zmir-enable-passes=+ConstProp,+SimplifyConstCondition-after-const-prop,+DestinationPropagation
+
+// EMIT_MIR unreachable.f.DestinationPropagation.diff
+pub fn f<T: Copy>(a: T) {
+ let b = a;
+ if false {
+ g(a, b);
+ } else {
+ g(b, b);
+ }
+}
+
+#[inline(never)]
+pub fn g<T: Copy>(_: T, _: T) {}
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _10 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _11 = Ne(_7, move _10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
bb1: {
bb2: {
- _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
- }
-
- bb3: {
+
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
}
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _8) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _12 = Ne(_8, move _11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(move _12) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
bb1: {
- _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _6) -> [0: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
- }
-
- bb2: {
- bb3: {
- _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _7) -> [1: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
- }
-
- bb4: {
+
+ bb5: {
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(_8) -> [0: bb3, 1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
}
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _10 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ _11 = Ne(_7, move _10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
bb1: {
bb2: {
- _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
-- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+- switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
- }
-
- bb3: {
+
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++ switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
}
}
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
_10 = discriminant((_4.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
-- switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+- switchInt(move _10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+ StorageLive(_14); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+ _14 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+ StorageLive(_15); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+ _15 = Ne(_10, move _14); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+ StorageDead(_14); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+ switchInt(move _15) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++ switchInt(move _15) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
}
bb1: {
bb2: {
- _9 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
-- switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+- switchInt(move _9) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
- }
-
- bb3: {
_8 = discriminant((_4.2: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
-- switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+ switchInt(move _8) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+- switchInt(move _8) -> [1: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++ switchInt(move _8) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
}
- bb4: {
+
+ bb5: {
+ StorageDead(_15); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+ switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++ switchInt(_10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
}
}
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
_34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _11) -> [0: bb1, 1: bb3, 2: bb4, 3: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb1: {
_35 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_7 = discriminant((*_35)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _7) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb2: {
bb3: {
_36 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_8 = discriminant((*_36)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _8) -> [1: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb4: {
_37 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_9 = discriminant((*_37)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _9) -> [2: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb5: {
_38 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
_10 = discriminant((*_38)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+ switchInt(move _10) -> [3: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
}
bb6: {
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+ switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
}
bb1: {
_6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+ switchInt(move _6) -> [0: bb2, 1: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
}
bb2: {
bb4: {
_7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+ switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
}
bb5: {
bb0: {
_3 = discriminant(_1); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:11: +1:12
- switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
+ switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
}
bb1: {
bb2: {
_4 = discriminant((*_2)); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:26: +3:28
- switchInt(move _4) -> [1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
+ switchInt(move _4) -> [1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
}
bb3: {
bb0: {
_3 = discriminant((*_1)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
- switchInt(move _3) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+ switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
}
bb1: {
_4 = deref_copy (((*_1) as Some).0: &E<'_>); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
_2 = discriminant((*_4)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
- switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+ switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
}
bb2: {
- _2 = Eq(move _3, const true); // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
+ _2 = move _3; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
StorageDead(_3); // scope 0 at $DIR/equal_true.rs:+1:16: +1:17
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
}
bb1: {
bb0: {
FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential_or.rs:+1:11: +1:12
- switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
+ switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
}
bb1: {
bb2: {
_2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
- switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+ switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
}
bb3: {
- switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+ switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
}
bb4: {
_5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
- switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+ switchInt(move _5) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
}
bb5: {
_6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
- switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+ switchInt(move _6) -> [0: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
}
bb6: {
_3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
- switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+ switchInt(move _3) -> [0: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
}
bb7: {
_4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
- switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+ switchInt(move _4) -> [0: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
}
bb8: {
bb1: {
StorageDead(_5); // scope 0 at $DIR/funky_arms.rs:+4:36: +4:37
StorageLive(_6); // scope 1 at $DIR/funky_arms.rs:+8:9: +8:13
- switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
+ switchInt(_4) -> [0: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
}
bb2: {
bb5: {
StorageDead(_8); // scope 3 at $DIR/funky_arms.rs:+13:44: +13:45
_9 = discriminant(_7); // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
- switchInt(move _9) -> [1_isize: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
+ switchInt(move _9) -> [1: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
}
bb6: {
bb0: {
_8 = discriminant((*_1)); // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
- switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
+ switchInt(move _8) -> [0: bb7, 3: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
}
bb1: {
bb0: {
_11 = discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
- switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
+ switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
}
bb1: {
bb0: {
StorageLive(_2); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
_2 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
_2 = Eq(move _3, const -42f32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:17: +1:18
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14
- _2 = Eq(move _3, const 17_i8); // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
-- switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
+- switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
+ _2 = Eq(_3, const 17_i8); // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
-+ switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
++ switchInt(move _3) -> [17: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- _2 = Eq(move _3, const 'x'); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+ switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++ switchInt(move _3) -> [120: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- _2 = Eq(move _3, const 42_i8); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+ switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++ switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++ switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
}
bb1: {
_5 = _1; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16
- _4 = Ne(move _5, const 21_u32); // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
- StorageDead(_5); // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
-- switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
+- switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
+ nop; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
+ nop; // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
-+ switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
++ switchInt(move _5) -> [21: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
}
bb3: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+ switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++ switchInt(move _3) -> [4294967254: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
}
bb1: {
_3 = _1; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
- _2 = Eq(move _3, const 42_u32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
- StorageDead(_3); // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+ nop; // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+ switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++ switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
}
bb1: {
_3 = _1; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9
_2 = Gt(move _3, const 0_i32); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
StorageDead(_3); // scope 0 at $DIR/inline_diverging.rs:+1:12: +1:13
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
}
bb1: {
+ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46
+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
+ _9 = discriminant((*_10)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
}
- bb3: {
+
+ bb3: {
+ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+ switchInt(move _7) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
++ switchInt(move _7) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
+ }
+
+ bb4: {
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
_4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
- Retag(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
_3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
- Retag(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
_9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
// + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
_7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
- Retag(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
_6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
- Retag(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
+ StorageLive(_6); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
+ StorageLive(_7); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
+ _6 = discriminant((*_5)); // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-+ switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
++ switchInt(move _6) -> [0: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
}
bb2: {
}
bb3: {
- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
+ switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
}
bb4: {
StorageLive(_3); // scope 1 at $DIR/issue_38669.rs:+3:9: +5:10
StorageLive(_4); // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
_4 = _1; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
- switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
+ switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
}
bb3: {
}
bb8 (cleanup): {
- switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ switchInt(_5) -> [0: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
}
}
}
bb14 (cleanup): {
- switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
}
}
}
bb1: {
- switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+ switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
}
bb2: {
bb4: {
StorageDead(_3); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
_5 = discriminant(_1); // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
- switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+ switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
}
bb5: {
bb19: {
_10 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
}
bb20: {
- switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
}
bb21 (cleanup): {
_11 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
}
bb22 (cleanup): {
- switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
}
}
bb2: {
StorageDead(_7); // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20
_8 = discriminant(_6); // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
- switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
+ switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
}
bb3: {
StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ switchInt(move _15) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb4: {
StorageDead(_12); // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_10 = Not(move _11); // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_11); // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _10) -> [false: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ switchInt(move _10) -> [0: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb3: {
StorageDead(_33); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_31 = Not(move _32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _31) -> [false: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ switchInt(move _31) -> [0: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb12: {
bb2: {
_7 = discriminant(_2); // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
- switchInt(move _7) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+ switchInt(move _7) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
}
bb3: {
StorageDead(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
StorageDead(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
- switchInt(move _9) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
+ switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
}
bb6: {
bb1: {
StorageDead(_3); // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53
- switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+ switchInt(_2[0 of 4]) -> [0: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
}
bb2: {
- switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+ switchInt(_2[1 of 4]) -> [0: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
}
bb3: {
- switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+ switchInt(_2[2 of 4]) -> [0: bb5, 4294901760: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
}
bb4: {
StorageLive(_1); // scope 0 at $DIR/loop_test.rs:+4:5: +6:6
StorageLive(_2); // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
_2 = const true; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
}
bb1: {
_3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+ switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
}
bb2: {
_3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+ switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
}
bb2: {
_3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
}
bb1: {
_3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+ switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
}
bb1: {
_3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
StorageDead(_5); // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
StorageDead(_4); // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
- switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
+ switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
}
bb2: {
bb0: {
- FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16
-- switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+ switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+- switchInt((_2.0: bool)) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
}
bb1: {
- falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match_arm_scopes.rs:+2:9: +2:22
-+ switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++ switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
}
bb2: {
-- switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+ switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+- switchInt((_2.1: bool)) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
}
bb3: {
- }
-
- bb4: {
-- switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+- switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
- }
-
- bb5: {
StorageLive(_9); // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
StorageLive(_10); // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
_10 = _1; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-- switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+ switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+- switchInt(move _10) -> [0: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++ switchInt(move _10) -> [0: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
}
- bb9: {
- bb10: {
+ bb7: {
_9 = (*_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
-- switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+ switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+- switchInt(move _9) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++ switchInt(move _9) -> [0: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
}
- bb11: {
StorageLive(_12); // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
StorageLive(_13); // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
_13 = _1; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-- switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+ switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+- switchInt(move _13) -> [0: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++ switchInt(move _13) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
}
- bb14: {
- bb15: {
+ bb12: {
_12 = (*_6); // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
-- switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+ switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+- switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++ switchInt(move _12) -> [0: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
}
- bb16: {
StorageLive(_3); // scope 2 at $DIR/match_test.rs:+6:5: +11:6
FakeRead(ForMatchedPlace(None), _1); // scope 2 at $DIR/match_test.rs:+6:11: +6:12
_6 = Le(const 0_i32, _1); // scope 2 at $DIR/match_test.rs:+7:9: +7:14
- switchInt(move _6) -> [false: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+ switchInt(move _6) -> [0: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
}
bb1: {
_7 = Lt(_1, const 10_i32); // scope 2 at $DIR/match_test.rs:+7:9: +7:14
- switchInt(move _7) -> [false: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+ switchInt(move _7) -> [0: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
}
bb2: {
bb4: {
_4 = Le(const 10_i32, _1); // scope 2 at $DIR/match_test.rs:+8:9: +8:16
- switchInt(move _4) -> [false: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+ switchInt(move _4) -> [0: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
}
bb5: {
_5 = Le(_1, const 20_i32); // scope 2 at $DIR/match_test.rs:+8:9: +8:16
- switchInt(move _5) -> [false: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+ switchInt(move _5) -> [0: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
}
bb6: {
}
bb7: {
- switchInt(_1) -> [-1_i32: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
+ switchInt(_1) -> [4294967295: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
}
bb8: {
_8 = &shallow _1; // scope 2 at $DIR/match_test.rs:+6:11: +6:12
StorageLive(_9); // scope 2 at $DIR/match_test.rs:+7:18: +7:19
_9 = _2; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
- switchInt(move _9) -> [false: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
+ switchInt(move _9) -> [0: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
}
bb10: {
StorageLive(_4); // scope 2 at $DIR/matches_reduce_branches.rs:+3:9: +3:10
StorageLive(_5); // scope 3 at $DIR/matches_reduce_branches.rs:+4:9: +4:10
StorageLive(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +21:6
-- switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
+- switchInt(_1) -> [7: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
- }
-
- bb1: {
bb0: {
StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
-- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ StorageLive(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _4 = move _3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _2 = Eq(_4, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ StorageDead(_4); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+ switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb1: {
- }
-
- bb3: {
-- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb4: {
StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
_6 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
-- switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+- switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
- }
-
- bb1: {
+ _5 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
-- switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+- switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
- }
-
- bb4: {
+ _4 = Ne(_8, const false); // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
+ StorageDead(_8); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
-- switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+- switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
- }
-
- bb7: {
- }
-
- bb9: {
-- switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+- switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
- }
-
- bb10: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+ switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
}
bb1: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+ switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
}
bb1: {
FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
StorageLive(_7); // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
_7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
- switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+ switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
}
bb2: {
FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
StorageLive(_7); // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
_7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
- switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+ switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
}
bb2: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:11: +1:14
- switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
+ switchInt(move _2) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
}
bb1: {
- _2 = Ne(move _3, const false); // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
+ _2 = move _3; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
StorageDead(_3); // scope 0 at $DIR/not_equal_false.rs:+1:17: +1:18
- switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
}
bb1: {
- FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
_3 = discriminant(_1); // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
- switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+ switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
}
bb1: {
}
bb2: {
- switchInt((*(*((_1 as Some).0: &&i32)))) -> [0_i32: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+ switchInt((*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
}
bb3: {
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
StorageLive(_8); // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
_8 = _2; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
- switchInt(move _8) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
+ switchInt(move _8) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
}
bb5: {
bb3: {
- StorageDead(_8); // scope 2 at $DIR/remove_storage_markers.rs:+2:18: +2:19
_10 = discriminant(_7); // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
}
bb4: {
StorageLive(_3); // scope 1 at $DIR/retag.rs:+2:13: +2:19
StorageLive(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
_4 = &mut _1; // scope 1 at $DIR/retag.rs:+2:13: +2:19
- Retag(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
_3 = &raw mut (*_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19
- Retag([raw] _3); // scope 1 at $DIR/retag.rs:+2:13: +2:19
_2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
StorageDead(_3); // scope 1 at $DIR/retag.rs:+2:32: +2:33
StorageDead(_4); // scope 1 at $DIR/retag.rs:+2:33: +2:34
StorageLive(_10); // scope 4 at $DIR/retag.rs:+6:13: +6:15
StorageLive(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
_11 = &_8; // scope 4 at $DIR/retag.rs:+6:13: +6:15
- Retag(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
_10 = &raw const (*_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15
- Retag([raw] _10); // scope 4 at $DIR/retag.rs:+6:13: +6:15
_9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
StorageDead(_10); // scope 4 at $DIR/retag.rs:+6:30: +6:31
StorageDead(_11); // scope 4 at $DIR/retag.rs:+6:31: +6:32
StorageDead(_17); // scope 6 at $DIR/retag.rs:+7:33: +7:34
_15 = (*_16); // scope 6 at $DIR/retag.rs:+7:25: +7:34
_14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], 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
Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_24); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_22 = Not(move _23); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_23); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _22) -> [false: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ switchInt(move _22) -> [0: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
}
bb3: {
StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
bb0: {
- Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
// mir::Constant
_3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19
Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19
_0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10
- Retag(_0); // scope 1 at $DIR/retag.rs:+2:9: +2:10
StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6
return; // scope 0 at $DIR/retag.rs:+3:6: +3:6
}
Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
(_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
- Retag(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
_7 = &mut _1; // scope 1 at $DIR/retag.rs:+3:29: +3:35
- Retag(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
_6 = &mut (*_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
- Retag([2phase] _6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
_3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
// mir::Constant
// + span: $DIR/retag.rs:33:25: 33:28
_9 = move _3; // scope 2 at $DIR/retag.rs:+4:19: +4:20
Retag(_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
_8 = &mut (*_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20
- Retag(_8); // scope 2 at $DIR/retag.rs:+4:19: +4:20
StorageDead(_9); // scope 2 at $DIR/retag.rs:+4:22: +4:23
StorageLive(_10); // scope 3 at $DIR/retag.rs:+5:13: +5:14
_10 = move _8; // scope 3 at $DIR/retag.rs:+5:17: +5:18
StorageLive(_11); // scope 4 at $DIR/retag.rs:+7:13: +7:15
StorageLive(_12); // scope 4 at $DIR/retag.rs:+7:18: +7:29
_12 = &raw mut (*_10); // scope 4 at $DIR/retag.rs:+7:18: +7:19
- Retag([raw] _12); // scope 4 at $DIR/retag.rs:+7:18: +7:19
_11 = _12; // scope 4 at $DIR/retag.rs:+7:18: +7:29
StorageDead(_12); // scope 4 at $DIR/retag.rs:+7:29: +7:30
_2 = const (); // scope 1 at $DIR/retag.rs:+2:5: +8:6
StorageLive(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18
StorageLive(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
_18 = &_1; // scope 6 at $DIR/retag.rs:+15:16: +15:18
- Retag(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
_17 = &(*_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18
- Retag(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18
_15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
}
Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
(_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
- Retag(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
_28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23
// + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
_23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23
- Retag(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
_22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
- Retag(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
_19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
// mir::Constant
// + span: $DIR/retag.rs:48:13: 48:20
StorageLive(_25); // scope 7 at $DIR/retag.rs:+21:9: +21:11
StorageLive(_26); // scope 7 at $DIR/retag.rs:+21:14: +21:28
_26 = &raw const (*_15); // scope 7 at $DIR/retag.rs:+21:14: +21:16
- Retag([raw] _26); // scope 7 at $DIR/retag.rs:+21:14: +21:16
_25 = _26; // scope 7 at $DIR/retag.rs:+21:14: +21:28
StorageDead(_26); // scope 7 at $DIR/retag.rs:+21:28: +21:29
StorageLive(_27); // scope 8 at $DIR/retag.rs:+23:5: +23:18
Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24
StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
_3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10
- Retag(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
_0 = &mut (*_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10
- Retag(_0); // scope 0 at $DIR/retag.rs:+1:9: +1:10
StorageDead(_3); // scope 0 at $DIR/retag.rs:+2:5: +2:6
return; // scope 0 at $DIR/retag.rs:+2:6: +2:6
}
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- switchInt(move _10) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+- switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
bb1: {
- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
- }
-
- bb2: {
- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
- bb6: {
- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
- bb8: {
bb0: {
StorageLive(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
_3 = discriminant(_1); // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
- switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+ switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
}
bb1: {
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+ switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
}
bb2: {
-
- bb4: {
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-- switchInt(move _8) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+ switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+- switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
}
- bb5: {
}
- bb3: {
-- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+- switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+ bb2: {
-+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
++ switchInt(move _2) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
}
- bb4: {
}
bb3: {
- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+ switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
}
bb4: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
_1 = const false; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
-- switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
+- switchInt(const false) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
+ goto -> bb3; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
}
StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
_5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
- switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+ switchInt(move _5) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
}
bb1: {
_4 = discriminant((_1.1: std::option::Option<T>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
- switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+ switchInt(move _4) -> [0: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
}
bb2: {
- _5 = const false; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
- _5 = const true; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
_2 = discriminant(_1); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12
+ switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12
}
bb1: {
- _1 = _2; // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
+ _1 = const false; // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
StorageDead(_2); // scope 0 at $DIR/simplify_match.rs:+1:30: +1:31
-- switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
-+ switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+- switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
++ switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
}
bb1: {
bb4 (cleanup): {
_6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
bb5: {
bb6: {
_8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
bb7: {
bb10 (cleanup): {
_12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
bb11: {
bb12: {
_14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
bb13: {
bb15: {
_2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
_3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
}
discriminant(_2) = 1; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+1:28: +1:29
_4 = discriminant(_2); // scope 1 at $DIR/sroa.rs:+1:12: +1:19
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
+ switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
}
bb1: {
bb0: {
StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
_3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
- switchInt(move _3) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+ switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
}
bb1: {
((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
discriminant(_2) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
_6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
}
bb2: {
((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
discriminant(_2) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
_6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
}
bb3: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
- switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
+ switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
}
bb1: {
Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+ switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
}
bb1: {
Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- switchInt(move _8) -> [4_isize: bb5, 5_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+ switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb2: {
Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
-- switchInt(move _3) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
-+ switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
++ switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
}
bb1: {
Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- switchInt(move _8) -> [4_isize: bb8, 5_isize: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+ switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb6: {
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
_4 = &(_1.1: Test1); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
_5 = discriminant((*_4)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
- switchInt(move _5) -> [2_isize: bb3, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+ switchInt(move _5) -> [2: bb3, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
}
bb1: {
StorageDead(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
StorageLive(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
_10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
- switchInt(move _10) -> [2_isize: bb7, 3_isize: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+ switchInt(move _10) -> [2: bb7, 3: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
}
bb5: {
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
_4 = &(_1.1: Test1); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
_5 = discriminant((*_4)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
-- switchInt(move _5) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
-+ switchInt(move _5) -> [2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
++ switchInt(move _5) -> [2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
}
bb1: {
StorageDead(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
StorageLive(_9); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
_10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
-- switchInt(move _10) -> [0_isize: bb9, 1_isize: bb10, 2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
-+ switchInt(move _10) -> [2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+- switchInt(move _10) -> [0: bb9, 1: bb10, 2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
++ switchInt(move _10) -> [2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
}
bb7: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
-- switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+ switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++ switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
}
bb1: {
bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
-- switchInt(move _2) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+ switchInt(move _2) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++ switchInt(move _2) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
}
bb1: {
bb1: {
_2 = discriminant(_1); // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
-- switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
-+ switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
+- switchInt(move _2) -> [1: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
++ switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
}
bb2: {
- StorageLive(_5); // scope 2 at $DIR/unreachable.rs:+4:9: +8:10
- StorageLive(_6); // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
- _6 = const true; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
-- switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
+- switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
+ unreachable; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
}
bb1: {
_3 = discriminant(_2); // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
- switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
+ switchInt(move _3) -> [1: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
}
bb2: {
StorageLive(_5); // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
StorageLive(_6); // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
_6 = _1; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
- switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
+ switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
}
bb3: {
Deinit(_3); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
discriminant(_3) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- _4 = discriminant(_3); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
-- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+ _4 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
-+ switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
++ switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
}
bb1: {
- switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+ switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
}
bb2: {
bb2: {
StorageDead(_3); // scope 0 at $DIR/while_storage.rs:+1:21: +1:22
- switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
+ switchInt(move _2) -> [0: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
}
bb3: {
bb4: {
StorageDead(_5); // scope 0 at $DIR/while_storage.rs:+2:22: +2:23
- switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+ switchInt(move _4) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
}
bb5: {
include ../tools.mk
all:
- $(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse
+ $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse
if crate_type != CrateType::Rlib {
sess.fatal(&format!("Crate type is {:?}", crate_type));
}
- let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+ let output_name = out_filename(sess, crate_type, &outputs, crate_name);
let mut out_file = ::std::fs::File::create(output_name).unwrap();
write!(out_file, "This has been \"compiled\" successfully.").unwrap();
}
rm -f expected_*
endif
-include clear_expected_if_blessed
+-include clear_expected_if_blessed
%: $(SOURCEDIR)/lib/%.rs
# Compile the test library with coverage instrumentation
# ignore-msvc
# needs-rust-lld
+# ignore-s390x lld does not yet support s390x as target
all:
RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
+++ /dev/null
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-assert: ("#functions")
-goto: "./struct.Foo.html"
-assert: ("div.item-decl")
// This test checks that the source code pages sidebar toggle is working as expected.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
click: ".srclink"
-wait-for: "#sidebar-toggle"
-click: "#sidebar-toggle"
+wait-for: "#src-sidebar-toggle"
+click: "#src-sidebar-toggle"
fail: true
assert-css: ("#source-sidebar", { "left": "-300px" })
{"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
)),
- ("move-cursor-to", ".docblock .example-wrap.compile_fail"),
+ ("move-cursor-to", ".docblock .example-wrap.compile_fail .tooltip"),
("assert-css", (
".docblock .example-wrap.compile_fail .tooltip",
{"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
)),
- ("move-cursor-to", ".docblock .example-wrap.should_panic"),
+ ("move-cursor-to", ".docblock .example-wrap.should_panic .tooltip"),
("assert-css", (
".docblock .example-wrap.should_panic .tooltip",
{"border-left": "2px solid rgba(255, 142, 0, 0.6)"},
)),
- ("move-cursor-to", ".docblock .example-wrap.ignore"),
+ ("move-cursor-to", ".docblock .example-wrap.ignore .tooltip"),
("assert-css", (
".docblock .example-wrap.ignore .tooltip",
// the sidebar toggle button on the source code pages
goto: "file://" + |DOC_PATH| + "/src/lib2/lib.rs.html"
-assert-css: ("#sidebar-toggle > button", {"cursor": "pointer"})
+assert-css: ("#src-sidebar-toggle > button", {"cursor": "pointer"})
// Little explanations for this test: if the text wasn't displayed on two lines, it would take
// around 20px (which is the font size).
assert-property: (".docblock p > code", {"offsetHeight": "44"})
+
+// Same check, but where the long code block is also a link
+goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
+assert-property: (".docblock p > a > code", {"offsetHeight": "44"})
click: "input#line-numbers"
wait-for: 100 // wait-for-false does not exist
assert-false: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "false" }
// Finally, turn it on again.
click: "input#line-numbers"
wait-for: "pre.example-line-numbers"
+assert-local-storage: {"rustdoc-line-numbers": "true" }
compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"])
compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock table td", ["border"])
+
+define-function: (
+ "check-colors",
+ (theme, border_color, zebra_stripe_color),
+ [
+ ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+ ("reload"),
+ ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", {
+ "background-color": "rgba(0, 0, 0, 0)",
+ })),
+ ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", {
+ "background-color": |zebra_stripe_color|,
+ })),
+ ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", {
+ "background-color": "rgba(0, 0, 0, 0)",
+ })),
+ ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", {
+ "background-color": |zebra_stripe_color|,
+ })),
+ ("assert-css", (".top-doc .docblock table td", {
+ "border-style": "solid",
+ "border-width": "1px",
+ "border-color": |border_color|,
+ })),
+ ("assert-css", (".top-doc .docblock table th", {
+ "border-style": "solid",
+ "border-width": "1px",
+ "border-color": |border_color|,
+ })),
+ ]
+)
+
+call-function: ("check-colors", {
+ "theme": "dark",
+ "border_color": "rgb(224, 224, 224)",
+ "zebra_stripe_color": "rgb(42, 42, 42)",
+})
+call-function: ("check-colors", {
+ "theme": "ayu",
+ "border_color": "rgb(92, 103, 115)",
+ "zebra_stripe_color": "rgb(25, 31, 38)",
+})
+call-function: ("check-colors", {
+ "theme": "light",
+ "border_color": "rgb(224, 224, 224)",
+ "zebra_stripe_color": "rgb(245, 245, 245)",
+})
"color": |color|,
"background-color": |background|,
"box-shadow": |box_shadow| + " 0px -1px 0px 0px inset",
- "cursor": "default",
}, ALL)),
],
)
--- /dev/null
+// A docblock on an impl must have a margin to separate it from the contents.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
+
+// The text is about 24px tall, so if there's a margin, then their position will be >24px apart
+compare-elements-position-near-false: (
+ "#implementations-list > .implementors-toggle > .docblock > p",
+ "#implementations-list > .implementors-toggle > .impl-items",
+ {"y": 24}
+)
goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+// The next/prev buttons vertically scroll the code viewport between examples
store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
focus: ".scraped-example-list > .scraped-example .next"
press-key: "Enter"
"scrollTop": |initialScrollTop|
})
+// The expand button increases the scrollHeight of the minimized code viewport
store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
assert-property-false: (".scraped-example-list > .scraped-example pre", {
"scrollHeight": |smallOffsetHeight|
--- /dev/null
+goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+// Clicking "More examples..." will open additional examples
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+click: ".more-examples-toggle"
+assert-attribute: (".more-examples-toggle", {"open": ""})
+
+// Toggling all docs will close additional examples
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+
+// After re-opening the docs, the additional examples should stay closed
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
javascript: false
goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// Since the javascript is disabled, there shouldn't be a toggle.
-assert-false: "#sidebar-toggle"
+assert-false: "#src-sidebar-toggle"
wait-for-css: (".sidebar", {"display": "none"})
// Let's retry with javascript enabled.
javascript: true
reload:
-wait-for: "#sidebar-toggle"
-assert-css: ("#sidebar-toggle", {"visibility": "visible"})
-assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden"})
+wait-for: "#src-sidebar-toggle"
+assert-css: ("#src-sidebar-toggle", {"visibility": "visible"})
+assert-css: (".sidebar > *:not(#src-sidebar-toggle)", {"visibility": "hidden"})
// Let's expand the sidebar now.
-click: "#sidebar-toggle"
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
+click: "#src-sidebar-toggle"
+wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
// We now check that opening the sidebar and clicking a link will leave it open.
// The behavior here on desktop is different than the behavior on mobile,
[
("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
("reload"),
- ("wait-for-css", ("#sidebar-toggle", {"visibility": "visible"})),
+ ("wait-for-css", ("#src-sidebar-toggle", {"visibility": "visible"})),
("assert-css", (
"#source-sidebar details[open] > .files a.selected",
{"color": |color_hover|, "background-color": |background|},
)),
// Without hover or focus.
- ("assert-css", ("#sidebar-toggle > button", {"background-color": |background_toggle|})),
+ ("assert-css", ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})),
// With focus.
- ("focus", "#sidebar-toggle > button"),
+ ("focus", "#src-sidebar-toggle > button"),
("assert-css", (
- "#sidebar-toggle > button:focus",
+ "#src-sidebar-toggle > button:focus",
{"background-color": |background_toggle_hover|},
)),
("focus", ".search-input"),
// With hover.
- ("move-cursor-to", "#sidebar-toggle > button"),
+ ("move-cursor-to", "#src-sidebar-toggle > button"),
("assert-css", (
- "#sidebar-toggle > button:hover",
+ "#src-sidebar-toggle > button:hover",
{"background-color": |background_toggle_hover|},
)),
size: (500, 700)
reload:
// Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
+wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
// We now check it takes the full size of the display.
assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"})
assert-property: (".sidebar", {"clientWidth": "500", "clientHeight": "700"})
// We now check the display of the toggle once the sidebar is expanded.
-assert-property: ("#sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"})
+assert-property: ("#src-sidebar-toggle", {"clientWidth": "500", "clientHeight": "39"})
assert-css: (
- "#sidebar-toggle",
+ "#src-sidebar-toggle",
{
"border-top-width": "0px",
"border-right-width": "0px",
)
// We now check that the scroll position is kept when opening the sidebar.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: (".sidebar", {"width": "0px"})
// We scroll to line 117 to change the scroll position.
scroll-to: '//*[@id="117"]'
assert-window-property: {"pageYOffset": "2542"}
// Expanding the sidebar...
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: (".sidebar", {"width": "500px"})
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: (".sidebar", {"width": "0px"})
// The "scrollTop" property should be the same.
assert-window-property: {"pageYOffset": "2542"}
// We now check that the scroll position is restored if the window is resized.
size: (500, 700)
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
assert-window-property: {"pageYOffset": "0"}
size: (900, 900)
assert-window-property: {"pageYOffset": "2542"}
size: (500, 700)
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
// We now check that opening the sidebar and clicking a link will close it.
// but common sense dictates that if you have a list of files that fills the entire screen, and
// you click one of them, you probably want to actually see the file's contents, and not just
// make it the current selection.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
click: ".sidebar a.selected"
size: (1000, 1000)
wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
// Checking the source code sidebar.
// First we "open" it.
-click: "#sidebar-toggle"
+click: "#src-sidebar-toggle"
assert: ".source-sidebar-expanded"
// We check that the first entry of the sidebar is collapsed
/// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`.
pub mod long_code_block {}
+/// Very long code text [`hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`][lnk].
+///
+/// [lnk]: crate::long_code_block_link
+pub mod long_code_block_link {}
+
#[macro_export]
macro_rules! repro {
() => {};
/// | header1 | header2 |
/// |--------------------------|--------------------------|
/// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+ /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+ /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+ /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
pub struct DocBlockTable {}
impl DocBlockTableTrait for DocBlockTable {
fn function2() {}
}
}
+
+pub struct TypeWithImplDoc;
+
+/// impl doc
+impl TypeWithImplDoc {
+ /// fn doc
+ pub fn test_fn() {}
+}
--- /dev/null
+// All stability badges should have rounded corners and colored backgrounds.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+show-text: true
+define-function: (
+ "check-badge",
+ (theme, background, color),
+ [
+ ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+ ("assert", (".docblock .stab")),
+ ("assert", (".item-table .stab")),
+ ("assert-css", (".stab", {
+ "border-radius": "3px",
+ "color": |color|,
+ "background-color": |background|,
+ })),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"),
+ ("assert", (".item-info .stab")),
+ ("assert-css", (".stab", {
+ "border-radius": "3px",
+ "color": |color|,
+ "background-color": |background|,
+ })),
+ ]
+)
+
+call-function: ("check-badge", {
+ "theme": "ayu",
+ "color": "rgb(197, 197, 197)",
+ "background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+ "theme": "dark",
+ "color": "rgb(221, 221, 221)",
+ "background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+ "theme": "light",
+ "color": "rgb(0, 0, 0)",
+ "background": "rgb(255, 245, 214)",
+})
--- /dev/null
+// Just check we don't get an ICE for `N`.
+
+use std::cell::Cell;
+use std::mem;
+
+pub struct S {
+ s: Cell<usize>
+}
+
+pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+//~^ ERROR evaluation of constant value failed
--- /dev/null
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-evalutation-ice.rs:10:22
+ |
+LL | pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
--> $DIR/doc-cfg.rs:3:7
|
LL | #[doc(cfg(), cfg(foo, bar))]
- | ^^^^^
+ | ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
error: multiple `cfg` predicates are specified
--> $DIR/doc-cfg.rs:3:23
--> $DIR/doc-cfg.rs:7:7
|
LL | #[doc(cfg())]
- | ^^^^^
+ | ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
error: multiple `cfg` predicates are specified
--> $DIR/doc-cfg.rs:8:16
--- /dev/null
+// This test ensures that it's not crashing rustdoc.
+
+pub struct Foo<'a, 'b, T> {
+ field1: dyn Bar<'a, 'b,>,
+ //~^ ERROR
+ //~^^ ERROR
+}
+
+pub trait Bar<'x, 's, U>
+ where U: 'x,
+ Self:'x,
+ Self:'s
+{}
--- /dev/null
+error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/unable-fulfill-trait.rs:4:17
+ |
+LL | field1: dyn Bar<'a, 'b,>,
+ | ^^^ expected 1 generic argument
+ |
+note: trait defined here, with 1 generic parameter: `U`
+ --> $DIR/unable-fulfill-trait.rs:9:11
+ |
+LL | pub trait Bar<'x, 's, U>
+ | ^^^ -
+help: add missing generic argument
+ |
+LL | field1: dyn Bar<'a, 'b, U,>,
+ | +++
+
+error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
+ --> $DIR/unable-fulfill-trait.rs:4:13
+ |
+LL | field1: dyn Bar<'a, 'b,>,
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0227.
+For more information about an error, try `rustc --explain E0107`.
-Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
-Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
-Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+ -Z dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown)
-Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
-Z dylib-lto=val -- enables LTO for dylib crate type
-Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+++ /dev/null
-// Just check we don't get an ICE for `N`.
-
-use std::cell::Cell;
-use std::mem;
-
-pub struct S {
- s: Cell<usize>
-}
-
-pub const N: usize = 0 - (mem::size_of::<S>() != 4) as usize;
--- /dev/null
+// Regression test for https://github.com/rust-lang/rust/issues/105677.
+// This test ensures that the "Read more" link is only generated when
+// there is actually more documentation to read after the short summary.
+
+#![crate_name = "foo"]
+
+pub trait MyFrom {
+ /// # Hello
+ /// ## Yolo
+ /// more!
+ fn try_from1();
+ /// a
+ /// b
+ /// c
+ fn try_from2();
+ /// a
+ ///
+ /// b
+ ///
+ /// c
+ fn try_from3();
+}
+
+pub struct NonZero;
+
+// @has 'foo/struct.NonZero.html'
+impl MyFrom for NonZero {
+ // @matches - '//*[@class="docblock"]' '^Hello Read more$'
+ fn try_from1() {}
+ // @matches - '//*[@class="docblock"]' '^a\sb\sc$'
+ fn try_from2() {}
+ // @matches - '//*[@class="docblock"]' '^a Read more$'
+ fn try_from3() {}
+}
// summary. Trait methods with no documentation should not be wrapped.
//
// @has foo/trait.Foo.html
+// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
pub trait Foo {
+ /// is documented
+ type Item;
+
+ type Item2;
+
fn not_documented();
/// is_documented is documented
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]' 'These docs contain'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'reference link'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'https://example.com'
- // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'Read more'
- // @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.b'
fn b() {}
// @!has - '//*[@id="method.c"]/../../div[@class="docblock"]' 'code block'
TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
- TyKind::Projection(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
- TyKind::Opaque(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+ TyKind::Alias(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Param(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Placeholder(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:36:9
|
-LL | TyKind::Projection(..) => (),
+LL | TyKind::Alias(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:37:9
|
-LL | TyKind::Opaque(..) => (),
- | ^^^^^^ help: try using `ty::<kind>` directly: `ty`
-
-error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:38:9
- |
LL | TyKind::Param(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:39:9
+ --> $DIR/ty_tykind_usage.rs:38:9
|
LL | TyKind::Bound(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:40:9
+ --> $DIR/ty_tykind_usage.rs:39:9
|
LL | TyKind::Placeholder(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:41:9
+ --> $DIR/ty_tykind_usage.rs:40:9
|
LL | TyKind::Infer(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:42:9
+ --> $DIR/ty_tykind_usage.rs:41:9
|
LL | TyKind::Error(_) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:47:12
+ --> $DIR/ty_tykind_usage.rs:46:12
|
LL | if let TyKind::Int(int_ty) = kind {}
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:49:24
+ --> $DIR/ty_tykind_usage.rs:48:24
|
LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
| ^^^^^^^^^^
= help: try using `Ty` instead
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:51:37
+ --> $DIR/ty_tykind_usage.rs:50:37
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
= help: try using `Ty` instead
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:51:53
+ --> $DIR/ty_tykind_usage.rs:50:53
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
= help: try using `Ty` instead
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:54:9
+ --> $DIR/ty_tykind_usage.rs:53:9
|
LL | IrTyKind::Bool
| --------^^^^^^
| |
| help: try using `ty::<kind>` directly: `ty`
-error: aborting due to 33 previous errors
+error: aborting due to 32 previous errors
#[diag(compiletest_example)]
struct SubdiagnosticBad {
#[subdiagnostic(bad)]
- //~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
+ //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note,
}
#[diag(compiletest_example)]
struct SubdiagnosticBadLitStr {
#[subdiagnostic("bad")]
- //~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
+ //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note,
}
#[diag(compiletest_example)]
struct SubdiagnosticEagerCorrect {
#[subdiagnostic(eager)]
+ //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note,
}
#[diag(compiletest_example)]
struct SubdiagnosticEagerSuggestion {
#[subdiagnostic(eager)]
+ //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
sub: SubdiagnosticWithSuggestion,
}
|
= help: `#[label]` and `#[suggestion]` can only be applied to fields
-error: `#[subdiagnostic(bad)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:685:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:685:5
|
LL | #[subdiagnostic(bad)]
- | ^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
|
- = help: `eager` is the only supported nested attribute for `subdiagnostic`
+ = help: `subdiagnostic` does not support nested attributes
error: `#[subdiagnostic = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:693:5
|
LL | #[subdiagnostic = "bad"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: `eager` is the only supported nested attribute for `subdiagnostic`
error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:701:5
LL | #[subdiagnostic(bad, bad)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: `eager` is the only supported nested attribute for `subdiagnostic`
+ = help: `subdiagnostic` does not support nested attributes
-error: `#[subdiagnostic("...")]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:709:21
+error: `#[subdiagnostic(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:709:5
|
LL | #[subdiagnostic("bad")]
- | ^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: `eager` is the only supported nested attribute for `subdiagnostic`
+ = help: `subdiagnostic` does not support nested attributes
error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:717:5
LL | #[subdiagnostic(eager)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: eager subdiagnostics are not supported on lints
+ = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:725:5
+ |
+LL | #[subdiagnostic(eager)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `subdiagnostic` does not support nested attributes
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:746:5
+ |
+LL | #[subdiagnostic(eager)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `subdiagnostic` does not support nested attributes
error: expected at least one string literal for `code(...)`
- --> $DIR/diagnostic-derive.rs:775:18
+ --> $DIR/diagnostic-derive.rs:777:18
|
LL | #[suggestion(code())]
| ^^^^^^
error: `code(...)` must contain only string literals
- --> $DIR/diagnostic-derive.rs:783:23
+ --> $DIR/diagnostic-derive.rs:785:23
|
LL | #[suggestion(code(foo))]
| ^^^
error: `code = "..."`/`code(...)` must contain only string literals
- --> $DIR/diagnostic-derive.rs:791:18
+ --> $DIR/diagnostic-derive.rs:793:18
|
LL | #[suggestion(code = 3)]
| ^^^^^^^^
= help: normalized in stderr
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
- |
-LL | arg: impl IntoDiagnosticArg,
- | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
- = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 83 previous errors
+error: aborting due to 85 previous errors
Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
= note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
note: struct `core::alloc::Layout` is defined in crate `core`
--> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
- |
-LL | pub struct Layout {
- | ^^^^^^^^^^^^^^^^^
note: struct `Layout` is defined in the current crate
--> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
|
// compile-flags:-C panic=abort
// aux-build:helper.rs
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
+#![feature(rustc_private, lang_items)]
#![feature(alloc_error_handler)]
#![no_std]
+#![no_main]
extern crate alloc;
extern crate libc;
#[no_mangle]
pub fn __aeabi_unwind_cpp_pr1() {}
-use core::ptr::null_mut;
-use core::alloc::{GlobalAlloc, Layout};
use alloc::boxed::Box;
+use alloc::string::ToString;
+use core::alloc::{GlobalAlloc, Layout};
+use core::ptr::null_mut;
extern crate helper;
struct MyAllocator;
#[alloc_error_handler]
-fn my_oom(layout: Layout) -> !
-{
+fn my_oom(layout: Layout) -> ! {
use alloc::fmt::write;
unsafe {
let size = layout.size();
let mut s = alloc::string::String::new();
write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
- let s = s.as_str();
- libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
+ libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
libc::exit(0)
}
}
unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- if layout.size() < 4096 {
- libc::malloc(layout.size()) as _
- } else {
- null_mut()
- }
+ if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}
#[panic_handler]
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
unsafe {
- if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
- const PSTR: &str = "panic occurred: ";
- const CR: &str = "\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
- libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
- }
- if let Some(args) = panic_info.message() {
- let mut s = alloc::string::String::new();
- alloc::fmt::write(&mut s, *args).unwrap();
- let s = s.as_str();
- const PSTR: &str = "panic occurred: ";
- const CR: &str = "\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
- libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
- } else {
- const PSTR: &str = "panic occurred\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- }
+ let s = panic_info.to_string();
+ const PSTR: &str = "panic occurred: ";
+ const CR: &str = "\n";
+ libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
+ libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
+ libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
libc::exit(1)
}
}
// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
// unwind. So, for this test case we will define the symbol.
#[lang = "eh_personality"]
-extern fn rust_eh_personality() {}
+extern "C" fn rust_eh_personality() {}
-#[derive(Debug)]
+#[derive(Default, Debug)]
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
- let zero = Box::<Page>::new_zeroed();
- let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+ let zero = Box::<Page>::new(Default::default());
helper::work_with(&zero);
1
}
// only-linux
// compile-flags:-C panic=abort
// aux-build:helper.rs
-// gate-test-default_alloc_error_handler
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
-#![feature(default_alloc_error_handler)]
+#![feature(rustc_private, lang_items)]
#![no_std]
+#![no_main]
extern crate alloc;
extern crate libc;
pub fn __aeabi_unwind_cpp_pr1() {}
use alloc::boxed::Box;
+use alloc::string::ToString;
use core::alloc::{GlobalAlloc, Layout};
use core::ptr::null_mut;
unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- if layout.size() < 4096 {
- libc::malloc(layout.size()) as _
- } else {
- null_mut()
- }
+ if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}
#[panic_handler]
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
unsafe {
- if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
- const PSTR: &str = "panic occurred: ";
- const CR: &str = "\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
- libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
- }
- if let Some(args) = panic_info.message() {
- let mut s = alloc::string::String::new();
- alloc::fmt::write(&mut s, *args).unwrap();
- let s = s.as_str();
- const PSTR: &str = "panic occurred: ";
- const CR: &str = "\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
- libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
- } else {
- const PSTR: &str = "panic occurred\n";
- libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
- }
+ let s = panic_info.to_string();
+ const PSTR: &str = "panic occurred: ";
+ const CR: &str = "\n";
+ libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
+ libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
+ libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
libc::exit(0)
}
}
// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
// unwind. So, for this test case we will define the symbol.
#[lang = "eh_personality"]
-extern fn rust_eh_personality() {}
+extern "C" fn rust_eh_personality() {}
-#[derive(Debug)]
+#[derive(Default, Debug)]
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
- let zero = Box::<Page>::new_zeroed();
- let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+ let zero = Box::<Page>::new(Default::default());
helper::work_with(&zero);
1
}
|
LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
| ^^^^^^^^^^^^ required by this bound in `f1`
+help: consider borrowing the argument
+ |
+LL | f1(|_: &(), _: &()| {});
+ | ~~~ ~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:3:5
|
LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2`
+help: consider borrowing the argument
+ |
+LL | f2(|_: &'a (), _: &()| {});
+ | ~~~~~~ ~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
|
LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
| ^^^^^^^^^^^^^^^ required by this bound in `f3`
+help: consider borrowing the argument
+ |
+LL | f3(|_: &(), _: &()| {});
+ | ~~~ ~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:5:5
|
LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4`
+help: consider borrowing the argument
+ |
+LL | f4(|_: &(), _: &'r ()| {});
+ | ~~~ ~~~~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
|
LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5`
+help: consider borrowing the argument
+ |
+LL | f5(|_: &'r (), _: &'r ()| {});
+ | ~~~~~~ ~~~~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:7:5
|
LL | g1(|_: (), _: ()| {});
- | ^^ -------------- found signature defined here
- | |
+ | ^^ --------------
+ | | | |
+ | | | help: consider borrowing the argument: `&()`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
--> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
|
LL | g2(|_: (), _: ()| {});
- | ^^ -------------- found signature defined here
- | |
+ | ^^ --------------
+ | | | |
+ | | | help: consider borrowing the argument: `&()`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
--> $DIR/anonymous-higher-ranked-lifetime.rs:9:5
|
LL | g3(|_: (), _: ()| {});
- | ^^ -------------- found signature defined here
- | |
+ | ^^ --------------
+ | | | |
+ | | | help: consider borrowing the argument: `&'s ()`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
|
LL | g4(|_: (), _: ()| {});
- | ^^ -------------- found signature defined here
- | |
+ | ^^ --------------
+ | | | |
+ | | | help: consider borrowing the argument: `&()`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
|
LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1`
+help: consider borrowing the argument
+ |
+LL | h1(|_: &(), _: (), _: &(), _: ()| {});
+ | ~~~ ~~~
error[E0631]: type mismatch in closure arguments
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
|
LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2`
+help: consider borrowing the argument
+ |
+LL | h2(|_: &(), _: (), _: &'t0 (), _: ()| {});
+ | ~~~ ~~~~~~~
error: aborting due to 11 previous errors
--- /dev/null
+use std::fmt::Display;
+
+fn foo(x: &(dyn Display + Send)) {}
+
+fn main() {
+ foo();
+ //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
--- /dev/null
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/display-is-suggestable.rs:6:5
+ |
+LL | foo();
+ | ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing
+ |
+note: function defined here
+ --> $DIR/display-is-suggestable.rs:3:4
+ |
+LL | fn foo(x: &(dyn Display + Send)) {}
+ | ^^^ ------------------------
+help: provide the argument
+ |
+LL | foo(/* &dyn std::fmt::Display + Send */);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
|
help: consider giving this pattern a type
|
-LL | let [_, _]: _ = a.into();
- | +++
+LL | let [_, _]: /* Type */ = a.into();
+ | ++++++++++++
error: aborting due to previous error
--- /dev/null
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features, dead_code)]
+#![deny(non_camel_case_types)]
+
+struct S;
+
+impl S {
+ type typ = ();
+ //~^ ERROR associated type `typ` should have an upper camel case name
+}
+
+fn main() {}
--- /dev/null
+error: associated type `typ` should have an upper camel case name
+ --> $DIR/style.rs:8:10
+ |
+LL | type typ = ();
+ | ^^^ help: convert the identifier to upper camel case: `Typ`
+ |
+note: the lint level is defined here
+ --> $DIR/style.rs:3:9
+ |
+LL | #![deny(non_camel_case_types)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// check-pass
+// compile-flags: -C debug_assertions=yes -Zunstable-options
+
+#[allow(dead_code)]
+fn problematic_function<Space>()
+where
+ DefaultAlloc: FinAllok<R1, Space>,
+{
+ let e = Edge2dElement;
+ let _ = Into::<Point>::into(e.map_reference_coords());
+}
+impl<N> Allocator<N, R0> for DefaultAlloc {
+ type Buffer = MStorage;
+}
+impl<N> Allocator<N, R1> for DefaultAlloc {
+ type Buffer = MStorage;
+}
+impl<N, D> From<VectorN<N, D>> for Point
+where
+ DefaultAlloc: Allocator<N, D>,
+{
+ fn from(_: VectorN<N, D>) -> Self {
+ unimplemented!()
+ }
+}
+impl<GeometryDim, NodalDim> FinAllok<GeometryDim, NodalDim> for DefaultAlloc
+where
+ DefaultAlloc: Allocator<Ure, GeometryDim>,
+ DefaultAlloc: Allocator<Ure, NodalDim>
+{
+}
+impl FiniteElement<R1> for Edge2dElement {
+ fn map_reference_coords(&self) -> VectorN<Ure, R1> {
+ unimplemented!()
+ }
+}
+type VectorN<N, R> = (N, R, <DefaultAlloc as Allocator<N, R>>::Buffer);
+struct DefaultAlloc;
+struct R0;
+struct R1;
+struct MStorage;
+struct Point;
+struct Edge2dElement;
+struct Ure;
+trait Allocator<N, R> {
+ type Buffer;
+}
+trait FinAllok<GeometryDim, NodalDim>:
+ Allocator<Ure, GeometryDim> +
+ Allocator<Ure, NodalDim> +
+{
+}
+trait FiniteElement<Rau>
+where
+ DefaultAlloc: FinAllok<Rau, Rau>,
+{
+ fn map_reference_coords(&self) -> VectorN<Ure, Rau>;
+}
+fn main() {}
--- /dev/null
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/const-projection-err.rs:4:26
+ |
+LL | #![cfg_attr(gce, feature(generic_const_exprs))]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+ --> $DIR/const-projection-err.rs:14:11
+ |
+LL | foo::<T>();
+ | ^ expected `0`, found `1`
+ |
+note: required by a bound in `foo`
+ --> $DIR/const-projection-err.rs:11:28
+ |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
--- /dev/null
+// revisions: stock gce
+
+#![feature(associated_const_equality)]
+#![cfg_attr(gce, feature(generic_const_exprs))]
+//[gce]~^ WARN the feature `generic_const_exprs` is incomplete
+
+trait TraitWAssocConst {
+ const A: usize;
+}
+
+fn foo<T: TraitWAssocConst<A = 1>>() {}
+
+fn bar<T: TraitWAssocConst<A = 0>>() {
+ foo::<T>();
+ //~^ ERROR type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+}
+
+fn main() {}
--- /dev/null
+error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
+ --> $DIR/const-projection-err.rs:14:11
+ |
+LL | foo::<T>();
+ | ^ expected `1`, found `<T as TraitWAssocConst>::A`
+ |
+ = note: expected constant `1`
+ found constant `<T as TraitWAssocConst>::A`
+note: required by a bound in `foo`
+ --> $DIR/const-projection-err.rs:11:28
+ |
+LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
|
note: associated type defined here
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | type Item;
- | ^^^^^^^^^
error: aborting due to 2 previous errors
fn main() {
let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
- //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+ //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
}
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
--> $DIR/associated-types-overridden-binding-2.rs:6:43
|
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
...
LL | let x: isize = Foo::bar();
| ^^^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | let x: isize = <isize as Foo>::bar();
+ | +++++++++ +
error: aborting due to previous error
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^ required by this bound in `Vec`
error: aborting due to previous error
|
note: required by a bound in `Add`
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Add<Rhs = Self> {
- | ^^^^^^^^^^ required by this bound in `Add`
help: consider further restricting `Self`
|
LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> + Sized {}
--> $DIR/async-await-let-else.rs:33:28
|
LL | (Rc::new(()), bar().await);
- | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
- | |
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
| has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
- --> $DIR/async-await-let-else.rs:33:35
- |
-LL | (Rc::new(()), bar().await);
- | ^
note: required by a bound in `is_send`
--> $DIR/async-await-let-else.rs:19:15
|
--> $DIR/async-await-let-else.rs:33:28
|
LL | (Rc::new(()), bar().await);
- | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
- | |
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
| has type `Rc<()>` which is not `Send`
-note: `Rc::new(())` is later dropped here
- --> $DIR/async-await-let-else.rs:33:35
- |
-LL | (Rc::new(()), bar().await);
- | ^
note: required by a bound in `is_send`
--> $DIR/async-await-let-else.rs:19:15
|
--- /dev/null
+// compile-flags: -Zdrop-tracking
+// edition: 2021
+
+fn main() {}
+
+async fn foo() {
+ None { value: (), ..Default::default() }.await;
+ //~^ ERROR `Option<_>` is not a future
+ //~| ERROR variant `Option<_>::None` has no field named `value`
+}
--- /dev/null
+error[E0559]: variant `Option<_>::None` has no field named `value`
+ --> $DIR/drop-track-bad-field-in-fru.rs:7:12
+ |
+LL | None { value: (), ..Default::default() }.await;
+ | ^^^^^ `Option<_>::None` does not have this field
+
+error[E0277]: `Option<_>` is not a future
+ --> $DIR/drop-track-bad-field-in-fru.rs:7:45
+ |
+LL | None { value: (), ..Default::default() }.await;
+ | ^^^^^^
+ | |
+ | `Option<_>` is not a future
+ | help: remove the `.await`
+ |
+ = help: the trait `Future` is not implemented for `Option<_>`
+ = note: Option<_> must be a future or must implement `IntoFuture` to be awaited
+ = note: required for `Option<_>` to implement `IntoFuture`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0559.
+For more information about an error, try `rustc --explain E0277`.
found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
note: function defined here
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
- | ^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/generator-desc.rs:12:16
-// check-pass
// edition: 2021
#![feature(async_fn_in_trait)]
}
impl MyTrait for i32 {
- // This will break once a PR that implements #102745 is merged
fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
- Box::pin(async {
- *self
- })
+ //~^ ERROR method `foo` should be async
+ Box::pin(async { *self })
}
}
--- /dev/null
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/async-example-desugared-boxed.rs:15:5
+ |
+LL | async fn foo(&self) -> i32;
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::Poll;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+#[derive(Clone)]
+struct MyFuture(i32);
+
+impl Future for MyFuture {
+ type Output = i32;
+ fn poll(
+ self: Pin<&mut Self>,
+ _: &mut std::task::Context<'_>,
+ ) -> Poll<<Self as Future>::Output> {
+ Poll::Ready(self.0)
+ }
+}
+
+impl MyTrait for i32 {
+ // FIXME: this should eventually require `#[refine]` to compile, because it also provides
+ // `Clone`.
+ fn foo(&self) -> impl Future<Output = i32> + Clone {
+ MyFuture(*self)
+ }
+}
+
+fn main() {}
--- /dev/null
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::task::Poll;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+struct MyFuture;
+impl Future for MyFuture {
+ type Output = i32;
+ fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+ Poll::Ready(0)
+ }
+}
+
+impl MyTrait for u32 {
+ fn foo(&self) -> MyFuture {
+ //~^ ERROR method `foo` should be async
+ MyFuture
+ }
+}
+
+fn main() {}
--- /dev/null
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/async-example-desugared-manual.rs:23:5
+ |
+LL | async fn foo(&self) -> i32;
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> MyFuture {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
}
impl MyTrait for i32 {
- // This will break once a PR that implements #102745 is merged
fn foo(&self) -> impl Future<Output = i32> + '_ {
- async {
- *self
- }
+ async { *self }
}
}
--- /dev/null
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait MyTrait {
+ async fn bar(&abc self);
+ //~^ ERROR expected identifier, found keyword `self`
+ //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self`
+}
+
+impl MyTrait for () {
+ async fn bar(&self) {}
+}
+
+fn main() {}
--- /dev/null
+error: expected identifier, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+ --> $DIR/bad-signatures.rs:7:23
+ |
+LL | async fn bar(&abc self);
+ | -----^^^^
+ | | |
+ | | expected one of `:`, `@`, or `|`
+ | help: declare the type after the parameter binding: `<identifier>: <type>`
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/bad-signatures.rs:3:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
impl MyTrait for i32 {
fn foo(&self) -> i32 {
- //~^ ERROR: `i32` is not a future [E0277]
+ //~^ ERROR: method `foo` should be async
*self
}
}
-error[E0277]: `i32` is not a future
- --> $DIR/fn-not-async-err.rs:11:22
- |
-LL | fn foo(&self) -> i32 {
- | ^^^ `i32` is not a future
- |
- = help: the trait `Future` is not implemented for `i32`
- = note: i32 must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `MyTrait::foo::{opaque#0}`
- --> $DIR/fn-not-async-err.rs:7:28
+error: method `foo` should be async because the method from the trait is async
+ --> $DIR/fn-not-async-err.rs:11:5
|
LL | async fn foo(&self) -> i32;
- | ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
+ | --------------------------- required because the trait method is async
+...
+LL | fn foo(&self) -> i32 {
+ | ^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0277`.
impl MyTrait for i32 {
fn foo(&self) -> impl Future<Output = i32> {
//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
- async {
- *self
- }
+ async { *self }
}
}
--- /dev/null
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+pub trait Pool {
+ type Conn;
+
+ async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+ &'a self,
+ callback: F,
+ ) -> ();
+}
+
+pub struct PoolImpl;
+pub struct ConnImpl;
+
+impl Pool for PoolImpl {
+ type Conn = ConnImpl;
+
+ async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future<Output = ()>>(
+ &'a self,
+ _callback: F,
+ ) -> () {
+ todo!()
+ }
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+ async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
| _____________-
LL | | foo(tx.clone());
LL | | }).await;
- | | - ^^^^^^ await occurs here, with the value maybe used later
- | |_________|
+ | | - ^^^^^^- the value is later dropped here
+ | | | |
+ | |_________| await occurs here, with the value maybe used later
| has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send`
-note: the value is later dropped here
- --> $DIR/issue-70935-complex-spans.rs:19:17
- |
-LL | }).await;
- | ^
error: aborting due to previous error
|
note: required by a bound in `File::open`
--> $SRC_DIR/std/src/fs.rs:LL:COL
- |
-LL | pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
- | ^^^^^^^^^^^ required by this bound in `File::open`
error: aborting due to previous error
| |
| expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic argument
|
LL | async fn copy() -> Result<(), E>
--> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
|
LL | bar(Foo(std::ptr::null())).await;
- | ---------------- ^^^^^^ await occurs here, with `std::ptr::null()` maybe used later
- | |
+ | ---------------- ^^^^^^- `std::ptr::null()` is later dropped here
+ | | |
+ | | await occurs here, with `std::ptr::null()` maybe used later
| has type `*const u8` which is not `Send`
-note: `std::ptr::null()` is later dropped here
- --> $DIR/issue-65436-raw-ptr-not-send.rs:18:41
- |
-LL | bar(Foo(std::ptr::null())).await;
- | ^
help: consider moving this into a `let` binding to create a shorter lived borrow
--> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
|
--> $DIR/auxiliary/issue_67893.rs:9:26
|
LL | f(*x.lock().unwrap()).await;
- | ----------------- ^^^^^^ await occurs here, with `x.lock().unwrap()` maybe used later
- | |
+ | ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
+ | | |
+ | | await occurs here, with `x.lock().unwrap()` maybe used later
| has type `MutexGuard<'_, ()>` which is not `Send`
-note: `x.lock().unwrap()` is later dropped here
- --> $DIR/auxiliary/issue_67893.rs:9:32
- |
-LL | f(*x.lock().unwrap()).await;
- | ^
note: required by a bound in `g`
--> $DIR/issue-67893.rs:6:14
|
| ^^^^^
note: required by a bound in `Pin::<P>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL
- |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
- | ^^^^^ required by this bound in `Pin::<P>::new`
error: aborting due to previous error
...
LL | self.sleep.poll(cx)
| ^^^^ method not found in `Sleep`
+ --> $SRC_DIR/core/src/future/future.rs:LL:COL
|
- ::: $SRC_DIR/core/src/future/future.rs:LL:COL
- |
-LL | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
- | ---- the method is available for `Pin<&mut Sleep>` here
+ = note: the method is available for `Pin<&mut Sleep>` here
|
help: consider wrapping the receiver expression with the appropriate type
|
--- /dev/null
+// edition:2021
+
+#![feature(closure_track_caller, stmt_expr_attributes)]
+
+fn main() {
+ let _ = #[track_caller] async {
+ //~^ ERROR attribute should be applied to a function definition [E0739]
+ };
+}
--- /dev/null
+error[E0739]: attribute should be applied to a function definition
+ --> $DIR/async-block.rs:6:13
+ |
+LL | let _ = #[track_caller] async {
+ | _____________^^^^^^^^^^^^^^^_-
+LL | |
+LL | | };
+ | |_____- not a function definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0739`.
--- /dev/null
+// edition:2021
+
+#![feature(async_closure, stmt_expr_attributes)]
+
+fn main() {
+ let _ = #[track_caller] async || {
+ //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
+ //~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
+ };
+}
--- /dev/null
+error[E0658]: `#[track_caller]` on closures is currently unstable
+ --> $DIR/async-closure-gate.rs:6:13
+ |
+LL | let _ = #[track_caller] async || {
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error[E0658]: `#[track_caller]` on closures is currently unstable
+ --> $DIR/async-closure-gate.rs:6:38
+ |
+LL | let _ = #[track_caller] async || {
+ | ______________________________________^
+LL | |
+LL | |
+LL | | };
+ | |_____^
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
// run-pass
// edition:2021
// needs-unwind
-#![feature(closure_track_caller)]
+#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
use std::future::Future;
use std::panic;
Foo::bar_assoc().await
}
+async fn foo_closure() {
+ let c = #[track_caller] async || {
+ panic!();
+ };
+ c().await
+}
+
fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
let loc = Arc::new(Mutex::new(None));
assert_eq!(panicked_at(|| block_on(foo())), 41);
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
+ assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
}
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn sub(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn mul(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn div(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn rem(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn bitand(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn bitor(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn bitxor(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn shl(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn shr(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^^
help: consider further restricting this bound
|
LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^^
error[E0507]: cannot move out of `*n` which is behind a shared reference
--> $DIR/binop-move-semantics.rs:32:5
|
LL | struct A;
| ^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Add<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot subtract `A` from `A`
--> $DIR/issue-28837.rs:8:7
|
LL | struct A;
| ^^^^^^^^ must implement `Sub<_>`
-note: the following trait must be implemented
+note: the trait `Sub` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Sub<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot multiply `A` by `A`
--> $DIR/issue-28837.rs:10:7
|
LL | struct A;
| ^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Mul<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot divide `A` by `A`
--> $DIR/issue-28837.rs:12:7
|
LL | struct A;
| ^^^^^^^^ must implement `Div<_>`
-note: the following trait must be implemented
+note: the trait `Div` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Div<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot mod `A` by `A`
--> $DIR/issue-28837.rs:14:7
|
LL | struct A;
| ^^^^^^^^ must implement `Rem<_>`
-note: the following trait must be implemented
+note: the trait `Rem` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Rem<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: no implementation for `A & A`
--> $DIR/issue-28837.rs:16:7
|
LL | struct A;
| ^^^^^^^^ must implement `BitAnd<_>`
-note: the following trait must be implemented
+note: the trait `BitAnd` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait BitAnd<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: no implementation for `A | A`
--> $DIR/issue-28837.rs:18:7
|
LL | struct A;
| ^^^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait BitOr<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: no implementation for `A << A`
--> $DIR/issue-28837.rs:20:7
|
LL | struct A;
| ^^^^^^^^ must implement `Shl<_>`
-note: the following trait must be implemented
+note: the trait `Shl` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait Shl<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: no implementation for `A >> A`
--> $DIR/issue-28837.rs:22:7
|
LL | struct A;
| ^^^^^^^^ must implement `Shr<_>`
-note: the following trait must be implemented
+note: the trait `Shr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait Shr<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: binary operation `==` cannot be applied to type `A`
--> $DIR/issue-28837.rs:24:7
|
LL | struct Thing {
| ^^^^^^^^^^^^ must implement `Mul<_>`
-note: the following trait must be implemented
+note: the trait `Mul` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Mul<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
|
LL | match *s { S(v) => v }
| ^^ -
- | | |
- | | data moved here
- | | move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*s`
+ | |
+ | data moved here
+ | move occurs because `v` has type `Vec<isize>`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *s { S(v) => v }
+LL + match s { S(v) => v }
+ |
error: aborting due to previous error
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15
|
LL | for &a in x.iter() {
- | -- ^^^^^^^^
- | ||
- | |data moved here
- | |move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `a`
+ | - ^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - for &a in x.iter() {
+LL + for a in x.iter() {
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15
|
LL | for &a in &f.a {
- | -- ^^^^
- | ||
- | |data moved here
- | |move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `a`
+ | - ^^^^
+ | |
+ | data moved here
+ | move occurs because `a` has type `Box<isize>`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - for &a in &f.a {
+LL + for a in &f.a {
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
|
LL | for &a in x.iter() {
- | -- ^^^^^^^^
- | ||
- | |data moved here
- | |move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `a`
+ | - ^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `a` has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - for &a in x.iter() {
+LL + for a in x.iter() {
+ |
error: aborting due to 3 previous errors
--- /dev/null
+// run-rustfix
+fn main() {
+
+ let x: Option<Box<_>> = Some(Box::new(1));
+
+ match x {
+ Some(ref y) => {
+ let _b = y; //~ ERROR cannot move out
+ }
+ _ => {}
+ }
+}
+// run-rustfix
fn main() {
let x: Option<Box<_>> = Some(Box::new(1));
error[E0507]: cannot move out of `*y` which is behind a shared reference
- --> $DIR/borrowck-issue-2657-2.rs:7:18
+ --> $DIR/borrowck-issue-2657-2.rs:8:18
|
LL | let _b = *y;
- | ^^
- | |
- | move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*y`
+ | ^^ move occurs because `*y` has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let _b = *y;
+LL + let _b = y;
+ |
error: aborting due to previous error
--- /dev/null
+// run-rustfix
+#![allow(unused)]
+enum Foo {
+ Foo1(Box<u32>, Box<u32>),
+ Foo2(Box<u32>),
+ Foo3,
+}
+
+
+
+fn blah() {
+ let f = &Foo::Foo1(Box::new(1), Box::new(2));
+ match f { //~ ERROR cannot move out of
+ Foo::Foo1(num1,
+ num2) => (),
+ Foo::Foo2(num) => (),
+ Foo::Foo3 => ()
+ }
+}
+
+struct S {
+ f: String,
+ g: String
+}
+impl Drop for S {
+ fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+ match (S {f: "foo".to_string(), g: "bar".to_string()}) {
+ //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+ S {
+ f: ref _s,
+ g: ref _t
+ } => {}
+ }
+}
+
+// from issue-8064
+struct A {
+ a: Box<isize>,
+}
+
+fn free<T>(_: T) {}
+
+fn blah2() {
+ let a = &A { a: Box::new(1) };
+ match &a.a { //~ ERROR cannot move out of
+ n => {
+ free(n)
+ }
+ }
+ free(a)
+}
+
+fn main() {}
+// run-rustfix
+#![allow(unused)]
enum Foo {
Foo1(Box<u32>, Box<u32>),
Foo2(Box<u32>),
error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference
- --> $DIR/borrowck-move-error-with-note.rs:11:11
+ --> $DIR/borrowck-move-error-with-note.rs:13:11
|
LL | match *f {
- | ^^ help: consider borrowing here: `&*f`
+ | ^^
LL | Foo::Foo1(num1,
| ---- data moved here
LL | num2) => (),
| --- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the dereference here
+ |
+LL - match *f {
+LL + match f {
+ |
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-error-with-note.rs:28:11
+ --> $DIR/borrowck-move-error-with-note.rs:30:11
|
LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| -- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | f: ref _s,
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | g: ref _t
+ | +++
error[E0507]: cannot move out of `a.a` which is behind a shared reference
- --> $DIR/borrowck-move-error-with-note.rs:46:11
+ --> $DIR/borrowck-move-error-with-note.rs:48:11
|
LL | match a.a {
- | ^^^ help: consider borrowing here: `&a.a`
+ | ^^^
LL | n => {
| -
| |
| data moved here
| move occurs because `n` has type `Box<isize>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &a.a {
+ | +
error: aborting due to 3 previous errors
--> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13
|
LL | let y = *x;
- | ^^
- | |
- | move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*x`
+ | ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let y = *x;
+LL + let y = x;
+ |
error: aborting due to previous error
|
LL | fn arg_item(&_x: &String) {}
| ^--
- | ||
- | |data moved here
- | |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `_x`
+ | |
+ | data moved here
+ | move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - fn arg_item(&_x: &String) {}
+LL + fn arg_item(_x: &String) {}
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/borrowck-move-in-irrefut-pat.rs:7:11
|
LL | with(|&_x| ())
| ^--
- | ||
- | |data moved here
- | |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `_x`
+ | |
+ | data moved here
+ | move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - with(|&_x| ())
+LL + with(|_x| ())
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/borrowck-move-in-irrefut-pat.rs:12:15
|
LL | let &_x = &"hi".to_string();
- | --- ^^^^^^^^^^^^^^^^^
- | ||
- | |data moved here
- | |move occurs because `_x` has type `String`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `_x`
+ | -- ^^^^^^^^^^^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_x` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &_x = &"hi".to_string();
+LL + let _x = &"hi".to_string();
+ |
error: aborting due to 3 previous errors
| | value moved due to this method call
| move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
error: aborting due to previous error
--> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14
|
LL | let _x = *Rc::new("hi".to_string());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | move occurs because value has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*Rc::new("hi".to_string())`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let _x = *Rc::new("hi".to_string());
+LL + let _x = Rc::new("hi".to_string());
+ |
error: aborting due to previous error
--- /dev/null
+// run-rustfix
+#![allow(unused)]
+struct S {f:String}
+impl Drop for S {
+ fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn move_in_match() {
+ match (S {f:"foo".to_string()}) {
+ //~^ ERROR [E0509]
+ S {f:ref _s} => {}
+ }
+}
+
+fn move_in_let() {
+ let S {f:ref _s} = S {f:"foo".to_string()};
+ //~^ ERROR [E0509]
+}
+
+fn move_in_fn_arg(S {f:ref _s}: S) {
+ //~^ ERROR [E0509]
+}
+
+fn main() {}
+// run-rustfix
+#![allow(unused)]
struct S {f:String}
impl Drop for S {
fn drop(&mut self) { println!("{}", self.f); }
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:7:11
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11
|
LL | match (S {f:"foo".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
| move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | S {f:ref _s} => {}
+ | +++
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:14:20
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20
|
LL | let S {f:_s} = S {f:"foo".to_string()};
| -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
| move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let S {f:ref _s} = S {f:"foo".to_string()};
+ | +++
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:19
+ --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19
|
LL | fn move_in_fn_arg(S {f:_s}: S) {
| ^^^^^--^
| | data moved here
| | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
| cannot move out of here
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn move_in_fn_arg(S {f:ref _s}: S) {
+ | +++
error: aborting due to 3 previous errors
--- /dev/null
+// run-rustfix
+#![allow(unused)]
+struct S(String);
+impl Drop for S {
+ fn drop(&mut self) { }
+}
+
+fn move_in_match() {
+ match S("foo".to_string()) {
+ //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+ S(ref _s) => {}
+ }
+}
+
+fn move_in_let() {
+ let S(ref _s) = S("foo".to_string());
+ //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn move_in_fn_arg(S(ref _s): S) {
+ //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait
+}
+
+fn main() {}
+// run-rustfix
+#![allow(unused)]
struct S(String);
impl Drop for S {
fn drop(&mut self) { }
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11
|
LL | match S("foo".to_string()) {
| ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
| move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | S(ref _s) => {}
+ | +++
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17
|
LL | let S(_s) = S("foo".to_string());
| -- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
| |
| data moved here
| move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let S(ref _s) = S("foo".to_string());
+ | +++
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
- --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19
+ --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19
|
LL | fn move_in_fn_arg(S(_s): S) {
| ^^--^
| | data moved here
| | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
| cannot move out of here
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn move_in_fn_arg(S(ref _s): S) {
+ | +++
error: aborting due to 3 previous errors
| - ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
|
-LL ~ [Foo { string: a },
-LL ~ Foo { string: b }] => {
+LL - &[Foo { string: a },
+LL + [Foo { string: a },
|
error: aborting due to previous error
--> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15
|
LL | let bad = v[0];
- | ^^^^
- | |
- | move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&v[0]`
+ | ^^^^ move occurs because value has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let bad = &v[0];
+ | +
error: aborting due to previous error
&mut [_a,
//~^ NOTE data moved here
//~| NOTE move occurs because `_a` has type
- //~| HELP consider removing the `&mut`
+ //~| HELP consider removing the mutable borrow
..
] => {
}
//~^ ERROR cannot move out
//~| NOTE cannot move out
&mut [
- //~^ HELP consider removing the `&mut`
+ //~^ HELP consider removing the mutable borrow
_b] => {}
//~^ NOTE data moved here
//~| NOTE move occurs because `_b` has type
//~^ NOTE data moved here
//~| NOTE and here
//~| NOTE and here
- //~| HELP consider removing the `&mut`
+ //~| HELP consider removing the mutable borrow
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
| data moved here
| move occurs because `_a` has type `Box<isize>`, which does not implement the `Copy` trait
|
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
|
-LL ~ [_a,
-LL +
-LL +
-LL +
-LL + ..
-LL ~ ] => {
+LL - &mut [_a,
+LL + [_a,
|
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
| |
| cannot move out of here
| move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&vec[0]`
+ |
+help: consider borrowing here
+ |
+LL | let a = &vec[0];
+ | +
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:55:11
| data moved here
| move occurs because `_b` has type `Box<isize>`, which does not implement the `Copy` trait
|
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
|
-LL ~ [
-LL +
-LL ~ _b] => {}
+LL - &mut [
+LL + [
|
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
| |
| cannot move out of here
| move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&vec[0]`
+ |
+help: consider borrowing here
+ |
+LL | let a = &vec[0];
+ | +
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:74:11
| ^^^ cannot move out of here
...
LL | &mut [_a, _b, _c] => {}
- | -----------------
- | | | | |
- | | | | ...and here
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `[_a, _b, _c]`
+ | -- -- -- ...and here
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut [_a, _b, _c] => {}
+LL + [_a, _b, _c] => {}
+ |
error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:85:13
| |
| cannot move out of here
| move occurs because `vec[_]` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&vec[0]`
+ |
+help: consider borrowing here
+ |
+LL | let a = &vec[0];
+ | +
error: aborting due to 8 previous errors
--- /dev/null
+// edition:2018
+// check-pass
+
+#![allow(dead_code)]
+async fn fail<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass<'a, 'c, 'b>(_: &'static str) where 'a: 'c, 'b: 'c, {}
+async fn pass2<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, 'c: 'a, {}
+async fn pass3<'a, 'b, 'c>(_: &'static str) where 'a: 'b, 'b: 'c, 'c: 'a, {}
+
+fn main() { }
--> $DIR/issue-17718-static-move.rs:6:14
|
LL | let _a = FOO;
- | ^^^
- | |
- | move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&FOO`
+ | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let _a = &FOO;
+ | +
error: aborting due to previous error
--> $DIR/issue-20801.rs:26:22
|
LL | let a = unsafe { *mut_ref() };
- | ^^^^^^^^^^
- | |
- | move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*mut_ref()`
+ | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let a = unsafe { *mut_ref() };
+LL + let a = unsafe { mut_ref() };
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/issue-20801.rs:29:22
|
LL | let b = unsafe { *imm_ref() };
- | ^^^^^^^^^^
- | |
- | move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*imm_ref()`
+ | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let b = unsafe { *imm_ref() };
+LL + let b = unsafe { imm_ref() };
+ |
error[E0507]: cannot move out of a raw pointer
--> $DIR/issue-20801.rs:32:22
|
LL | let c = unsafe { *mut_ptr() };
- | ^^^^^^^^^^
- | |
- | move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*mut_ptr()`
+ | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let c = unsafe { *mut_ptr() };
+LL + let c = unsafe { mut_ptr() };
+ |
error[E0507]: cannot move out of a raw pointer
--> $DIR/issue-20801.rs:35:22
|
LL | let d = unsafe { *const_ptr() };
- | ^^^^^^^^^^^^
- | |
- | move occurs because value has type `T`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*const_ptr()`
+ | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let d = unsafe { *const_ptr() };
+LL + let d = unsafe { const_ptr() };
+ |
error: aborting due to 4 previous errors
--- /dev/null
+// run-pass
+// This test ensures that vec.into_iter does not overconstrain element lifetime.
+
+pub fn main() {
+ original_report();
+ revision_1();
+ revision_2();
+}
+
+fn original_report() {
+ drop(vec![&()].into_iter())
+}
+
+fn revision_1() {
+ // below is what above `vec!` expands into at time of this writing.
+ drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter())
+}
+
+fn revision_2() {
+ drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter())
+}
--> $DIR/issue-47215-ice-from-drop-elab.rs:17:21
|
LL | let mut x = X;
- | ^
- | |
- | move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&X`
+ | ^ move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let mut x = &X;
+ | +
error: aborting due to previous error
--- /dev/null
+use std::any::TypeId;
+use std::collections::HashMap;
+use std::hash::Hash;
+
+trait State {
+ type EventType;
+ fn get_type_id_of_state(&self) -> TypeId;
+}
+
+struct StateMachine<EventType: Hash + Eq> {
+ current_state: Box<dyn State<EventType = EventType>>,
+ transition_table:
+ HashMap<TypeId, HashMap<EventType, fn() -> Box<dyn State<EventType = EventType>>>>,
+}
+
+impl<EventType: Hash + Eq> StateMachine<EventType> {
+ fn inner_process_event(&mut self, event: EventType) -> Result<(), i8> {
+ let new_state_creation_function = self
+ .transition_table
+ .iter()
+ .find(|(&event_typeid, _)| event_typeid == self.current_state.get_type_id_of_state())
+ .ok_or(1)?
+ .1
+ .iter()
+ .find(|(&event_type, _)| event == event_type)
+ //~^ ERROR cannot move out of a shared reference
+ .ok_or(2)?
+ .1;
+
+ self.current_state = new_state_creation_function();
+ Ok(())
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/issue-51301.rs:25:20
+ |
+LL | .find(|(&event_type, _)| event == event_type)
+ | ^^----------^^^^
+ | |
+ | data moved here
+ | move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | .find(|(&ref event_type, _)| event == event_type)
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
--- /dev/null
+// run-rustfix
+// Regression test for #51415: match default bindings were failing to
+// see the "move out" implied by `&s` below.
+
+fn main() {
+ let a = vec![String::from("a")];
+ let opt = a.iter().enumerate().find(|(_, &ref s)| {
+ //~^ ERROR cannot move out
+ *s == String::from("d")
+ }).map(|(i, _)| i);
+ println!("{:?}", opt);
+}
+// run-rustfix
// Regression test for #51415: match default bindings were failing to
// see the "move out" implied by `&s` below.
error[E0507]: cannot move out of a shared reference
- --> $DIR/issue-51415.rs:6:42
+ --> $DIR/issue-51415.rs:7:42
|
LL | let opt = a.iter().enumerate().find(|(_, &s)| {
| ^^^^^-^
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let opt = a.iter().enumerate().find(|(_, &ref s)| {
+ | +++
error: aborting due to previous error
--> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:14:13
|
LL | *array
- | ^^^^^^
- | |
- | move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*array`
+ | ^^^^^^ move occurs because `*array` has type `Vec<Value>`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - *array
+LL + array
+ |
error: aborting due to previous error
error[E0080]: evaluation of constant value failed
--> $DIR/issue-81899.rs:11:5
|
-LL | const _CONST: &[u8] = &f(&[], |_| {});
- | -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
-...
+LL | panic!()
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
+ |
+note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>`
+ --> $DIR/issue-81899.rs:11:5
+ |
LL | panic!()
| ^^^^^^^^
- | |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
- | inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+ --> $DIR/issue-81899.rs:4:24
|
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+ | ^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
LL | let _y = foo;
| ^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn unwrap(self) -> T {
- | ^^^^
error[E0382]: use of moved value: `foo`
--> $DIR/issue-83760.rs:37:14
LL | } else if true {
LL | foo = Some(Struct);
| ^^^^^^^^^^^^^^^^^^
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `foo`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn unwrap(self) -> T {
- | ^^^^
error: aborting due to 3 previous errors
| -- captured by this `FnMut` closure
LL |
LL | let _foo: String = val;
- | ^^^
- | |
- | move occurs because `val` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&val`
+ | ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let _foo: String = &val;
+ | +
error: aborting due to previous error
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-minimal-example.rs:10:5
|
-LL | const _CONST: &() = &f(&|_| {});
- | ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
-...
+LL | panic!()
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
+ |
+note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>`
+ --> $DIR/issue-88434-minimal-example.rs:10:5
+ |
LL | panic!()
| ^^^^^^^^
- | |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
- | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+ --> $DIR/issue-88434-minimal-example.rs:3:22
|
+LL | const _CONST: &() = &f(&|_| {});
+ | ^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
-LL | const _CONST: &[u8] = &f(&[], |_| {});
- | -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
-...
+LL | panic!()
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+ |
+note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>`
+ --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+ |
LL | panic!()
| ^^^^^^^^
- | |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
- | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+ --> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+ | ^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
--> $DIR/move-error-snippets-ext.rs:5:17
|
LL | let a = $c;
- | ^^
- | |
- | move occurs because `D` has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&$c`
+ | ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait
|
::: $DIR/move-error-snippets.rs:21:1
|
| ------ in this macro invocation
|
= note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider borrowing here
+ |
+LL | let a = &$c;
+ | +
error: aborting due to previous error
LL | fill_segment(state);
| ^^^^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `state`
+note: `into_iter` takes ownership of the receiver `self`, which moves `state`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider creating a fresh reborrow of `state` here
|
LL | for _ in &mut *state {}
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves `*cb`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `*cb`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn map<U, F>(self, f: F) -> Option<U>
- | ^^^^
error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
--> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
| |
| move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `into_iter` takes ownership of the receiver `self`, which moves `y`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
error: aborting due to previous error
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Box::<T, A>::into_boxed_slice`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | impl<T, A: Allocator> Box<T, A> {
- | ^ required by this bound in `Box::<T, A>::into_boxed_slice`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/into-boxed-slice-fail.rs:7:13
= help: the trait `Sized` is not implemented for `dyn Debug`
note: required by a bound in `Box::<T, A>::into_boxed_slice`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | impl<T, A: Allocator> Box<T, A> {
- | ^ required by this bound in `Box::<T, A>::into_boxed_slice`
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/into-boxed-slice-fail.rs:11:13
&E::Foo => {}
&E::Bar(ref identifier) => println!("{}", *identifier)
};
+ if let &E::Bar(identifier) = &s.x { //~ ERROR cannot move
+ f(identifier.clone());
+ };
+ let &E::Bar(identifier) = &s.x else { //~ ERROR cannot move
+ return;
+ };
+ f(identifier.clone());
}
| ^^^^
LL | &E::Foo => {}
LL | &E::Bar(identifier) => f(identifier.clone())
- | -------------------
- | | |
- | | data moved here
- | | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `E::Bar(identifier)`
+ | ----------
+ | |
+ | data moved here
+ | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &E::Bar(identifier) => f(identifier.clone())
+LL + E::Bar(identifier) => f(identifier.clone())
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/by-move-pattern-binding.rs:22:34
+ |
+LL | if let &E::Bar(identifier) = &s.x {
+ | ---------- ^^^^
+ | |
+ | data moved here
+ | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let &E::Bar(identifier) = &s.x {
+LL + if let E::Bar(identifier) = &s.x {
+ |
+
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/by-move-pattern-binding.rs:25:31
+ |
+LL | let &E::Bar(identifier) = &s.x else {
+ | ---------- ^^^^
+ | |
+ | data moved here
+ | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &E::Bar(identifier) = &s.x else {
+LL + let E::Bar(identifier) = &s.x else {
+ |
-error: aborting due to previous error
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0507`.
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
|
help: a trait with a similar name exists
|
= note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `identity_future`
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
- | ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
--> $DIR/async.rs:7:29
= help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
note: required by a bound in `identity_future`
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
- | ^ required by this bound in `identity_future`
error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
--> $DIR/async.rs:7:25
--> $DIR/check-static-values-constraints.rs:110:45
|
LL | let y = { static x: Box<isize> = box 3; x };
- | ^
- | |
- | move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&x`
+ | ^ move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let y = { static x: Box<isize> = box 3; &x };
+ | +
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:110:38
|
help: consider giving this closure parameter an explicit type
|
-LL | with_closure(|x: u32, y: _| {});
- | +++
+LL | with_closure(|x: u32, y: /* Type */| {});
+ | ++++++++++++
error: aborting due to previous error
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `Option::<T>::or_else`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | F: ~const FnOnce() -> Option<T>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::or_else`
error: aborting due to previous error
| ^^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
- |
-LL | F: Send + 'static,
- | ^^^^ required by this bound in `spawn`
error[E0277]: `Sender<()>` cannot be shared between threads safely
--> $DIR/closure-move-sync.rs:18:19
| ^^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
- |
-LL | F: Send + 'static,
- | ^^^^ required by this bound in `spawn`
error: aborting due to 2 previous errors
--> $DIR/closure-return-type-must-be-sized.rs:14:19
|
LL | pub fn bar<F: FnOnce() -> R, R: ?Sized>() {}
- | ^^^^^^^^^^^^^ required by this bound in `a::bar`
+ | ^^^^^^^^^^^^^ required by this bound in `bar`
error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
--> $DIR/closure-return-type-must-be-sized.rs:56:5
--> $DIR/closure-return-type-must-be-sized.rs:28:19
|
LL | pub fn bar<F: Fn() -> R, R: ?Sized>() {}
- | ^^^^^^^^^ required by this bound in `b::bar`
+ | ^^^^^^^^^ required by this bound in `bar`
error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
--> $DIR/closure-return-type-must-be-sized.rs:63:5
--> $DIR/closure-return-type-must-be-sized.rs:42:19
|
LL | pub fn bar<F: FnMut() -> R, R: ?Sized>() {}
- | ^^^^^^^^^^^^ required by this bound in `c::bar`
+ | ^^^^^^^^^^^^ required by this bound in `bar`
error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
--> $DIR/closure-return-type-must-be-sized.rs:70:5
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | F: ~const FnOnce(T) -> U,
- | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
error: aborting due to previous error
|
help: consider giving this closure parameter an explicit type
|
-LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
- | +++
+LL | [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize]
+ | ++++++++++++
error: aborting due to 2 previous errors
|
LL | _func: F,
| ^
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
|
help: a trait with a similar name exists
|
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
error[E0308]: mismatched types
--> $DIR/issue-87461.rs:17:8
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
error[E0308]: mismatched types
--> $DIR/issue-87461.rs:26:12
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
error: aborting due to 3 previous errors
|
LL | type_ascribe!(2, n([u8; || 1]))
| ^ help: a trait with a similar name exists: `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0308]: mismatched types
--> $DIR/issue-90871.rs:4:29
--> $DIR/multiple-fn-bounds.rs:10:5
|
LL | foo(move |x| v);
- | ^^^ -------- found signature defined here
- | |
+ | ^^^ --------
+ | | | |
+ | | | help: do not borrow the argument: `char`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `fn(char) -> _`
--- /dev/null
+// run-pass
+// ^-- The above is needed as this issue is related to LLVM/codegen.
+// min-llvm-version:15.0.0
+// ^-- The above is needed as this issue is fixed by the opaque pointers.
+
+fn main() {
+ type_error(|x| &x);
+}
+
+fn type_error<T>(
+ _selector: for<'a> fn(&'a Vec<Box<dyn for<'b> Fn(&'b u8)>>) -> &'a Vec<Box<dyn Fn(T)>>,
+) {
+}
LL | println!("{:?}", some_vec);
| ^^^^^^^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `some_vec`
+note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
|
--> $DIR/cfg-attr-syntax-validation.rs:7:1
|
LL | #[cfg()]
- | ^^^^^^^^
+ | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
error: multiple `cfg` predicates are specified
--> $DIR/cfg-attr-syntax-validation.rs:10:10
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
--> $DIR/issue-33784.rs:27:7
|
LL | p.closure();
LL | (p.closure)();
| + +
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
--> $DIR/issue-33784.rs:29:7
|
LL | q.fn_ptr();
+++ /dev/null
-error: type parameters must be declared prior to const parameters
- --> $DIR/complex-unord-param.rs:8:41
- |
-LL | struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> {
- | ---------------------^----------------------^--------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, A: 'a, T: 'a = u32, const N: usize, const M: usize>`
-
-error: aborting due to previous error
-
| ^ ------------------- type must be known at this point
|
= note: cannot satisfy `_: MaskElement`
+ = help: the following types implement trait `MaskElement`:
+ i16
+ i32
+ i64
+ i8
+ isize
note: required by a bound in `Mask::<T, LANES>::splat`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
- |
-LL | T: MaskElement,
- | ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
|
LL | let y: Mask<_, LANES> = Mask::<_, _>::splat(false);
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:17:5
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error: unconstrained generic constant
--> $DIR/abstract-const-as-cast-3.rs:20:19
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:20:5
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:23:5
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:25:5
--> $DIR/abstract-const-as-cast-3.rs:14:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error: unconstrained generic constant
--> $DIR/abstract-const-as-cast-3.rs:35:19
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:35:5
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error: unconstrained generic constant
--> $DIR/abstract-const-as-cast-3.rs:38:19
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:38:5
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:41:5
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:43:5
--> $DIR/abstract-const-as-cast-3.rs:32:23
|
LL | fn assert_impl<T: Trait>() {}
- | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+ | ^^^^^ required by this bound in `assert_impl`
error: aborting due to 12 previous errors
--- /dev/null
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+ fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+}
+
+fn main() {}
--- /dev/null
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/issue-105257.rs:5:12
+ |
+LL | fn fnc<const N: usize = "">(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/issue-105257.rs:6:12
+ |
+LL | fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Combination<const STRATEGIES: usize>;
+
+impl<const STRATEGIES: usize> Combination<STRATEGIES> {
+ fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> {
+ Combination
+ }
+}
+
+pub fn main() {
+ Combination::<0>.and::<_>().and::<_>();
+ //~^ ERROR: type annotations needed
+}
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/issue-105608.rs:13:22
+ |
+LL | Combination::<0>.and::<_>().and::<_>();
+ | ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+ |
+help: consider specifying the generic argument
+ |
+LL | Combination::<0>.and::<_>().and::<_>();
+ | ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
LL | IsLessOrEqual<I, 8>: True,
| ^^^^
|
- = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+ --> $DIR/issue-72787.rs:10:1
+ |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | IsLessOrEqual<I, 8>: True,
+ | ^^^^
+...
+LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+ | ^^^^
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
--> $DIR/issue-72787.rs:21:26
LL | IsLessOrEqual<I, 8>: True,
| ^^^^
|
- = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
+note: multiple `impl`s or `where` clauses satisfying `IsLessOrEqual<I, 8>: True` found
+ --> $DIR/issue-72787.rs:10:1
+ |
+LL | impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | IsLessOrEqual<I, 8>: True,
+ | ^^^^
+...
+LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+ | ^^^^
error: aborting due to 6 previous errors
--> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
|
LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+ | |
+ | expected because this is `<Self as Foo>::Assoc`
|
= note: expected associated type `<Self as Foo>::Assoc`
found array `[(); _]`
error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
-LL | intrinsics::size_of::<T>()
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | size_of called on unsized type `dyn Debug`
- | inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ = note: size_of called on unsized type `dyn Debug`
|
- ::: $DIR/issue-80742.rs:22:10
+note: inside `std::mem::size_of::<dyn Debug>`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `Inline::<dyn Debug>::{constant#0}`
+ --> $DIR/issue-80742.rs:22:10
|
LL | [u8; size_of::<T>() + 1]: ,
- | -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:22:10
+ | ^^^^^^^^^^^^^^
error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied
--> $DIR/issue-80742.rs:30:36
...
LL | let dst = Inline::<dyn Debug>::new(0);
| ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
+ --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
- |
-LL | pub trait Debug {
- | --------------- doesn't satisfy `dyn Debug: Sized`
+ = note: doesn't satisfy `dyn Debug: Sized`
|
= note: the following trait bounds were not satisfied:
`dyn Debug: Sized`
error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
-LL | intrinsics::size_of::<T>()
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | size_of called on unsized type `dyn Debug`
- | inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ = note: size_of called on unsized type `dyn Debug`
|
- ::: $DIR/issue-80742.rs:14:10
+note: inside `std::mem::size_of::<dyn Debug>`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `Inline::<dyn Debug>::{constant#0}`
+ --> $DIR/issue-80742.rs:14:10
|
LL | [u8; size_of::<T>() + 1]: ,
- | -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:14:10
+ | ^^^^^^^^^^^^^^
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/issue-80742.rs:30:15
--- /dev/null
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_braces)]
+
+#[rustfmt::skip]
+fn foo<const N: usize>() {
+ bar::<{{{{{{ N }}}}}}>();
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
LL | let _: u32 = 5i32.try_into::<32>().unwrap();
| ^^^^^^^^ expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
- |
-LL | fn try_into(self) -> Result<T, Self::Error>;
- | ^^^^^^^^
help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument
|
LL | let _: u32 = TryInto::<32>::try_into(5i32).unwrap();
| ^^^^ --- help: remove this generic argument
| |
| expected 1 generic argument
- |
-note: struct defined here, with 1 generic parameter: `T`
- --> $SRC_DIR/core/src/cell.rs:LL:COL
- |
-LL | pub struct Cell<T: ?Sized> {
- | ^^^^ -
error: aborting due to previous error
--- /dev/null
+// check-pass
+// edition:2021
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+#[allow(unused)]
+async fn foo<'a>() {
+ let _data = &mut [0u8; { 1 + 4 }];
+ bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
error[E0080]: evaluation of constant value failed
--> $DIR/issue-100313.rs:10:13
|
+LL | *(B as *const bool as *mut bool) = false;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only
+ |
+note: inside `T::<&true>::set_false`
+ --> $DIR/issue-100313.rs:10:13
+ |
LL | *(B as *const bool as *mut bool) = false;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | writing to alloc7 which is read-only
- | inside `T::<&true>::set_false` at $DIR/issue-100313.rs:10:13
-...
+note: inside `_`
+ --> $DIR/issue-100313.rs:18:5
+ |
LL | x.set_false();
- | ------------- inside `_` at $DIR/issue-100313.rs:18:5
+ | ^^^^^^^^^^^^^
error: aborting due to previous error
|
help: consider giving this pattern a type
|
-LL | let _: _ = foo([0; 1]);
- | +++
+LL | let _: /* Type */ = foo([0; 1]);
+ | ++++++++++++
error: aborting due to previous error
+++ /dev/null
-error: type parameters must be declared prior to const parameters
- --> $DIR/type-after-const-ok.rs:8:26
- |
-LL | struct A<const N: usize, T>(T);
- | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
-
-error: aborting due to previous error
-
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/forbidden_slices.rs:18:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S0`
+ --> $DIR/forbidden_slices.rs:18:34
|
LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
- | ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/forbidden_slices.rs:19:33
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S1`
+ --> $DIR/forbidden_slices.rs:19:33
|
LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
- | ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:22:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S2`
+ --> $DIR/forbidden_slices.rs:22:34
|
LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
- | ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:25:1
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─ALLOC_ID─╼ 01 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─ALLOC_ID─╼ 04 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─ALLOC_ID─╼ 04 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:32:1
|
LL | pub static S7: &[u16] = unsafe {
- | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+ | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─A_ID+0x1─╼ 04 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID+0x2╼ 04 00 00 00 │ ╾──╼....
}
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S8`
+ --> $DIR/forbidden_slices.rs:43:5
|
LL | from_raw_parts(ptr, 1)
- | ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
|
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:46:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R0`
+ --> $DIR/forbidden_slices.rs:46:34
|
LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
- | ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:47:33
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, ()>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R1`
+ --> $DIR/forbidden_slices.rs:47:33
|
LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
- | ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
- |
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL | unsafe { self.offset(count as isize) }
- | --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:50:25
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R2`
+ --> $DIR/forbidden_slices.rs:50:25
|
LL | from_ptr_range(ptr..ptr.add(2))
- | ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+ | ^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:52:1
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- â\95¾ALLOC_IDâ\94\80â\95¼ 01 00 00 00 â\94\82 â\95¾â\94\80â\94\80â\95¼....
+ ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
= note: the raw bytes of the constant (size: 8, align: 4) {
- â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00 â\94\82 â\95¾â\94\80â\94\80â\95¼....
+ ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- â\95¾ALLOC_IDâ\94\80â\95¼ 04 00 00 00 â\94\82 â\95¾â\94\80â\94\80â\95¼....
+ ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
}
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | pub static R7: &[u16] = unsafe {
- | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+ = note: accessing memory with alignment 1, but alignment 2 is required
|
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 8, align: 4) {
- ╾A_ID+0x1─╼ 04 00 00 00 │ ╾──╼....
- }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+ --> $DIR/forbidden_slices.rs:69:5
+ |
+LL | from_ptr_range(ptr..ptr.add(4))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL | unsafe { self.offset(count as isize) }
- | --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:74:25
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R8`
+ --> $DIR/forbidden_slices.rs:73:25
|
LL | from_ptr_range(ptr..ptr.add(1))
- | ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+ | ^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `ptr_offset_from_unsigned` called on pointers into different allocations
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:79:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R9`
+ --> $DIR/forbidden_slices.rs:78:34
|
LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
- | ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `ptr_offset_from_unsigned` called on pointers into different allocations
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:80:35
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R10`
+ --> $DIR/forbidden_slices.rs:79:35
|
LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
- | ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 18 previous errors
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/forbidden_slices.rs:18:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S0`
+ --> $DIR/forbidden_slices.rs:18:34
|
LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
- | ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/forbidden_slices.rs:19:33
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S1`
+ --> $DIR/forbidden_slices.rs:19:33
|
LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
- | ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:22:34
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S2`
+ --> $DIR/forbidden_slices.rs:22:34
|
LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
- | ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:25:1
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:32:1
|
LL | pub static S7: &[u16] = unsafe {
- | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+ | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾─────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | &*ptr::slice_from_raw_parts(data, len)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `S8`
+ --> $DIR/forbidden_slices.rs:43:5
|
LL | from_raw_parts(ptr, 1)
- | ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
|
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:46:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R0`
+ --> $DIR/forbidden_slices.rs:46:34
|
LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
- | ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:47:33
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, ()>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R1`
+ --> $DIR/forbidden_slices.rs:47:33
|
LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
- | ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
- |
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL | unsafe { self.offset(count as isize) }
- | --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:50:25
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R2`
+ --> $DIR/forbidden_slices.rs:50:25
|
LL | from_ptr_range(ptr..ptr.add(2))
- | ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+ | ^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/forbidden_slices.rs:52:1
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────ALLOC_ID───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────ALLOC_ID───────╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────ALLOC_ID───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/forbidden_slices.rs:67:1
+error[E0080]: could not evaluate static initializer
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
-LL | pub static R7: &[u16] = unsafe {
- | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+ = note: accessing memory with alignment 1, but alignment 2 is required
|
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 16, align: 8) {
- ╾────ALLOC_ID+0x1─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
- }
+note: inside `std::slice::from_raw_parts::<'_, u16>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `from_ptr_range::<'_, u16>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R7`
+ --> $DIR/forbidden_slices.rs:69:5
+ |
+LL | from_ptr_range(ptr..ptr.add(4))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL | unsafe { self.offset(count as isize) }
- | --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
|
- ::: $DIR/forbidden_slices.rs:74:25
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `R8`
+ --> $DIR/forbidden_slices.rs:73:25
|
LL | from_ptr_range(ptr..ptr.add(1))
- | ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+ | ^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `ptr_offset_from_unsigned` called on pointers into different allocations
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:79:34
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R9`
+ --> $DIR/forbidden_slices.rs:78:34
|
LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
- | ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `ptr_offset_from_unsigned` called on pointers into different allocations
- | inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
- ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
-LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
- |
- ::: $DIR/forbidden_slices.rs:80:35
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `from_ptr_range::<'_, u32>`
+ --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `R10`
+ --> $DIR/forbidden_slices.rs:79:35
|
LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
- | ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 18 previous errors
// stderr-per-bitwidth
-// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
-// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x"
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
+// normalize-stderr-test "alloc\d+" -> "allocN"
// error-pattern: could not evaluate static initializer
#![feature(
slice_from_ptr_range,
// Reading padding is not ok
pub static S7: &[u16] = unsafe {
//~^ ERROR: it is undefined behavior to use this value
- let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
+ let ptr = (&D2 as *const Struct as *const u16).add(1);
from_raw_parts(ptr, 4)
};
from_ptr_range(ptr..ptr.add(4))
};
pub static R7: &[u16] = unsafe {
- //~^ ERROR: it is undefined behavior to use this value
let ptr = (&D2 as *const Struct as *const u16).byte_add(1);
- from_ptr_range(ptr..ptr.add(4))
+ from_ptr_range(ptr..ptr.add(4)) //~ inside `R7`
};
pub static R8: &[u64] = unsafe {
let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>();
- from_ptr_range(ptr..ptr.add(1))
+ from_ptr_range(ptr..ptr.add(1)) //~ inside `R8`
};
// This is sneaky: &D0 and &D0 point to different objects
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
- | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
- ::: $DIR/out_of_bounds_read.rs:12:33
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `_READ`
+ --> $DIR/out_of_bounds_read.rs:12:33
|
LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
- | ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:12:33
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
- | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
-LL | unsafe { read(self) }
- | ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $DIR/out_of_bounds_read.rs:13:39
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `_CONST_READ`
+ --> $DIR/out_of_bounds_read.rs:13:39
|
LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
- | ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:13:39
+ | ^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
- | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
- ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- |
-LL | unsafe { read(self) }
- | ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
- |
- ::: $DIR/out_of_bounds_read.rs:14:37
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::mut_ptr::<impl *mut u32>::read`
+ --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+note: inside `_MUT_READ`
+ --> $DIR/out_of_bounds_read.rs:14:37
|
LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
- | --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:14:37
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error[E0080]: evaluation of constant value failed
--> $DIR/const_fn_ptr_fail2.rs:9:5
|
+LL | x(y)
+ | ^^^^ calling non-const function `double`
+ |
+note: inside `bar`
+ --> $DIR/const_fn_ptr_fail2.rs:9:5
+ |
LL | x(y)
| ^^^^
- | |
- | calling non-const function `double`
- | inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Y`
+ --> $DIR/const_fn_ptr_fail2.rs:14:18
+ |
LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
- | --------- inside `Y` at $DIR/const_fn_ptr_fail2.rs:14:18
+ | ^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $DIR/const_fn_ptr_fail2.rs:9:5
|
+LL | x(y)
+ | ^^^^ calling non-const function `double`
+ |
+note: inside `bar`
+ --> $DIR/const_fn_ptr_fail2.rs:9:5
+ |
LL | x(y)
| ^^^^
- | |
- | calling non-const function `double`
- | inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Z`
+ --> $DIR/const_fn_ptr_fail2.rs:15:18
+ |
LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
- | -------------- inside `Z` at $DIR/const_fn_ptr_fail2.rs:15:18
+ | ^^^^^^^^^^^^^^
warning: skipping const checks
|
error[E0080]: evaluation of constant value failed
--> $DIR/const_panic_track_caller.rs:15:5
|
+LL | b()
+ | ^^^ the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
+ |
+note: inside `c`
+ --> $DIR/const_panic_track_caller.rs:15:5
+ |
LL | b()
| ^^^
- | |
- | the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
- | inside `c` at $DIR/const_panic_track_caller.rs:15:5
-...
+note: inside `X`
+ --> $DIR/const_panic_track_caller.rs:21:16
+ |
LL | const X: u32 = c();
- | --- inside `X` at $DIR/const_panic_track_caller.rs:21:16
+ | ^^^
error: aborting due to previous error
error[E0080]: evaluation of constant value failed
--> $DIR/alloc_intrinsic_errors.rs:9:17
|
-LL | const FOO: i32 = foo();
- | ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
-...
+LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
+ |
+note: inside `foo`
+ --> $DIR/alloc_intrinsic_errors.rs:9:17
+ |
LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | align has to be a power of 2, `3` is not a power of 2
- | inside `foo` at $DIR/alloc_intrinsic_errors.rs:9:17
+note: inside `FOO`
+ --> $DIR/alloc_intrinsic_errors.rs:6:18
+ |
+LL | const FOO: i32 = foo();
+ | ^^^^^
error: aborting due to previous error
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:13:1
+ --> $DIR/ub-ref-ptr.rs:14:1
|
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:17:1
+ --> $DIR/ub-ref-ptr.rs:18:1
|
LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:21:1
+ --> $DIR/ub-ref-ptr.rs:22:1
|
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:24:1
+ --> $DIR/ub-ref-ptr.rs:25:1
|
LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:31:1
+ --> $DIR/ub-ref-ptr.rs:32:1
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:34:39
+ --> $DIR/ub-ref-ptr.rs:35:39
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant used
- --> $DIR/ub-ref-ptr.rs:34:38
+ --> $DIR/ub-ref-ptr.rs:35:38
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:37:86
+ --> $DIR/ub-ref-ptr.rs:38:86
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant used
- --> $DIR/ub-ref-ptr.rs:37:85
+ --> $DIR/ub-ref-ptr.rs:38:85
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:40:1
+ --> $DIR/ub-ref-ptr.rs:41:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:43:1
+ --> $DIR/ub-ref-ptr.rs:44:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:46:41
+ --> $DIR/ub-ref-ptr.rs:47:41
|
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:50:1
+ --> $DIR/ub-ref-ptr.rs:51:1
|
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:52:38
+ --> $DIR/ub-ref-ptr.rs:53:38
|
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:55:1
+ --> $DIR/ub-ref-ptr.rs:56:1
|
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:57:1
+ --> $DIR/ub-ref-ptr.rs:58:1
|
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
╾─alloc41─╼ │ ╾──╼
}
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ |
+ = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+ --> $DIR/ub-ref-ptr.rs:65:5
+ |
+LL | ptr.read();
+ | ^^^^^^^^^^
+ = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ |
+ = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+ --> $DIR/ub-ref-ptr.rs:65:5
+ |
+LL | ptr.read();
+ | ^^^^^^^^^^
+ = note: `#[deny(invalid_alignment)]` on by default
+
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:13:1
+ --> $DIR/ub-ref-ptr.rs:14:1
|
LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:17:1
+ --> $DIR/ub-ref-ptr.rs:18:1
|
LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:21:1
+ --> $DIR/ub-ref-ptr.rs:22:1
|
LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:24:1
+ --> $DIR/ub-ref-ptr.rs:25:1
|
LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:31:1
+ --> $DIR/ub-ref-ptr.rs:32:1
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:34:39
+ --> $DIR/ub-ref-ptr.rs:35:39
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant used
- --> $DIR/ub-ref-ptr.rs:34:38
+ --> $DIR/ub-ref-ptr.rs:35:38
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:37:86
+ --> $DIR/ub-ref-ptr.rs:38:86
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
note: erroneous constant used
- --> $DIR/ub-ref-ptr.rs:37:85
+ --> $DIR/ub-ref-ptr.rs:38:85
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
| ^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:40:1
+ --> $DIR/ub-ref-ptr.rs:41:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:43:1
+ --> $DIR/ub-ref-ptr.rs:44:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:46:41
+ --> $DIR/ub-ref-ptr.rs:47:41
|
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:50:1
+ --> $DIR/ub-ref-ptr.rs:51:1
|
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:52:38
+ --> $DIR/ub-ref-ptr.rs:53:38
|
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:55:1
+ --> $DIR/ub-ref-ptr.rs:56:1
|
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:57:1
+ --> $DIR/ub-ref-ptr.rs:58:1
|
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
╾───────alloc41───────╼ │ ╾──────╼
}
-error: aborting due to 14 previous errors
+error: accessing memory with alignment 1, but alignment 4 is required
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ |
+ = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+ --> $DIR/ub-ref-ptr.rs:65:5
+ |
+LL | ptr.read();
+ | ^^^^^^^^^^
+ = note: `#[deny(invalid_alignment)]` on by default
+
+error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0080`.
+Future incompatibility report: Future breakage diagnostic:
+error: accessing memory with alignment 1, but alignment 4 is required
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ |
+ = 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 #68585 <https://github.com/rust-lang/rust/issues/104616>
+note: inside `std::ptr::read::<u32>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNALIGNED_READ`
+ --> $DIR/ub-ref-ptr.rs:65:5
+ |
+LL | ptr.read();
+ | ^^^^^^^^^^
+ = note: `#[deny(invalid_alignment)]` on by default
+
// ignore-tidy-linelength
// stderr-per-bitwidth
#![allow(invalid_value)]
+#![feature(const_ptr_read)]
use std::mem;
const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
//~^ ERROR it is undefined behavior to use this value
+
+const UNALIGNED_READ: () = unsafe {
+ let x = &[0u8; 4];
+ let ptr = x.as_ptr().cast::<u32>();
+ ptr.read(); //~ inside `UNALIGNED_READ`
+};
+
+
fn main() {}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:36:1
+ --> $DIR/ub-wide-ptr.rs:37:1
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN──╼ e7 03 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:38:1
+ --> $DIR/ub-wide-ptr.rs:39:1
|
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ ff ff ff ff │ ╾──╼....
+ ╾ALLOC_ID╼ ff ff ff ff │ ╾──╼....
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:41:1
+ --> $DIR/ub-wide-ptr.rs:42:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:44:1
+ --> $DIR/ub-wide-ptr.rs:45:1
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:46:1
+ --> $DIR/ub-wide-ptr.rs:47:1
|
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ ff ff ff ff │ ╾──╼....
+ ╾ALLOC_ID╼ ff ff ff ff │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:50:1
+ --> $DIR/ub-wide-ptr.rs:51:1
|
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ 01 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:53:1
+ --> $DIR/ub-wide-ptr.rs:54:1
|
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ 01 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼....
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:60:1
+ --> $DIR/ub-wide-ptr.rs:61:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:67:1
+ --> $DIR/ub-wide-ptr.rs:68:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ e7 03 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:70:1
+ --> $DIR/ub-wide-ptr.rs:71:1
|
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ ff ff ff 7f │ ╾──╼....
+ ╾ALLOC_ID╼ ff ff ff 7f │ ╾──╼....
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:73:1
+ --> $DIR/ub-wide-ptr.rs:74:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:76:1
+ --> $DIR/ub-wide-ptr.rs:77:1
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾─allocN─╼ e7 03 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼....
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:79:1
+ --> $DIR/ub-wide-ptr.rs:80:1
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:83:1
+ --> $DIR/ub-wide-ptr.rs:84:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
- ╾─allocN─╼ │ ╾──╼
+ ╾ALLOC_ID╼ │ ╾──╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:83:40
+ --> $DIR/ub-wide-ptr.rs:84:40
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:90:1
+ --> $DIR/ub-wide-ptr.rs:91:1
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
- ╾allocN─╼ │ ╾──╼
+ ╾ALLOC_ID╼ │ ╾──╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:90:42
+ --> $DIR/ub-wide-ptr.rs:91:42
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:94:1
+ --> $DIR/ub-wide-ptr.rs:95:1
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
- ╾allocN─╼ │ ╾──╼
+ ╾ALLOC_ID╼ │ ╾──╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:94:42
+ --> $DIR/ub-wide-ptr.rs:95:42
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:102:1
+ --> $DIR/ub-wide-ptr.rs:103:1
|
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:111:1
+ --> $DIR/ub-wide-ptr.rs:112:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:115:1
+ --> $DIR/ub-wide-ptr.rs:116:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:119:1
+ --> $DIR/ub-wide-ptr.rs:120:1
|
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ 04 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:122:57
+ --> $DIR/ub-wide-ptr.rs:123:57
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:125:57
+ --> $DIR/ub-wide-ptr.rs:126:57
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:128:56
+ --> $DIR/ub-wide-ptr.rs:129:56
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:131:1
+ --> $DIR/ub-wide-ptr.rs:132:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:136:1
+ --> $DIR/ub-wide-ptr.rs:137:1
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:141:1
+ --> $DIR/ub-wide-ptr.rs:142:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ 00 00 00 00 │ ╾──╼....
+ ╾ALLOC_ID╼ 00 00 00 00 │ ╾──╼....
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:143:1
+ --> $DIR/ub-wide-ptr.rs:144:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:149:5
+ --> $DIR/ub-wide-ptr.rs:150:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:153:5
+ --> $DIR/ub-wide-ptr.rs:154:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:36:1
+ --> $DIR/ub-wide-ptr.rs:37:1
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN────────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:38:1
+ --> $DIR/ub-wide-ptr.rs:39:1
|
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+ ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:41:1
+ --> $DIR/ub-wide-ptr.rs:42:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:44:1
+ --> $DIR/ub-wide-ptr.rs:45:1
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:46:1
+ --> $DIR/ub-wide-ptr.rs:47:1
|
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
+ ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:50:1
+ --> $DIR/ub-wide-ptr.rs:51:1
|
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:53:1
+ --> $DIR/ub-wide-ptr.rs:54:1
|
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:60:1
+ --> $DIR/ub-wide-ptr.rs:61:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:67:1
+ --> $DIR/ub-wide-ptr.rs:68:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:70:1
+ --> $DIR/ub-wide-ptr.rs:71:1
|
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
+ ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:73:1
+ --> $DIR/ub-wide-ptr.rs:74:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:76:1
+ --> $DIR/ub-wide-ptr.rs:77:1
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:79:1
+ --> $DIR/ub-wide-ptr.rs:80:1
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:83:1
+ --> $DIR/ub-wide-ptr.rs:84:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
- ╾───────allocN───────╼ │ ╾──────╼
+ ╾ALLOC_ID╼ │ ╾──────╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:83:40
+ --> $DIR/ub-wide-ptr.rs:84:40
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:90:1
+ --> $DIR/ub-wide-ptr.rs:91:1
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
- ╾──────allocN───────╼ │ ╾──────╼
+ ╾ALLOC_ID╼ │ ╾──────╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:90:42
+ --> $DIR/ub-wide-ptr.rs:91:42
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:94:1
+ --> $DIR/ub-wide-ptr.rs:95:1
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
- ╾──────allocN───────╼ │ ╾──────╼
+ ╾ALLOC_ID╼ │ ╾──────╼
}
note: erroneous constant used
- --> $DIR/ub-wide-ptr.rs:94:42
+ --> $DIR/ub-wide-ptr.rs:95:42
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:102:1
+ --> $DIR/ub-wide-ptr.rs:103:1
|
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:111:1
+ --> $DIR/ub-wide-ptr.rs:112:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:115:1
+ --> $DIR/ub-wide-ptr.rs:116:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:119:1
+ --> $DIR/ub-wide-ptr.rs:120:1
|
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:122:57
+ --> $DIR/ub-wide-ptr.rs:123:57
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:125:57
+ --> $DIR/ub-wide-ptr.rs:126:57
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:128:56
+ --> $DIR/ub-wide-ptr.rs:129:56
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:131:1
+ --> $DIR/ub-wide-ptr.rs:132:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:136:1
+ --> $DIR/ub-wide-ptr.rs:137:1
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:141:1
+ --> $DIR/ub-wide-ptr.rs:142:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+ ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:143:1
+ --> $DIR/ub-wide-ptr.rs:144:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:149:5
+ --> $DIR/ub-wide-ptr.rs:150:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:153:5
+ --> $DIR/ub-wide-ptr.rs:154:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
use std::mem;
+// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼"
// normalize-stderr-test "offset \d+" -> "offset N"
// normalize-stderr-test "alloc\d+" -> "allocN"
// normalize-stderr-test "size \d+" -> "size N"
error[E0080]: evaluation of constant value failed
--> $DIR/unwind-abort.rs:4:5
|
+LL | panic!()
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
+ |
+note: inside `foo`
+ --> $DIR/unwind-abort.rs:4:5
+ |
LL | panic!()
| ^^^^^^^^
- | |
- | the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
- | inside `foo` at $SRC_DIR/std/src/panic.rs:LL:COL
-...
-LL | const _: () = foo();
- | ----- inside `_` at $DIR/unwind-abort.rs:7:15
+note: inside `_`
+ --> $DIR/unwind-abort.rs:7:15
|
+LL | const _: () = foo();
+ | ^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
+LL | unsafe { std::mem::transmute(()) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+ |
+note: inside `foo`
+ --> $DIR/validate_uninhabited_zsts.rs:4:14
+ |
LL | unsafe { std::mem::transmute(()) }
| ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | transmuting to uninhabited type
- | inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+ --> $DIR/validate_uninhabited_zsts.rs:19:33
+ |
LL | const FOO: [empty::Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+ | ^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_uninhabited_zsts.rs:21:1
error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
+LL | unsafe { std::mem::transmute(()) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+ |
+note: inside `foo`
+ --> $DIR/validate_uninhabited_zsts.rs:4:14
+ |
LL | unsafe { std::mem::transmute(()) }
| ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | transmuting to uninhabited type
- | inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+ --> $DIR/validate_uninhabited_zsts.rs:19:33
+ |
LL | const FOO: [empty::Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+ | ^^^^^
error[E0080]: it is undefined behavior to use this value
--> $DIR/validate_uninhabited_zsts.rs:21:1
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/num/f32.rs:LL:COL
|
-LL | panic!("const-eval error: cannot use f32::to_bits on a NaN")
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
- | inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL | unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
- | -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+ = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:28:30
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+ --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+ --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `f32::MASKED_NAN1`
+ --> $DIR/const-float-bits-reject-conv.rs:28:30
|
LL | const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
- | ------------------ inside `f32::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:28:30
- |
+ | ^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/num/f32.rs:LL:COL
|
-LL | panic!("const-eval error: cannot use f32::to_bits on a NaN")
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
- | inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL | unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
- | -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+ = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:30:30
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+ --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+ --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `f32::MASKED_NAN2`
+ --> $DIR/const-float-bits-reject-conv.rs:30:30
|
LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
- | ------------------ inside `f32::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:30:30
- |
+ | ^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/num/f64.rs:LL:COL
|
-LL | panic!("const-eval error: cannot use f64::to_bits on a NaN")
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
- | inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL | unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
- | -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+ = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:50:30
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+ --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+ --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `f64::MASKED_NAN1`
+ --> $DIR/const-float-bits-reject-conv.rs:50:30
|
LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
- | ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:50:30
- |
+ | ^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/num/f64.rs:LL:COL
|
-LL | panic!("const-eval error: cannot use f64::to_bits on a NaN")
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
- | inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL | unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
- | -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+ = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:52:30
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+ --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+ --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `f64::MASKED_NAN2`
+ --> $DIR/const-float-bits-reject-conv.rs:52:30
|
LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
- | ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:52:30
- |
+ | ^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant used
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | impl<I: Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constant functions
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | impl<I: Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
error[E0080]: evaluation of constant value failed
--> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
|
+LL | Some(&mut *(42 as *mut i32))
+ | ^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+ |
+note: inside `helper`
+ --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
+ |
LL | Some(&mut *(42 as *mut i32))
| ^^^^^^^^^^^^^^^^^^^^^^
- | |
- | dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
- | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10
-...
+note: inside `A`
+ --> $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+ |
LL | const A: Option<&mut i32> = helper();
- | -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+ | ^^^^^^^^
error: encountered dangling pointer in final constant
--> $DIR/mut_ref_in_final_dynamic_check.rs:25:1
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/hint.rs:LL:COL
|
-LL | intrinsics::unreachable()
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | entering unreachable code
- | inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
+ = note: entering unreachable code
|
- ::: $DIR/const_unsafe_unreachable_ub.rs:6:18
+note: inside `unreachable_unchecked`
+ --> $SRC_DIR/core/src/hint.rs:LL:COL
+note: inside `foo`
+ --> $DIR/const_unsafe_unreachable_ub.rs:6:18
|
LL | false => std::hint::unreachable_unchecked(),
- | ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:6:18
-...
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `BAR`
+ --> $DIR/const_unsafe_unreachable_ub.rs:10:28
+ |
LL | const BAR: bool = unsafe { foo(false) };
- | ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:10:28
+ | ^^^^^^^^^^
error: aborting due to previous error
// Since we are not copying anything, this should be allowed.
let src = ();
let mut dst = ();
- copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
+ copy_nonoverlapping(&src as *const _ as *const u8, &mut dst as *mut _ as *mut u8, 0);
};
const COPY_OOB_1: () = unsafe {
//[with_flag]~| invalid value
};
-const UNALIGNED_READ: () = {
- INNER; //[with_flag]~ constant
- // There is an error here but its span is in the standard library so we cannot match it...
- // so we have this in a *nested* const, such that the *outer* const fails to use it.
- const INNER: () = unsafe {
- let x = &[0u8; 4];
- let ptr = x.as_ptr().cast::<u32>();
- ptr.read();
- };
-};
-
fn main() {}
LL | let _x: &u32 = transmute(&[0u8; 4]);
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
-error[E0080]: evaluation of constant value failed
- --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- |
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | accessing memory with alignment 1, but alignment 4 is required
- | inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { read(self) }
- | ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $DIR/detect-extra-ub.rs:38:9
- |
-LL | ptr.read();
- | ---------- inside `INNER` at $DIR/detect-extra-ub.rs:38:9
-
-note: erroneous constant used
- --> $DIR/detect-extra-ub.rs:32:5
- |
-LL | INNER;
- | ^^^^^
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | unable to copy parts of a pointer from memory at ALLOC
- | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- |
- ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { read(self) }
- | ---------- inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
- ::: $DIR/issue-miri-1910.rs:8:5
- |
-LL | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
- | ------------------------------------------------------------------- inside `C` at $DIR/issue-miri-1910.rs:8:5
+ = note: unable to copy parts of a pointer from memory at ALLOC
|
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<u8>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u8>::read`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `C`
+ --> $DIR/issue-miri-1910.rs:8:5
+ |
+LL | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0080]: could not evaluate static initializer
--> $DIR/abi-mismatch.rs:9:5
|
+LL | my_fn();
+ | ^^^^^^^ calling a function with calling convention C using calling convention Rust
+ |
+note: inside `call_rust_fn`
+ --> $DIR/abi-mismatch.rs:9:5
+ |
LL | my_fn();
| ^^^^^^^
- | |
- | calling a function with calling convention C using calling convention Rust
- | inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
-...
+note: inside `VAL`
+ --> $DIR/abi-mismatch.rs:15:18
+ |
LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
- | --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:15:18
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: skipping const checks
|
error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | calling non-const function `<Vec<u32> as Drop>::drop`
- | inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- | inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ = note: calling non-const function `<Vec<u32> as Drop>::drop`
|
- ::: $DIR/assoc_const.rs:12:31
+note: inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `<String as Bar<Vec<u32>, String>>::F`
+ --> $DIR/assoc_const.rs:12:31
|
LL | const F: u32 = (U::X, 42).1;
- | - inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:12:31
+ | ^
note: erroneous constant used
--> $DIR/assoc_const.rs:29:13
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
-LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | calling non-const function `<Vec<i32> as Drop>::drop`
- | inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ = note: calling non-const function `<Vec<i32> as Drop>::drop`
|
- ::: $DIR/drop.rs:17:1
+note: inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `TEST_BAD`
+ --> $DIR/drop.rs:17:1
|
LL | };
- | - inside `TEST_BAD` at $DIR/drop.rs:17:1
+ | ^
warning: skipping const checks
|
--- /dev/null
+// compile-flags: -Z ui-testing=no
+// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
+
+#![feature(const_swap)]
+#![feature(const_mut_refs)]
+use std::{
+ mem::{self, MaybeUninit},
+ ptr,
+};
+
+const X: () = {
+ let mut ptr1 = &1;
+ let mut ptr2 = &2;
+
+ // Swap them, bytewise.
+ unsafe {
+ ptr::swap_nonoverlapping(
+ &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+ &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+ mem::size_of::<&i32>(),
+ );
+ }
+};
+
+fn main() {
+ X
+}
--- /dev/null
+error[E0080]: evaluation of constant value failed
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ |
+ = note: unable to copy parts of a pointer from memory at ALLOC_ID
+ |
+ = help: this code performed an operation that depends on the underlying bytes representing a pointer
+ = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<MaybeUninit<MaybeUninit<u8>>>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `mem::swap_simple::<MaybeUninit<MaybeUninit<u8>>>`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `ptr::swap_nonoverlapping_simple_untyped::<MaybeUninit<u8>>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `swap_nonoverlapping::<MaybeUninit<u8>>`
+ --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `X`
+ --> $DIR/missing_span_in_backtrace.rs:17:9
+ |
+17 | / ptr::swap_nonoverlapping(
+18 | | &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+19 | | &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+20 | | mem::size_of::<&i32>(),
+21 | | );
+ | |_________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `ptr_offset_from` called on pointers into different allocations
- | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: `ptr_offset_from` called on pointers into different allocations
|
- ::: $DIR/offset_from_ub.rs:24:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NOT_PTR`
+ --> $DIR/offset_from_ub.rs:24:14
|
LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize }
- | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $DIR/offset_from_ub.rs:31:14
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/offset_from_ub.rs:115:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OFFSET_VERY_FAR1`
+ --> $DIR/offset_from_ub.rs:115:14
|
LL | unsafe { ptr2.offset_from(ptr1) }
- | ---------------------- inside `OFFSET_VERY_FAR1` at $DIR/offset_from_ub.rs:115:14
+ | ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/offset_from_ub.rs:121:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OFFSET_VERY_FAR2`
+ --> $DIR/offset_from_ub.rs:121:14
|
LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
- | ----------------------------------------- inside `OFFSET_VERY_FAR2` at $DIR/offset_from_ub.rs:121:14
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 15 previous errors
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | overflowing in-bounds pointer arithmetic
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: overflowing in-bounds pointer arithmetic
|
- ::: $DIR/offset_ub.rs:7:46
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `BEFORE_START`
+ --> $DIR/offset_ub.rs:7:46
|
LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
- | ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:7:46
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/offset_ub.rs:8:43
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `AFTER_END`
+ --> $DIR/offset_ub.rs:8:43
|
LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
- | ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:8:43
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/offset_ub.rs:9:45
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `AFTER_ARRAY`
+ --> $DIR/offset_ub.rs:9:45
|
LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
- | ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | overflowing in-bounds pointer arithmetic
- | inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: overflowing in-bounds pointer arithmetic
|
- ::: $DIR/offset_ub.rs:11:43
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OVERFLOW`
+ --> $DIR/offset_ub.rs:11:43
|
LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
- | ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | overflowing in-bounds pointer arithmetic
- | inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: overflowing in-bounds pointer arithmetic
|
- ::: $DIR/offset_ub.rs:12:44
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW`
+ --> $DIR/offset_ub.rs:12:44
|
LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
- | ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | overflowing in-bounds pointer arithmetic
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: overflowing in-bounds pointer arithmetic
|
- ::: $DIR/offset_ub.rs:13:56
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `OVERFLOW_ADDRESS_SPACE`
+ --> $DIR/offset_ub.rs:13:56
|
LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
- | ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | overflowing in-bounds pointer arithmetic
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: overflowing in-bounds pointer arithmetic
|
- ::: $DIR/offset_ub.rs:14:57
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW_ADDRESS_SPACE`
+ --> $DIR/offset_ub.rs:14:57
|
LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
- | --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
|
- ::: $DIR/offset_ub.rs:15:49
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NEGATIVE_OFFSET`
+ --> $DIR/offset_ub.rs:15:49
|
LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
- | ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:15:49
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
|
- ::: $DIR/offset_ub.rs:17:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ZERO_SIZED_ALLOC`
+ --> $DIR/offset_ub.rs:17:50
|
LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
- | --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:17:50
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) as *mut T }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
- | inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
|
- ::: $DIR/offset_ub.rs:18:42
+note: inside `ptr::mut_ptr::<impl *mut u8>::offset`
+ --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+note: inside `DANGLING`
+ --> $DIR/offset_ub.rs:18:42
|
LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
- | ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:18:42
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
|
- ::: $DIR/offset_ub.rs:21:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `NULL_OFFSET_ZERO`
+ --> $DIR/offset_ub.rs:21:50
|
LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
- | --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:21:50
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
- | inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
|
- ::: $DIR/offset_ub.rs:24:47
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `UNDERFLOW_ABS`
+ --> $DIR/offset_ub.rs:24:47
|
LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
- | -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:24:47
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 12 previous errors
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | unsafe { intrinsics::offset(self, count) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
- | inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
|
- ::: $DIR/ptr_comparisons.rs:50:34
+note: inside `ptr::const_ptr::<impl *const usize>::offset`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `_`
+ --> $DIR/ptr_comparisons.rs:50:34
|
LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
- | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:50:34
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
--> $DIR/ptr_comparisons.rs:53:33
error[E0080]: evaluation of constant value failed
--> $DIR/recursive.rs:4:5
|
+LL | f(x);
+ | ^^^^ reached the configured maximum number of stack frames
+ |
+note: inside `f::<i32>`
+ --> $DIR/recursive.rs:4:5
+ |
LL | f(x);
| ^^^^
- | |
- | reached the configured maximum number of stack frames
- | inside `f::<i32>` at $DIR/recursive.rs:4:5
- | [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
-...
+note: [... 126 additional calls inside `f::<i32>` ...]
+ --> $DIR/recursive.rs:4:5
+ |
+LL | f(x);
+ | ^^^^
+note: inside `X`
+ --> $DIR/recursive.rs:8:15
+ |
LL | const X: () = f(1);
- | ---- inside `X` at $DIR/recursive.rs:8:15
+ | ^^^^
error: aborting due to previous error; 1 warning emitted
error[E0080]: evaluation of `<i32 as Const>::CONSTANT` failed
--> $DIR/uninhabited-const-issue-61744.rs:4:5
|
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^ reached the configured maximum number of stack frames
+ |
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
LL | hint_unreachable()
| ^^^^^^^^^^^^^^^^^^
- | |
- | reached the configured maximum number of stack frames
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-...
-LL | fake_type()
- | -----------
- | |
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-...
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+ --> $DIR/uninhabited-const-issue-61744.rs:8:5
+ |
+LL | fake_type()
+ | ^^^^^^^^^^^
+note: inside `fake_type::<i32>`
+ --> $DIR/uninhabited-const-issue-61744.rs:4:5
+ |
+LL | hint_unreachable()
+ | ^^^^^^^^^^^^^^^^^^
+note: inside `<i32 as Const>::CONSTANT`
+ --> $DIR/uninhabited-const-issue-61744.rs:12:36
+ |
LL | const CONSTANT: i32 = unsafe { fake_type() };
- | ----------- inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:12:36
+ | ^^^^^^^^^^^
note: erroneous constant used
--> $DIR/uninhabited-const-issue-61744.rs:18:10
--- /dev/null
+// run-pass
+// compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3
+
+fn main() {
+ TranslatorI.visit_pre();
+}
+
+impl TranslatorI {
+ fn visit_pre(self) {
+ Some(())
+ .map(|_| self.flags())
+ .unwrap_or_else(|| self.flags());
+ }
+}
+
+struct TranslatorI;
+
+impl TranslatorI {
+ fn flags(&self) {}
+}
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `Error` with `#[derive(Eq)]`
|
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `Error` with `#[derive(Eq)]`
|
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `Error` with `#[derive(Eq)]`
|
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `Error` with `#[derive(Eq)]`
|
|
LL | #[derive(Eqr)]
| ^^^ help: a derive macro with a similar name exists: `Eq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
|
- ::: $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub macro Eq($item:item) {
- | ------------ similarly named derive macro `Eq` defined here
+ = note: similarly named derive macro `Eq` defined here
error: cannot find derive macro `Eqr` in this scope
--> $DIR/deriving-meta-unknown-trait.rs:1:10
|
LL | #[derive(Eqr)]
| ^^^ help: a derive macro with a similar name exists: `Eq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
|
- ::: $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub macro Eq($item:item) {
- | ------------ similarly named derive macro `Eq` defined here
+ = note: similarly named derive macro `Eq` defined here
error: aborting due to 2 previous errors
= note: required for `Option<f64>` to implement `Eq`
note: required by a bound in `AssertParamIsEq`
--> $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
|
LL | struct S { x: u8, y: u8 }
| ^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait AddAssign<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0067]: invalid left-hand side of assignment
--> $DIR/note-unsupported.rs:17:22
--- /dev/null
+// compile-flags: --diagnostic-width=60
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+mod a {
+ // Force the "short path for unique types" machinery to trip up
+ pub struct Atype;
+ pub struct Btype;
+ pub struct Ctype;
+}
+
+mod b {
+ pub struct Atype<T, K>(T, K);
+ pub struct Btype<T, K>(T, K);
+ pub struct Ctype<T, K>(T, K);
+}
+
+use b::*;
+
+fn main() {
+ let x: Atype<
+ Btype<
+ Ctype<
+ Atype<
+ Btype<
+ Ctype<
+ Atype<
+ Btype<
+ Ctype<i32, i32>,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok("")
+ ))))))))))))))))))))))))))))))
+ ))))))))))))))))))))))))))))));
+ //~^^^^^ ERROR E0308
+
+ let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+ Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+ Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+ Some(Some(Some(Some(Some(Some(Some(Some(Some("")))))))))
+ )))))))))))))))))
+ ))))))))))))))))))
+ ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+ ))))))))))))))))))))))))))))))
+ ))))))))))))))))))))))));
+ //~^^^^^ ERROR E0308
+
+ let x: Atype<
+ Btype<
+ Ctype<
+ Atype<
+ Btype<
+ Ctype<
+ Atype<
+ Btype<
+ Ctype<i32, i32>,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ >,
+ i32
+ > = ();
+ //~^ ERROR E0308
+
+ let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+ Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+ ))))))))))))))))))))))))))))))
+ ))))))))))))))))))))))));
+ //~^^^^^ ERROR E0308
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/long-E0308.rs:44:9
+ |
+LL | let x: Atype<
+ | _____________-
+LL | | Btype<
+LL | | Ctype<
+LL | | Atype<
+... |
+LL | | i32
+LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+ | | _____-___^
+ | ||_____|
+ | | expected due to this
+LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+LL | | Ok("")
+LL | | ))))))))))))))))))))))))))))))
+LL | | ))))))))))))))))))))))))))))));
+ | |__________________________________^ expected struct `Atype`, found enum `Result`
+ |
+ = note: expected struct `Atype<Btype<..., ...>, ...>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ found enum `Result<Result<..., ...>, ...>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+ --> $DIR/long-E0308.rs:57:26
+ |
+LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+ | __________________________^
+LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | | ))))))))))))))))))))))))))))))
+LL | | ))))))))))))))))))))))));
+ | |____________________________^ expected enum `Option`, found enum `Result`
+ |
+ = note: expected enum `Option<Result<..., ...>>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ found enum `Result<Result<..., ...>, ...>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+ --> $DIR/long-E0308.rs:88:9
+ |
+LL | let x: Atype<
+ | ____________-
+LL | | Btype<
+LL | | Ctype<
+LL | | Atype<
+... |
+LL | | i32
+LL | | > = ();
+ | | - ^^ expected struct `Atype`, found `()`
+ | |_____|
+ | expected due to this
+ |
+ = note: expected struct `Atype<Btype<..., ...>, ...>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+ found unit type `()`
+
+error[E0308]: mismatched types
+ --> $DIR/long-E0308.rs:91:17
+ |
+LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+ | ____________--___^
+ | | |
+ | | expected due to this
+LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | | ))))))))))))))))))))))))))))))
+LL | | ))))))))))))))))))))))));
+ | |____________________________^ expected `()`, found enum `Result`
+ |
+ = note: expected unit type `()`
+ found enum `Result<Result<..., ...>, ...>`
+ the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+struct X {
+ x: String,
+}
+
+impl Drop for X {
+ fn drop(&mut self) {
+ println!("value: {}", self.x);
+ }
+}
+
+fn unwrap(x: X) -> String {
+ let X { x: ref y } = x; //~ ERROR cannot move out of type
+ y.to_string()
+}
+
+fn main() {
+ let x = X { x: "hello".to_string() };
+ let y = unwrap(x);
+ println!("contents: {}", y);
+}
+// run-rustfix
struct X {
x: String,
}
fn unwrap(x: X) -> String {
let X { x: y } = x; //~ ERROR cannot move out of type
- y
+ y.to_string()
}
fn main() {
error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
- --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22
+ --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22
|
LL | let X { x: y } = x;
| - ^ cannot move out of here
| |
| data moved here
| move occurs because `y` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let X { x: ref y } = x;
+ | +++
error: aborting due to previous error
--- /dev/null
+// run-rustfix
+struct X {
+ x: String,
+}
+
+impl Drop for X {
+ fn drop(&mut self) {
+ println!("value: {}", self.x);
+ }
+}
+
+fn main() {
+ let x = X { x: "hello".to_string() };
+
+ match x {
+ //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait
+ X { x: ref y } => println!("contents: {}", y)
+ }
+}
+// run-rustfix
struct X {
x: String,
}
error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
- --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11
+ --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11
|
LL | match x {
| ^ cannot move out of here
| |
| data moved here
| move occurs because `y` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | X { x: ref y } => println!("contents: {}", y)
+ | +++
error: aborting due to previous error
--> $DIR/disambiguate-identical-names.rs:13:10
|
LL | test(&v);
- | ---- ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+ | ---- ^^ expected struct `Vec`, found struct `HashMap`
| |
| arguments to this function are incorrect
|
--- /dev/null
+// run-pass
+#![allow(unreachable_code)]
+// Issue #21486: Make sure that all structures are dropped, even when
+// created via FRU and control-flow breaks in the middle of
+// construction.
+
+use std::sync::atomic::{Ordering, AtomicUsize};
+
+#[derive(Debug)]
+struct Noisy(u8);
+impl Drop for Noisy {
+ fn drop(&mut self) {
+ // println!("splat #{}", self.0);
+ event(self.0);
+ }
+}
+
+#[allow(dead_code)]
+#[derive(Debug)]
+struct Foo { n0: Noisy, n1: Noisy }
+impl Foo {
+ fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
+}
+
+fn leak_1_ret() -> Foo {
+ let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
+ Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+ .._old_foo
+ };
+}
+
+fn leak_2_ret() -> Foo {
+ let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
+ Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+ .._old_foo
+ };
+}
+
+// In this case, the control flow break happens *before* we construct
+// `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the
+// event log.
+fn leak_3_ret() -> Foo {
+ let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) };
+ Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
+ .._old_foo()
+ };
+}
+
+pub fn main() {
+ reset_log();
+ assert_eq!(leak_1_ret().vals(), (3,4));
+ assert_eq!(0x01_02_03_04, event_log());
+
+ reset_log();
+ assert_eq!(leak_2_ret().vals(), (3,4));
+ assert_eq!(0x01_02_03_04, event_log());
+
+ reset_log();
+ assert_eq!(leak_3_ret().vals(), (3,4));
+ assert_eq!(0x03_04, event_log());
+}
+
+static LOG: AtomicUsize = AtomicUsize::new(0);
+
+fn reset_log() {
+ LOG.store(0, Ordering::SeqCst);
+}
+
+fn event_log() -> usize {
+ LOG.load(Ordering::SeqCst)
+}
+
+fn event(tag: u8) {
+ let old_log = LOG.load(Ordering::SeqCst);
+ let new_log = (old_log << 8) + tag as usize;
+ LOG.store(new_log, Ordering::SeqCst);
+}
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0320`.
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0320`.
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0320`.
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Box::<T>::new`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | impl<T> Box<T> {
- | ^ required by this bound in `Box::<T>::new`
error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
--> $DIR/dst-rvalue.rs:8:37
= help: the trait `Sized` is not implemented for `[isize]`
note: required by a bound in `Box::<T>::new`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | impl<T> Box<T> {
- | ^ required by this bound in `Box::<T>::new`
error: aborting due to 2 previous errors
--- /dev/null
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+trait Tr {}
+
+fn f(x: dyn* Tr) -> usize {
+ x as usize
+ //~^ ERROR casting `(dyn* Tr + 'static)` as `usize` is invalid
+}
+
+fn main() {}
--- /dev/null
+error[E0606]: casting `(dyn* Tr + 'static)` as `usize` is invalid
+ --> $DIR/dyn-to-rigid.rs:7:5
+ |
+LL | x as usize
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
--> $DIR/no-implicit-dyn-star.rs:6:48
|
LL | dyn_star_foreign::require_dyn_star_display(1usize);
- | ------------------------------------------ ^^^^^^ expected trait object `dyn std::fmt::Display`, found `usize`
+ | ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize`
| |
| arguments to this function are incorrect
|
LL | let xe1 = XEmpty2();
| ~~~~~~~
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:25:19
|
LL | let xe3 = XE::Empty3;
| ^^^^^^
| |
- | variant or associated item not found in `empty_struct::XE`
+ | variant or associated item not found in `XE`
| help: there is a variant with a similar name: `XEmpty3`
-error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:26:19
|
LL | let xe3 = XE::Empty3();
| ^^^^^^
| |
- | variant or associated item not found in `empty_struct::XE`
+ | variant or associated item not found in `XE`
| help: there is a variant with a similar name: `XEmpty3`
error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE`
|
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | None,
- | ^^^^ not covered
-...
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^ not covered
+ = note: not covered
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
= note: the matched value is of type `Option<i32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | None,
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
|
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | ^^^^^ required by this bound in `Fn`
error: aborting due to previous error
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>` to implement `Foo`
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
--> $DIR/E0275.rs:6:9
|
LL | impl<T> Foo for T where Bar<T>: Foo {}
|
help: consider giving `x` an explicit type
|
-LL | let x: _ = "hello".chars().rev().collect();
- | +++
+LL | let x: Vec<_> = "hello".chars().rev().collect();
+ | ++++++++
error: aborting due to previous error
|
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | None,
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<i32>`
error: aborting due to previous error
|
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
| ^^^^ required by this bound in `bfnr`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
|
LL | bfnr::<U, V, W>(x);
| +++++++++++
| | value moved due to this method call
| move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves value
+note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value
--> $DIR/E0507.rs:6:24
|
LL | fn nothing_is_true(self) {}
| |
| cannot move out of here
| move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&array[0]`
+ |
+help: consider borrowing here
+ |
+LL | let _value = &array[0];
+ | +
error: aborting due to previous error
| |
| cannot move out of here
| move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&array[0]`
+ |
+help: consider borrowing here
+ |
+LL | let _value = &array[0];
+ | +
error: aborting due to previous error
| |
| cannot move out of here
| move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&drop_struct.fancy`
+ |
+help: consider borrowing here
+ |
+LL | let fancy_field = &drop_struct.fancy;
+ | +
error: aborting due to previous error
|
help: use the fully-qualified path to the only available implementation
|
-LL | inner::<MyStruct as MyTrait>::my_fn();
- | ++++++++++++ +
+LL | <MyStruct as inner::MyTrait>::my_fn();
+ | ++++++++++++ +
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:30:13
|
help: use the fully-qualified path to the only available implementation
|
-LL | let _ = inner::<MyStruct as MyTrait>::MY_ASSOC_CONST;
- | ++++++++++++ +
+LL | let _ = <MyStruct as inner::MyTrait>::MY_ASSOC_CONST;
+ | ++++++++++++ +
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:50:5
|
LL | enum Question {
| ^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait Not {
- | ^^^^^^^^^^^^^
error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/error-festival.rs:25:5
LL | |
LL | | |x| println!("doubling {}", x);
LL | | Some(x * 2)
- | | ----------- this tail expression is of type `std::option::Option<_>`
+ | | ----------- this tail expression is of type `Option<_>`
LL | |
LL | | });
| |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
= help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
note: required by a bound in `Option::<T>::and_then`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | F: ~const FnOnce(T) -> Option<U>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::and_then`
error: aborting due to 2 previous errors
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
|
-LL | pub enum Result<T, E> {
- | ---------------------
-...
-LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
- | ^^^ not covered
+ = note: not covered
= note: the matched value is of type `Result<u32, !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
|
LL | fn f() -> impl Fn() -> impl Sized { || () }
| ^^^^^^^^^^
+ |
+ = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+ = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
|
LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
| ^^^^^^^^^^
+ |
+ = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+ = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
error: aborting due to 2 previous errors
extern "C" {
- #[linkage = "extern_weak"] static foo: isize;
+ #[linkage = "extern_weak"] static foo: *mut isize;
//~^ ERROR: the `linkage` attribute is experimental and not portable
}
error[E0658]: the `linkage` attribute is experimental and not portable across platforms
--> $DIR/feature-gate-linkage.rs:2:5
|
-LL | #[linkage = "extern_weak"] static foo: isize;
+LL | #[linkage = "extern_weak"] static foo: *mut isize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #29603 <https://github.com/rust-lang/rust/issues/29603> for more information
+#![allow(unused, bare_trait_objects)]
#[repr(align(256))]
-#[allow(dead_code)]
struct A {
v: u8,
}
}
}
-fn foo(x: dyn Foo) {
- //~^ ERROR [E0277]
+fn foo(x: dyn Foo) { //~ ERROR [E0277]
x.foo()
}
+fn bar(x: Foo) { //~ ERROR [E0277]
+ x.foo()
+}
+
+fn qux(_: [()]) {} //~ ERROR [E0277]
+
fn main() {
let x: Box<dyn Foo> = Box::new(A { v: 22 });
- foo(*x);
- //~^ ERROR [E0277]
+ foo(*x); //~ ERROR [E0277]
}
|
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn foo(x: impl Foo) {
+ | ~~~~
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn foo(x: &dyn Foo) {
| +
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
- --> $DIR/feature-gate-unsized_fn_params.rs:24:9
+ --> $DIR/feature-gate-unsized_fn_params.rs:21:8
+ |
+LL | fn bar(x: Foo) {
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+ = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn bar(x: impl Foo) {
+ | ++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn bar(x: &Foo) {
+ | +
+
+error[E0277]: the size for values of type `[()]` cannot be known at compilation time
+ --> $DIR/feature-gate-unsized_fn_params.rs:25:8
+ |
+LL | fn qux(_: [()]) {}
+ | ^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[()]`
+ = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+ |
+LL | fn qux(_: &[()]) {}
+ | +
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+ --> $DIR/feature-gate-unsized_fn_params.rs:29:9
|
LL | foo(*x);
| ^^ doesn't have a size known at compile-time
= note: all function arguments must have a statically known size
= help: unsized fn params are gated as an unstable feature
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.
|
= help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn f(f: impl FnOnce()) {}
+ | ~~~~
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn f(f: &dyn FnOnce()) {}
found reference `&{float}`
note: associated function defined here
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
- |
-LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
- | ^^^^^^^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
found reference `&{float}`
note: associated function defined here
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
- |
-LL | pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
- | ^^^^^^^^^^
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 38 previous errors
= note: required for `&str` to implement `UpperHex`
note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
- |
-LL | arg_new!(new_upper_hex, UpperHex);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ArgumentV1::<'a>::new_upper_hex`
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
LL | trait Bar {
| ^^^^^^^^^
-error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope
--> $DIR/fn-help-with-err.rs:23:10
|
LL | arc2.bar();
- | ^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:22:36: 22:38]>`
+ | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Bar` defines an item `bar`, perhaps you need to implement it
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/generator.rs:LL:COL
- |
-LL | fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
- | ^^^^^^
help: provide the argument
|
LL | Pin::new(&mut b).resume(());
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `GeneratorState`
--> $SRC_DIR/core/src/ops/generator.rs:LL:COL
- |
-LL | pub enum GeneratorState<Y, R> {
- | ^ required by this bound in `GeneratorState`
error: aborting due to 2 previous errors
--> $DIR/auxiliary/foo_defn.rs:4:15
|
LL | type Bar: AsRef<()>;
- | ^^^^^^^^^ required by this bound in `foo_defn::Foo::Bar`
+ | ^^^^^^^^^ required by this bound in `Foo::Bar`
error: aborting due to previous error
error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied
- --> $DIR/issue-101020.rs:31:5
+ --> $DIR/issue-101020.rs:31:22
|
LL | (&mut EmptyIter).consume(());
- | ^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
+ | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`
|
note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>`
--> $DIR/issue-101020.rs:27:20
LL | type A = HashMap;
| ^^^^^^^ expected at least 2 generic arguments
|
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^ - -
help: add missing generic arguments
|
LL | type A = HashMap<K, V>;
| |
| expected at least 2 generic arguments
|
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^ - -
help: add missing generic argument
|
LL | type B = HashMap<String, V>;
| ^^^^^^^--------- help: remove these generics
| |
| expected 0 lifetime arguments
- |
-note: struct defined here, with 0 lifetime parameters
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^
error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:318:18
LL | type C = HashMap<'static>;
| ^^^^^^^ expected at least 2 generic arguments
|
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^ - -
help: add missing generic arguments
|
LL | type C = HashMap<'static, K, V>;
| ^^^^^^^ --- help: remove this generic argument
| |
| expected at most 3 generic arguments
- |
-note: struct defined here, with at most 3 generic parameters: `K`, `V`, `S`
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^ - - ---------------
error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:328:18
LL | type E = HashMap<>;
| ^^^^^^^ expected at least 2 generic arguments
|
-note: struct defined here, with at least 2 generic parameters: `K`, `V`
- --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | pub struct HashMap<K, V, S = RandomState> {
- | ^^^^^^^ - -
help: add missing generic arguments
|
LL | type E = HashMap<K, V>;
LL | type A = Result;
| ^^^^^^ expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic arguments
|
LL | type A = Result<T, E>;
| |
| expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic argument
|
LL | type B = Result<String, E>;
| ^^^^^^--------- help: remove these generics
| |
| expected 0 lifetime arguments
- |
-note: enum defined here, with 0 lifetime parameters
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^
error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:342:18
LL | type C = Result<'static>;
| ^^^^^^ expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic arguments
|
LL | type C = Result<'static, T, E>;
| ^^^^^^ ---- help: remove this generic argument
| |
| expected 2 generic arguments
- |
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:352:18
LL | type E = Result<>;
| ^^^^^^ expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic arguments
|
LL | type E = Result<T, E>;
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99.., _] => {},
- | ^^ expected struct `std::ops::Range`, found integer
+ | ^^ expected struct `Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99..] => {},
- | ^^ expected struct `std::ops::Range`, found integer
+ | ^^ expected struct `Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | ^ expected struct `std::ops::Range`, found integer
+ | ^ expected struct `Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | [..9, 99..100, _] => {},
| ^^ --- this is of type `{integer}`
| |
- | expected struct `std::ops::Range`, found integer
+ | expected struct `Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | -- ^^^ expected struct `std::ops::Range`, found integer
+ | -- ^^^ expected struct `Range`, found integer
| |
| this is of type `{integer}`
|
--- /dev/null
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+fn id(
+ f: &dyn Fn(u32),
+) -> &dyn Fn(
+ &dyn Fn(
+ &dyn Fn(
+ &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+ ),
+ ),
+) {
+ f
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/hang-on-deeply-nested-dyn.rs:12:5
+ |
+LL | ) -> &dyn Fn(
+ | ______-
+LL | | &dyn Fn(
+LL | | &dyn Fn(
+LL | | &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))),
+LL | | ),
+LL | | ),
+LL | | ) {
+ | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
+LL | f
+ | ^ expected reference, found `u32`
+ |
+ = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+ the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+ found reference `&dyn Fn(u32)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>`, but its trait bounds were not satisfied
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:118:22
|
LL | pub struct Map<S, F> {
| doesn't satisfy `_: StreamExt`
...
LL | let filter = map.filterx(|x: &_| true);
- | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>` due to unsatisfied trait bounds
+ | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:130:24
|
LL | pub struct Filter<S, F> {
| doesn't satisfy `_: StreamExt`
...
LL | let count = filter.countx();
- | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+ | ^^^^^^ method cannot be called due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
-error[E0271]: expected `[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]` to be a closure that returns `Unit3`, but it returns `Unit4`
+error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4`
--> $DIR/issue-62203-hrtb-ice.rs:39:9
|
LL | let v = Unit2.m(
--- /dev/null
+// run-pass
+#![allow(path_statements)]
+// pretty-expanded FIXME #23616
+
+macro_rules! inner {
+ ($e:pat ) => ($e)
+}
+
+macro_rules! outer {
+ ($e:pat ) => (inner!($e))
+}
+
+fn main() {
+ let outer!(g1) = 13;
+ g1;
+}
--- /dev/null
+struct MutType;
+
+pub trait MutTrait {
+ fn function(&mut self)
+ where
+ Self: Sized;
+ //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+ fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+ fn function(&self)
+ where
+ Self: Sized;
+ //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+ fn function(&self) {}
+}
+
+fn main() {
+ (&MutType as &dyn MutTrait).function();
+ //~^ ERROR the `function` method cannot be invoked on a trait object
+ //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+ (&mut Type as &mut dyn Trait).function();
+ //~^ ERROR the `function` method cannot be invoked on a trait object
+ //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
+}
--- /dev/null
+error: the `function` method cannot be invoked on a trait object
+ --> $DIR/mutability-mismatch.rs:28:33
+ |
+LL | Self: Sized;
+ | ----- this has a `Sized` requirement
+...
+LL | (&MutType as &dyn MutTrait).function();
+ | ^^^^^^^^
+ |
+ = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
+
+error: the `function` method cannot be invoked on a trait object
+ --> $DIR/mutability-mismatch.rs:31:35
+ |
+LL | Self: Sized;
+ | ----- this has a `Sized` requirement
+...
+LL | (&mut Type as &mut dyn Trait).function();
+ | ^^^^^^^^
+ |
+ = note: you need `&dyn Trait` instead of `&mut dyn Trait`
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+struct MutType;
+
+pub trait MutTrait {
+ fn function(&mut self)
+ where
+ Self: Sized;
+ //~^ this has a `Sized` requirement
+}
+
+impl MutTrait for MutType {
+ fn function(&mut self) {}
+}
+
+struct Type;
+
+pub trait Trait {
+ fn function(&self)
+ where
+ Self: Sized;
+ //~^ this has a `Sized` requirement
+}
+
+impl Trait for Type {
+ fn function(&self) {}
+}
+
+fn main() {
+ (&mut MutType as &mut dyn MutTrait).function();
+ //~^ ERROR the `function` method cannot be invoked on a trait object
+ (&Type as &dyn Trait).function();
+ //~^ ERROR the `function` method cannot be invoked on a trait object
+}
--- /dev/null
+error: the `function` method cannot be invoked on a trait object
+ --> $DIR/regular.rs:28:41
+ |
+LL | Self: Sized;
+ | ----- this has a `Sized` requirement
+...
+LL | (&mut MutType as &mut dyn MutTrait).function();
+ | ^^^^^^^^
+
+error: the `function` method cannot be invoked on a trait object
+ --> $DIR/regular.rs:30:27
+ |
+LL | Self: Sized;
+ | ----- this has a `Sized` requirement
+...
+LL | (&Type as &dyn Trait).function();
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
LL | fn bak() -> dyn Trait { unimplemented!() }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
- |
-LL | fn bak() -> T { unimplemented!() }
- | ~
help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | fn bak() -> impl Trait { unimplemented!() }
|
LL | fn hash(&self, hasher: &mut impl Hasher) {}
| ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+ --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
- |
-LL | fn hash<H: Hasher>(&self, state: &mut H);
- | - declaration in trait here
+ = note: declaration in trait here
error: aborting due to 4 previous errors
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^ required by this bound in `Vec`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/wf-bounds.rs:12:23
|
= note: the following trait bounds were not satisfied:
`RawImpl<()>: Raw<()>`
-note: the following trait must be implemented
+note: the trait `Raw` must be implemented
--> $DIR/issue-62742.rs:12:1
|
LL | pub trait Raw<T: ?Sized> {
|
help: consider giving this closure parameter an explicit type
|
-LL | |_: _| true
- | +++
+LL | |_: /* Type */| true
+ | ++++++++++++
error: aborting due to 3 previous errors
LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec> {
| ^^^ expected at least 1 generic argument
|
-note: struct defined here, with at least 1 generic parameter: `T`
- --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^^^ -
help: add missing generic argument
|
LL | fn f<T>(data: &[T]) -> impl Iterator<Item = Vec<T>> {
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:50:37
|
LL | no_method_suggested_traits::Foo.method2();
- | ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+ | ^^^^^^^ method not found in `Foo`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:52:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
- | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:54:40
|
LL | no_method_suggested_traits::Bar::X.method2();
- | ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+ | ^^^^^^^ method not found in `Bar`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:56:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
- | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
| ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
-error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:71:37
|
LL | no_method_suggested_traits::Foo.method3();
- | ^^^^^^^ method not found in `no_method_suggested_traits::Foo`
+ | ^^^^^^^ method not found in `Foo`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:72:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
- | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Foo>>`
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
-error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:74:40
|
LL | no_method_suggested_traits::Bar::X.method3();
- | ^^^^^^^ method not found in `no_method_suggested_traits::Bar`
+ | ^^^^^^^ method not found in `Bar`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:75:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
- | ^^^^^^^ method not found in `Rc<&mut Box<&no_method_suggested_traits::Bar>>`
+ | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>`
error: aborting due to 24 previous errors
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected struct `a::Bar`, found opaque type
+ | expected struct `Bar`, found opaque type
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
= note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected opaque type, found struct `b::Bar`
+ | expected opaque type, found struct `Bar`
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
= note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
...
LL | define_vec!();
| ------------- in this macro invocation
-note: `Vec` could also refer to the struct defined here
+note: `Vec` could also refer to a struct from prelude
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
- |
-LL | pub use super::v1::*;
- | ^^^^^^^^^^^^
= note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
--- /dev/null
+// check-pass
+
+extern crate core;
+use core as core_export;
+use self::x::*;
+mod x {}
+
+fn main() {}
--> $DIR/deref-suggestion.rs:37:5
|
LL | assert_eq!(3i32, &3i32);
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32`
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected `i32`, found `&i32`
+ | expected because this is `i32`
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
| ^^^^^^^ required by this bound in `foo`
-help: consider specifying the type arguments in the function call
+help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
|
-LL | let foo = foo::<T, K, W, Z>(1, "");
- | ++++++++++++++
+LL | let foo: Foo<i32, &str, W, Z> = foo(1, "");
+ | ++++++++++++++++++++++
error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
--> $DIR/erase-type-params-in-label.rs:5:9
|
LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
| ^^^^^^^ required by this bound in `bar`
-help: consider specifying the type arguments in the function call
+help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
|
-LL | let bar = bar::<T, K, Z>(1, "");
- | +++++++++++
+LL | let bar: Bar<i32, &str, Z> = bar(1, "");
+ | +++++++++++++++++++
error: aborting due to 2 previous errors
where T: ?Sized;
note: required by a bound in `HashMap::<K, V, S>::get`
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | K: Borrow<Q>,
- | ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
help: consider specifying the generic argument
|
LL | .get::<Q>(&"key".into())
|
help: consider giving this closure parameter an explicit type
|
-LL | |x: _| String::from("x".as_ref());
- | +++
+LL | |x: /* Type */| String::from("x".as_ref());
+ | ++++++++++++
error[E0283]: type annotations needed
--> $DIR/issue-72690.rs:12:26
--> $DIR/infinite-recursion-const-fn.rs:4:5
|
LL | b()
+ | ^^^ reached the configured maximum number of stack frames
+ |
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
| ^^^
- | |
- | reached the configured maximum number of stack frames
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
- | inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-...
-LL | a()
- | ---
- | |
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
- | inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-LL | }
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `b`
+ --> $DIR/infinite-recursion-const-fn.rs:7:5
+ |
+LL | a()
+ | ^^^
+note: inside `a`
+ --> $DIR/infinite-recursion-const-fn.rs:4:5
+ |
+LL | b()
+ | ^^^
+note: inside `ARR::{constant#0}`
+ --> $DIR/infinite-recursion-const-fn.rs:9:18
+ |
LL | const ARR: [i32; a()] = [5; 6];
- | --- inside `ARR::{constant#0}` at $DIR/infinite-recursion-const-fn.rs:9:18
+ | ^^^
error: aborting due to previous error
--- /dev/null
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/expr-unsafe-err.rs:8:9
+ |
+LL | require_unsafe();
+ | ^^^^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+ const {
+ require_unsafe();
+ //~^ ERROR [E0133]
+ }
+}
--- /dev/null
+error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block
+ --> $DIR/expr-unsafe-err.rs:8:9
+ |
+LL | require_unsafe();
+ | ^^^^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+warning: unnecessary `unsafe` block
+ --> $DIR/expr-unsafe.rs:12:13
+ |
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/expr-unsafe.rs:4:9
+ |
+LL | #![warn(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
--- /dev/null
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+#![warn(unused_unsafe)]
+#![feature(inline_const)]
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+ unsafe {
+ const {
+ require_unsafe();
+ unsafe {}
+ //~^ WARNING unnecessary `unsafe` block
+ }
+ }
+}
--- /dev/null
+warning: unnecessary `unsafe` block
+ --> $DIR/expr-unsafe.rs:12:13
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/expr-unsafe.rs:4:9
+ |
+LL | #![warn(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
--- /dev/null
+// ignore-test This is currently broken
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+ match () {
+ const {
+ require_unsafe();
+ //~^ ERROR [E0133]
+ } => (),
+ }
+}
--- /dev/null
+// ignore-test This is currently broken
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(incomplete_features)]
+#![warn(unused_unsafe)]
+#![feature(inline_const_pat)]
+
+const unsafe fn require_unsafe() -> usize { 1 }
+
+fn main() {
+ unsafe {
+ match () {
+ const {
+ require_unsafe();
+ unsafe {}
+ //~^ WARNING unnecessary `unsafe` block
+ } => (),
+ }
+ }
+}
| ^^
note: required by a bound in `catch_unwind`
--> $SRC_DIR/std/src/panic.rs:LL:COL
- |
-LL | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
- | ^^^^^^^^^^ required by this bound in `catch_unwind`
error: aborting due to previous error
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
- |
-LL | F: FnOnce<ARG, Output = RET>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error: this argument must be a function item
--> $DIR/const-eval-select-bad.rs:10:31
= note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
- |
-LL | G: FnOnce<ARG, Output = RET>,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
--> $DIR/const-eval-select-bad.rs:32:34
|
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
- |
-LL | G: FnOnce<ARG, Output = RET>,
- | ^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0631]: type mismatch in function arguments
--> $DIR/const-eval-select-bad.rs:37:32
found function signature `fn(i32) -> _`
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
- |
-LL | F: FnOnce<ARG, Output = RET>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error: this argument must be a `const fn`
--> $DIR/const-eval-select-bad.rs:42:29
-error: -Zbranch-protection is only supported on aarch64
+error: `-Zbranch-protection` is only supported on aarch64
error: aborting due to previous error
// [BADFLAGS] check-fail
// [BADFLAGS] needs-llvm-components: aarch64
// [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti
-// [BADTARGET] build-fail
+// [BADTARGET] check-fail
// [BADTARGET] needs-llvm-components: x86
#![crate_type = "lib"]
LL | #[no_sanitize(brontosaurus)]
| ^^^^^^^^^^^^
|
- = note: expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+ = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
error: aborting due to previous error
+++ /dev/null
-mod inner {
- pub trait Trait {
- fn f(&self) { f(); }
- fn f_ufcs(&self) { f_ufcs(); }
- }
-
- impl Trait for isize {}
-
- fn f() {}
- fn f_ufcs() {}
-}
-
-pub fn foo<T: inner::Trait>(t: T) {
- t.f();
-}
-pub fn foo_ufcs<T: inner::Trait>(t: T) {
- T::f_ufcs(&t);
-}
+++ /dev/null
-use inner::Trait;
-
-mod inner {
- pub struct Foo;
- pub trait Trait {
- fn f(&self);
- fn f_ufcs(&self);
- }
-
- impl Trait for Foo {
- fn f(&self) { }
- fn f_ufcs(&self) { }
- }
-}
-
-pub trait Outer {
- fn foo<T: Trait>(&self, t: T) { t.f(); }
- fn foo_ufcs<T: Trait>(&self, t: T) { T::f(&t); }
-}
-
-impl Outer for isize {}
-
-pub fn foo<T: Outer>(t: T) {
- t.foo(inner::Foo);
-}
-pub fn foo_ufcs<T: Outer>(t: T) {
- T::foo_ufcs(&t, inner::Foo)
-}
+++ /dev/null
-trait PrivateTrait {
- fn private_trait_method(&self);
- fn private_trait_method_ufcs(&self);
-}
-
-struct PrivateStruct;
-
-impl PrivateStruct {
- fn private_inherent_method(&self) { }
- fn private_inherent_method_ufcs(&self) { }
-}
-
-impl PrivateTrait for PrivateStruct {
- fn private_trait_method(&self) { }
- fn private_trait_method_ufcs(&self) { }
-}
-
-#[inline]
-pub fn public_inlinable_function() {
- PrivateStruct.private_trait_method();
- PrivateStruct.private_inherent_method();
-}
-
-#[inline]
-pub fn public_inlinable_function_ufcs() {
- PrivateStruct::private_trait_method(&PrivateStruct);
- PrivateStruct::private_inherent_method(&PrivateStruct);
-}
--> $DIR/issue-105330.rs:12:11
|
LL | foo::<Demo>()();
- | ^^^^ types differ
+ | ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
|
+ = note: expected constant `32`
+ found constant `<Demo as TraitWAssocConst>::A`
note: required by a bound in `foo`
--> $DIR/issue-105330.rs:11:28
|
--> $DIR/issue-105330.rs:19:11
|
LL | foo::<Demo>();
- | ^^^^ types differ
+ | ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A`
|
+ = note: expected constant `32`
+ found constant `<Demo as TraitWAssocConst>::A`
note: required by a bound in `foo`
--> $DIR/issue-105330.rs:11:28
|
+++ /dev/null
-// run-pass
-// aux-build:issue-11225-1.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_1 as foo;
-
-pub fn main() {
- foo::foo(1);
- foo::foo_ufcs(1);
-}
+++ /dev/null
-// run-pass
-// aux-build:issue-11225-2.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_2 as foo;
-
-pub fn main() {
- foo::foo(1);
- foo::foo_ufcs(1);
-}
+++ /dev/null
-// run-pass
-// aux-build:issue-11225-3.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate issue_11225_3;
-
-pub fn main() {
- issue_11225_3::public_inlinable_function();
- issue_11225_3::public_inlinable_function_ufcs();
-}
| --- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | (&[ref hd1, ..], &[hd2, ..])
+ | +++
error[E0508]: cannot move out of type `[T]`, a non-copy slice
--> $DIR/issue-12567.rs:2:11
| --- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | (&[hd1, ..], &[ref hd2, ..])
+ | +++
error: aborting due to 2 previous errors
|
LL | pub struct BytePos(pub u32);
| ^^^^^^^^^^^^^^^^^^ must implement `Not`
-note: the following trait must be implemented
+note: the trait `Not` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait Not {
- | ^^^^^^^^^^^^^
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
LL | fn fn1(0: Box) {}
| ^^^ expected at least 1 generic argument
|
-note: struct defined here, with at least 1 generic parameter: `T`
- --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | pub struct Box<
- | ^^^
-LL | T: ?Sized,
- | -
help: add missing generic argument
|
LL | fn fn1(0: Box<T>) {}
+++ /dev/null
-// run-pass
-#![allow(path_statements)]
-// pretty-expanded FIXME #23616
-
-macro_rules! inner {
- ($e:pat ) => ($e)
-}
-
-macro_rules! outer {
- ($e:pat ) => (inner!($e))
-}
-
-fn main() {
- let outer!(g1) = 13;
- g1;
-}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
|
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider specifying the generic argument
- --> $SRC_DIR/std/src/panic.rs:LL:COL
- |
-LL | $crate::rt::begin_panic::<M>($msg)
- | +++++
error: aborting due to previous error
|
LL | fn new() -> NoResult<MyEnum, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | --------------------- similarly named enum `Result` defined here
+ = note: similarly named enum `Result` defined here
|
help: try using the variant's enum
|
|
LL | fn newer() -> NoResult<foo::MyEnum, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | --------------------- similarly named enum `Result` defined here
+ = note: similarly named enum `Result` defined here
|
help: try using the variant's enum
|
= help: the trait `Sized` is not implemented for `[{integer}]`
note: required by a bound in `Box::<T>::new`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | impl<T> Box<T> {
- | ^ required by this bound in `Box::<T>::new`
error: aborting due to previous error
LL | dyn AbstractRenderer
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
-help: use some type `T` that is `T: Sized` as the return type if all return paths have the same type
- |
-LL | T
- |
help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
|
LL | impl AbstractRenderer
|
help: consider giving `x` an explicit type
|
-LL | let x: _;
- | +++
+LL | let x: /* Type */;
+ | ++++++++++++
error: aborting due to previous error
| ^^^ -- help: remove this lifetime argument
| |
| expected 0 lifetime arguments
- |
-note: struct defined here, with 0 lifetime parameters
- --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | pub struct Box<
- | ^^^
error: aborting due to previous error
error[E0277]: the trait bound `X: Ord` is not satisfied
- --> $DIR/issue-20162.rs:5:5
+ --> $DIR/issue-20162.rs:5:7
|
LL | b.sort();
- | ^ ---- required by a bound introduced by this call
- | |
- | the trait `Ord` is not implemented for `X`
+ | ^^^^ the trait `Ord` is not implemented for `X`
|
note: required by a bound in `slice::<impl [T]>::sort`
--> $SRC_DIR/alloc/src/slice.rs:LL:COL
- |
-LL | T: Ord,
- | ^^^ required by this bound in `slice::<impl [T]>::sort`
help: consider annotating `X` with `#[derive(Ord)]`
|
LL | #[derive(Ord)]
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>` to implement `Foo`
+note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>>>>>>>` to implement `Foo`
--> $DIR/issue-20413.rs:9:9
|
LL | impl<T> Foo for T where NoData<T>: Foo {
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
--> $DIR/issue-20413.rs:28:9
|
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
| ^^^ ^
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
--> $DIR/issue-20413.rs:35:9
|
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
--> $DIR/issue-20413.rs:35:9
|
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
| ^^^ ^
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
--> $DIR/issue-20413.rs:28:9
|
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
= help: the trait `Sized` is not implemented for `[i32]`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^ required by this bound in `Vec`
error: aborting due to previous error
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-
-use std::fmt::Debug;
-
-struct NT(str);
-struct DST { a: u32, b: str }
-
-macro_rules! check {
- (val: $ty_of:expr, $expected:expr) => {
- assert_eq!(type_name_of_val($ty_of), $expected);
- };
- ($ty:ty, $expected:expr) => {
- assert_eq!(std::any::type_name::<$ty>(), $expected);
- };
-}
-
-fn main() {
- // type_name should support unsized types
- check!([u8], "[u8]");
- check!(str, "str");
- check!(dyn Send, "dyn core::marker::Send");
- check!(NT, "issue_21058::NT");
- check!(DST, "issue_21058::DST");
- check!(&i32, "&i32");
- check!(&'static i32, "&i32");
- check!((i32, u32), "(i32, u32)");
- check!(val: foo(), "issue_21058::Foo");
- check!(val: Foo::new, "issue_21058::Foo::new");
- check!(val:
- <Foo as Debug>::fmt,
- "<issue_21058::Foo as core::fmt::Debug>::fmt"
- );
- check!(val: || {}, "issue_21058::main::{{closure}}");
- bar::<i32>();
-}
-
-trait Trait {
- type Assoc;
-}
-
-impl Trait for i32 {
- type Assoc = String;
-}
-
-fn bar<T: Trait>() {
- check!(T::Assoc, "alloc::string::String");
- check!(T, "i32");
-}
-
-fn type_name_of_val<T>(_: T) -> &'static str {
- std::any::type_name::<T>()
-}
-
-#[derive(Debug)]
-struct Foo;
-
-impl Foo {
- fn new() -> Self { Foo }
-}
-
-fn foo() -> impl Debug {
- Foo
-}
+++ /dev/null
-// run-pass
-#![allow(unreachable_code)]
-// Issue #21486: Make sure that all structures are dropped, even when
-// created via FRU and control-flow breaks in the middle of
-// construction.
-
-use std::sync::atomic::{Ordering, AtomicUsize};
-
-#[derive(Debug)]
-struct Noisy(u8);
-impl Drop for Noisy {
- fn drop(&mut self) {
- // println!("splat #{}", self.0);
- event(self.0);
- }
-}
-
-#[allow(dead_code)]
-#[derive(Debug)]
-struct Foo { n0: Noisy, n1: Noisy }
-impl Foo {
- fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) }
-}
-
-fn leak_1_ret() -> Foo {
- let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
- Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
- .._old_foo
- };
-}
-
-fn leak_2_ret() -> Foo {
- let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) };
- Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
- .._old_foo
- };
-}
-
-// In this case, the control flow break happens *before* we construct
-// `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the
-// event log.
-fn leak_3_ret() -> Foo {
- let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) };
- Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } },
- .._old_foo()
- };
-}
-
-pub fn main() {
- reset_log();
- assert_eq!(leak_1_ret().vals(), (3,4));
- assert_eq!(0x01_02_03_04, event_log());
-
- reset_log();
- assert_eq!(leak_2_ret().vals(), (3,4));
- assert_eq!(0x01_02_03_04, event_log());
-
- reset_log();
- assert_eq!(leak_3_ret().vals(), (3,4));
- assert_eq!(0x03_04, event_log());
-}
-
-static LOG: AtomicUsize = AtomicUsize::new(0);
-
-fn reset_log() {
- LOG.store(0, Ordering::SeqCst);
-}
-
-fn event_log() -> usize {
- LOG.load(Ordering::SeqCst)
-}
-
-fn event(tag: u8) {
- let old_log = LOG.load(Ordering::SeqCst);
- let new_log = (old_log << 8) + tag as usize;
- LOG.store(new_log, Ordering::SeqCst);
-}
|
help: consider giving `x` an explicit type
|
-LL | let x: _ = panic!();
- | +++
+LL | let x: /* Type */ = panic!();
+ | ++++++++++++
error: aborting due to previous error
LL | where &'a T : Foo,
| ^^^
|
- = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+ --> $DIR/issue-21974.rs:11:19
+ |
+LL | where &'a T : Foo,
+ | ^^^
+LL | &'b T : Foo
+ | ^^^
error: aborting due to previous error
LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3));
| ^^ expected 1 generic argument
|
-note: trait defined here, with 1 generic parameter: `Args`
- --> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | ^^ ----
help: add missing generic argument
|
LL | println!("{:?}",(vfnfer[0] as dyn Fn<Args>)(3));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
--> $DIR/issue-23122-2.rs:10:15
|
LL | impl<T: Next> Next for GetNext<T> {
= help: the trait `FnMut<(_, char)>` is not implemented for `()`
note: required by a bound in `fold`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(B, Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold`
error: aborting due to previous error
|
help: consider giving this closure parameter an explicit type
|
-LL | 1 => |c: _| c + 1,
- | +++
+LL | 1 => |c: /* Type */| c + 1,
+ | ++++++++++++
error: aborting due to 2 previous errors
LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
| ^^^^^^^^^^^
|
- = note: cannot satisfy `T0: Trait0<'l0>`
+note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found
+ --> $DIR/issue-24424.rs:4:57
+ |
+LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {}
+ | ^^^^^^^^^^^ ^^^^^^^^^^^
error: aborting due to previous error
+++ /dev/null
-// check-pass
-
-extern crate core;
-use core as core_export;
-use self::x::*;
-mod x {}
-
-fn main() {}
|
LL | None @ _ => {}
| ^^^^ cannot be named the same as a unit variant
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
- ::: $SRC_DIR/std/src/prelude/mod.rs:LL:COL
- |
-LL | pub use super::v1::*;
- | ------------ the unit variant `None` is defined here
+ = note: the unit variant `None` is defined here
error[E0530]: match bindings cannot shadow constants
--> $DIR/issue-27033.rs:7:9
+++ /dev/null
-// run-pass
-// This test ensures that vec.into_iter does not overconstrain element lifetime.
-
-pub fn main() {
- original_report();
- revision_1();
- revision_2();
-}
-
-fn original_report() {
- drop(vec![&()].into_iter())
-}
-
-fn revision_1() {
- // below is what above `vec!` expands into at time of this writing.
- drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter())
-}
-
-fn revision_2() {
- drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter())
-}
+++ /dev/null
-// run-pass
-// ignore-tidy-linelength
-
-// Regression test for #29227. The problem here was that MIR
-// construction for these gigantic match expressions was very
-// inefficient.
-
-pub trait CharExt : Sized + Copy {
- fn is_unicode_uppercase_letter(self) -> bool { false }
- fn is_unicode_lowercase_letter(self) -> bool { false }
- fn is_unicode_titlecase_letter(self) -> bool { false }
- fn is_unicode_modifier_letter(self) -> bool { false }
- fn is_unicode_other_letter(self) -> bool { false }
- fn is_unicode_letter_number(self) -> bool { false }
- fn is_unicode_nonspacing_mark(self) -> bool { false }
- fn is_unicode_combining_spacing_mark(self) -> bool { false }
- fn is_unicode_decimal_number(self) -> bool{ false }
- fn is_unicode_connector_punctiation(self) -> bool { false }
- fn is_unicode_space_separator(self) -> bool { false }
-
- fn is_es_identifier_start(self) -> bool { false }
- fn is_es_identifier_part(self) -> bool { false }
- fn is_es_whitespace(self) -> bool { false }
- fn is_es_line_terminator(self) -> bool { false }
-
- fn is_unicode_letter(self) -> bool {
- self.is_unicode_uppercase_letter()
- || self.is_unicode_lowercase_letter()
- || self.is_unicode_titlecase_letter()
- || self.is_unicode_modifier_letter()
- || self.is_unicode_modifier_letter()
- || self.is_unicode_letter_number()
- }
-
-}
-
-
-macro_rules! match_char_class {
- ($thing:expr, $($c:expr),*) => {
- match $thing {
- $($c)|* => true,
- _ => false
- }
- }
-}
-
-impl CharExt for char {
- fn is_unicode_uppercase_letter(self) -> bool {
- match_char_class!(self,
- '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}')
- }
-
- fn is_unicode_lowercase_letter(self) -> bool {
- match_char_class!(self,
- '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}')
-
- }
-
- fn is_unicode_titlecase_letter(self) -> bool {
- match_char_class!(self,
- '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}')
- }
-
- fn is_unicode_modifier_letter(self) -> bool {
- match_char_class!(self,
- '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}')
- }
-
- fn is_unicode_other_letter(self) -> bool {
- match_char_class!(self,
- '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
- }
-
- fn is_unicode_letter_number(self) -> bool {
- match_char_class!(self,
- '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}')
- }
-
- fn is_unicode_nonspacing_mark(self) -> bool {
- match_char_class!(self,
- '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}', '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
- }
-
- fn is_unicode_combining_spacing_mark(self) -> bool {
- match_char_class!(self,
- '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}')
- }
-
- fn is_unicode_decimal_number(self) -> bool {
- match_char_class!(self,
- '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}')
- }
-
- fn is_unicode_connector_punctiation(self) -> bool {
- match_char_class!(self,
- '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}')
- }
-
- fn is_unicode_space_separator(self) -> bool {
- match_char_class!(self,
- '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}')
- }
-
- fn is_es_identifier_start(self) -> bool {
- match self {
- '$' | '_' | '\\' => true,
- c if c.is_unicode_letter() => true,
- _ => false
- }
- }
-
- // see section 7.6
- fn is_es_identifier_part(self) -> bool {
- match self {
- '\u{200C}' | '\u{200D}' => true,
- c if c.is_es_identifier_start() => true,
- c if c.is_unicode_combining_spacing_mark() => true,
- c if c.is_unicode_nonspacing_mark() => true,
- c if c.is_unicode_decimal_number() => true,
- c if c.is_unicode_connector_punctiation() => true,
- _ => false
- }
- }
-
- fn is_es_whitespace(self) -> bool {
- match self {
- '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true,
- c => c.is_unicode_space_separator()
- }
- }
-
- fn is_es_line_terminator(self) -> bool {
- match self {
- '\n' | '\r' | '\u{2028}' | '\u{2029}' => true,
- _ => false
- }
- }
-}
-
-fn main() {
-
-}
-error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
--> $DIR/issue-30123.rs:7:33
|
LL | let ug = Graph::<i32, i32>::new_undirected();
- | ^^^^^^^^^^^^^^ function or associated item not found in `issue_30123_aux::Graph<i32, i32>`
+ | ^^^^^^^^^^^^^^ function or associated item not found in `Graph<i32, i32>`
|
= note: the function or associated item was found for
- `issue_30123_aux::Graph<N, E, Undirected>`
|
note: associated function defined here
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn fold<B, F>(mut self, init: B, mut f: F) -> B
- | ^^^^
help: provide the argument
|
LL ~ needlesArr.iter().fold(|x, y| {
let mut found_e = false;
let temp: Vec<u8> = it
- //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
.take_while(|&x| {
found_e = true;
false
})
- .cloned()
+ .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8`
.collect(); //~ ERROR the method
}
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
- --> $DIR/issue-31173.rs:6:25
+error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8`
+ --> $DIR/issue-31173.rs:11:10
|
-LL | let temp: Vec<u8> = it
- | _________________________^
-LL | |
-LL | | .take_while(|&x| {
-LL | | found_e = true;
-LL | | false
-LL | | })
- | |__________^ expected reference, found `u8`
-LL | .cloned()
- | ------ required by a bound introduced by this call
+LL | .cloned()
+ | ^^^^^^ expected reference, found `u8`
|
= note: expected reference `&_`
found type `u8`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/issue-31173.rs:3:20
+ |
+LL | pub fn get_tok(it: &mut IntoIter<u8>) {
+ | ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here
+...
+LL | .take_while(|&x| {
+ | __________-
+LL | | found_e = true;
+LL | | false
+LL | | })
+ | |__________- `Iterator::Item` remains `u8` here
note: required by a bound in `cloned`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | Self: Sized + Iterator<Item = &'a T>,
- | ^^^^^^^^^^^^ required by this bound in `cloned`
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
- --> $DIR/issue-31173.rs:13:10
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
+ --> $DIR/issue-31173.rs:12:10
|
LL | .collect();
- | ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
- |
- ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
- |
-LL | pub struct TakeWhile<I, P> {
- | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
+ | ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+ --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
|
- ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
+ = note: doesn't satisfy `<_ as Iterator>::Item = &_`
+ --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
|
-LL | pub struct Cloned<I> {
- | -------------------- doesn't satisfy `_: Iterator`
+ = note: doesn't satisfy `_: Iterator`
|
= note: the following trait bounds were not satisfied:
- `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
- which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
- `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
- which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+ `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
+ which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+ `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+ which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
error: aborting due to 2 previous errors
...
LL | foo!();
| ------ in this macro invocation
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | pub macro derive_const($item:item) {
- | ---------------------- similarly named attribute macro `derive_const` defined here
+ = note: similarly named attribute macro `derive_const` defined here
|
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
|
LL | #[derive_Clone]
| ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | pub macro derive_const($item:item) {
- | ---------------------- similarly named attribute macro `derive_const` defined here
+ = note: similarly named attribute macro `derive_const` defined here
error: aborting due to 2 previous errors
+++ /dev/null
-fn main() {
- let baz = ().foo(); //~ ERROR no method named `foo` found
- <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
-}
+++ /dev/null
-error[E0599]: no method named `foo` found for unit type `()` in the current scope
- --> $DIR/issue-33575.rs:2:18
- |
-LL | let baz = ().foo();
- | ^^^ method not found in `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
use std::collections::HashMap;
fn main() {
- for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
- //~^ ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
- //~| ERROR expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+ for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+ //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+ //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
}
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
- --> $DIR/issue-33941.rs:6:14
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+ --> $DIR/issue-33941.rs:6:36
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
- | |
- | expected reference, found tuple
+ | ^^^^^^ expected reference, found tuple
|
= note: expected reference `&_`
found tuple `(&_, &_)`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/issue-33941.rs:6:29
+ |
+LL | for _ in HashMap::new().iter().cloned() {}
+ | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
+ | |
+ | this expression has type `HashMap<_, _>`
note: required by a bound in `cloned`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | Self: Sized + Iterator<Item = &'a T>,
- | ^^^^^^^^^^^^ required by this bound in `cloned`
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
-error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
+error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
| +
error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
- --> $DIR/issue-34334.rs:5:33
+ --> $DIR/issue-34334.rs:5:87
|
LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+ | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
|
= help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/issue-34334.rs:5:43
+ |
+LL | let sr: Vec<(u32, _, _) = vec![];
+ | ------ this expression has type `Vec<(_, _, _)>`
+...
+LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+ | |
+ | `Iterator::Item` is `&(_, _, _)` here
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to 2 previous errors
LL | x.zero()
| ^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `Foo::zero` takes ownership of the receiver `self`, which moves `x`
--> $DIR/issue-34721.rs:4:13
|
LL | fn zero(self) -> Self;
+++ /dev/null
-// check-pass
-
-#![warn(unused)]
-
-type Z = dyn for<'x> Send;
-//~^ WARN type alias `Z` is never used
-
-fn main() {}
+++ /dev/null
-warning: type alias `Z` is never used
- --> $DIR/issue-37515.rs:5:6
- |
-LL | type Z = dyn for<'x> Send;
- | ^
- |
-note: the lint level is defined here
- --> $DIR/issue-37515.rs:3:9
- |
-LL | #![warn(unused)]
- | ^^^^^^
- = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
-
-warning: 1 warning emitted
-
+++ /dev/null
-trait A<T>: std::ops::Add<Self> + Sized {}
-trait B<T>: A<T> {}
-trait C<T>: A<dyn B<T, Output=usize>> {}
-//~^ ERROR the trait `B` cannot be made into an object
-
-fn main() {}
+++ /dev/null
-error[E0038]: the trait `B` cannot be made into an object
- --> $DIR/issue-38404.rs:3:15
- |
-LL | trait C<T>: A<dyn B<T, Output=usize>> {}
- | ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-38404.rs:1:13
- |
-LL | trait A<T>: std::ops::Add<Self> + Sized {}
- | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
-LL | trait B<T>: A<T> {}
- | - this trait cannot be made into an object...
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0038`.
|
note: the module `sys` is defined here
--> $SRC_DIR/std/src/lib.rs:LL:COL
- |
-LL | mod sys;
- | ^^^^^^^
error: aborting due to 2 previous errors
+++ /dev/null
-fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
-
-fn main() {}
+++ /dev/null
-error: expected type, found `0`
- --> $DIR/issue-39616.rs:1:12
- |
-LL | fn foo(a: [0; 1]) {}
- | ^ expected type
-
-error: aborting due to previous error
-
--> $DIR/issue-40402-1.rs:9:13
|
LL | let e = f.v[0];
- | ^^^^^^
- | |
- | move occurs because value has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&f.v[0]`
+ | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let e = &f.v[0];
+ | +
error: aborting due to previous error
--> $DIR/issue-40402-2.rs:5:18
|
LL | let (a, b) = x[0];
- | - - ^^^^ help: consider borrowing here: `&x[0]`
+ | - - ^^^^
| | |
| | ...and here
| data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+ |
+LL | let (a, b) = &x[0];
+ | +
error: aborting due to previous error
| ------------------------ method `iter` not found for this struct
...
LL | println!("{:?}", a.iter().take(10).collect::<Vec<usize>>());
- | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:27]>`
+ | ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>`
error: aborting due to previous error
|
= help: the trait `Sized` is not implemented for `(dyn ToString + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | pub fn f(_: impl ToString) {}
+ | ~~~~
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | pub fn f(_: &dyn ToString) {}
+++ /dev/null
-// run-rustfix
-
-#![allow(unused_must_use, unused_comparisons)]
-
-macro_rules! is_plainly_printable {
- ($i: ident) => {
- ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments
- };
-}
-
-fn main() {
- let c = 'a';
- is_plainly_printable!(c);
-}
+++ /dev/null
-// run-rustfix
-
-#![allow(unused_must_use, unused_comparisons)]
-
-macro_rules! is_plainly_printable {
- ($i: ident) => {
- $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments
- };
-}
-
-fn main() {
- let c = 'a';
- is_plainly_printable!(c);
-}
+++ /dev/null
-error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
- --> $DIR/issue-42954.rs:7:19
- |
-LL | $i as u32 < 0
- | ^ - interpreted as generic arguments
- | |
- | not interpreted as comparison
-...
-LL | is_plainly_printable!(c);
- | ------------------------ in this macro invocation
- |
- = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: try comparing the cast value
- |
-LL | ($i as u32) < 0
- | + +
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-// To work around #46855
-// compile-flags: -Z mir-opt-level=0
-// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
-
-use std::mem;
-
-#[derive(Copy, Clone)]
-enum Never { }
-
-// A single uninhabited variant shouldn't make the whole union uninhabited.
-union Foo {
- a: u64,
- _b: Never
-}
-
-// If all the variants are uninhabited, however, the union should be uninhabited.
-// NOTE(#49298) the union being uninhabited shouldn't change its size.
-union Bar {
- _a: (Never, u64),
- _b: (u64, Never)
-}
-
-fn main() {
- assert_eq!(mem::size_of::<Foo>(), 8);
- // See the note on `Bar`'s definition for why this isn't `0`.
- assert_eq!(mem::size_of::<Bar>(), 8);
-
- let f = [Foo { a: 42 }, Foo { a: 10 }];
- println!("{}", unsafe { f[0].a });
- assert_eq!(unsafe { f[1].a }, 10);
-}
--> $DIR/issue-47486.rs:2:10
|
LL | () < std::mem::size_of::<_>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+ | |
+ | expected because this is `()`
error[E0282]: type annotations needed
--> $DIR/issue-47486.rs:3:11
found reference `&'static str`
note: associated function defined here
--> $SRC_DIR/core/src/slice/mod.rs:LL:COL
- |
-LL | pub fn starts_with(&self, needle: &[T]) -> bool
- | ^^^^^^^^^^^
= note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
+++ /dev/null
-// Test for #49257:
-// emits good diagnostics for `..` pattern fragments not in the last position.
-
-#![allow(unused)]
-
-struct Point { x: u8, y: u8 }
-
-fn main() {
- let p = Point { x: 0, y: 0 };
- let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
- let Point { .., y } = p; //~ ERROR expected `}`, found `,`
- let Point { .., } = p; //~ ERROR expected `}`, found `,`
- let Point { .. } = p;
-}
+++ /dev/null
-error: expected `}`, found `,`
- --> $DIR/issue-49257.rs:10:19
- |
-LL | let Point { .., y, } = p;
- | --^
- | | |
- | | expected `}`
- | `..` must be at the end and cannot have a trailing comma
- |
-help: move the `..` to the end of the field list
- |
-LL - let Point { .., y, } = p;
-LL + let Point { y, .. } = p;
- |
-
-error: expected `}`, found `,`
- --> $DIR/issue-49257.rs:11:19
- |
-LL | let Point { .., y } = p;
- | --^
- | | |
- | | expected `}`
- | `..` must be at the end and cannot have a trailing comma
- |
-help: move the `..` to the end of the field list
- |
-LL - let Point { .., y } = p;
-LL + let Point { y , .. } = p;
- |
-
-error: expected `}`, found `,`
- --> $DIR/issue-49257.rs:12:19
- |
-LL | let Point { .., } = p;
- | --^
- | | |
- | | expected `}`
- | | help: remove this comma
- | `..` must be at the end and cannot have a trailing comma
-
-error: aborting due to 3 previous errors
-
+++ /dev/null
-#[derive(Clone, Copy)]
-//~^ ERROR the trait `Copy` may not be implemented for this type
-struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-//~^ ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
-
-#[derive(Clone, Copy)]
-//~^ ERROR the trait `Copy` may not be implemented for this type
-struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-//~^ ERROR cannot find type `NotDefined` in this scope
-//~| ERROR cannot find type `N` in this scope
-//~| ERROR `i32` is not an iterator
-
-fn main() {}
+++ /dev/null
-error[E0412]: cannot find type `N` in this scope
- --> $DIR/issue-50480.rs:3:12
- |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | -^ not found in this scope
- | |
- | help: you might be missing a type parameter: `<N>`
-
-error[E0412]: cannot find type `NotDefined` in this scope
- --> $DIR/issue-50480.rs:3:15
- |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | ^^^^^^^^^^ not found in this scope
-
-error[E0412]: cannot find type `N` in this scope
- --> $DIR/issue-50480.rs:3:12
- |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | -^ not found in this scope
- | |
- | help: you might be missing a type parameter: `<N>`
-
-error[E0412]: cannot find type `NotDefined` in this scope
- --> $DIR/issue-50480.rs:3:15
- |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | - ^^^^^^^^^^ not found in this scope
- | |
- | help: you might be missing a type parameter: `<NotDefined>`
-
-error[E0412]: cannot find type `N` in this scope
- --> $DIR/issue-50480.rs:12:18
- |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | - ^
- | |
- | similarly named type parameter `T` defined here
- |
-help: a type parameter with a similar name exists
- |
-LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | ~
-help: you might be missing a type parameter
- |
-LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | +++
-
-error[E0412]: cannot find type `NotDefined` in this scope
- --> $DIR/issue-50480.rs:12:21
- |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | ^^^^^^^^^^ not found in this scope
-
-error[E0277]: `i32` is not an iterator
- --> $DIR/issue-50480.rs:3:27
- |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
- |
- = help: the trait `Iterator` is not implemented for `i32`
- = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-
-error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/issue-50480.rs:1:17
- |
-LL | #[derive(Clone, Copy)]
- | ^^^^
-LL |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | -------- ------ this field does not implement `Copy`
- | |
- | this field does not implement `Copy`
- |
- = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0277]: `i32` is not an iterator
- --> $DIR/issue-50480.rs:12:33
- |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
- |
- = help: the trait `Iterator` is not implemented for `i32`
- = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-
-error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/issue-50480.rs:10:17
- |
-LL | #[derive(Clone, Copy)]
- | ^^^^
-LL |
-LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
- | -------- ------ this field does not implement `Copy`
- | |
- | this field does not implement `Copy`
- |
- = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 10 previous errors
-
-Some errors have detailed explanations: E0204, E0277, E0412.
-For more information about an error, try `rustc --explain E0204`.
= help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
note: associated function defined here
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | pub fn new(x: T) -> Self {
- | ^^^
error: aborting due to previous error
+++ /dev/null
-use std::any::TypeId;
-use std::collections::HashMap;
-use std::hash::Hash;
-
-trait State {
- type EventType;
- fn get_type_id_of_state(&self) -> TypeId;
-}
-
-struct StateMachine<EventType: Hash + Eq> {
- current_state: Box<dyn State<EventType = EventType>>,
- transition_table:
- HashMap<TypeId, HashMap<EventType, fn() -> Box<dyn State<EventType = EventType>>>>,
-}
-
-impl<EventType: Hash + Eq> StateMachine<EventType> {
- fn inner_process_event(&mut self, event: EventType) -> Result<(), i8> {
- let new_state_creation_function = self
- .transition_table
- .iter()
- .find(|(&event_typeid, _)| event_typeid == self.current_state.get_type_id_of_state())
- .ok_or(1)?
- .1
- .iter()
- .find(|(&event_type, _)| event == event_type)
- //~^ ERROR cannot move out of a shared reference
- .ok_or(2)?
- .1;
-
- self.current_state = new_state_creation_function();
- Ok(())
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0507]: cannot move out of a shared reference
- --> $DIR/issue-51301.rs:25:20
- |
-LL | .find(|(&event_type, _)| event == event_type)
- | ^^----------^^^^
- | |
- | data moved here
- | move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0507`.
+++ /dev/null
-// In case of macro expansion, the errors should be matched using the deepest callsite in the
-// macro call stack whose span is in the current file
-
-macro_rules! macro_with_error {
- ( ) => {
- println!("{"); //~ ERROR invalid
- };
-}
-
-fn foo() {
-
-}
-
-fn main() {
- macro_with_error!();
- //^ In case of a local macro we want the error to be matched in the macro definition, not here
-
- println!("}"); //~ ERROR invalid
- //^ In case of an external macro we want the error to be matched here
-}
+++ /dev/null
-error: invalid format string: expected `'}'` but string was terminated
- --> $DIR/issue-51848.rs:6:20
- |
-LL | println!("{");
- | -^ expected `'}'` in format string
- | |
- | because of this opening brace
-...
-LL | macro_with_error!();
- | ------------------- in this macro invocation
- |
- = note: if you intended to print `{`, you can escape it using `{{`
- = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: invalid format string: unmatched `}` found
- --> $DIR/issue-51848.rs:18:15
- |
-LL | println!("}");
- | ^ unmatched `}` in format string
- |
- = note: if you intended to print `}`, you can escape it using `}}`
-
-error: aborting due to 2 previous errors
-
+++ /dev/null
-// check-pass
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-const INVALID_ENUM : u32 = 0;
-const INVALID_VALUE : u32 = 1;
-
-fn gl_err_str(err: u32) -> String
-{
- match err
- {
- INVALID_ENUM => { "Invalid enum".to_string() },
- INVALID_VALUE => { "Invalid value".to_string() },
- _ => { "Unknown error".to_string() }
- }
-}
-
-pub fn main() {}
|
= help: the trait `Sized` is not implemented for `(dyn A + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | r: impl A + 'static
+ | ~~~~
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | r: &dyn A + 'static
LL | bad_letters.push('s');
| ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `bad_letters`
+note: `into_iter` takes ownership of the receiver `self`, which moves `bad_letters`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<char>`'s content to avoid moving into the `for` loop
|
LL | for l in &bad_letters {
| |
| value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `orig`
+note: `into_iter` takes ownership of the receiver `self`, which moves `orig`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
|
LL | for _val in &orig {}
error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
- --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
+ --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
|
LL | let x2: Vec<f64> = x1.into_iter().collect();
- | ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+ | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
|
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
+ |
+LL | let x1: &[f64] = &v;
+ | -- this expression has type `&Vec<f64>`
+LL | let x2: Vec<f64> = x1.into_iter().collect();
+ | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
- --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
+ --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
|
LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
- | ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+ | ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
|
= help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
+ |
+LL | let x1: &[f64] = &v;
+ | -- this expression has type `&Vec<f64>`
+...
+LL | let x3 = x1.into_iter().collect::<Vec<f64>>();
+ | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to 2 previous errors
|
LL | impl Fo {
| ^^ help: a trait with a similar name exists: `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error: aborting due to previous error
+++ /dev/null
-// compile-flags: -Zmir-opt-level=3 -Copt-level=0
-// run-pass
-
-type M = [i64; 2];
-
-fn f(a: &M) -> M {
- let mut b: M = M::default();
- b[0] = a[0] * a[0];
- b
-}
-
-fn main() {
- let mut a: M = [1, 1];
- a = f(&a);
- assert_eq!(a[0], 1);
-}
LL | for n in v {
| ^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `v`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider creating a fresh reborrow of `v` here
|
LL | for n in &mut *v {
//~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
//~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
//~| NOTE required by a bound in `collect`
- //~| NOTE required by a bound introduced by this call
}
error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
- --> $DIR/collect-into-array.rs:2:31
+ --> $DIR/collect-into-array.rs:2:39
|
LL | let whatever: [u32; 10] = (0..10).collect();
- | ^^^^^^^ ------- required by a bound introduced by this call
- | |
- | try collecting into a `Vec<{integer}>`, then using `.try_into()`
+ | ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
|
= help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to previous error
//~| NOTE all local variables must have a statically known size
//~| NOTE doesn't have a size known at compile-time
//~| NOTE doesn't have a size known at compile-time
- //~| NOTE required by a bound introduced by this call
process_slice(&some_generated_vec);
}
= help: the trait `Sized` is not implemented for `[i32]`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^ required by this bound in `collect`
error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
- --> $DIR/collect-into-slice.rs:6:30
+ --> $DIR/collect-into-slice.rs:6:38
|
LL | let some_generated_vec = (0..10).collect();
- | ^^^^^^^ ------- required by a bound introduced by this call
- | |
- | try explicitly collecting into a `Vec<{integer}>`
+ | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
|
= help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to 3 previous errors
--- /dev/null
+use std::collections::hash_set::Iter;
+use std::collections::HashSet;
+
+fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+ let i = i.map(|x| x.clone());
+ i.collect() //~ ERROR E0277
+}
+
+fn main() {
+ let scores = vec![(0, 0)]
+ .iter()
+ .map(|(a, b)| {
+ a + b;
+ });
+ println!("{}", scores.sum::<i32>()); //~ ERROR E0277
+ println!(
+ "{}",
+ vec![0, 1]
+ .iter()
+ .map(|x| x * 2)
+ .map(|x| x as f64)
+ .map(|x| x as i64)
+ .filter(|x| *x > 0)
+ .map(|x| { x + 1 })
+ .map(|x| { x; })
+ .sum::<i32>(), //~ ERROR E0277
+ );
+ println!(
+ "{}",
+ vec![0, 1]
+ .iter()
+ .map(|x| x * 2)
+ .map(|x| x as f64)
+ .filter(|x| *x > 0.0)
+ .map(|x| { x + 1.0 })
+ .sum::<i32>(), //~ ERROR E0277
+ );
+ println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>()); //~ ERROR E0277
+ println!("{}", vec![(), ()].iter().sum::<i32>()); //~ ERROR E0277
+ let a = vec![0];
+ let b = a.into_iter();
+ let c = b.map(|x| x + 1);
+ let d = c.filter(|x| *x > 10 );
+ let e = d.map(|x| {
+ x + 1;
+ });
+ let f = e.filter(|_| false);
+ let g: Vec<i32> = f.collect(); //~ ERROR E0277
+
+ let mut s = HashSet::new();
+ s.insert(1u8);
+ println!("{:?}", iter_to_vec(s.iter()));
+}
--- /dev/null
+error[E0277]: a value of type `Vec<X>` cannot be built from an iterator over elements of type `&X`
+ --> $DIR/invalid-iterator-chain.rs:6:7
+ |
+LL | i.collect()
+ | ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
+ |
+ = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
+ = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:4:26
+ |
+LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec<X> {
+ | ^^^^^^^^^^^ `Iterator::Item` is `&X` here
+LL | let i = i.map(|x| x.clone());
+ | ------------------ `Iterator::Item` remains `&X` here
+note: required by a bound in `collect`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+ --> $DIR/invalid-iterator-chain.rs:15:27
+ |
+LL | println!("{}", scores.sum::<i32>());
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+ |
+ = help: the trait `Sum<()>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:12:10
+ |
+LL | let scores = vec![(0, 0)]
+ | ------------ this expression has type `Vec<({integer}, {integer})>`
+LL | .iter()
+ | ------ `Iterator::Item` is `&({integer}, {integer})` here
+LL | .map(|(a, b)| {
+ | __________^
+LL | | a + b;
+LL | | });
+ | |__________^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+ --> $DIR/invalid-iterator-chain.rs:26:14
+ |
+LL | .sum::<i32>(),
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+ |
+ = help: the trait `Sum<()>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:20:14
+ |
+LL | vec![0, 1]
+ | ---------- this expression has type `Vec<{integer}>`
+LL | .iter()
+ | ------ `Iterator::Item` is `&{integer}` here
+LL | .map(|x| x * 2)
+ | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL | .map(|x| x as f64)
+ | ----------------- `Iterator::Item` changed to `f64` here
+LL | .map(|x| x as i64)
+ | ----------------- `Iterator::Item` changed to `i64` here
+LL | .filter(|x| *x > 0)
+ | ------------------ `Iterator::Item` remains `i64` here
+LL | .map(|x| { x + 1 })
+ | ------------------ `Iterator::Item` remains `i64` here
+LL | .map(|x| { x; })
+ | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64`
+ --> $DIR/invalid-iterator-chain.rs:36:14
+ |
+LL | .sum::<i32>(),
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=f64>`
+ |
+ = help: the trait `Sum<f64>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:32:14
+ |
+LL | vec![0, 1]
+ | ---------- this expression has type `Vec<{integer}>`
+LL | .iter()
+ | ------ `Iterator::Item` is `&{integer}` here
+LL | .map(|x| x * 2)
+ | ^^^^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here
+LL | .map(|x| x as f64)
+ | ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here
+LL | .filter(|x| *x > 0.0)
+ | -------------------- `Iterator::Item` remains `f64` here
+LL | .map(|x| { x + 1.0 })
+ | -------------------- `Iterator::Item` remains `f64` here
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()`
+ --> $DIR/invalid-iterator-chain.rs:38:54
+ |
+LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=()>`
+ |
+ = help: the trait `Sum<()>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:38:38
+ |
+LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::<i32>());
+ | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here
+ | | |
+ | | `Iterator::Item` is `&{integer}` here
+ | this expression has type `Vec<{integer}>`
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+ --> $DIR/invalid-iterator-chain.rs:39:40
+ |
+LL | println!("{}", vec![(), ()].iter().sum::<i32>());
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+ |
+ = help: the trait `Sum<&()>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:39:33
+ |
+LL | println!("{}", vec![(), ()].iter().sum::<i32>());
+ | ------------ ^^^^^^ `Iterator::Item` is `&()` here
+ | |
+ | this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
+ --> $DIR/invalid-iterator-chain.rs:48:25
+ |
+LL | let g: Vec<i32> = f.collect();
+ | ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
+ |
+ = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+ = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+note: the method call chain might not have had the expected associated types
+ --> $DIR/invalid-iterator-chain.rs:44:15
+ |
+LL | let a = vec![0];
+ | ------- this expression has type `Vec<{integer}>`
+LL | let b = a.into_iter();
+ | ----------- `Iterator::Item` is `{integer}` here
+LL | let c = b.map(|x| x + 1);
+ | -------------- `Iterator::Item` remains `{integer}` here
+LL | let d = c.filter(|x| *x > 10 );
+ | -------------------- `Iterator::Item` remains `{integer}` here
+LL | let e = d.map(|x| {
+ | _______________^
+LL | | x + 1;
+LL | | });
+ | |______^ `Iterator::Item` changed to `()` here
+LL | let f = e.filter(|_| false);
+ | ----------------- `Iterator::Item` remains `()` here
+note: required by a bound in `collect`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
|
LL | vec![true, false].map(|v| !v).collect::<Vec<_>>();
| ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<bool>: Iterator`
+ = note: doesn't satisfy `Vec<bool>: Iterator`
|
= note: the following trait bounds were not satisfied:
`Vec<bool>: Iterator`
error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
- --> $DIR/branches.rs:19:9
+ --> $DIR/branches.rs:19:28
|
LL | std::iter::empty().collect()
- | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+ | ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
|
= help: the trait `FromIterator<_>` is not implemented for `Bar`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to previous error
|
help: consider giving this closure parameter an explicit type
|
-LL | |s: _| s.len()
- | +++
+LL | |s: /* Type */| s.len()
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/branches3.rs:15:10
|
help: consider giving this closure parameter an explicit type
|
-LL | |s: _| s.len()
- | +++
+LL | |s: /* Type */| s.len()
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/branches3.rs:23:10
|
help: consider giving this closure parameter an explicit type
|
-LL | |s: _| s.len()
- | +++
+LL | |s: /* Type */| s.len()
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/branches3.rs:30:10
|
help: consider giving this closure parameter an explicit type
|
-LL | |s: _| s.len()
- | +++
+LL | |s: /* Type */| s.len()
+ | ++++++++++++
error: aborting due to 4 previous errors
error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
- --> $DIR/recursion4.rs:10:9
+ --> $DIR/recursion4.rs:10:28
|
LL | x = std::iter::empty().collect();
- | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+ | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
|
= help: the trait `FromIterator<_>` is not implemented for `Foo`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
- --> $DIR/recursion4.rs:19:9
+ --> $DIR/recursion4.rs:19:28
|
LL | x = std::iter::empty().collect();
- | ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
- | |
- | value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+ | ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
|
= help: the trait `FromIterator<_>` is not implemented for `impl Debug`
note: required by a bound in `collect`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn collect<B: FromIterator<Self::Item>>(self) -> B
- | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
error: aborting due to 2 previous errors
LL | let Bar(z) = x;
| ^^^^^^ - this expression has type `&mut irrefutable::Foo`
| |
- | expected struct `irrefutable::Foo`, found struct `irrefutable::Bar`
+ | expected struct `Foo`, found struct `Bar`
error: aborting due to 2 previous errors
--- /dev/null
+//~ type annotations needed: cannot satisfy `Self: Gen<'source>`
+
+pub trait Gen<'source> {
+ type Output;
+
+ fn gen<T>(&self) -> T
+ where
+ Self: for<'s> Gen<'s, Output = T>;
+}
+
+fn main() {}
--- /dev/null
+error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>`
+ |
+note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found
+ --> $DIR/conflicting-bounds.rs:3:1
+ |
+LL | pub trait Gen<'source> {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | Self: for<'s> Gen<'s, Output = T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
LL | &'a (): Foo,
| ^^^
|
- = note: cannot satisfy `&'a (): Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found
+ --> $DIR/issue-34979.rs:2:1
+ |
+LL | impl<'a, T> Foo for &'a T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | &'a (): Foo,
+ | ^^^
+LL | &'static (): Foo;
+ | ^^^
error: aborting due to previous error
error[E0080]: values of the type `[u8; SIZE]` are too big for the current architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
-LL | intrinsics::size_of::<T>()
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
- ::: $DIR/issue-55878.rs:7:26
+note: inside `std::mem::size_of::<[u8; SIZE]>`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `main`
+ --> $DIR/issue-55878.rs:7:26
|
LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
- | ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: erroneous constant used
--> $DIR/issue-55878.rs:7:26
--- /dev/null
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+#[linkage="external"]
+pub static EXTERN: u32 = 0;
+++ /dev/null
-#![feature(linkage)]
-#![crate_type = "lib"]
-
-#[linkage="external"]
-pub static EXTERN: u32 = 0;
--- /dev/null
+// build-pass
+// aux-build:def_external.rs
+
+extern crate def_external as dep;
+
+fn main() {
+ println!("{:p}", &dep::EXTERN);
+}
+++ /dev/null
-// rust-lang/rust#59548: We used to ICE when trying to use a static
-// with a type that violated its own `#[linkage]`.
-
-// build-fail
-// aux-build:def_illtyped_external.rs
-
-extern crate def_illtyped_external as dep;
-
-fn main() {
- println!("{:p}", &dep::EXTERN);
-}
+++ /dev/null
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
- --> $DIR/auxiliary/def_illtyped_external.rs:5:1
- |
-LL | pub static EXTERN: u32 = 0;
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-// FIXME https://github.com/rust-lang/rust/issues/59774
-
-// build-fail
-// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// ignore-sgx no weak linkages permitted
+// check-fail
#![feature(linkage)]
extern "C" {
#[linkage = "extern_weak"]
static foo: i32;
-//~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+//~^ ERROR: invalid type for variable with `#[linkage]` attribute
}
fn main() {
-error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
- --> $DIR/linkage2.rs:12:5
+error[E0791]: invalid type for variable with `#[linkage]` attribute
+ --> $DIR/linkage2.rs:7:5
|
LL | static foo: i32;
| ^^^^^^^^^^^^^^^
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0791`.
|
note: enums with multiple inhabited variants have to be initialized to a variant
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^^^^^^^^^^^^^^^^
error: the type `&i32` does not permit zero-initialization
--> $DIR/invalid_value.rs:152:34
= note: the mutable reference will refer to this temporary, not the original `const` item
note: mutable reference created due to call to this method
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub fn push(&mut self, value: T) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `const` item defined here
--> $DIR/lint-const-item-mutation.rs:31:1
|
--- /dev/null
+// check-pass
+#![deny(missing_copy_implementations)]
+
+// Don't recommend implementing Copy on something stateful like an iterator.
+pub struct MyIterator {
+ num: u8,
+}
+
+impl Iterator for MyIterator {
+ type Item = u8;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ todo!()
+ }
+}
+
+pub struct Handle {
+ inner: *mut (),
+}
+
+pub struct Handle2 {
+ inner: *const (),
+}
+
+pub enum MaybeHandle {
+ Ptr(*mut ()),
+}
+
+pub union UnionHandle {
+ ptr: *mut (),
+}
+
+pub struct Array([u8; 2048]);
+
+fn main() {}
match foo::Foo::Foo {
Foo => {}
-//~^ ERROR variable `Foo` should have a snake case name
-//~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
-//~^^^ WARN unused variable: `Foo`
+ //~^ ERROR variable `Foo` should have a snake case name
+ //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+ //~^^^ WARN unused variable: `Foo`
}
let Foo = foo::Foo::Foo;
//~^ ERROR variable `Foo` should have a snake case name
- //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
+ //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
//~^^^ WARN unused variable: `Foo`
fn in_param(Foo: foo::Foo) {}
//~^ ERROR variable `Foo` should have a snake case name
- //~^^ WARN `Foo` is named the same as one of the variants of the type `Foo`
+ //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
//~^^^ WARN unused variable: `Foo`
test(1);
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
--> $DIR/lint-uppercase-variables.rs:22:9
|
LL | Foo => {}
- | ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+ | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
|
= note: `#[warn(bindings_with_variant_name)]` on by default
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
--> $DIR/lint-uppercase-variables.rs:28:9
|
LL | let Foo = foo::Foo::Foo;
- | ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+ | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
-warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `Foo`
+warning[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo`
--> $DIR/lint-uppercase-variables.rs:33:17
|
LL | fn in_param(Foo: foo::Foo) {}
- | ^^^ help: to match on the variant, qualify the path: `Foo::Foo`
+ | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo`
warning: unused variable: `Foo`
--> $DIR/lint-uppercase-variables.rs:22:9
// run-rustfix
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
#![allow(
dead_code,
let _x = #[allow(dead_code)] (1 + 2);
}
+fn _no_lint_yeet() -> Result<(), ()> {
+ #[allow(unreachable_code)]
+ if (do yeet) {}
+
+ Ok(())
+}
+
// Don't lint in these cases (#64106).
fn or_patterns_no_lint() {
match Box::new(0) {
// run-rustfix
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
#![allow(
dead_code,
let _x = #[allow(dead_code)] (1 + 2);
}
+fn _no_lint_yeet() -> Result<(), ()> {
+ #[allow(unreachable_code)]
+ if (do yeet) {}
+
+ Ok(())
+}
+
// Don't lint in these cases (#64106).
fn or_patterns_no_lint() {
match Box::new(0) {
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:49:12
+ --> $DIR/issue-54538-unused-parens-lint.rs:56:12
|
LL | if let (0 | 1) = 0 {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:50:13
+ --> $DIR/issue-54538-unused-parens-lint.rs:57:13
|
LL | if let ((0 | 1),) = (0,) {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:51:13
+ --> $DIR/issue-54538-unused-parens-lint.rs:58:13
|
LL | if let [(0 | 1)] = [0] {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:52:16
+ --> $DIR/issue-54538-unused-parens-lint.rs:59:16
|
LL | if let 0 | (1 | 2) = 0 {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:54:15
+ --> $DIR/issue-54538-unused-parens-lint.rs:61:15
|
LL | if let TS((0 | 1)) = TS(0) {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:56:20
+ --> $DIR/issue-54538-unused-parens-lint.rs:63:20
|
LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:66:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:73:9
|
LL | (_) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:67:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:74:9
|
LL | (y) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:68:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:75:9
|
LL | (ref r) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:69:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:76:9
|
LL | (e @ 1...2) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:75:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:82:9
|
LL | (e @ &(1...2)) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:76:10
+ --> $DIR/issue-54538-unused-parens-lint.rs:83:10
|
LL | &(_) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:87:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:94:9
|
LL | (_) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:88:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:95:9
|
LL | (y) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:89:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:96:9
|
LL | (ref r) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:90:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:97:9
|
LL | (e @ 1..=2) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:96:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:103:9
|
LL | (e @ &(1..=2)) => {}
| ^ ^
|
error: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:97:10
+ --> $DIR/issue-54538-unused-parens-lint.rs:104:10
|
LL | &(_) => {}
| ^ ^
LL | let z = x;
| ^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
|
LL | for y in &x {
--- /dev/null
+// Auxiliary crate for test issue-105637: the LTOed dylib which had duplicate symbols from libstd,
+// breaking the panic hook feature.
+//
+// This simulates the `rustc_driver` crate, and the main crate simulates rustc's main binary hooking
+// into this driver.
+
+// compile-flags: -Zdylib-lto -C lto=thin
+
+use std::panic;
+
+pub fn main() {
+ // Install the hook we want to see executed
+ panic::set_hook(Box::new(|_| {
+ eprintln!("LTOed auxiliary crate panic hook");
+ }));
+
+ // Trigger the panic hook with an ICE
+ run_compiler();
+}
+
+fn run_compiler() {
+ panic!("ICEing");
+}
--- /dev/null
+// Regression test for issue #105637: `-Zdylib-lto` with LTO duplicated symbols from other dylibs,
+// in this case from libstd.
+//
+// That manifested as both `rustc_driver` and rustc's "main" (`compiler/rustc`) having their own
+// `std::panicking::HOOK` static, and the hook in rustc's main (the default stdlib's) being executed
+// when rustc ICEs, instead of the overriden hook from `rustc_driver` (which also displays the query
+// stack and information on how to open a GH issue for the encountered ICE).
+//
+// In this test, we reproduce this setup by installing a panic hook in both the main and an LTOed
+// dylib: the last hook set should be the one being executed, the dylib's.
+
+// aux-build: thinlto-dylib.rs
+// run-fail
+// check-run-results
+
+extern crate thinlto_dylib;
+
+use std::panic;
+
+fn main() {
+ // We don't want to see this panic hook executed
+ std::panic::set_hook(Box::new(|_| {
+ eprintln!("main crate panic hook");
+ }));
+
+ // Have the LTOed dylib install its own hook and panic, we want to see its hook executed.
+ thinlto_dylib::main();
+}
--- /dev/null
+LTOed auxiliary crate panic hook
| |
| `mutex` dropped here while still borrowed
|
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
- --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | $dst.write_fmt($crate::format_args!($($arg)*));
- | +
error[E0597]: `mutex` does not live long enough
--> $DIR/format-args-temporaries-in-write.rs:47:29
| |
| `mutex` dropped here while still borrowed
|
-help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
- --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | $dst.write_fmt($crate::format_args_nl!($($arg)*));
- | +
error: aborting due to 2 previous errors
--- /dev/null
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+ ($i: ident) => {
+ ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments
+ };
+}
+
+fn main() {
+ let c = 'a';
+ is_plainly_printable!(c);
+}
--- /dev/null
+// run-rustfix
+
+#![allow(unused_must_use, unused_comparisons)]
+
+macro_rules! is_plainly_printable {
+ ($i: ident) => {
+ $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments
+ };
+}
+
+fn main() {
+ let c = 'a';
+ is_plainly_printable!(c);
+}
--- /dev/null
+error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
+ --> $DIR/issue-42954.rs:7:19
+ |
+LL | $i as u32 < 0
+ | ^ - interpreted as generic arguments
+ | |
+ | not interpreted as comparison
+...
+LL | is_plainly_printable!(c);
+ | ------------------------ in this macro invocation
+ |
+ = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: try comparing the cast value
+ |
+LL | ($i as u32) < 0
+ | + +
+
+error: aborting due to previous error
+
--- /dev/null
+// In case of macro expansion, the errors should be matched using the deepest callsite in the
+// macro call stack whose span is in the current file
+
+macro_rules! macro_with_error {
+ ( ) => {
+ println!("{"); //~ ERROR invalid
+ };
+}
+
+fn foo() {
+
+}
+
+fn main() {
+ macro_with_error!();
+ //^ In case of a local macro we want the error to be matched in the macro definition, not here
+
+ println!("}"); //~ ERROR invalid
+ //^ In case of an external macro we want the error to be matched here
+}
--- /dev/null
+error: invalid format string: expected `'}'` but string was terminated
+ --> $DIR/issue-51848.rs:6:20
+ |
+LL | println!("{");
+ | -^ expected `'}'` in format string
+ | |
+ | because of this opening brace
+...
+LL | macro_with_error!();
+ | ------------------- in this macro invocation
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+ = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid format string: unmatched `}` found
+ --> $DIR/issue-51848.rs:18:15
+ |
+LL | println!("}");
+ | ^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 2 previous errors
+
| ^^^^^^^^^
...
LL | foo!()
- | ------- help: you might be missing a semicolon here: `;`
- | |
- | caused by the macro expansion here
+ | ------ caused by the macro expansion here
|
= note: the usage of `foo!` is likely invalid in expression context
+help: you might be missing a semicolon here
+ |
+LL | foo!();
+ | +
warning: trailing semicolon in macro used in expression position
--> $DIR/macro-in-expression-context.rs:5:29
|
LL | printlx!("oh noes!");
| ^^^^^^^ help: a macro with a similar name exists: `println`
+ --> $SRC_DIR/std/src/macros.rs:LL:COL
|
- ::: $SRC_DIR/std/src/macros.rs:LL:COL
- |
-LL | macro_rules! println {
- | -------------------- similarly named macro `println` defined here
+ = note: similarly named macro `println` defined here
error: aborting due to previous error
|
LL | inline!();
| ^^^^^^ help: a macro with a similar name exists: `line`
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | macro_rules! line {
- | ----------------- similarly named macro `line` defined here
+ = note: similarly named macro `line` defined here
|
= note: `inline` is in scope, but it is an attribute: `#[inline]`
error[E0773]: attempted to define built-in macro more than once
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
-LL | macro_rules! line {
- | ^^^^^^^^^^^^^^^^^
- |
note: previously defined here
--> $DIR/unknown-builtin.rs:9:1
|
|
note: required by a bound in `Copy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^^ required by this bound in `Copy`
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Test1` with `#[derive(Clone)]`
|
|
note: required by a bound in `Copy`
--> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^^ required by this bound in `Copy`
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Test2` with `#[derive(Clone)]`
|
|
help: consider giving `x` an explicit type
|
-LL | let x: _ = match () {
- | +++
+LL | let x: /* Type */ = match () {
+ | ++++++++++++
error: aborting due to previous error
--- /dev/null
+#![feature(auto_traits)]
+
+auto trait Foo {
+ fn g(&self); //~ ERROR auto traits cannot have associated items
+}
+
+trait Bar {
+ fn f(&self) {
+ self.g(); //~ ERROR the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0380]: auto traits cannot have associated items
+ --> $DIR/issue-105732.rs:4:8
+ |
+LL | auto trait Foo {
+ | --- auto trait cannot have associated items
+LL | fn g(&self);
+ | ---^-------- help: remove these associated items
+
+error[E0599]: the method `g` exists for reference `&Self`, but its trait bounds were not satisfied
+ --> $DIR/issue-105732.rs:9:14
+ |
+LL | self.g();
+ | ^
+ |
+ = note: the following trait bounds were not satisfied:
+ `Self: Foo`
+ which is required by `&Self: Foo`
+ `&Self: Foo`
+ = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `g`, perhaps you need to add a supertrait for it:
+ |
+LL | trait Bar: Foo {
+ | +++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0380, E0599.
+For more information about an error, try `rustc --explain E0380`.
--> $DIR/issue-90315.rs:28:8
|
LL | if 1..(end + 1).is_empty() {
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
--> $DIR/issue-90315.rs:34:8
|
LL | if 1..(end + 1).is_sorted() {
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
--> $DIR/issue-90315.rs:40:21
|
LL | let _res: i32 = 3..6.take(2).sum();
- | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+ | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
| |
| expected due to this
|
--> $DIR/issue-90315.rs:45:21
|
LL | let _sum: i32 = 3..6.sum();
- | --- ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+ | --- ^^^^^^^^^^ expected `i32`, found struct `Range`
| |
| expected due to this
|
--> $DIR/issue-90315.rs:62:8
|
LL | if 1..end.error_method() {
- | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
= note: the following trait bounds were not satisfied:
`Foo: Iterator`
which is required by `&mut Foo: Iterator`
-note: the following trait must be implemented
+note: the trait `Iterator` must be implemented
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | pub trait Iterator {
- | ^^^^^^^^^^^^^^^^^^
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `take`, perhaps you need to implement it:
candidate #1: `Iterator`
|
LL | 0.clone::<'a>();
| ^^
+ --> $SRC_DIR/core/src/clone.rs:LL:COL
|
- ::: $SRC_DIR/core/src/clone.rs:LL:COL
- |
-LL | fn clone(&self) -> Self;
- | - the late bound lifetime parameter is introduced here
+ = note: the late bound lifetime parameter is introduced here
|
= 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 #42868 <https://github.com/rust-lang/rust/issues/42868>
--> $DIR/method-not-found-generic-arg-elision.rs:87:29
|
LL | v.iter().map(|x| x * x).extend(std::iter::once(100));
- | ^^^^^^ method not found in `Map<std::slice::Iter<'_, i32>, [closure@$DIR/method-not-found-generic-arg-elision.rs:87:18: 87:21]>`
+ | ^^^^^^ method not found in `Map<Iter<'_, i32>, [closure@method-not-found-generic-arg-elision.rs:87:18]>`
error[E0599]: no method named `method` found for struct `Wrapper<bool>` in the current scope
--> $DIR/method-not-found-generic-arg-elision.rs:90:13
--- /dev/null
+// build-pass
+struct Inv<'a>(&'a mut &'a ());
+enum Foo<T> {
+ Bar,
+ Var(T),
+}
+type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
+
+fn foo(x: Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>) {
+ match x {
+ Supertype::Bar => {}
+ Supertype::Var(x) => {}
+ }
+}
+
+fn foo_nested(x: Foo<Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>>) {
+ match x {
+ Foo::Bar => {}
+ Foo::Var(Supertype::Bar) => {}
+ Foo::Var(Supertype::Var(x)) => {}
+ }
+}
+
+fn main() {}
--- /dev/null
+// build-pass
+
+enum Foo<T> {
+ Var(T),
+} // `T` is covariant.
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+ let Foo::Var(x): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+ let Foo::Var(Foo::Var(x)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn main() {}
--- /dev/null
+// build-pass
+
+struct Foo<T>(T); // `T` is covariant.
+
+struct Bar<T> {
+ x: T,
+} // `T` is covariant.
+
+fn bar<'b>(x: Bar<for<'a> fn(&'a ())>) {
+ let Bar { x }: Bar<fn(&'b ())> = x;
+}
+
+fn bar_nested<'b>(x: Bar<Bar<for<'a> fn(&'a ())>>) {
+ let Bar { x: Bar { x } }: Bar<Bar<fn(&'b ())>> = x;
+}
+
+fn bar_foo_nested<'b>(x: Bar<Foo<for<'a> fn(&'a ())>>) {
+ let Bar { x: Foo ( x ) }: Bar<Foo<fn(&'b ())>> = x;
+}
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+ let Foo(y): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+ let Foo(Foo(y)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn tuple<'b>(x: (u32, for<'a> fn(&'a ()))) {
+ let (_, y): (u32, fn(&'b ())) = x;
+}
+
+fn tuple_nested<'b>(x: (u32, (u32, for<'a> fn(&'a ())))) {
+ let (_, (_, y)): (u32, (u32, fn(&'b ()))) = x;
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+// ignore-tidy-linelength
+
+// Regression test for #29227. The problem here was that MIR
+// construction for these gigantic match expressions was very
+// inefficient.
+
+pub trait CharExt : Sized + Copy {
+ fn is_unicode_uppercase_letter(self) -> bool { false }
+ fn is_unicode_lowercase_letter(self) -> bool { false }
+ fn is_unicode_titlecase_letter(self) -> bool { false }
+ fn is_unicode_modifier_letter(self) -> bool { false }
+ fn is_unicode_other_letter(self) -> bool { false }
+ fn is_unicode_letter_number(self) -> bool { false }
+ fn is_unicode_nonspacing_mark(self) -> bool { false }
+ fn is_unicode_combining_spacing_mark(self) -> bool { false }
+ fn is_unicode_decimal_number(self) -> bool{ false }
+ fn is_unicode_connector_punctiation(self) -> bool { false }
+ fn is_unicode_space_separator(self) -> bool { false }
+
+ fn is_es_identifier_start(self) -> bool { false }
+ fn is_es_identifier_part(self) -> bool { false }
+ fn is_es_whitespace(self) -> bool { false }
+ fn is_es_line_terminator(self) -> bool { false }
+
+ fn is_unicode_letter(self) -> bool {
+ self.is_unicode_uppercase_letter()
+ || self.is_unicode_lowercase_letter()
+ || self.is_unicode_titlecase_letter()
+ || self.is_unicode_modifier_letter()
+ || self.is_unicode_modifier_letter()
+ || self.is_unicode_letter_number()
+ }
+
+}
+
+
+macro_rules! match_char_class {
+ ($thing:expr, $($c:expr),*) => {
+ match $thing {
+ $($c)|* => true,
+ _ => false
+ }
+ }
+}
+
+impl CharExt for char {
+ fn is_unicode_uppercase_letter(self) -> bool {
+ match_char_class!(self,
+ '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}')
+ }
+
+ fn is_unicode_lowercase_letter(self) -> bool {
+ match_char_class!(self,
+ '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}')
+
+ }
+
+ fn is_unicode_titlecase_letter(self) -> bool {
+ match_char_class!(self,
+ '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}')
+ }
+
+ fn is_unicode_modifier_letter(self) -> bool {
+ match_char_class!(self,
+ '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}')
+ }
+
+ fn is_unicode_other_letter(self) -> bool {
+ match_char_class!(self,
+ '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
+ }
+
+ fn is_unicode_letter_number(self) -> bool {
+ match_char_class!(self,
+ '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}')
+ }
+
+ fn is_unicode_nonspacing_mark(self) -> bool {
+ match_char_class!(self,
+ '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}', '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}')
+ }
+
+ fn is_unicode_combining_spacing_mark(self) -> bool {
+ match_char_class!(self,
+ '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}')
+ }
+
+ fn is_unicode_decimal_number(self) -> bool {
+ match_char_class!(self,
+ '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}')
+ }
+
+ fn is_unicode_connector_punctiation(self) -> bool {
+ match_char_class!(self,
+ '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}')
+ }
+
+ fn is_unicode_space_separator(self) -> bool {
+ match_char_class!(self,
+ '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}')
+ }
+
+ fn is_es_identifier_start(self) -> bool {
+ match self {
+ '$' | '_' | '\\' => true,
+ c if c.is_unicode_letter() => true,
+ _ => false
+ }
+ }
+
+ // see section 7.6
+ fn is_es_identifier_part(self) -> bool {
+ match self {
+ '\u{200C}' | '\u{200D}' => true,
+ c if c.is_es_identifier_start() => true,
+ c if c.is_unicode_combining_spacing_mark() => true,
+ c if c.is_unicode_nonspacing_mark() => true,
+ c if c.is_unicode_decimal_number() => true,
+ c if c.is_unicode_connector_punctiation() => true,
+ _ => false
+ }
+ }
+
+ fn is_es_whitespace(self) -> bool {
+ match self {
+ '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true,
+ c => c.is_unicode_space_separator()
+ }
+ }
+
+ fn is_es_line_terminator(self) -> bool {
+ match self {
+ '\n' | '\r' | '\u{2028}' | '\u{2029}' => true,
+ _ => false
+ }
+ }
+}
+
+fn main() {
+
+}
--- /dev/null
+// run-pass
+// To work around #46855
+// compile-flags: -Z mir-opt-level=0
+// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never { }
+
+// A single uninhabited variant shouldn't make the whole union uninhabited.
+union Foo {
+ a: u64,
+ _b: Never
+}
+
+// If all the variants are uninhabited, however, the union should be uninhabited.
+// NOTE(#49298) the union being uninhabited shouldn't change its size.
+union Bar {
+ _a: (Never, u64),
+ _b: (u64, Never)
+}
+
+fn main() {
+ assert_eq!(mem::size_of::<Foo>(), 8);
+ // See the note on `Bar`'s definition for why this isn't `0`.
+ assert_eq!(mem::size_of::<Bar>(), 8);
+
+ let f = [Foo { a: 42 }, Foo { a: 10 }];
+ println!("{}", unsafe { f[0].a });
+ assert_eq!(unsafe { f[1].a }, 10);
+}
--- /dev/null
+// compile-flags: -Zmir-opt-level=3 -Copt-level=0
+// run-pass
+
+type M = [i64; 2];
+
+fn f(a: &M) -> M {
+ let mut b: M = M::default();
+ b[0] = a[0] * a[0];
+ b
+}
+
+fn main() {
+ let mut a: M = [1, 1];
+ a = f(&a);
+ assert_eq!(a[0], 1);
+}
+++ /dev/null
-// check-pass
-// compile-flags: -Zvalidate-mir
-
-fn foo(_a: &str) {}
-
-fn main() {
- let x = foo as fn(&'static str);
-
- let _ = x == foo;
-}
--- /dev/null
+// check-pass
+// compile-flags: -Zvalidate-mir
+
+fn foo(_a: &str) {}
+
+fn main() {
+ let x = foo as fn(&'static str);
+
+ let _ = x == foo;
+}
--- /dev/null
+// Regression test for #105009. the issue here was that even after the `RevealAll` pass,
+// `validate` still used `Reveal::UserFacing`. This meant that it now ends up comparing
+// opaque types with their revealed version, resulting in an ICE.
+//
+// We're using these flags to run the `RevealAll` pass while making it less likely to
+// accidentally removing the assignment from `Foo<fn_ptr>` to `Foo<fn_def>`.
+
+// compile-flags: -Zinline_mir=yes -Zmir-opt-level=0 -Zvalidate-mir
+// run-pass
+
+use std::hint::black_box;
+
+trait Func {
+ type Ret: Id;
+}
+
+trait Id {
+ type Assoc;
+}
+impl Id for u32 {
+ type Assoc = u32;
+}
+impl Id for i32 {
+ type Assoc = i32;
+}
+
+impl<F: FnOnce() -> R, R: Id> Func for F {
+ type Ret = R;
+}
+
+fn bar() -> impl Copy + Id {
+ 0u32
+}
+
+struct Foo<T: Func> {
+ _func: T,
+ value: Option<<<T as Func>::Ret as Id>::Assoc>,
+}
+
+fn main() {
+ let mut fn_def = black_box(Foo {
+ _func: bar,
+ value: None,
+ });
+ let fn_ptr = black_box(Foo {
+ _func: bar as fn() -> _,
+ value: None,
+ });
+
+ fn_def.value = fn_ptr.value;
+ black_box(fn_def);
+}
|
LL | struct Foo;
| ^^^^^^^^^^ must implement `AddAssign<_>`
-note: the following trait must be implemented
+note: the trait `AddAssign` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait AddAssign<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
|
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
--> $DIR/closure-arg-count.rs:27:57
|
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
--> $DIR/closure-arg-count.rs:29:57
|
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
--> $DIR/closure-arg-count.rs:32:45
|
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
--> $DIR/closure-arg-count.rs:35:10
--> $DIR/closure-arg-type-mismatch.rs:3:14
|
LL | a.iter().map(|_: (u32, u32)| 45);
- | ^^^ --------------- found signature defined here
- | |
+ | ^^^ ---------------
+ | | | |
+ | | | help: consider borrowing the argument: `&(u32, u32)`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `fn(&(u32, u32)) -> _`
found closure signature `fn((u32, u32)) -> _`
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:4:14
found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:5:14
found closure signature `fn((u16, u16)) -> _`
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | F: FnMut(Self::Item) -> B,
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
error: aborting due to 3 previous errors
found type `bool` (`bool`)
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
error: aborting due to previous error
--> $DIR/issue-36053-2.rs:7:32
|
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
- | ^^^^^^ --------- found signature defined here
- | |
+ | ^^^^^^ ---------
+ | | | |
+ | | | help: consider borrowing the argument: `&&str`
+ | | found signature defined here
| expected due to this
|
= note: expected closure signature `for<'a> fn(&'a &str) -> _`
found closure signature `for<'a> fn(&'a str) -> _`
note: required by a bound in `filter`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | P: FnMut(&Self::Item) -> bool,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
-error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>`, but its trait bounds were not satisfied
+error[E0599]: the method `count` exists for struct `Filter<Fuse<Once<&str>>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied
--> $DIR/issue-36053-2.rs:7:55
|
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
- | --------- ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>` due to unsatisfied trait bounds
+ | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds
| |
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
| doesn't satisfy `_: FnMut<(&&str,)>`
+ --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
|
- ::: $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL
- |
-LL | pub struct Filter<I, P> {
- | ----------------------- doesn't satisfy `_: Iterator`
+ = note: doesn't satisfy `_: Iterator`
|
= note: the following trait bounds were not satisfied:
`<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool`
|
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | F: ~const FnOnce(T) -> U,
- | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
error: aborting due to previous error
|
note: required by a bound in `Option::<T>::map`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | F: ~const FnOnce(T) -> U,
- | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Option::<T>::map`
error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
--> $DIR/issue-47706.rs:27:9
|
LL | fn next(&mut self) -> Option<IteratorChunk<T, S>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
- ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | fn next(&mut self) -> Option<Self::Item>;
- | ----------------------------------------- expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+ = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
|
= note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
error[E0277]: `Foo` doesn't implement `Debug`
- --> $DIR/method-help-unsatisfied-bound.rs:5:5
+ --> $DIR/method-help-unsatisfied-bound.rs:5:7
|
LL | a.unwrap();
- | ^ ------ required by a bound introduced by this call
- | |
- | `Foo` cannot be formatted using `{:?}`
+ | ^^^^^^ `Foo` cannot be formatted using `{:?}`
|
= help: the trait `Debug` is not implemented for `Foo`
= note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
note: required by a bound in `Result::<T, E>::unwrap`
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | E: fmt::Debug,
- | ^^^^^^^^^^ required by this bound in `Result::<T, E>::unwrap`
help: consider annotating `Foo` with `#[derive(Debug)]`
|
LL | #[derive(Debug)]
= note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
note: enum `std::option::Option` is defined in crate `core`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub enum Option<T> {
- | ^^^^^^^^^^^^^^^^^^
note: enum `Option` is defined in the current crate
--> $DIR/similar_paths.rs:1:1
|
--> $DIR/wrap-suggestion-privacy.rs:22:17
|
LL | needs_ready(Some(0));
- | ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
+ | ----------- ^^^^^^^ expected struct `Ready`, found enum `Option`
| |
| arguments to this function are incorrect
|
+++ /dev/null
-// compile-flags: -C panic=abort
-// no-prefer-dynamic
-
-#![no_std]
-#![crate_type = "staticlib"]
-#![feature(alloc_error_handler)]
-
-#[panic_handler]
-fn panic(_: &core::panic::PanicInfo) -> ! {
- loop {}
-}
-
-extern crate alloc;
-
-#[global_allocator]
-static A: MyAlloc = MyAlloc;
-
-struct MyAlloc;
-
-unsafe impl core::alloc::GlobalAlloc for MyAlloc {
- unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
- unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
-}
+++ /dev/null
-error: `#[alloc_error_handler]` function required, but not found
-
-note: use `#![feature(default_alloc_error_handler)]` for a default error handler
-
-error: aborting due to previous error
-
| ^
LL |
LL | &Some(_y) => (),
- | ---------
- | | |
- | | data moved here
- | | move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Some(_y)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_y` has type `Box<i32>`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Some(_y) => (),
+LL + Some(_y) => (),
+ |
error: aborting due to previous error
LL | val.0;
| ^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `val.0`
+note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
= note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo`
LL | foo;
| ^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Foo::use_self` takes ownership of the receiver `self`, which moves `foo`
--> $DIR/move-fn-self-receiver.rs:13:17
|
LL | fn use_self(self) {}
LL | boxed_foo;
| ^^^^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
+note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `boxed_foo`
--> $DIR/move-fn-self-receiver.rs:14:21
|
LL | fn use_box_self(self: Box<Self>) {}
LL | pin_box_foo;
| ^^^^^^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
+note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which moves `pin_box_foo`
--> $DIR/move-fn-self-receiver.rs:15:25
|
LL | fn use_pin_box_self(self: Pin<Box<Self>>) {}
LL | rc_foo;
| ^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `rc_foo`
+note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc_foo`
--> $DIR/move-fn-self-receiver.rs:16:20
|
LL | fn use_rc_self(self: Rc<Self>) {}
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^^
error[E0382]: use of moved value: `implicit_into_iter`
--> $DIR/move-fn-self-receiver.rs:63:5
LL | container;
| ^^^^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `container`
+note: `Container::custom_into_iter` takes ownership of the receiver `self`, which moves `container`
--> $DIR/move-fn-self-receiver.rs:23:25
|
LL | fn custom_into_iter(self) -> impl Iterator<Item = bool> {
--> $DIR/move-out-of-array-ref.rs:8:24
|
LL | let [_, e, _, _] = *a;
- | - ^^
- | | |
- | | cannot move out of here
- | | help: consider borrowing here: `&*a`
+ | - ^^ cannot move out of here
+ | |
| data moved here
| move occurs because `e` has type `D`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let [_, e, _, _] = *a;
+LL + let [_, e, _, _] = a;
+ |
error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
--> $DIR/move-out-of-array-ref.rs:13:27
|
LL | let [_, s @ .. , _] = *a;
- | - ^^
- | | |
- | | cannot move out of here
- | | help: consider borrowing here: `&*a`
+ | - ^^ cannot move out of here
+ | |
| data moved here
| move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let [_, s @ .. , _] = *a;
+LL + let [_, s @ .. , _] = a;
+ |
error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
--> $DIR/move-out-of-array-ref.rs:18:24
|
LL | let [_, e, _, _] = *a;
- | - ^^
- | | |
- | | cannot move out of here
- | | help: consider borrowing here: `&*a`
+ | - ^^ cannot move out of here
+ | |
| data moved here
| move occurs because `e` has type `D`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let [_, e, _, _] = *a;
+LL + let [_, e, _, _] = a;
+ |
error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
--> $DIR/move-out-of-array-ref.rs:23:27
|
LL | let [_, s @ .. , _] = *a;
- | - ^^
- | | |
- | | cannot move out of here
- | | help: consider borrowing here: `&*a`
+ | - ^^ cannot move out of here
+ | |
| data moved here
| move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let [_, s @ .. , _] = *a;
+LL + let [_, s @ .. , _] = a;
+ |
error: aborting due to 4 previous errors
| |
| data moved here
| move occurs because `a` has type `A`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | box [ref a] => {},
+ | +++
error: aborting due to previous error
#![feature(unsized_locals)]
//~^ WARN the feature `unsized_locals` is incomplete
+#![allow(unused)]
struct A;
#[derive(Clone, Copy)]
= note: `#[warn(incomplete_features)]` on by default
error[E0508]: cannot move out of type `[A]`, a non-copy slice
- --> $DIR/move-out-of-slice-2.rs:10:11
+ --> $DIR/move-out-of-slice-2.rs:11:11
|
LL | match *a {
| ^^ cannot move out of here
| |
| data moved here
| move occurs because `a` has type `[A]`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | [ref a @ ..] => {}
+ | +++
error[E0508]: cannot move out of type `[A]`, a non-copy slice
- --> $DIR/move-out-of-slice-2.rs:16:11
+ --> $DIR/move-out-of-slice-2.rs:17:11
|
LL | match *b {
| ^^ cannot move out of here
| |
| data moved here
| move occurs because `b` has type `[A]`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | [_, _, ref b @ .., _] => {}
+ | +++
error[E0508]: cannot move out of type `[C]`, a non-copy slice
- --> $DIR/move-out-of-slice-2.rs:24:11
+ --> $DIR/move-out-of-slice-2.rs:25:11
|
LL | match *c {
| ^^ cannot move out of here
| |
| data moved here
| move occurs because `c` has type `[C]`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | [ref c @ ..] => {}
+ | +++
error[E0508]: cannot move out of type `[C]`, a non-copy slice
- --> $DIR/move-out-of-slice-2.rs:30:11
+ --> $DIR/move-out-of-slice-2.rs:31:11
|
LL | match *d {
| ^^ cannot move out of here
| |
| data moved here
| move occurs because `d` has type `[C]`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | [_, _, ref d @ .., _] => {}
+ | +++
error: aborting due to 4 previous errors; 1 warning emitted
LL | touch(&x[0]);
| ^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider cloning the value if the performance cost is acceptable
|
LL | consume(x.clone().into_iter().next().unwrap());
--> $DIR/moves-based-on-type-block-bad.rs:22:19
|
LL | match hellothere.x {
- | ^^^^^^^^^^^^ help: consider borrowing here: `&hellothere.x`
+ | ^^^^^^^^^^^^
LL | box E::Foo(_) => {}
LL | box E::Bar(x) => println!("{}", x.to_string()),
| -
| |
| data moved here
| move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &hellothere.x {
+ | +
error: aborting due to previous error
LL | touch(&x);
| ^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider cloning the value if the performance cost is acceptable
|
LL | let _y = x.clone().into_iter().next().unwrap();
LL | touch(&x);
| ^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `x`
+note: `into_iter` takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider cloning the value if the performance cost is acceptable
|
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
-error[E0271]: expected `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to be a closure that returns `()`, but it returns `!`
+error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!`
--> $DIR/fallback-closure-wrap.rs:18:31
|
LL | let error = Closure::wrap(Box::new(move || {
| --- ^^^^^^^^
| | |
| | the trait `T` is not implemented for `()`
- | | this tail expression is of type `_`
+ | | this tail expression is of type `()`
| required by a bound introduced by this call
|
note: required by a bound in `foo`
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | impl<I: Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constants
found struct `RangeTo<{integer}>`
note: associated function defined here
--> $SRC_DIR/core/src/ops/range.rs:LL:COL
- |
-LL | pub const fn new(start: Idx, end: Idx) -> Self {
- | ^^^
error: aborting due to 2 previous errors
--> $DIR/cannot-move-block-spans.rs:5:15
|
LL | let x = { *r };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = { *r };
+LL + let x = { r };
+ |
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:6:22
|
LL | let y = unsafe { *r };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let y = unsafe { *r };
+LL + let y = unsafe { r };
+ |
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:7:26
|
LL | let z = loop { break *r; };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let z = loop { break *r; };
+LL + let z = loop { break r; };
+ |
error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:11:15
| |
| cannot move out of here
| move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&arr[0]`
+ |
+help: consider borrowing here
+ |
+LL | let x = { &arr[0] };
+ | +
error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:12:22
| |
| cannot move out of here
| move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&arr[0]`
+ |
+help: consider borrowing here
+ |
+LL | let y = unsafe { &arr[0] };
+ | +
error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
--> $DIR/cannot-move-block-spans.rs:13:26
| |
| cannot move out of here
| move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&arr[0]`
+ |
+help: consider borrowing here
+ |
+LL | let z = loop { break &arr[0]; };
+ | +
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:17:38
|
LL | let x = { let mut u = 0; u += 1; *r };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = { let mut u = 0; u += 1; *r };
+LL + let x = { let mut u = 0; u += 1; r };
+ |
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:18:45
|
LL | let y = unsafe { let mut u = 0; u += 1; *r };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let y = unsafe { let mut u = 0; u += 1; *r };
+LL + let y = unsafe { let mut u = 0; u += 1; r };
+ |
error[E0507]: cannot move out of `*r` which is behind a shared reference
--> $DIR/cannot-move-block-spans.rs:19:49
|
LL | let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
- | ^^
- | |
- | move occurs because `*r` has type `String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let z = loop { let mut u = 0; u += 1; break *r; u += 2; };
+LL + let z = loop { let mut u = 0; u += 1; break r; u += 2; };
+ |
error: aborting due to 9 previous errors
| |
| cannot move out of here
| move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&s.url`
+ |
+help: consider borrowing here
+ |
+LL | let p = &s.url; p
+ | +
error: aborting due to 4 previous errors
--> $DIR/move-errors.rs:6:13
|
LL | let b = *a;
- | ^^
- | |
- | move occurs because `*a` has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*a`
+ | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let b = *a;
+LL + let b = a;
+ |
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:12:13
| |
| cannot move out of here
| move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&a[0]`
+ |
+help: consider borrowing here
+ |
+LL | let b = &a[0];
+ | +
error[E0507]: cannot move out of `**r` which is behind a shared reference
--> $DIR/move-errors.rs:19:13
|
LL | let s = **r;
- | ^^^
- | |
- | move occurs because `**r` has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&**r`
+ | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let s = **r;
+LL + let s = *r;
+ |
error[E0507]: cannot move out of an `Rc`
--> $DIR/move-errors.rs:27:13
|
LL | let s = *r;
- | ^^
- | |
- | move occurs because value has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*r`
+ | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let s = *r;
+LL + let s = r;
+ |
error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
--> $DIR/move-errors.rs:32:13
| |
| cannot move out of here
| move occurs because value has type `A`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&[A("".to_string())][0]`
+ |
+help: consider borrowing here
+ |
+LL | let a = &[A("".to_string())][0];
+ | +
error[E0507]: cannot move out of `a` which is behind a shared reference
--> $DIR/move-errors.rs:38:16
|
LL | let A(s) = *a;
- | - ^^ help: consider borrowing here: `&*a`
+ | - ^^
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let A(s) = *a;
+LL + let A(s) = a;
+ |
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:44:19
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let C(D(ref s)) = c;
+ | +++
error[E0507]: cannot move out of `*a` which is behind a shared reference
--> $DIR/move-errors.rs:51:9
--> $DIR/move-errors.rs:74:11
|
LL | match x[0] {
- | ^^^^
- | |
- | cannot move out of here
- | help: consider borrowing here: `&x[0]`
+ | ^^^^ cannot move out of here
LL |
LL | B::U(d) => (),
| - data moved here
| - ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing here
+ |
+LL | match &x[0] {
+ | +
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:83:11
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | B::U(D(ref s)) => (),
+ | +++
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:92:11
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (D(ref s), &t) => (),
+ | +++
error[E0507]: cannot move out of `*x.1` which is behind a shared reference
--> $DIR/move-errors.rs:92:11
| |
| data moved here
| move occurs because `t` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (D(s), &ref t) => (),
+ | +++
error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
--> $DIR/move-errors.rs:102:11
| data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | F(ref s, mut t) => (),
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | F(s, ref mut t) => (),
+ | +++
error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference
--> $DIR/move-errors.rs:110:11
|
LL | match *x {
- | ^^ help: consider borrowing here: `&*x`
+ | ^^
LL |
LL | Ok(s) | Err(s) => (),
| -
| |
| data moved here
| move occurs because `s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *x {
+LL + match x {
+ |
error: aborting due to 14 previous errors
| ^^^^^^^^ value borrowed here after move
|
= note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
- --> $SRC_DIR/alloc/src/sync.rs:LL:COL
- |
-LL | type Target = T;
- | ^^^^^^^^^^^
error: aborting due to previous error
| ^^^^^^^^ value borrowed here after move
|
= note: borrow occurs due to deref coercion to `Vec<i32>`
-note: deref defined here
- --> $SRC_DIR/alloc/src/sync.rs:LL:COL
- |
-LL | type Target = T;
- | ^^^^^^^^^^^
error: aborting due to previous error
| ^^^^^^
note: required by a bound in `spawn`
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
- |
-LL | F: Send + 'static,
- | ^^^^ required by this bound in `spawn`
error: aborting due to previous error
error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
- --> $DIR/not-clone-closure.rs:11:17
+ --> $DIR/not-clone-closure.rs:11:23
|
LL | let hello = move || {
| ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
...
LL | let hello = hello.clone();
- | ^^^^^ ----- required by a bound introduced by this call
- | |
- | within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+ | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
|
note: required because it's used within this closure
--> $DIR/not-clone-closure.rs:7:17
--> $DIR/numeric-cast-binop.rs:23:16
|
LL | x_u8 > x_u16;
- | ^^^^^ expected `u8`, found `u16`
+ | ---- ^^^^^ expected `u8`, found `u16`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
|
--> $DIR/numeric-cast-binop.rs:25:16
|
LL | x_u8 > x_u32;
- | ^^^^^ expected `u8`, found `u32`
+ | ---- ^^^^^ expected `u8`, found `u32`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
|
--> $DIR/numeric-cast-binop.rs:27:16
|
LL | x_u8 > x_u64;
- | ^^^^^ expected `u8`, found `u64`
+ | ---- ^^^^^ expected `u8`, found `u64`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
|
--> $DIR/numeric-cast-binop.rs:29:16
|
LL | x_u8 > x_u128;
- | ^^^^^^ expected `u8`, found `u128`
+ | ---- ^^^^^^ expected `u8`, found `u128`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
|
--> $DIR/numeric-cast-binop.rs:31:16
|
LL | x_u8 > x_usize;
- | ^^^^^^^ expected `u8`, found `usize`
+ | ---- ^^^^^^^ expected `u8`, found `usize`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
|
--> $DIR/numeric-cast-binop.rs:34:17
|
LL | x_u16 > x_u8;
- | ^^^^ expected `u16`, found `u8`
+ | ----- ^^^^ expected `u16`, found `u8`
+ | |
+ | expected because this is `u16`
|
help: you can convert a `u8` to a `u16`
|
--> $DIR/numeric-cast-binop.rs:36:17
|
LL | x_u16 > x_u32;
- | ^^^^^ expected `u16`, found `u32`
+ | ----- ^^^^^ expected `u16`, found `u32`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
|
--> $DIR/numeric-cast-binop.rs:38:17
|
LL | x_u16 > x_u64;
- | ^^^^^ expected `u16`, found `u64`
+ | ----- ^^^^^ expected `u16`, found `u64`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
|
--> $DIR/numeric-cast-binop.rs:40:17
|
LL | x_u16 > x_u128;
- | ^^^^^^ expected `u16`, found `u128`
+ | ----- ^^^^^^ expected `u16`, found `u128`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
|
--> $DIR/numeric-cast-binop.rs:42:17
|
LL | x_u16 > x_usize;
- | ^^^^^^^ expected `u16`, found `usize`
+ | ----- ^^^^^^^ expected `u16`, found `usize`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
|
--> $DIR/numeric-cast-binop.rs:45:17
|
LL | x_u32 > x_u8;
- | ^^^^ expected `u32`, found `u8`
+ | ----- ^^^^ expected `u32`, found `u8`
+ | |
+ | expected because this is `u32`
|
help: you can convert a `u8` to a `u32`
|
--> $DIR/numeric-cast-binop.rs:47:17
|
LL | x_u32 > x_u16;
- | ^^^^^ expected `u32`, found `u16`
+ | ----- ^^^^^ expected `u32`, found `u16`
+ | |
+ | expected because this is `u32`
|
help: you can convert a `u16` to a `u32`
|
--> $DIR/numeric-cast-binop.rs:49:17
|
LL | x_u32 > x_u64;
- | ^^^^^ expected `u32`, found `u64`
+ | ----- ^^^^^ expected `u32`, found `u64`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
|
--> $DIR/numeric-cast-binop.rs:51:17
|
LL | x_u32 > x_u128;
- | ^^^^^^ expected `u32`, found `u128`
+ | ----- ^^^^^^ expected `u32`, found `u128`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
|
--> $DIR/numeric-cast-binop.rs:53:17
|
LL | x_u32 > x_usize;
- | ^^^^^^^ expected `u32`, found `usize`
+ | ----- ^^^^^^^ expected `u32`, found `usize`
+ | |
+ | expected because this is `u32`
|
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:56:17
|
LL | x_u64 > x_u8;
- | ^^^^ expected `u64`, found `u8`
+ | ----- ^^^^ expected `u64`, found `u8`
+ | |
+ | expected because this is `u64`
|
help: you can convert a `u8` to a `u64`
|
--> $DIR/numeric-cast-binop.rs:58:17
|
LL | x_u64 > x_u16;
- | ^^^^^ expected `u64`, found `u16`
+ | ----- ^^^^^ expected `u64`, found `u16`
+ | |
+ | expected because this is `u64`
|
help: you can convert a `u16` to a `u64`
|
--> $DIR/numeric-cast-binop.rs:60:17
|
LL | x_u64 > x_u32;
- | ^^^^^ expected `u64`, found `u32`
+ | ----- ^^^^^ expected `u64`, found `u32`
+ | |
+ | expected because this is `u64`
|
help: you can convert a `u32` to a `u64`
|
--> $DIR/numeric-cast-binop.rs:62:17
|
LL | x_u64 > x_u128;
- | ^^^^^^ expected `u64`, found `u128`
+ | ----- ^^^^^^ expected `u64`, found `u128`
+ | |
+ | expected because this is `u64`
|
help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
|
--> $DIR/numeric-cast-binop.rs:64:17
|
LL | x_u64 > x_usize;
- | ^^^^^^^ expected `u64`, found `usize`
+ | ----- ^^^^^^^ expected `u64`, found `usize`
+ | |
+ | expected because this is `u64`
|
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:67:18
|
LL | x_u128 > x_u8;
- | ^^^^ expected `u128`, found `u8`
+ | ------ ^^^^ expected `u128`, found `u8`
+ | |
+ | expected because this is `u128`
|
help: you can convert a `u8` to a `u128`
|
--> $DIR/numeric-cast-binop.rs:69:18
|
LL | x_u128 > x_u16;
- | ^^^^^ expected `u128`, found `u16`
+ | ------ ^^^^^ expected `u128`, found `u16`
+ | |
+ | expected because this is `u128`
|
help: you can convert a `u16` to a `u128`
|
--> $DIR/numeric-cast-binop.rs:71:18
|
LL | x_u128 > x_u32;
- | ^^^^^ expected `u128`, found `u32`
+ | ------ ^^^^^ expected `u128`, found `u32`
+ | |
+ | expected because this is `u128`
|
help: you can convert a `u32` to a `u128`
|
--> $DIR/numeric-cast-binop.rs:73:18
|
LL | x_u128 > x_u64;
- | ^^^^^ expected `u128`, found `u64`
+ | ------ ^^^^^ expected `u128`, found `u64`
+ | |
+ | expected because this is `u128`
|
help: you can convert a `u64` to a `u128`
|
--> $DIR/numeric-cast-binop.rs:75:18
|
LL | x_u128 > x_usize;
- | ^^^^^^^ expected `u128`, found `usize`
+ | ------ ^^^^^^^ expected `u128`, found `usize`
+ | |
+ | expected because this is `u128`
|
help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:78:19
|
LL | x_usize > x_u8;
- | ^^^^ expected `usize`, found `u8`
+ | ------- ^^^^ expected `usize`, found `u8`
+ | |
+ | expected because this is `usize`
|
help: you can convert a `u8` to a `usize`
|
--> $DIR/numeric-cast-binop.rs:80:19
|
LL | x_usize > x_u16;
- | ^^^^^ expected `usize`, found `u16`
+ | ------- ^^^^^ expected `usize`, found `u16`
+ | |
+ | expected because this is `usize`
|
help: you can convert a `u16` to a `usize`
|
--> $DIR/numeric-cast-binop.rs:82:19
|
LL | x_usize > x_u32;
- | ^^^^^ expected `usize`, found `u32`
+ | ------- ^^^^^ expected `usize`, found `u32`
+ | |
+ | expected because this is `usize`
|
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:84:19
|
LL | x_usize > x_u64;
- | ^^^^^ expected `usize`, found `u64`
+ | ------- ^^^^^ expected `usize`, found `u64`
+ | |
+ | expected because this is `usize`
|
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:86:19
|
LL | x_usize > x_u128;
- | ^^^^^^ expected `usize`, found `u128`
+ | ------- ^^^^^^ expected `usize`, found `u128`
+ | |
+ | expected because this is `usize`
|
help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:92:16
|
LL | x_i8 > x_i16;
- | ^^^^^ expected `i8`, found `i16`
+ | ---- ^^^^^ expected `i8`, found `i16`
+ | |
+ | expected because this is `i8`
|
help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
|
--> $DIR/numeric-cast-binop.rs:94:16
|
LL | x_i8 > x_i32;
- | ^^^^^ expected `i8`, found `i32`
+ | ---- ^^^^^ expected `i8`, found `i32`
+ | |
+ | expected because this is `i8`
|
help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
|
--> $DIR/numeric-cast-binop.rs:96:16
|
LL | x_i8 > x_i64;
- | ^^^^^ expected `i8`, found `i64`
+ | ---- ^^^^^ expected `i8`, found `i64`
+ | |
+ | expected because this is `i8`
|
help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:98:16
|
LL | x_i8 > x_i128;
- | ^^^^^^ expected `i8`, found `i128`
+ | ---- ^^^^^^ expected `i8`, found `i128`
+ | |
+ | expected because this is `i8`
|
help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:100:16
|
LL | x_i8 > x_isize;
- | ^^^^^^^ expected `i8`, found `isize`
+ | ---- ^^^^^^^ expected `i8`, found `isize`
+ | |
+ | expected because this is `i8`
|
help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
|
--> $DIR/numeric-cast-binop.rs:103:17
|
LL | x_i16 > x_i8;
- | ^^^^ expected `i16`, found `i8`
+ | ----- ^^^^ expected `i16`, found `i8`
+ | |
+ | expected because this is `i16`
|
help: you can convert an `i8` to an `i16`
|
--> $DIR/numeric-cast-binop.rs:105:17
|
LL | x_i16 > x_i32;
- | ^^^^^ expected `i16`, found `i32`
+ | ----- ^^^^^ expected `i16`, found `i32`
+ | |
+ | expected because this is `i16`
|
help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
|
--> $DIR/numeric-cast-binop.rs:107:17
|
LL | x_i16 > x_i64;
- | ^^^^^ expected `i16`, found `i64`
+ | ----- ^^^^^ expected `i16`, found `i64`
+ | |
+ | expected because this is `i16`
|
help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:109:17
|
LL | x_i16 > x_i128;
- | ^^^^^^ expected `i16`, found `i128`
+ | ----- ^^^^^^ expected `i16`, found `i128`
+ | |
+ | expected because this is `i16`
|
help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:111:17
|
LL | x_i16 > x_isize;
- | ^^^^^^^ expected `i16`, found `isize`
+ | ----- ^^^^^^^ expected `i16`, found `isize`
+ | |
+ | expected because this is `i16`
|
help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
|
--> $DIR/numeric-cast-binop.rs:114:17
|
LL | x_i32 > x_i8;
- | ^^^^ expected `i32`, found `i8`
+ | ----- ^^^^ expected `i32`, found `i8`
+ | |
+ | expected because this is `i32`
|
help: you can convert an `i8` to an `i32`
|
--> $DIR/numeric-cast-binop.rs:116:17
|
LL | x_i32 > x_i16;
- | ^^^^^ expected `i32`, found `i16`
+ | ----- ^^^^^ expected `i32`, found `i16`
+ | |
+ | expected because this is `i32`
|
help: you can convert an `i16` to an `i32`
|
--> $DIR/numeric-cast-binop.rs:118:17
|
LL | x_i32 > x_i64;
- | ^^^^^ expected `i32`, found `i64`
+ | ----- ^^^^^ expected `i32`, found `i64`
+ | |
+ | expected because this is `i32`
|
help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:120:17
|
LL | x_i32 > x_i128;
- | ^^^^^^ expected `i32`, found `i128`
+ | ----- ^^^^^^ expected `i32`, found `i128`
+ | |
+ | expected because this is `i32`
|
help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:122:17
|
LL | x_i32 > x_isize;
- | ^^^^^^^ expected `i32`, found `isize`
+ | ----- ^^^^^^^ expected `i32`, found `isize`
+ | |
+ | expected because this is `i32`
|
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:125:17
|
LL | x_i64 > x_i8;
- | ^^^^ expected `i64`, found `i8`
+ | ----- ^^^^ expected `i64`, found `i8`
+ | |
+ | expected because this is `i64`
|
help: you can convert an `i8` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:127:17
|
LL | x_i64 > x_i16;
- | ^^^^^ expected `i64`, found `i16`
+ | ----- ^^^^^ expected `i64`, found `i16`
+ | |
+ | expected because this is `i64`
|
help: you can convert an `i16` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:129:17
|
LL | x_i64 > x_i32;
- | ^^^^^ expected `i64`, found `i32`
+ | ----- ^^^^^ expected `i64`, found `i32`
+ | |
+ | expected because this is `i64`
|
help: you can convert an `i32` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:131:17
|
LL | x_i64 > x_i128;
- | ^^^^^^ expected `i64`, found `i128`
+ | ----- ^^^^^^ expected `i64`, found `i128`
+ | |
+ | expected because this is `i64`
|
help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:133:17
|
LL | x_i64 > x_isize;
- | ^^^^^^^ expected `i64`, found `isize`
+ | ----- ^^^^^^^ expected `i64`, found `isize`
+ | |
+ | expected because this is `i64`
|
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:136:18
|
LL | x_i128 > x_i8;
- | ^^^^ expected `i128`, found `i8`
+ | ------ ^^^^ expected `i128`, found `i8`
+ | |
+ | expected because this is `i128`
|
help: you can convert an `i8` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:138:18
|
LL | x_i128 > x_i16;
- | ^^^^^ expected `i128`, found `i16`
+ | ------ ^^^^^ expected `i128`, found `i16`
+ | |
+ | expected because this is `i128`
|
help: you can convert an `i16` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:140:18
|
LL | x_i128 > x_i32;
- | ^^^^^ expected `i128`, found `i32`
+ | ------ ^^^^^ expected `i128`, found `i32`
+ | |
+ | expected because this is `i128`
|
help: you can convert an `i32` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:142:18
|
LL | x_i128 > x_i64;
- | ^^^^^ expected `i128`, found `i64`
+ | ------ ^^^^^ expected `i128`, found `i64`
+ | |
+ | expected because this is `i128`
|
help: you can convert an `i64` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:144:18
|
LL | x_i128 > x_isize;
- | ^^^^^^^ expected `i128`, found `isize`
+ | ------ ^^^^^^^ expected `i128`, found `isize`
+ | |
+ | expected because this is `i128`
|
help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:147:19
|
LL | x_isize > x_i8;
- | ^^^^ expected `isize`, found `i8`
+ | ------- ^^^^ expected `isize`, found `i8`
+ | |
+ | expected because this is `isize`
|
help: you can convert an `i8` to an `isize`
|
--> $DIR/numeric-cast-binop.rs:149:19
|
LL | x_isize > x_i16;
- | ^^^^^ expected `isize`, found `i16`
+ | ------- ^^^^^ expected `isize`, found `i16`
+ | |
+ | expected because this is `isize`
|
help: you can convert an `i16` to an `isize`
|
--> $DIR/numeric-cast-binop.rs:151:19
|
LL | x_isize > x_i32;
- | ^^^^^ expected `isize`, found `i32`
+ | ------- ^^^^^ expected `isize`, found `i32`
+ | |
+ | expected because this is `isize`
|
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:153:19
|
LL | x_isize > x_i64;
- | ^^^^^ expected `isize`, found `i64`
+ | ------- ^^^^^ expected `isize`, found `i64`
+ | |
+ | expected because this is `isize`
|
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:155:19
|
LL | x_isize > x_i128;
- | ^^^^^^ expected `isize`, found `i128`
+ | ------- ^^^^^^ expected `isize`, found `i128`
+ | |
+ | expected because this is `isize`
|
help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:161:16
|
LL | x_u8 > x_i8;
- | ^^^^ expected `u8`, found `i8`
+ | ---- ^^^^ expected `u8`, found `i8`
+ | |
+ | expected because this is `u8`
|
help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:163:16
|
LL | x_u8 > x_i16;
- | ^^^^^ expected `u8`, found `i16`
+ | ---- ^^^^^ expected `u8`, found `i16`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
|
--> $DIR/numeric-cast-binop.rs:165:16
|
LL | x_u8 > x_i32;
- | ^^^^^ expected `u8`, found `i32`
+ | ---- ^^^^^ expected `u8`, found `i32`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
|
--> $DIR/numeric-cast-binop.rs:167:16
|
LL | x_u8 > x_i64;
- | ^^^^^ expected `u8`, found `i64`
+ | ---- ^^^^^ expected `u8`, found `i64`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:169:16
|
LL | x_u8 > x_i128;
- | ^^^^^^ expected `u8`, found `i128`
+ | ---- ^^^^^^ expected `u8`, found `i128`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:171:16
|
LL | x_u8 > x_isize;
- | ^^^^^^^ expected `u8`, found `isize`
+ | ---- ^^^^^^^ expected `u8`, found `isize`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
|
--> $DIR/numeric-cast-binop.rs:174:17
|
LL | x_u16 > x_i8;
- | ^^^^ expected `u16`, found `i8`
+ | ----- ^^^^ expected `u16`, found `i8`
+ | |
+ | expected because this is `u16`
|
help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:176:17
|
LL | x_u16 > x_i16;
- | ^^^^^ expected `u16`, found `i16`
+ | ----- ^^^^^ expected `u16`, found `i16`
+ | |
+ | expected because this is `u16`
|
help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:178:17
|
LL | x_u16 > x_i32;
- | ^^^^^ expected `u16`, found `i32`
+ | ----- ^^^^^ expected `u16`, found `i32`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
|
--> $DIR/numeric-cast-binop.rs:180:17
|
LL | x_u16 > x_i64;
- | ^^^^^ expected `u16`, found `i64`
+ | ----- ^^^^^ expected `u16`, found `i64`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:182:17
|
LL | x_u16 > x_i128;
- | ^^^^^^ expected `u16`, found `i128`
+ | ----- ^^^^^^ expected `u16`, found `i128`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:184:17
|
LL | x_u16 > x_isize;
- | ^^^^^^^ expected `u16`, found `isize`
+ | ----- ^^^^^^^ expected `u16`, found `isize`
+ | |
+ | expected because this is `u16`
|
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:187:17
|
LL | x_u32 > x_i8;
- | ^^^^ expected `u32`, found `i8`
+ | ----- ^^^^ expected `u32`, found `i8`
+ | |
+ | expected because this is `u32`
|
help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:189:17
|
LL | x_u32 > x_i16;
- | ^^^^^ expected `u32`, found `i16`
+ | ----- ^^^^^ expected `u32`, found `i16`
+ | |
+ | expected because this is `u32`
|
help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:191:17
|
LL | x_u32 > x_i32;
- | ^^^^^ expected `u32`, found `i32`
+ | ----- ^^^^^ expected `u32`, found `i32`
+ | |
+ | expected because this is `u32`
|
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:193:17
|
LL | x_u32 > x_i64;
- | ^^^^^ expected `u32`, found `i64`
+ | ----- ^^^^^ expected `u32`, found `i64`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
|
--> $DIR/numeric-cast-binop.rs:195:17
|
LL | x_u32 > x_i128;
- | ^^^^^^ expected `u32`, found `i128`
+ | ----- ^^^^^^ expected `u32`, found `i128`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:197:17
|
LL | x_u32 > x_isize;
- | ^^^^^^^ expected `u32`, found `isize`
+ | ----- ^^^^^^^ expected `u32`, found `isize`
+ | |
+ | expected because this is `u32`
|
help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:200:17
|
LL | x_u64 > x_i8;
- | ^^^^ expected `u64`, found `i8`
+ | ----- ^^^^ expected `u64`, found `i8`
+ | |
+ | expected because this is `u64`
|
help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:202:17
|
LL | x_u64 > x_i16;
- | ^^^^^ expected `u64`, found `i16`
+ | ----- ^^^^^ expected `u64`, found `i16`
+ | |
+ | expected because this is `u64`
|
help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:204:17
|
LL | x_u64 > x_i32;
- | ^^^^^ expected `u64`, found `i32`
+ | ----- ^^^^^ expected `u64`, found `i32`
+ | |
+ | expected because this is `u64`
|
help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:206:17
|
LL | x_u64 > x_i64;
- | ^^^^^ expected `u64`, found `i64`
+ | ----- ^^^^^ expected `u64`, found `i64`
+ | |
+ | expected because this is `u64`
|
help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:208:17
|
LL | x_u64 > x_i128;
- | ^^^^^^ expected `u64`, found `i128`
+ | ----- ^^^^^^ expected `u64`, found `i128`
+ | |
+ | expected because this is `u64`
|
help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
|
--> $DIR/numeric-cast-binop.rs:210:17
|
LL | x_u64 > x_isize;
- | ^^^^^^^ expected `u64`, found `isize`
+ | ----- ^^^^^^^ expected `u64`, found `isize`
+ | |
+ | expected because this is `u64`
|
help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:213:18
|
LL | x_u128 > x_i8;
- | ^^^^ expected `u128`, found `i8`
+ | ------ ^^^^ expected `u128`, found `i8`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:215:18
|
LL | x_u128 > x_i16;
- | ^^^^^ expected `u128`, found `i16`
+ | ------ ^^^^^ expected `u128`, found `i16`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:217:18
|
LL | x_u128 > x_i32;
- | ^^^^^ expected `u128`, found `i32`
+ | ------ ^^^^^ expected `u128`, found `i32`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:219:18
|
LL | x_u128 > x_i64;
- | ^^^^^ expected `u128`, found `i64`
+ | ------ ^^^^^ expected `u128`, found `i64`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:221:18
|
LL | x_u128 > x_i128;
- | ^^^^^^ expected `u128`, found `i128`
+ | ------ ^^^^^^ expected `u128`, found `i128`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:223:18
|
LL | x_u128 > x_isize;
- | ^^^^^^^ expected `u128`, found `isize`
+ | ------ ^^^^^^^ expected `u128`, found `isize`
+ | |
+ | expected because this is `u128`
|
help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:226:19
|
LL | x_usize > x_i8;
- | ^^^^ expected `usize`, found `i8`
+ | ------- ^^^^ expected `usize`, found `i8`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:228:19
|
LL | x_usize > x_i16;
- | ^^^^^ expected `usize`, found `i16`
+ | ------- ^^^^^ expected `usize`, found `i16`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:230:19
|
LL | x_usize > x_i32;
- | ^^^^^ expected `usize`, found `i32`
+ | ------- ^^^^^ expected `usize`, found `i32`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:232:19
|
LL | x_usize > x_i64;
- | ^^^^^ expected `usize`, found `i64`
+ | ------- ^^^^^ expected `usize`, found `i64`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:234:19
|
LL | x_usize > x_i128;
- | ^^^^^^ expected `usize`, found `i128`
+ | ------- ^^^^^^ expected `usize`, found `i128`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:236:19
|
LL | x_usize > x_isize;
- | ^^^^^^^ expected `usize`, found `isize`
+ | ------- ^^^^^^^ expected `usize`, found `isize`
+ | |
+ | expected because this is `usize`
|
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:242:16
|
LL | x_i8 > x_u8;
- | ^^^^ expected `i8`, found `u8`
+ | ---- ^^^^ expected `i8`, found `u8`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:244:16
|
LL | x_i8 > x_u16;
- | ^^^^^ expected `i8`, found `u16`
+ | ---- ^^^^^ expected `i8`, found `u16`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:246:16
|
LL | x_i8 > x_u32;
- | ^^^^^ expected `i8`, found `u32`
+ | ---- ^^^^^ expected `i8`, found `u32`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:248:16
|
LL | x_i8 > x_u64;
- | ^^^^^ expected `i8`, found `u64`
+ | ---- ^^^^^ expected `i8`, found `u64`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:250:16
|
LL | x_i8 > x_u128;
- | ^^^^^^ expected `i8`, found `u128`
+ | ---- ^^^^^^ expected `i8`, found `u128`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:252:16
|
LL | x_i8 > x_usize;
- | ^^^^^^^ expected `i8`, found `usize`
+ | ---- ^^^^^^^ expected `i8`, found `usize`
+ | |
+ | expected because this is `i8`
|
help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:255:17
|
LL | x_i16 > x_u8;
- | ^^^^ expected `i16`, found `u8`
+ | ----- ^^^^ expected `i16`, found `u8`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `u8` to an `i16`
|
--> $DIR/numeric-cast-binop.rs:257:17
|
LL | x_i16 > x_u16;
- | ^^^^^ expected `i16`, found `u16`
+ | ----- ^^^^^ expected `i16`, found `u16`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:259:17
|
LL | x_i16 > x_u32;
- | ^^^^^ expected `i16`, found `u32`
+ | ----- ^^^^^ expected `i16`, found `u32`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:261:17
|
LL | x_i16 > x_u64;
- | ^^^^^ expected `i16`, found `u64`
+ | ----- ^^^^^ expected `i16`, found `u64`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:263:17
|
LL | x_i16 > x_u128;
- | ^^^^^^ expected `i16`, found `u128`
+ | ----- ^^^^^^ expected `i16`, found `u128`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:265:17
|
LL | x_i16 > x_usize;
- | ^^^^^^^ expected `i16`, found `usize`
+ | ----- ^^^^^^^ expected `i16`, found `usize`
+ | |
+ | expected because this is `i16`
|
help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:268:17
|
LL | x_i32 > x_u8;
- | ^^^^ expected `i32`, found `u8`
+ | ----- ^^^^ expected `i32`, found `u8`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `u8` to an `i32`
|
--> $DIR/numeric-cast-binop.rs:270:17
|
LL | x_i32 > x_u16;
- | ^^^^^ expected `i32`, found `u16`
+ | ----- ^^^^^ expected `i32`, found `u16`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `u16` to an `i32`
|
--> $DIR/numeric-cast-binop.rs:272:17
|
LL | x_i32 > x_u32;
- | ^^^^^ expected `i32`, found `u32`
+ | ----- ^^^^^ expected `i32`, found `u32`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:274:17
|
LL | x_i32 > x_u64;
- | ^^^^^ expected `i32`, found `u64`
+ | ----- ^^^^^ expected `i32`, found `u64`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:276:17
|
LL | x_i32 > x_u128;
- | ^^^^^^ expected `i32`, found `u128`
+ | ----- ^^^^^^ expected `i32`, found `u128`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:278:17
|
LL | x_i32 > x_usize;
- | ^^^^^^^ expected `i32`, found `usize`
+ | ----- ^^^^^^^ expected `i32`, found `usize`
+ | |
+ | expected because this is `i32`
|
help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:281:17
|
LL | x_i64 > x_u8;
- | ^^^^ expected `i64`, found `u8`
+ | ----- ^^^^ expected `i64`, found `u8`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `u8` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:283:17
|
LL | x_i64 > x_u16;
- | ^^^^^ expected `i64`, found `u16`
+ | ----- ^^^^^ expected `i64`, found `u16`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `u16` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:285:17
|
LL | x_i64 > x_u32;
- | ^^^^^ expected `i64`, found `u32`
+ | ----- ^^^^^ expected `i64`, found `u32`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `u32` to an `i64`
|
--> $DIR/numeric-cast-binop.rs:287:17
|
LL | x_i64 > x_u64;
- | ^^^^^ expected `i64`, found `u64`
+ | ----- ^^^^^ expected `i64`, found `u64`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:289:17
|
LL | x_i64 > x_u128;
- | ^^^^^^ expected `i64`, found `u128`
+ | ----- ^^^^^^ expected `i64`, found `u128`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:291:17
|
LL | x_i64 > x_usize;
- | ^^^^^^^ expected `i64`, found `usize`
+ | ----- ^^^^^^^ expected `i64`, found `usize`
+ | |
+ | expected because this is `i64`
|
help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:294:18
|
LL | x_i128 > x_u8;
- | ^^^^ expected `i128`, found `u8`
+ | ------ ^^^^ expected `i128`, found `u8`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `u8` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:296:18
|
LL | x_i128 > x_u16;
- | ^^^^^ expected `i128`, found `u16`
+ | ------ ^^^^^ expected `i128`, found `u16`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `u16` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:298:18
|
LL | x_i128 > x_u32;
- | ^^^^^ expected `i128`, found `u32`
+ | ------ ^^^^^ expected `i128`, found `u32`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `u32` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:300:18
|
LL | x_i128 > x_u64;
- | ^^^^^ expected `i128`, found `u64`
+ | ------ ^^^^^ expected `i128`, found `u64`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `u64` to an `i128`
|
--> $DIR/numeric-cast-binop.rs:302:18
|
LL | x_i128 > x_u128;
- | ^^^^^^ expected `i128`, found `u128`
+ | ------ ^^^^^^ expected `i128`, found `u128`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:304:18
|
LL | x_i128 > x_usize;
- | ^^^^^^^ expected `i128`, found `usize`
+ | ------ ^^^^^^^ expected `i128`, found `usize`
+ | |
+ | expected because this is `i128`
|
help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:307:19
|
LL | x_isize > x_u8;
- | ^^^^ expected `isize`, found `u8`
+ | ------- ^^^^ expected `isize`, found `u8`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `u8` to an `isize`
|
--> $DIR/numeric-cast-binop.rs:309:19
|
LL | x_isize > x_u16;
- | ^^^^^ expected `isize`, found `u16`
+ | ------- ^^^^^ expected `isize`, found `u16`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:311:19
|
LL | x_isize > x_u32;
- | ^^^^^ expected `isize`, found `u32`
+ | ------- ^^^^^ expected `isize`, found `u32`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:313:19
|
LL | x_isize > x_u64;
- | ^^^^^ expected `isize`, found `u64`
+ | ------- ^^^^^ expected `isize`, found `u64`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:315:19
|
LL | x_isize > x_u128;
- | ^^^^^^ expected `isize`, found `u128`
+ | ------- ^^^^^^ expected `isize`, found `u128`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-binop.rs:317:19
|
LL | x_isize > x_usize;
- | ^^^^^^^ expected `isize`, found `usize`
+ | ------- ^^^^^^^ expected `isize`, found `usize`
+ | |
+ | expected because this is `isize`
|
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
--> $DIR/numeric-cast-no-fix.rs:10:15
|
LL | x_usize > -1_isize;
- | ^^^^^^^^ expected `usize`, found `isize`
+ | ------- ^^^^^^^^ expected `usize`, found `isize`
+ | |
+ | expected because this is `usize`
|
= note: `-1_isize` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:12:14
|
LL | x_u128 > -1_isize;
- | ^^^^^^^^ expected `u128`, found `isize`
+ | ------ ^^^^^^^^ expected `u128`, found `isize`
+ | |
+ | expected because this is `u128`
|
= note: `-1_isize` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:14:13
|
LL | x_u64 > -1_isize;
- | ^^^^^^^^ expected `u64`, found `isize`
+ | ----- ^^^^^^^^ expected `u64`, found `isize`
+ | |
+ | expected because this is `u64`
|
= note: `-1_isize` cannot fit into type `u64`
--> $DIR/numeric-cast-no-fix.rs:16:13
|
LL | x_u32 > -1_isize;
- | ^^^^^^^^ expected `u32`, found `isize`
+ | ----- ^^^^^^^^ expected `u32`, found `isize`
+ | |
+ | expected because this is `u32`
|
= note: `-1_isize` cannot fit into type `u32`
--> $DIR/numeric-cast-no-fix.rs:18:13
|
LL | x_u16 > -1_isize;
- | ^^^^^^^^ expected `u16`, found `isize`
+ | ----- ^^^^^^^^ expected `u16`, found `isize`
+ | |
+ | expected because this is `u16`
|
= note: `-1_isize` cannot fit into type `u16`
--> $DIR/numeric-cast-no-fix.rs:20:12
|
LL | x_u8 > -1_isize;
- | ^^^^^^^^ expected `u8`, found `isize`
+ | ---- ^^^^^^^^ expected `u8`, found `isize`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
|
--> $DIR/numeric-cast-no-fix.rs:23:15
|
LL | x_usize > -1_i128;
- | ^^^^^^^ expected `usize`, found `i128`
+ | ------- ^^^^^^^ expected `usize`, found `i128`
+ | |
+ | expected because this is `usize`
|
= note: `-1_i128` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:25:14
|
LL | x_u128 > -1_i128;
- | ^^^^^^^ expected `u128`, found `i128`
+ | ------ ^^^^^^^ expected `u128`, found `i128`
+ | |
+ | expected because this is `u128`
|
= note: `-1_i128` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:27:13
|
LL | x_u64 > -1_i128;
- | ^^^^^^^ expected `u64`, found `i128`
+ | ----- ^^^^^^^ expected `u64`, found `i128`
+ | |
+ | expected because this is `u64`
|
help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
|
--> $DIR/numeric-cast-no-fix.rs:29:13
|
LL | x_u32 > -1_i128;
- | ^^^^^^^ expected `u32`, found `i128`
+ | ----- ^^^^^^^ expected `u32`, found `i128`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
|
--> $DIR/numeric-cast-no-fix.rs:31:13
|
LL | x_u16 > -1_i128;
- | ^^^^^^^ expected `u16`, found `i128`
+ | ----- ^^^^^^^ expected `u16`, found `i128`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
|
--> $DIR/numeric-cast-no-fix.rs:33:12
|
LL | x_u8 > -1_i128;
- | ^^^^^^^ expected `u8`, found `i128`
+ | ---- ^^^^^^^ expected `u8`, found `i128`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
|
--> $DIR/numeric-cast-no-fix.rs:36:15
|
LL | x_usize > -1_i64;
- | ^^^^^^ expected `usize`, found `i64`
+ | ------- ^^^^^^ expected `usize`, found `i64`
+ | |
+ | expected because this is `usize`
|
= note: `-1_i64` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:38:14
|
LL | x_u128 > -1_i64;
- | ^^^^^^ expected `u128`, found `i64`
+ | ------ ^^^^^^ expected `u128`, found `i64`
+ | |
+ | expected because this is `u128`
|
= note: `-1_i64` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:40:13
|
LL | x_u64 > -1_i64;
- | ^^^^^^ expected `u64`, found `i64`
+ | ----- ^^^^^^ expected `u64`, found `i64`
+ | |
+ | expected because this is `u64`
|
= note: `-1_i64` cannot fit into type `u64`
--> $DIR/numeric-cast-no-fix.rs:42:13
|
LL | x_u32 > -1_i64;
- | ^^^^^^ expected `u32`, found `i64`
+ | ----- ^^^^^^ expected `u32`, found `i64`
+ | |
+ | expected because this is `u32`
|
help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
|
--> $DIR/numeric-cast-no-fix.rs:44:13
|
LL | x_u16 > -1_i64;
- | ^^^^^^ expected `u16`, found `i64`
+ | ----- ^^^^^^ expected `u16`, found `i64`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
|
--> $DIR/numeric-cast-no-fix.rs:46:12
|
LL | x_u8 > -1_i64;
- | ^^^^^^ expected `u8`, found `i64`
+ | ---- ^^^^^^ expected `u8`, found `i64`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
|
--> $DIR/numeric-cast-no-fix.rs:49:15
|
LL | x_usize > -1_i32;
- | ^^^^^^ expected `usize`, found `i32`
+ | ------- ^^^^^^ expected `usize`, found `i32`
+ | |
+ | expected because this is `usize`
|
= note: `-1_i32` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:51:14
|
LL | x_u128 > -1_i32;
- | ^^^^^^ expected `u128`, found `i32`
+ | ------ ^^^^^^ expected `u128`, found `i32`
+ | |
+ | expected because this is `u128`
|
= note: `-1_i32` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:53:13
|
LL | x_u64 > -1_i32;
- | ^^^^^^ expected `u64`, found `i32`
+ | ----- ^^^^^^ expected `u64`, found `i32`
+ | |
+ | expected because this is `u64`
|
= note: `-1_i32` cannot fit into type `u64`
--> $DIR/numeric-cast-no-fix.rs:55:13
|
LL | x_u32 > -1_i32;
- | ^^^^^^ expected `u32`, found `i32`
+ | ----- ^^^^^^ expected `u32`, found `i32`
+ | |
+ | expected because this is `u32`
|
= note: `-1_i32` cannot fit into type `u32`
--> $DIR/numeric-cast-no-fix.rs:57:13
|
LL | x_u16 > -1_i32;
- | ^^^^^^ expected `u16`, found `i32`
+ | ----- ^^^^^^ expected `u16`, found `i32`
+ | |
+ | expected because this is `u16`
|
help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
|
--> $DIR/numeric-cast-no-fix.rs:59:12
|
LL | x_u8 > -1_i32;
- | ^^^^^^ expected `u8`, found `i32`
+ | ---- ^^^^^^ expected `u8`, found `i32`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
|
--> $DIR/numeric-cast-no-fix.rs:62:15
|
LL | x_usize > -1_i16;
- | ^^^^^^ expected `usize`, found `i16`
+ | ------- ^^^^^^ expected `usize`, found `i16`
+ | |
+ | expected because this is `usize`
|
= note: `-1_i16` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:64:14
|
LL | x_u128 > -1_i16;
- | ^^^^^^ expected `u128`, found `i16`
+ | ------ ^^^^^^ expected `u128`, found `i16`
+ | |
+ | expected because this is `u128`
|
= note: `-1_i16` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:66:13
|
LL | x_u64 > -1_i16;
- | ^^^^^^ expected `u64`, found `i16`
+ | ----- ^^^^^^ expected `u64`, found `i16`
+ | |
+ | expected because this is `u64`
|
= note: `-1_i16` cannot fit into type `u64`
--> $DIR/numeric-cast-no-fix.rs:68:13
|
LL | x_u32 > -1_i16;
- | ^^^^^^ expected `u32`, found `i16`
+ | ----- ^^^^^^ expected `u32`, found `i16`
+ | |
+ | expected because this is `u32`
|
= note: `-1_i16` cannot fit into type `u32`
--> $DIR/numeric-cast-no-fix.rs:70:13
|
LL | x_u16 > -1_i16;
- | ^^^^^^ expected `u16`, found `i16`
+ | ----- ^^^^^^ expected `u16`, found `i16`
+ | |
+ | expected because this is `u16`
|
= note: `-1_i16` cannot fit into type `u16`
--> $DIR/numeric-cast-no-fix.rs:72:12
|
LL | x_u8 > -1_i16;
- | ^^^^^^ expected `u8`, found `i16`
+ | ---- ^^^^^^ expected `u8`, found `i16`
+ | |
+ | expected because this is `u8`
|
help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
|
--> $DIR/numeric-cast-no-fix.rs:75:15
|
LL | x_usize > -1_i8;
- | ^^^^^ expected `usize`, found `i8`
+ | ------- ^^^^^ expected `usize`, found `i8`
+ | |
+ | expected because this is `usize`
|
= note: `-1_i8` cannot fit into type `usize`
--> $DIR/numeric-cast-no-fix.rs:77:14
|
LL | x_u128 > -1_i8;
- | ^^^^^ expected `u128`, found `i8`
+ | ------ ^^^^^ expected `u128`, found `i8`
+ | |
+ | expected because this is `u128`
|
= note: `-1_i8` cannot fit into type `u128`
--> $DIR/numeric-cast-no-fix.rs:79:13
|
LL | x_u64 > -1_i8;
- | ^^^^^ expected `u64`, found `i8`
+ | ----- ^^^^^ expected `u64`, found `i8`
+ | |
+ | expected because this is `u64`
|
= note: `-1_i8` cannot fit into type `u64`
--> $DIR/numeric-cast-no-fix.rs:81:13
|
LL | x_u32 > -1_i8;
- | ^^^^^ expected `u32`, found `i8`
+ | ----- ^^^^^ expected `u32`, found `i8`
+ | |
+ | expected because this is `u32`
|
= note: `-1_i8` cannot fit into type `u32`
--> $DIR/numeric-cast-no-fix.rs:83:13
|
LL | x_u16 > -1_i8;
- | ^^^^^ expected `u16`, found `i8`
+ | ----- ^^^^^ expected `u16`, found `i8`
+ | |
+ | expected because this is `u16`
|
= note: `-1_i8` cannot fit into type `u16`
--> $DIR/numeric-cast-no-fix.rs:85:12
|
LL | x_u8 > -1_i8;
- | ^^^^^ expected `u8`, found `i8`
+ | ---- ^^^^^ expected `u8`, found `i8`
+ | |
+ | expected because this is `u8`
|
= note: `-1_i8` cannot fit into type `u8`
--- /dev/null
+// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization
+// suggestions.
+
+fn main() {
+ _ = 123X1a3;
+ //~^ ERROR invalid suffix `X1a3` for number literal
+ //~| NOTE invalid suffix `X1a3`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+ _ = 456O123;
+ //~^ ERROR invalid suffix `O123` for number literal
+ //~| NOTE invalid suffix `O123`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+ _ = 789B101;
+ //~^ ERROR invalid suffix `B101` for number literal
+ //~| NOTE invalid suffix `B101`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+ _ = 0XYZ;
+ //~^ ERROR invalid suffix `XYZ` for number literal
+ //~| NOTE invalid suffix `XYZ`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+ _ = 0OPQ;
+ //~^ ERROR invalid suffix `OPQ` for number literal
+ //~| NOTE invalid suffix `OPQ`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+ _ = 0BCD;
+ //~^ ERROR invalid suffix `BCD` for number literal
+ //~| NOTE invalid suffix `BCD`
+ //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+}
--- /dev/null
+error: invalid suffix `X1a3` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9
+ |
+LL | _ = 123X1a3;
+ | ^^^^^^^ invalid suffix `X1a3`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `O123` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9
+ |
+LL | _ = 456O123;
+ | ^^^^^^^ invalid suffix `O123`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `B101` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9
+ |
+LL | _ = 789B101;
+ | ^^^^^^^ invalid suffix `B101`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `XYZ` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9
+ |
+LL | _ = 0XYZ;
+ | ^^^^ invalid suffix `XYZ`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `OPQ` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9
+ |
+LL | _ = 0OPQ;
+ | ^^^^ invalid suffix `OPQ`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: invalid suffix `BCD` for number literal
+ --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9
+ |
+LL | _ = 0BCD;
+ | ^^^^ invalid suffix `BCD`
+ |
+ = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// <https://github.com/rust-lang/rust/issues/105184>
+
+fn main() {
+ vec![(), ()].iter().sum::<i32>();
+ //~^ ERROR
+
+ vec![(), ()].iter().product::<i32>();
+ //~^ ERROR
+}
--- /dev/null
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+ --> $DIR/sum.rs:4:25
+ |
+LL | vec![(), ()].iter().sum::<i32>();
+ | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+ |
+ = help: the trait `Sum<&()>` is not implemented for `i32`
+ = help: the following other types implement trait `Sum<A>`:
+ <i32 as Sum<&'a i32>>
+ <i32 as Sum>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/sum.rs:4:18
+ |
+LL | vec![(), ()].iter().sum::<i32>();
+ | ------------ ^^^^^^ `Iterator::Item` is `&()` here
+ | |
+ | this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::sum`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
+ --> $DIR/sum.rs:7:25
+ |
+LL | vec![(), ()].iter().product::<i32>();
+ | ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+ |
+ = help: the trait `Product<&()>` is not implemented for `i32`
+ = help: the following other types implement trait `Product<A>`:
+ <i32 as Product<&'a i32>>
+ <i32 as Product>
+note: the method call chain might not have had the expected associated types
+ --> $DIR/sum.rs:7:18
+ |
+LL | vec![(), ()].iter().product::<i32>();
+ | ------------ ^^^^^^ `Iterator::Item` is `&()` here
+ | |
+ | this expression has type `Vec<()>`
+note: required by a bound in `std::iter::Iterator::product`
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
|
LL | enum E { A, B }
| ^^^^^^ must implement `BitOr<_>`
-note: the following trait must be implemented
+note: the trait `BitOr` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | pub trait BitOr<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
|
note: required by a bound in `FnMut`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
- | ^^^^^ required by this bound in `FnMut`
error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
--> $DIR/overloaded-calls-nontuple.rs:18:6
|
note: required by a bound in `FnOnce`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait FnOnce<Args: Tuple> {
- | ^^^^^ required by this bound in `FnOnce`
error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
--> $DIR/overloaded-calls-nontuple.rs:12:5
--> $DIR/bare-struct-body.rs:11:14
|
LL | x.val == 42;
- | ^^ expected `()`, found integer
+ | ----- ^^ expected `()`, found integer
+ | |
+ | expected because this is `()`
error: aborting due to 3 previous errors
--> $DIR/chained-comparison-suggestion.rs:4:14
|
LL | 1 < 2 <= 3;
- | ^ expected `bool`, found integer
+ | ----- ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/chained-comparison-suggestion.rs:13:14
|
LL | 1 <= 2 < 3;
- | ^ expected `bool`, found integer
+ | ------ ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/chained-comparison-suggestion.rs:18:15
|
LL | 1 <= 2 <= 3;
- | ^ expected `bool`, found integer
+ | ------ ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/chained-comparison-suggestion.rs:23:14
|
LL | 1 > 2 >= 3;
- | ^ expected `bool`, found integer
+ | ----- ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/chained-comparison-suggestion.rs:36:15
|
LL | 1 >= 2 >= 3;
- | ^ expected `bool`, found integer
+ | ------ ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/chained-comparison-suggestion.rs:49:15
|
LL | 1 == 2 == 3;
- | ^ expected `bool`, found integer
+ | ------ ^ expected `bool`, found integer
+ | |
+ | expected because this is `bool`
error: aborting due to 17 previous errors
--- /dev/null
+// run-rustfix
+
+struct Foo {
+ bar: Bar,
+}
+
+struct Bar {
+ qux: i32,
+}
+
+pub fn post_regular() {
+ let mut i = 0;
+ i += 1; //~ ERROR Rust has no postfix increment operator
+ println!("{}", i);
+}
+
+pub fn post_while() {
+ let mut i = 0;
+ while { let tmp = i; i += 1; tmp } < 5 {
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", i);
+ }
+}
+
+pub fn post_regular_tmp() {
+ let mut tmp = 0;
+ tmp += 1; //~ ERROR Rust has no postfix increment operator
+ println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+ let mut tmp = 0;
+ while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", tmp);
+ }
+}
+
+pub fn post_field() {
+ let mut foo = Foo { bar: Bar { qux: 0 } };
+ foo.bar.qux += 1;
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+ struct S {
+ tmp: i32
+ }
+ let mut s = S { tmp: 0 };
+ s.tmp += 1;
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+ let mut foo = Foo { bar: Bar { qux: 0 } };
+ foo.bar.qux += 1;
+ //~^ ERROR Rust has no prefix increment operator
+ println!("{}", foo.bar.qux);
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+struct Foo {
+ bar: Bar,
+}
+
+struct Bar {
+ qux: i32,
+}
+
+pub fn post_regular() {
+ let mut i = 0;
+ i++; //~ ERROR Rust has no postfix increment operator
+ println!("{}", i);
+}
+
+pub fn post_while() {
+ let mut i = 0;
+ while i++ < 5 {
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", i);
+ }
+}
+
+pub fn post_regular_tmp() {
+ let mut tmp = 0;
+ tmp++; //~ ERROR Rust has no postfix increment operator
+ println!("{}", tmp);
+}
+
+pub fn post_while_tmp() {
+ let mut tmp = 0;
+ while tmp++ < 5 {
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", tmp);
+ }
+}
+
+pub fn post_field() {
+ let mut foo = Foo { bar: Bar { qux: 0 } };
+ foo.bar.qux++;
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", foo.bar.qux);
+}
+
+pub fn post_field_tmp() {
+ struct S {
+ tmp: i32
+ }
+ let mut s = S { tmp: 0 };
+ s.tmp++;
+ //~^ ERROR Rust has no postfix increment operator
+ println!("{}", s.tmp);
+}
+
+pub fn pre_field() {
+ let mut foo = Foo { bar: Bar { qux: 0 } };
+ ++foo.bar.qux;
+ //~^ ERROR Rust has no prefix increment operator
+ println!("{}", foo.bar.qux);
+}
+
+fn main() {}
--- /dev/null
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:13:6
+ |
+LL | i++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | i += 1;
+ | ~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:19:12
+ |
+LL | while i++ < 5 {
+ | ----- ^^ not a valid postfix operator
+ | |
+ | while parsing the condition of this `while` expression
+ |
+help: use `+= 1` instead
+ |
+LL | while { let tmp = i; i += 1; tmp } < 5 {
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:27:8
+ |
+LL | tmp++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | tmp += 1;
+ | ~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:33:14
+ |
+LL | while tmp++ < 5 {
+ | ----- ^^ not a valid postfix operator
+ | |
+ | while parsing the condition of this `while` expression
+ |
+help: use `+= 1` instead
+ |
+LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
+ | ++++++++++++ ~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:41:16
+ |
+LL | foo.bar.qux++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | foo.bar.qux += 1;
+ | ~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/increment-autofix-2.rs:51:10
+ |
+LL | s.tmp++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | s.tmp += 1;
+ | ~~~~
+
+error: Rust has no prefix increment operator
+ --> $DIR/increment-autofix-2.rs:58:5
+ |
+LL | ++foo.bar.qux;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL - ++foo.bar.qux;
+LL + foo.bar.qux += 1;
+ |
+
+error: aborting due to 7 previous errors
+
+++ /dev/null
-struct Foo {
- bar: Bar,
-}
-
-struct Bar {
- qux: i32,
-}
-
-pub fn post_regular() {
- let mut i = 0;
- i++; //~ ERROR Rust has no postfix increment operator
- println!("{}", i);
-}
-
-pub fn post_while() {
- let mut i = 0;
- while i++ < 5 {
- //~^ ERROR Rust has no postfix increment operator
- println!("{}", i);
- }
-}
-
-pub fn post_regular_tmp() {
- let mut tmp = 0;
- tmp++; //~ ERROR Rust has no postfix increment operator
- println!("{}", tmp);
-}
-
-pub fn post_while_tmp() {
- let mut tmp = 0;
- while tmp++ < 5 {
- //~^ ERROR Rust has no postfix increment operator
- println!("{}", tmp);
- }
-}
-
-pub fn post_field() {
- let foo = Foo { bar: Bar { qux: 0 } };
- foo.bar.qux++;
- //~^ ERROR Rust has no postfix increment operator
- println!("{}", foo.bar.qux);
-}
-
-pub fn post_field_tmp() {
- struct S {
- tmp: i32
- }
- let s = S { tmp: 0 };
- s.tmp++;
- //~^ ERROR Rust has no postfix increment operator
- println!("{}", s.tmp);
-}
-
-pub fn pre_field() {
- let foo = Foo { bar: Bar { qux: 0 } };
- ++foo.bar.qux;
- //~^ ERROR Rust has no prefix increment operator
- println!("{}", foo.bar.qux);
-}
-
-fn main() {}
+++ /dev/null
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:11:6
- |
-LL | i++;
- | ^^ not a valid postfix operator
- |
-help: use `+= 1` instead
- |
-LL | { let tmp = i; i += 1; tmp };
- | +++++++++++ ~~~~~~~~~~~~~~~
-LL | i += 1;
- | ~~~~
-
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:17:12
- |
-LL | while i++ < 5 {
- | ----- ^^ not a valid postfix operator
- | |
- | while parsing the condition of this `while` expression
- |
-help: use `+= 1` instead
- |
-LL | while { let tmp = i; i += 1; tmp } < 5 {
- | +++++++++++ ~~~~~~~~~~~~~~~
-LL | while i += 1 < 5 {
- | ~~~~
-
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:25:8
- |
-LL | tmp++;
- | ^^ not a valid postfix operator
- |
-help: use `+= 1` instead
- |
-LL | { let tmp_ = tmp; tmp += 1; tmp_ };
- | ++++++++++++ ~~~~~~~~~~~~~~~~~~
-LL | tmp += 1;
- | ~~~~
-
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:31:14
- |
-LL | while tmp++ < 5 {
- | ----- ^^ not a valid postfix operator
- | |
- | while parsing the condition of this `while` expression
- |
-help: use `+= 1` instead
- |
-LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 {
- | ++++++++++++ ~~~~~~~~~~~~~~~~~~
-LL | while tmp += 1 < 5 {
- | ~~~~
-
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:39:16
- |
-LL | foo.bar.qux++;
- | ^^ not a valid postfix operator
- |
-help: use `+= 1` instead
- |
-LL | { let tmp = foo.bar.qux; foo.bar.qux += 1; tmp };
- | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
-LL | foo.bar.qux += 1;
- | ~~~~
-
-error: Rust has no postfix increment operator
- --> $DIR/increment-notfixed.rs:49:10
- |
-LL | s.tmp++;
- | ^^ not a valid postfix operator
- |
-help: use `+= 1` instead
- |
-LL | { let tmp = s.tmp; s.tmp += 1; tmp };
- | +++++++++++ ~~~~~~~~~~~~~~~~~~~
-LL | s.tmp += 1;
- | ~~~~
-
-error: Rust has no prefix increment operator
- --> $DIR/increment-notfixed.rs:56:5
- |
-LL | ++foo.bar.qux;
- | ^^ not a valid prefix operator
- |
-help: use `+= 1` instead
- |
-LL - ++foo.bar.qux;
-LL + foo.bar.qux += 1;
- |
-
-error: aborting due to 7 previous errors
-
--- /dev/null
+fn test1() {
+ let mut i = 0;
+ let _ = i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test2() {
+ let mut i = 0;
+ let _ = ++i + i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test3() {
+ let mut i = 0;
+ let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test4() {
+ let mut i = 0;
+ let _ = i + i++; //~ ERROR Rust has no postfix increment operator
+ // won't suggest since we can not handle the precedences
+}
+
+fn test5() {
+ let mut i = 0;
+ let _ = i++ + i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test6() {
+ let mut i = 0;
+ let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test7() {
+ let mut i = 0;
+ let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test8() {
+ let mut i = 0;
+ let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test9() {
+ let mut i = 0;
+ let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test10() {
+ let mut i = 0;
+ let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator
+}
+
+fn main() { }
--- /dev/null
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:3:17
+ |
+LL | let _ = i + ++i;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = i + { i += 1; i };
+ | ~ +++++++++
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:8:13
+ |
+LL | let _ = ++i + i;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { i += 1; i } + i;
+ | ~ +++++++++
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:13:13
+ |
+LL | let _ = ++i + ++i;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { i += 1; i } + ++i;
+ | ~ +++++++++
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:18:18
+ |
+LL | let _ = i + i++;
+ | ^^ not a valid postfix operator
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:24:14
+ |
+LL | let _ = i++ + i;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { let tmp = i; i += 1; tmp } + i;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:29:14
+ |
+LL | let _ = i++ + i++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { let tmp = i; i += 1; tmp } + i++;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:34:13
+ |
+LL | let _ = ++i + i++;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { i += 1; i } + i++;
+ | ~ +++++++++
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:39:14
+ |
+LL | let _ = i++ + ++i;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { let tmp = i; i += 1; tmp } + ++i;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:44:24
+ |
+LL | let _ = (1 + 2 + i)++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp };
+ | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec-2.rs:49:15
+ |
+LL | let _ = (i++ + 1) + 2;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: aborting due to 10 previous errors
+
--- /dev/null
+struct S {
+ x: i32,
+}
+
+fn test1() {
+ let mut i = 0;
+ i++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test2() {
+ let s = S { x: 0 };
+ s.x++; //~ ERROR Rust has no postfix increment operator
+}
+
+fn test3() {
+ let mut i = 0;
+ if i++ == 1 {} //~ ERROR Rust has no postfix increment operator
+}
+
+fn test4() {
+ let mut i = 0;
+ ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+fn test5() {
+ let mut i = 0;
+ if ++i == 1 { } //~ ERROR Rust has no prefix increment operator
+}
+
+fn test6() {
+ let mut i = 0;
+ loop { break; }
+ i++; //~ ERROR Rust has no postfix increment operator
+ loop { break; }
+ ++i;
+}
+
+fn test7() {
+ let mut i = 0;
+ loop { break; }
+ ++i; //~ ERROR Rust has no prefix increment operator
+}
+
+
+fn main() {}
--- /dev/null
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:7:6
+ |
+LL | i++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | i += 1;
+ | ~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:12:8
+ |
+LL | s.x++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | s.x += 1;
+ | ~~~~
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:17:9
+ |
+LL | if i++ == 1 {}
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | if { let tmp = i; i += 1; tmp } == 1 {}
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:22:5
+ |
+LL | ++i;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL - ++i;
+LL + i += 1;
+ |
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:27:8
+ |
+LL | if ++i == 1 { }
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL | if { i += 1; i } == 1 { }
+ | ~ +++++++++
+
+error: Rust has no postfix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:33:6
+ |
+LL | i++;
+ | ^^ not a valid postfix operator
+ |
+help: use `+= 1` instead
+ |
+LL | i += 1;
+ | ~~~~
+
+error: Rust has no prefix increment operator
+ --> $DIR/issue-104867-inc-dec.rs:41:5
+ |
+LL | ++i;
+ | ^^ not a valid prefix operator
+ |
+help: use `+= 1` instead
+ |
+LL - ++i;
+LL + i += 1;
+ |
+
+error: aborting due to 7 previous errors
+
--- /dev/null
+// run-rustfix
+
+struct Foo;
+
+impl From<i32> for Foo {
+ //~^ ERROR you might have meant to write `impl` instead of `fn`
+ fn from(_a: i32) -> Self {
+ Foo
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+struct Foo;
+
+fn From<i32> for Foo {
+ //~^ ERROR you might have meant to write `impl` instead of `fn`
+ fn from(_a: i32) -> Self {
+ Foo
+ }
+}
+
+fn main() {}
--- /dev/null
+error: you might have meant to write `impl` instead of `fn`
+ --> $DIR/issue-105366.rs:5:1
+ |
+LL | fn From<i32> for Foo {
+ | ^^
+ |
+help: replace `fn` with `impl` here
+ |
+LL | impl From<i32> for Foo {
+ | ~~~~
+
+error: aborting due to previous error
+
--- /dev/null
+fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
+
+fn main() {}
--- /dev/null
+error: expected type, found `0`
+ --> $DIR/issue-39616.rs:1:12
+ |
+LL | fn foo(a: [0; 1]) {}
+ | ^ expected type
+
+error: aborting due to previous error
+
--- /dev/null
+// Test for #49257:
+// emits good diagnostics for `..` pattern fragments not in the last position.
+
+#![allow(unused)]
+
+struct Point { x: u8, y: u8 }
+
+fn main() {
+ let p = Point { x: 0, y: 0 };
+ let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
+ let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+ let Point { .., } = p; //~ ERROR expected `}`, found `,`
+ let Point { .. } = p;
+}
--- /dev/null
+error: expected `}`, found `,`
+ --> $DIR/issue-49257.rs:10:19
+ |
+LL | let Point { .., y, } = p;
+ | --^
+ | | |
+ | | expected `}`
+ | `..` must be at the end and cannot have a trailing comma
+ |
+help: move the `..` to the end of the field list
+ |
+LL - let Point { .., y, } = p;
+LL + let Point { y, .. } = p;
+ |
+
+error: expected `}`, found `,`
+ --> $DIR/issue-49257.rs:11:19
+ |
+LL | let Point { .., y } = p;
+ | --^
+ | | |
+ | | expected `}`
+ | `..` must be at the end and cannot have a trailing comma
+ |
+help: move the `..` to the end of the field list
+ |
+LL - let Point { .., y } = p;
+LL + let Point { y , .. } = p;
+ |
+
+error: expected `}`, found `,`
+ --> $DIR/issue-49257.rs:12:19
+ |
+LL | let Point { .., } = p;
+ | --^
+ | | |
+ | | expected `}`
+ | | help: remove this comma
+ | `..` must be at the end and cannot have a trailing comma
+
+error: aborting due to 3 previous errors
+
LL |
LL | fn main() {}
| ^^ unexpected token
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | ($left:expr, $right:expr $(,)?) => {
- | ---------- while parsing argument for this `expr` macro fragment
+ = note: while parsing argument for this `expr` macro fragment
error: aborting due to 4 previous errors
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0405]: cannot find trait `r#fn` in this scope
--> $DIR/kw-in-trait-bounds.rs:17:4
|
LL | G: fn(),
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0405]: cannot find trait `r#fn` in this scope
--> $DIR/kw-in-trait-bounds.rs:3:27
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0405]: cannot find trait `r#fn` in this scope
--> $DIR/kw-in-trait-bounds.rs:3:41
|
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0405]: cannot find trait `r#struct` in this scope
--> $DIR/kw-in-trait-bounds.rs:24:10
--- /dev/null
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+ struct U;
+
+ // A tuple is a "non-reference pattern".
+ // A `mut` binding pattern resets the binding mode to by-value.
+
+ let mut p = (U, U);
+ let (a, ref mut b) = &mut p;
+ //~^ ERROR cannot move out of a mutable reference
+}
--- /dev/null
+// run-rustfix
+#![allow(unused_variables)]
+fn main() {
+ struct U;
+
+ // A tuple is a "non-reference pattern".
+ // A `mut` binding pattern resets the binding mode to by-value.
+
+ let mut p = (U, U);
+ let (a, mut b) = &mut p;
+ //~^ ERROR cannot move out of a mutable reference
+}
--- /dev/null
+error[E0507]: cannot move out of a mutable reference
+ --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22
+ |
+LL | let (a, mut b) = &mut p;
+ | ----- ^^^^^^
+ | |
+ | data moved here
+ | move occurs because `b` has type `U`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let (a, ref mut b) = &mut p;
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
let p = (U, U);
let (a, mut b) = &p;
//~^ ERROR cannot move out of a shared reference
-
- let mut p = (U, U);
- let (a, mut b) = &mut p;
- //~^ ERROR cannot move out of a mutable reference
}
| |
| data moved here
| move occurs because `b` has type `U`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a mutable reference
- --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22
|
-LL | let (a, mut b) = &mut p;
- | ----- ^^^^^^
- | |
- | data moved here
- | move occurs because `b` has type `U`, which does not implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | let (a, ref mut b) = &p;
+ | +++
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0507`.
|
help: consider giving `x` an explicit type
|
-LL | let x: _;
- | +++
+LL | let x: /* Type */;
+ | ++++++++++++
error[E0308]: mismatched types
--> $DIR/pat-tuple-bad-type.rs:10:9
|
help: consider giving this pattern a type
|
-LL | let x @ ..: _;
- | +++
+LL | let x @ ..: /* Type */;
+ | ++++++++++++
error: aborting due to 23 previous errors
|
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | None,
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<i32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
|
note: `Option<HiddenEnum>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<HiddenEnum>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
|
|
note: `Option<Enum>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub enum Option<T> {
- | ^^^^^^^^^^^^^^^^^^
= note: the matched value is of type `Option<Enum>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
|
|
note: `Box<ElementKind>` defined here
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
- |
-LL | / pub struct Box<
-LL | | T: ?Sized,
-LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
- | |_^
= note: the matched value is of type `Box<ElementKind>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
|
note: `Option<Option<Direction>>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
- | |
- | not covered
- | not covered
+ = note: not covered
+ |
+ = note: not covered
= note: the matched value is of type `Option<Option<Direction>>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
|
note: `Option<Private>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<Private>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
|
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
|
-LL | pub enum Option<T> {
- | ------------------
-...
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^ not covered
+ = note: not covered
= note: the matched value is of type `Option<i32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
--> $DIR/pptypedef.rs:4:37
|
LL | let_in(3u32, |i| { assert!(i == 3i32); });
- | ^^^^ expected `u32`, found `i32`
+ | - ^^^^ expected `u32`, found `i32`
+ | |
+ | expected because this is `u32`
|
help: change the type of the numeric literal from `i32` to `u32`
|
--> $DIR/pptypedef.rs:8:37
|
LL | let_in(3i32, |i| { assert!(i == 3u32); });
- | ^^^^ expected `i32`, found `u32`
+ | - ^^^^ expected `i32`, found `u32`
+ | |
+ | expected because this is `i32`
|
help: change the type of the numeric literal from `u32` to `i32`
|
--- /dev/null
+// compile-flags: -Z print-type-sizes --crate-type lib
+// edition:2021
+// build-pass
+// ignore-pass
+
+async fn wait() {}
+
+pub async fn test(arg: [u8; 8192]) {
+ wait().await;
+ drop(arg);
+}
--- /dev/null
+print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Suspend0`: 16385 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size field `.arg`: 8192 bytes
+print-type-size field `.__awaitee`: 1 bytes
+print-type-size variant `Unresumed`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 8192 bytes
+print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size field `.value`: 8192 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 8192 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 8192 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Ready`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Pending`: 0 bytes
--- /dev/null
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// build-pass
+// ignore-pass
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Return = ()> {
+ move |()| {
+ yield ();
+ let _ = array;
+ }
+}
+
+pub fn foo() {
+ let _ = generator([0; 8192]);
+}
--- /dev/null
+print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 8192 bytes
+print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
--- /dev/null
+// compile-flags: -Z print-type-sizes --crate-type lib
+// build-pass
+// ignore-pass
+
+// Tests a generator that has its discriminant as the *final* field.
+
+// Avoid emitting panic handlers, like the rest of these tests...
+#![feature(generators)]
+
+pub fn foo() {
+ let a = || {
+ {
+ let w: i32 = 4;
+ yield;
+ drop(w);
+ }
+ {
+ let z: i32 = 7;
+ yield;
+ drop(z);
+ }
+ };
+}
--- /dev/null
+print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Suspend0`: 7 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Suspend1`: 7 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.z`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// monomorphized, in the MIR of the original function in which they
// occur, to have their size reported.
-#![feature(start)]
-
-// In an ad-hoc attempt to avoid the injection of unwinding code
-// (which clutters the output of `-Z print-type-sizes` with types from
-// `unwind::libunwind`):
-//
-// * I am not using Default to build values because that seems to
-// cause the injection of unwinding code. (Instead I just make `fn new`
-// methods.)
-//
-// * Pair derive Copy to ensure that we don't inject
-// unwinding code into generic uses of Pair when T itself is also
-// Copy.
-//
-// (I suspect this reflect some naivety within the rust compiler
-// itself; it should be checking for drop glue, i.e., a destructor
-// somewhere in the monomorphized types. It should not matter whether
-// the type is Copy.)
#[derive(Copy, Clone)]
pub struct Pair<T> {
_car: T,
Pair::new(FiftyBytes::new(), FiftyBytes::new());
}
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn start() {
let _b: Pair<u8> = Pair::new(0, 0);
let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
let ref _z: ZeroSized = ZeroSized;
f1::<SevenBytes>(SevenBytes::new());
- 0
}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// This file illustrates that when multiple structural types occur in
// a function, every one of them is included in the output.
-#![feature(start)]
-
pub struct SevenBytes([u8; 7]);
pub struct FiftyBytes([u8; 50]);
Small(SevenBytes),
Large(FiftyBytes),
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- let _e: Enum;
- let _f: FiftyBytes;
- let _s: SevenBytes;
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// aligned (while on most it is 8-byte aligned) and so the resulting
// padding and overall computed sizes can be quite different.
-#![feature(start)]
#![feature(rustc_attrs)]
#![allow(dead_code)]
impl Default for NestedNonZero {
fn default() -> Self {
- NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
+ NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 }
}
}
b: B,
}
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
let _x: MyOption<NonZeroU32> = Default::default();
let _y: EmbeddedDiscr = Default::default();
let _z: MyOption<IndirectNonZero> = Default::default();
// ...even when theoretically possible.
let _j: MyOption<Union1<NonZeroU32>> = Default::default();
let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
-
- 0
}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// (even if multiple functions), it is only printed once in the
// print-type-sizes output.
-#![feature(start)]
-
pub struct SevenBytes([u8; 7]);
pub fn f1() {
let _s: SevenBytes = SevenBytes([0; 7]);
}
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
let _s: SevenBytes = SevenBytes([0; 7]);
- 0
}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// padding and overall computed sizes can be quite different.
#![allow(dead_code)]
-#![feature(start)]
#[derive(Default)]
#[repr(packed)]
-struct Packed1 {
+pub struct Packed1 {
a: u8,
b: u8,
g: i32,
#[derive(Default)]
#[repr(packed(2))]
-struct Packed2 {
+pub struct Packed2 {
a: u8,
b: u8,
g: i32,
#[derive(Default)]
#[repr(packed(2))]
#[repr(C)]
-struct Packed2C {
+pub struct Packed2C {
a: u8,
b: u8,
g: i32,
}
#[derive(Default)]
-struct Padded {
+pub struct Padded {
a: u8,
b: u8,
g: i32,
h: i16,
d: u8,
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- let _c: Packed1 = Default::default();
- let _d: Packed2 = Default::default();
- let _e: Packed2C = Default::default();
- let _f: Padded = Default::default();
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// This file illustrates how padding is handled: alignment
// aligned (while on most it is 8-byte aligned) and so the resulting
// padding and overall computed sizes can be quite different.
-#![feature(start)]
#![allow(dead_code)]
struct S {
A(i8, i32),
B(S),
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// It avoids using u64/i64 because on some targets that is only 4-byte
// aligned (while on most it is 8-byte aligned) and so the resulting
// padding and overall computed sizes can be quite different.
-#![feature(start)]
+
#![allow(dead_code)]
#[repr(align(16))]
}
#[derive(Default)]
-struct S {
+pub struct S {
a: i32,
b: i32,
c: A,
d: i8,
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- let _s: S = Default::default();
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
-#![feature(start)]
#![allow(dead_code)]
#[repr(C, u8)]
A(u16),
B,
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
#![feature(never_type)]
-#![feature(start)]
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
let _x: Option<!> = None;
let _y: Result<u32, !> = Ok(42);
let _z: Result<!, !> = loop {};
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// This file illustrates two things:
// 2. For an enum, the print-type-sizes output will also include the
// size of each variant.
-#![feature(start)]
-
pub struct SevenBytes([u8; 7]);
pub struct FiftyBytes([u8; 50]);
Small(SevenBytes),
Large(FiftyBytes),
}
-
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- let _e: Enum;
- 0
-}
-// compile-flags: -Z print-type-sizes
+// compile-flags: -Z print-type-sizes --crate-type=lib
// build-pass
// ignore-pass
// At one point, zero-sized fields such as those in this file were causing
// incorrect output from `-Z print-type-sizes`.
-#![feature(start)]
-
struct S1 {
x: u32,
y: u32,
tagz: TagZ,
}
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
+pub fn test() {
let _s1: S1 = S1 { x: 0, y: 0, tag: () };
let _s5: S5<(), Empty> = S5 {
z: 4,
tagz: Empty {},
};
- 0
}
Pub.method();
//~^ ERROR type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
<Pub as PrivTr>::CONST;
- //~^ ERROR associated constant `<Pub as PrivTr>::CONST` is private
+ //~^ ERROR associated constant `PrivTr::CONST` is private
let _: <Pub as PrivTr>::AssocTy;
- //~^ ERROR associated type `<Pub as PrivTr>::AssocTy` is private
+ //~^ ERROR associated type `PrivTr::AssocTy` is private
pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
//~^ ERROR trait `PrivTr` is private
pub trait InSignatureTr: PrivTr {}
|
= note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: associated constant `<Pub as PrivTr>::CONST` is private
+error: associated constant `PrivTr::CONST` is private
--> $DIR/associated-item-privacy-trait.rs:21:9
|
LL | <Pub as PrivTr>::CONST;
|
= note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: associated type `<Pub as PrivTr>::AssocTy` is private
+error: associated type `PrivTr::AssocTy` is private
--> $DIR/associated-item-privacy-trait.rs:23:16
|
LL | let _: <Pub as PrivTr>::AssocTy;
// aux-build:private-inferred-type.rs
// error-pattern:type `fn() {ext::priv_fn}` is private
-// error-pattern:static `PRIV_STATIC` is private
+// error-pattern:static `ext::PRIV_STATIC` is private
// error-pattern:type `ext::PrivEnum` is private
// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
|
= note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: static `PRIV_STATIC` is private
+error: static `ext::PRIV_STATIC` is private
--> $DIR/private-inferred-type-3.rs:16:5
|
LL | ext::m!();
--> $DIR/attr-invalid-exprs.rs:15:13
|
LL | let _ = #[duplicate] "Hello, world!";
- | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
- | |
- | caused by the macro expansion here
+ | ^^^^^^^^^^^^ caused by the macro expansion here
|
= note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+ |
+LL | let _ = #[duplicate]; "Hello, world!";
+ | +
error: macro expansion ignores token `,` and any following
--> $DIR/attr-invalid-exprs.rs:24:9
|
LL | #[duplicate]
- | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
- | |
- | caused by the macro expansion here
+ | ^^^^^^^^^^^^ caused by the macro expansion here
|
= note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+ |
+LL | #[duplicate];
+ | +
error: aborting due to 3 previous errors
pub fn foo12(input: TokenStream) -> TokenStream { input }
#[proc_macro_derive(d13, attributes("a"))]
-//~^ ERROR: not a meta item
+//~^ ERROR: attribute must be a meta item, not a literal
pub fn foo13(input: TokenStream) -> TokenStream { input }
#[proc_macro_derive(d14, attributes(a = ""))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
pub fn foo14(input: TokenStream) -> TokenStream { input }
#[proc_macro_derive(d15, attributes(m::a))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
pub fn foo15(input: TokenStream) -> TokenStream { input }
#[proc_macro_derive(d16, attributes(a(b)))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
pub fn foo16(input: TokenStream) -> TokenStream { input }
#[proc_macro_derive(d17, attributes(self))]
LL | #[proc_macro_derive(d12, attributes)]
| ^^^^^^^^^^
-error: not a meta item
+error: attribute must be a meta item, not a literal
--> $DIR/attribute.rs:55:37
|
LL | #[proc_macro_derive(d13, attributes("a"))]
| ^^^
-error: must only be one word
+error: attribute must only be a single word
--> $DIR/attribute.rs:59:37
|
LL | #[proc_macro_derive(d14, attributes(a = ""))]
| ^^^^^^
-error: must only be one word
+error: attribute must only be a single word
--> $DIR/attribute.rs:63:37
|
LL | #[proc_macro_derive(d15, attributes(m::a))]
| ^^^^
-error: must only be one word
+error: attribute must only be a single word
--> $DIR/attribute.rs:67:37
|
LL | #[proc_macro_derive(d16, attributes(a(b)))]
--> $DIR/expand-expr.rs:115:47
|
LL | expand_expr_is!("string", echo_tts!("string"; hello));
- | --------------------^^^^^-- help: you might be missing a semicolon here: `;`
- | |
- | caused by the macro expansion here
+ | --------------------^^^^^- caused by the macro expansion here
|
= note: the usage of `echo_tts!` is likely invalid in expression context
+help: you might be missing a semicolon here
+ |
+LL | expand_expr_is!("string", echo_tts!("string"; hello););
+ | +
error: macro expansion ignores token `;` and any following
--> $DIR/expand-expr.rs:116:44
|
LL | expand_expr_is!("string", echo_pm!("string"; hello));
- | -----------------^-------- help: you might be missing a semicolon here: `;`
- | |
- | caused by the macro expansion here
+ | -----------------^------- caused by the macro expansion here
|
= note: the usage of `echo_pm!` is likely invalid in expression context
+help: you might be missing a semicolon here
+ |
+LL | expand_expr_is!("string", echo_pm!("string"; hello););
+ | +
error: recursion limit reached while expanding `recursive_expand!`
--> $DIR/expand-expr.rs:124:16
= help: the trait `PartialEq` is not implemented for `PriorityQueue<T>`
note: required by a bound in `PartialOrd`
--> $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
- | ^^^^^^^^^^^^^^ required by this bound in `PartialOrd`
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `PriorityQueue<T>: Eq` is not satisfied
|
note: required by a bound in `Ord`
--> $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
- | ^^ required by this bound in `Ord`
= note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: can't compare `T` with `T`
| ^^^^^^^^^^
note: required by a bound in `Ord`
--> $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait Ord: Eq + PartialOrd<Self> {
- | ^^^^^^^^^^^^^^^^ required by this bound in `Ord`
= note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
...
LL | one!("hello", "world");
| ---------------------- in this macro invocation
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | -- similarly named tuple variant `Ok` defined here
+ = note: similarly named tuple variant `Ok` defined here
|
= note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
...
LL | two!("yay", "rust");
| ------------------- in this macro invocation
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | -- similarly named tuple variant `Ok` defined here
+ = note: similarly named tuple variant `Ok` defined here
|
= note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
...
LL | three!("hip", "hop");
| -------------------- in this macro invocation
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | -- similarly named tuple variant `Ok` defined here
+ = note: similarly named tuple variant `Ok` defined here
|
= note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info)
|
LL | #[derive(Dlone)]
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ --> $SRC_DIR/core/src/clone.rs:LL:COL
|
- ::: $SRC_DIR/core/src/clone.rs:LL:COL
- |
-LL | pub macro Clone($item:item) {
- | --------------- similarly named derive macro `Clone` defined here
+ = note: similarly named derive macro `Clone` defined here
error: cannot find derive macro `Dlone` in this scope
--> $DIR/resolve-error.rs:35:10
|
LL | #[derive(Dlone)]
| ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ --> $SRC_DIR/core/src/clone.rs:LL:COL
|
- ::: $SRC_DIR/core/src/clone.rs:LL:COL
- |
-LL | pub macro Clone($item:item) {
- | --------------- similarly named derive macro `Clone` defined here
+ = note: similarly named derive macro `Clone` defined here
error: cannot find attribute `FooWithLongNan` in this scope
--> $DIR/resolve-error.rs:32:3
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `ProcMacro::custom_derive`
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
- |
-LL | expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
error: aborting due to previous error
// ignore-pretty
// aux-build:span-api-tests.rs
// aux-build:span-test-macros.rs
+// compile-flags: -Ztranslate-remapped-path-to-local-path=yes
#[macro_use]
extern crate span_test_macros;
LL | take_range(std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `std::ops::Range`
+ | | expected reference, found struct `Range`
| | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
LL | take_range(::std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `std::ops::Range`
+ | | expected reference, found struct `Range`
| | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
LL | take_range(0..1);
| ---------- ^^^^
| | |
- | | expected reference, found struct `std::ops::Range`
+ | | expected reference, found struct `Range`
| | help: consider borrowing here: `&(0..1)`
| arguments to this function are incorrect
|
LL | demo(tell(1)..tell(10));
| ---- ^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `std::ops::Range`
+ | | expected `&Range<usize>`, found struct `Range`
| | help: consider borrowing here: `&(tell(1)..tell(10))`
| arguments to this function are incorrect
|
LL | demo(1..10);
| ---- ^^^^^
| | |
- | | expected reference, found struct `std::ops::Range`
+ | | expected `&Range<usize>`, found struct `Range`
| | help: consider borrowing here: `&(1..10)`
| arguments to this function are incorrect
|
= help: the trait `Sized` is not implemented for `[{integer}]`
note: required by a bound in `RangeFrom`
--> $SRC_DIR/core/src/ops/range.rs:LL:COL
- |
-LL | pub struct RangeFrom<Idx> {
- | ^^^ required by this bound in `RangeFrom`
error: aborting due to 3 previous errors
--- /dev/null
+mod inner {
+ pub trait Trait {
+ fn f(&self) { f(); }
+ fn f_ufcs(&self) { f_ufcs(); }
+ }
+
+ impl Trait for isize {}
+
+ fn f() {}
+ fn f_ufcs() {}
+}
+
+pub fn foo<T: inner::Trait>(t: T) {
+ t.f();
+}
+pub fn foo_ufcs<T: inner::Trait>(t: T) {
+ T::f_ufcs(&t);
+}
--- /dev/null
+use inner::Trait;
+
+mod inner {
+ pub struct Foo;
+ pub trait Trait {
+ fn f(&self);
+ fn f_ufcs(&self);
+ }
+
+ impl Trait for Foo {
+ fn f(&self) { }
+ fn f_ufcs(&self) { }
+ }
+}
+
+pub trait Outer {
+ fn foo<T: Trait>(&self, t: T) { t.f(); }
+ fn foo_ufcs<T: Trait>(&self, t: T) { T::f(&t); }
+}
+
+impl Outer for isize {}
+
+pub fn foo<T: Outer>(t: T) {
+ t.foo(inner::Foo);
+}
+pub fn foo_ufcs<T: Outer>(t: T) {
+ T::foo_ufcs(&t, inner::Foo)
+}
--- /dev/null
+trait PrivateTrait {
+ fn private_trait_method(&self);
+ fn private_trait_method_ufcs(&self);
+}
+
+struct PrivateStruct;
+
+impl PrivateStruct {
+ fn private_inherent_method(&self) { }
+ fn private_inherent_method_ufcs(&self) { }
+}
+
+impl PrivateTrait for PrivateStruct {
+ fn private_trait_method(&self) { }
+ fn private_trait_method_ufcs(&self) { }
+}
+
+#[inline]
+pub fn public_inlinable_function() {
+ PrivateStruct.private_trait_method();
+ PrivateStruct.private_inherent_method();
+}
+
+#[inline]
+pub fn public_inlinable_function_ufcs() {
+ PrivateStruct::private_trait_method(&PrivateStruct);
+ PrivateStruct::private_inherent_method(&PrivateStruct);
+}
--- /dev/null
+// run-pass
+// aux-build:issue-11225-1.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_1 as foo;
+
+pub fn main() {
+ foo::foo(1);
+ foo::foo_ufcs(1);
+}
--- /dev/null
+// run-pass
+// aux-build:issue-11225-2.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_2 as foo;
+
+pub fn main() {
+ foo::foo(1);
+ foo::foo_ufcs(1);
+}
--- /dev/null
+// run-pass
+// aux-build:issue-11225-3.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate issue_11225_3;
+
+pub fn main() {
+ issue_11225_3::public_inlinable_function();
+ issue_11225_3::public_inlinable_function_ufcs();
+}
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0320`.
error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
- = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
+ = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
error: aborting due to previous error; 1 warning emitted
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Result<u32, &R<'_>>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
|
-LL | pub enum Result<T, E> {
- | ---------------------
-...
-LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
- | ^^^ not covered
+ = note: not covered
= note: the matched value is of type `Result<u32, &R<'_>>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
use std::cell::Cell;
#[rustfmt::skip]
error[E0308]: mismatched types
- --> $DIR/issue-102374.rs:16:5
+ --> $DIR/issue-102374.rs:17:5
|
LL | ) -> i32 {
| --- expected `i32` because of return type
| ^ expected `i32`, found fn pointer
|
= note: expected type `i32`
- found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
+ found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+ the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
error: aborting due to previous error
--- /dev/null
+fn main() {
+ let foo = 1;
+ {
+ let bar = 2;
+ let test_func = |x| x > 3;
+ }
+ if bar == 2 { //~ ERROR cannot find value
+ println!("yes");
+ }
+ test_func(1); //~ ERROR cannot find function
+}
--- /dev/null
+error[E0425]: cannot find value `bar` in this scope
+ --> $DIR/issue-104700-inner_scope.rs:7:8
+ |
+LL | if bar == 2 {
+ | ^^^
+ |
+help: the binding `bar` is available in a different scope in the same function
+ --> $DIR/issue-104700-inner_scope.rs:4:13
+ |
+LL | let bar = 2;
+ | ^^^
+
+error[E0425]: cannot find function `test_func` in this scope
+ --> $DIR/issue-104700-inner_scope.rs:10:5
+ |
+LL | test_func(1);
+ | ^^^^^^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
|
= help: the trait `Sized` is not implemented for `(dyn I + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn foo(_x: impl K) {}
+ | ++++
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn foo(_x: &K) {}
|
help: consider giving `N` an explicit type
|
-LL | let mut N: _;
- | +++
+LL | let mut N: /* Type */;
+ | ++++++++++++
error: aborting due to 3 previous errors
|
LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
| ^^^^^^ help: an enum with a similar name exists: `Option`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
|
- ::: $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub enum Option<T> {
- | ------------------ similarly named enum `Option` defined here
+ = note: similarly named enum `Option` defined here
error[E0412]: cannot find type `Baz` in this scope
--> $DIR/levenshtein.rs:16:14
|
note: function defined here
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^^^^^^^
help: remove the extra argument
|
LL | std::mem::size_of();
= note: required for `Result<f32, ParseFloatError>` to implement `Termination`
note: required by a bound in `assert_test_result`
--> $SRC_DIR/test/src/lib.rs:LL:COL
- |
-LL | pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
- | ^^^^^^^^^^^ required by this bound in `assert_test_result`
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
| |
| data moved here
| move occurs because `m` has type `Foo`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | for (n, ref mut m) in &tups {
+ | +++
error: aborting due to previous error
LL | let _ = dbg!(a);
| ^ value used here after move
|
-help: borrow this binding in the pattern to avoid moving the value
- --> $SRC_DIR/std/src/macros.rs:LL:COL
- |
-LL | ref tmp => {
- | +++
error: aborting due to previous error
--> $DIR/disallowed-positions.rs:157:8
|
LL | if true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:171:8
|
LL | if let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:175:8
|
LL | if let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `std::ops::Range`
+ | expected fn pointer, found struct `Range`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:182:8
|
LL | if let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | if let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:190:8
|
LL | if let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
--> $DIR/disallowed-positions.rs:249:11
|
LL | while true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:263:11
|
LL | while let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:267:11
|
LL | while let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `std::ops::Range`
+ | expected fn pointer, found struct `Range`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:274:11
|
LL | while let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | while let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
--> $DIR/disallowed-positions.rs:282:11
|
LL | while let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
LL | (let Range { start: _, end: _ } = true..true || false);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `std::ops::Range`
+ | expected `bool`, found struct `Range`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
- --> $DIR/const-default-method-bodies.rs:24:5
+ --> $DIR/const-default-method-bodies.rs:24:18
|
LL | NonConstImpl.a();
- | ^^^^^^^^^^^^ - required by a bound introduced by this call
- | |
- | the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+ | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
|
note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
--> $DIR/const-default-method-bodies.rs:24:5
--- /dev/null
+// check-pass
+#![allow(incomplete_features)]
+#![feature(
+ associated_type_bounds,
+ const_trait_impl,
+ const_cmp,
+ return_position_impl_trait_in_trait,
+)]
+
+use std::marker::Destruct;
+
+const fn cmp(a: &impl ~const PartialEq) -> bool {
+ a == a
+}
+
+const fn wrap(x: impl ~const PartialEq + ~const Destruct)
+ -> impl ~const PartialEq + ~const Destruct
+{
+ x
+}
+
+#[const_trait]
+trait Foo {
+ fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+}
+
+impl const Foo for () {
+ fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+ 123
+ }
+}
+
+const _: () = {
+ assert!(cmp(&0xDEADBEEFu32));
+ assert!(cmp(&()));
+ assert!(wrap(123) == wrap(123));
+ assert!(wrap(123) != wrap(456));
+ let x = <() as Foo>::huh();
+ assert!(x == x);
+};
+
+#[const_trait]
+trait T {}
+struct S;
+impl const T for S {}
+
+const fn rpit() -> impl ~const T { S }
+
+const fn apit(_: impl ~const T + ~const Destruct) {}
+
+const fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+
+const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {}
+
+fn main() {}
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
- --> $DIR/cross-crate.rs:17:5
+ --> $DIR/cross-crate.rs:17:14
|
LL | NonConst.func();
- | ^^^^^^^^ ---- required by a bound introduced by this call
- | |
- | the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+ | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
|
note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
--> $DIR/cross-crate.rs:17:5
error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
- --> $DIR/cross-crate.rs:17:5
+ --> $DIR/cross-crate.rs:17:14
|
LL | NonConst.func();
- | ^^^^^^^^ ---- required by a bound introduced by this call
- | |
- | the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+ | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
|
note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
--> $DIR/cross-crate.rs:17:5
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
- --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
+ --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
|
LL | ().a()
- | ^^ - required by a bound introduced by this call
- | |
- | the trait `~const Tr` is not implemented for `()`
+ | ^ the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
--> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
error[E0277]: the trait bound `T: ~const Foo` is not satisfied
- --> $DIR/super-traits-fail-2.rs:15:5
+ --> $DIR/super-traits-fail-2.rs:15:7
|
LL | x.a();
- | ^ - required by a bound introduced by this call
- | |
- | the trait `~const Foo` is not implemented for `T`
+ | ^ the trait `~const Foo` is not implemented for `T`
|
note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
--> $DIR/super-traits-fail-2.rs:15:5
error[E0277]: the trait bound `T: ~const Foo` is not satisfied
- --> $DIR/super-traits-fail-2.rs:15:5
+ --> $DIR/super-traits-fail-2.rs:15:7
|
LL | x.a();
- | ^ - required by a bound introduced by this call
- | |
- | the trait `~const Foo` is not implemented for `T`
+ | ^ the trait `~const Foo` is not implemented for `T`
|
note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
--> $DIR/super-traits-fail-2.rs:15:5
#![feature(const_trait_impl)]
#![feature(associated_type_bounds)]
-#[const_trait]
-trait T {}
-struct S;
-impl T for S {}
-
-fn rpit() -> impl ~const T { S }
-//~^ ERROR `~const` is not allowed
-
-fn apit(_: impl ~const T) {}
-//~^ ERROR `~const` is not allowed
-
-fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
-//~^ ERROR `~const` is not allowed
-
-fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
-//~^ ERROR `~const` is not allowed
-
struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
//~^ ERROR `~const` and `?` are mutually exclusive
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:9:19
- |
-LL | fn rpit() -> impl ~const T { S }
- | ^^^^^^^^
- |
- = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:12:17
- |
-LL | fn apit(_: impl ~const T) {}
- | ^^^^^^^^
- |
- = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:15:50
- |
-LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
- | ^^^^^^^^
- |
- = note: `impl Trait`s cannot have `~const` trait bounds
-
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:18:48
- |
-LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
- | ^^^^^^^^
- |
- = note: `impl Trait`s cannot have `~const` trait bounds
-
error: `~const` and `?` are mutually exclusive
- --> $DIR/tilde-const-invalid-places.rs:21:25
+ --> $DIR/tilde-const-invalid-places.rs:4:25
|
LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^
-error: aborting due to 5 previous errors
+error: aborting due to previous error
|
LL | enum World {
| ^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Add<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot add `String` to `&str`
--> $DIR/issue-39018.rs:11:22
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/xyz -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z ui-testing=no
struct MyError;
impl std::error::Error for MyError {}
= help: the trait `std::fmt::Display` is not implemented for `MyError`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
error[E0277]: `MyError` doesn't implement `Debug`
--> $DIR/issue-71363.rs:4:6
= help: the trait `Debug` is not implemented for `MyError`
= note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
help: consider annotating `MyError` with `#[derive(Debug)]`
|
3 | #[derive(Debug)]
|
help: consider giving `x` an explicit type
|
-LL | let mut x: _ = Default::default();
- | +++
+LL | let mut x: /* Type */ = Default::default();
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/method-and-field-eager-resolution.rs:11:9
|
help: consider giving `x` an explicit type
|
-LL | let mut x: _ = Default::default();
- | +++
+LL | let mut x: /* Type */ = Default::default();
+ | ++++++++++++
error: aborting due to 2 previous errors
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
help: provide the argument
|
LL | let _: Result<(), String> = Ok(());
| ^^^^^^^^^^^^^^^^---^^^^^-
| |
| unsatisfied trait bound introduced here
-note: the following trait must be implemented
+note: the trait `Foo` must be implemented
--> $DIR/specialization-trait-not-implemented.rs:7:1
|
LL | trait Foo {
|
note: the module `thread_info` is defined here
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
- |
-LL | use crate::sys_common::thread_info;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
--> $DIR/std-uncopyable-atomics.rs:9:13
|
LL | let x = *&x;
- | ^^^
- | |
- | move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*&x`
+ | ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = *&x;
+LL + let x = &x;
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:11:13
|
LL | let x = *&x;
- | ^^^
- | |
- | move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*&x`
+ | ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = *&x;
+LL + let x = &x;
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:13:13
|
LL | let x = *&x;
- | ^^^
- | |
- | move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*&x`
+ | ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = *&x;
+LL + let x = &x;
+ |
error[E0507]: cannot move out of a shared reference
--> $DIR/std-uncopyable-atomics.rs:15:13
|
LL | let x = *&x;
- | ^^^
- | |
- | move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&*&x`
+ | ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr<usize>`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let x = *&x;
+LL + let x = &x;
+ |
error: aborting due to 4 previous errors
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+struct NT(str);
+struct DST { a: u32, b: str }
+
+macro_rules! check {
+ (val: $ty_of:expr, $expected:expr) => {
+ assert_eq!(type_name_of_val($ty_of), $expected);
+ };
+ ($ty:ty, $expected:expr) => {
+ assert_eq!(std::any::type_name::<$ty>(), $expected);
+ };
+}
+
+fn main() {
+ // type_name should support unsized types
+ check!([u8], "[u8]");
+ check!(str, "str");
+ check!(dyn Send, "dyn core::marker::Send");
+ check!(NT, "issue_21058::NT");
+ check!(DST, "issue_21058::DST");
+ check!(&i32, "&i32");
+ check!(&'static i32, "&i32");
+ check!((i32, u32), "(i32, u32)");
+ check!(val: foo(), "issue_21058::Foo");
+ check!(val: Foo::new, "issue_21058::Foo::new");
+ check!(val:
+ <Foo as Debug>::fmt,
+ "<issue_21058::Foo as core::fmt::Debug>::fmt"
+ );
+ check!(val: || {}, "issue_21058::main::{{closure}}");
+ bar::<i32>();
+}
+
+trait Trait {
+ type Assoc;
+}
+
+impl Trait for i32 {
+ type Assoc = String;
+}
+
+fn bar<T: Trait>() {
+ check!(T::Assoc, "alloc::string::String");
+ check!(T, "i32");
+}
+
+fn type_name_of_val<T>(_: T) -> &'static str {
+ std::any::type_name::<T>()
+}
+
+#[derive(Debug)]
+struct Foo;
+
+impl Foo {
+ fn new() -> Self { Foo }
+}
+
+fn foo() -> impl Debug {
+ Foo
+}
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
note: required by a bound in `core::str::<impl str>::get`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get`
error[E0277]: the type `str` cannot be indexed by `{integer}`
--> $DIR/str-idx.rs:5:29
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
note: required by a bound in `core::str::<impl str>::get_unchecked`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub const unsafe fn get_unchecked<I: ~const SliceIndex<str>>(&self, i: I) -> &I::Output {
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked`
error[E0277]: the type `str` cannot be indexed by `char`
--> $DIR/str-idx.rs:6:19
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
note: required by a bound in `core::str::<impl str>::get_mut`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_mut`
error[E0277]: the type `str` cannot be indexed by `{integer}`
--> $DIR/str-mut-idx.rs:11:25
= help: the trait `SliceIndex<[T]>` is implemented for `usize`
note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub const unsafe fn get_unchecked_mut<I: ~const SliceIndex<str>>(
- | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `core::str::<impl str>::get_unchecked_mut`
error[E0277]: the type `str` cannot be indexed by `char`
--> $DIR/str-mut-idx.rs:13:7
--> $DIR/struct-record-suggestion.rs:23:20
|
LL | let q = B { b: 1..Default::default() };
- | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::ops::Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range`
|
= note: expected type `u32`
found struct `std::ops::Range<{integer}>`
--- /dev/null
+struct S {
+ a: u32,
+}
+
+fn main() {
+ let s1 = S { a: 1 };
+
+ let _ = || {
+ let s2 = Oops { a: 2, ..s1 };
+ //~^ ERROR cannot find struct, variant or union type `Oops` in this scope
+ };
+}
--- /dev/null
+error[E0422]: cannot find struct, variant or union type `Oops` in this scope
+ --> $DIR/unresolved-struct-with-fru.rs:9:18
+ |
+LL | let s2 = Oops { a: 2, ..s1 };
+ | ^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0422`.
found type `{integer}`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: remove the extra argument
|
LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: provide the argument
|
LL | let _: Option<(i8,)> = Some(/* (i8,) */);
found type `usize`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:17:34
found type `usize`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
error: aborting due to 5 previous errors
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
help: wrap these arguments in parentheses to construct a tuple
|
LL | let _: Result<(i32, i8), ()> = Ok((1, 2));
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: wrap these arguments in parentheses to construct a tuple
|
LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi"));
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: provide the argument
|
LL | let _: Option<()> = Some(());
found type `{integer}`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: use a trailing comma to create a tuple with one element
|
LL | let _: Option<(i32,)> = Some((3,));
found type `{integer}`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: use a trailing comma to create a tuple with one element
|
LL | let _: Option<(i32,)> = Some((3,));
LL | let _y = foo;
| ^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `foo`
+note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn map<U, F>(self, f: F) -> Option<U>
- | ^^^^
error: aborting due to previous error
|
LL | #[tests]
| ^^^^^ help: an attribute macro with a similar name exists: `test`
+ --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
-LL | pub macro test($item:item) {
- | -------------- similarly named attribute macro `test` defined here
+ = note: similarly named attribute macro `test` defined here
error: cannot find attribute `deprcated` in this scope
--> $DIR/attribute-typos.rs:1:3
LL | for j in a {
| ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
|
-note: this function takes ownership of the receiver `self`, which moves `a`
+note: `into_iter` takes ownership of the receiver `self`, which moves `a`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
|
LL | for j in &a {
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider further restricting `Self`
|
LL | trait Foo<T>: Sized {
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider further restricting `Self`
|
LL | trait Bar: std::fmt::Display + Sized {
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider further restricting `Self`
|
LL | trait Baz: Sized where Self: std::fmt::Display {
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider further restricting `Self`
|
LL | trait Qux<T>: Sized where Self: std::fmt::Display {
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider further restricting `Self`
|
LL | trait Bat<T>: std::fmt::Display + Sized {
--- /dev/null
+// run-rustfix
+fn wat<T: Clone>(t: &T) -> T {
+ t.clone() //~ ERROR E0308
+}
+
+#[derive(Clone)]
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+ t.clone() //~ ERROR E0308
+}
+
+fn main() {
+ wat(&42);
+ wut(&Foo);
+}
--- /dev/null
+// run-rustfix
+fn wat<T>(t: &T) -> T {
+ t.clone() //~ ERROR E0308
+}
+
+struct Foo;
+
+fn wut(t: &Foo) -> Foo {
+ t.clone() //~ ERROR E0308
+}
+
+fn main() {
+ wat(&42);
+ wut(&Foo);
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+ |
+LL | fn wat<T>(t: &T) -> T {
+ | - - expected `T` because of return type
+ | |
+ | this type parameter
+LL | t.clone()
+ | ^^^^^^^^^ expected type parameter `T`, found `&T`
+ |
+ = note: expected type parameter `T`
+ found reference `&T`
+note: `T` does not implement `Clone`, so `&T` was cloned instead
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
+ |
+LL | t.clone()
+ | ^
+help: consider restricting type parameter `T`
+ |
+LL | fn wat<T: Clone>(t: &T) -> T {
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+ |
+LL | fn wut(t: &Foo) -> Foo {
+ | --- expected `Foo` because of return type
+LL | t.clone()
+ | ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+ |
+note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
+ --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
+ |
+LL | t.clone()
+ | ^
+help: consider annotating `Foo` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
| ^^^^^^^^^^^^ ^^^^^^^^^
note: required by a bound in `Eq`
--> $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait Eq: PartialEq<Self> {
- | ^^^^^^^^^^^^^^^ required by this bound in `Eq`
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
|
`Enum: Clone`
`Enum: Default`
`CloneEnum: Default`
-note: the following trait must be implemented
+note: the trait `Default` must be implemented
--> $SRC_DIR/core/src/default.rs:LL:COL
- |
-LL | pub trait Default: Sized {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider annotating `Enum` with `#[derive(Clone)]`
|
LL | #[derive(Clone)]
...
LL | let y = x.test();
| ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/time.rs:LL:COL
|
- ::: $SRC_DIR/std/src/time.rs:LL:COL
- |
-LL | pub struct Instant(time::Instant);
- | ------------------ doesn't satisfy `Instant: Default`
- |
- ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ = note: doesn't satisfy `Instant: Default`
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+ = note: doesn't satisfy `Vec<Enum>: Clone`
|
= note: the following trait bounds were not satisfied:
`Vec<Enum>: Clone`
|
LL | impl result {
| ^^^^^^ help: an enum with a similar name exists: `Result`
+ --> $SRC_DIR/core/src/result.rs:LL:COL
|
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | --------------------- similarly named enum `Result` defined here
+ = note: similarly named enum `Result` defined here
error[E0573]: expected type, found variant `Err`
--> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25
let &(X(_t), X(_u)) = &(x.clone(), x.clone());
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION (X(_t), X(_u))
+ //~| HELP consider removing the borrow
if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~| HELP consider removing the borrow
while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~| HELP consider removing the borrow
match &(e.clone(), e.clone()) {
//~^ ERROR cannot move
&(Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the borrow
&(Either::Two(_t), Either::One(_u)) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+ //~^ HELP consider removing the borrow
_ => (),
}
match &(e.clone(), e.clone()) {
//~^ ERROR cannot move
&(Either::One(_t), Either::Two(_u))
- //~^ HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the borrow
| &(Either::Two(_t), Either::One(_u)) => (),
// FIXME: would really like a suggestion here too
_ => (),
match &(e.clone(), e.clone()) {
//~^ ERROR cannot move
&(Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the borrow
&(Either::Two(ref _t), Either::One(ref _u)) => (),
_ => (),
}
match &(e.clone(), e.clone()) {
//~^ ERROR cannot move
&(Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the borrow
(Either::Two(_t), Either::One(_u)) => (),
_ => (),
}
fn f5(&(X(_t), X(_u)): &(X, X)) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION (X(_t), X(_u))
+ //~| HELP consider removing the borrow
let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION (X(_t), X(_u))
+ //~| HELP consider removing the mutable borrow
if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~| HELP consider removing the mutable borrow
while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~| HELP consider removing the mutable borrow
match &mut (em.clone(), em.clone()) {
//~^ ERROR cannot move
&mut (Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
&mut (Either::Two(_t), Either::One(_u)) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+ //~^ HELP consider removing the mutable borrow
_ => (),
}
match &mut (em.clone(), em.clone()) {
//~^ ERROR cannot move
&mut (Either::One(_t), Either::Two(_u))
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
| &mut (Either::Two(_t), Either::One(_u)) => (),
// FIXME: would really like a suggestion here too
_ => (),
match &mut (em.clone(), em.clone()) {
//~^ ERROR cannot move
&mut (Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
&mut (Either::Two(ref _t), Either::One(ref _u)) => (),
_ => (),
}
match &mut (em.clone(), em.clone()) {
//~^ ERROR cannot move
&mut (Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
&mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
_ => (),
}
match &mut (em.clone(), em.clone()) {
//~^ ERROR cannot move
&mut (Either::One(_t), Either::Two(_u)) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+ //~^ HELP consider removing the mutable borrow
(Either::Two(_t), Either::One(_u)) => (),
_ => (),
}
fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION (X(_t), X(_u))
+ //~| HELP consider removing the mutable borrow
}
--> $DIR/duplicate-suggestions.rs:39:27
|
LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone());
- | --------------- ^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(X(_t), X(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+LL + let (X(_t), X(_u)) = &(x.clone(), x.clone());
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:43:50
+ --> $DIR/duplicate-suggestions.rs:42:50
|
LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
- | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL + if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:47:53
+ --> $DIR/duplicate-suggestions.rs:45:53
|
LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
- | ----------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+LL + while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:51:11
+ --> $DIR/duplicate-suggestions.rs:48:11
|
LL | match &(e.clone(), e.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^
| -- -- ...and here
| |
| data moved here
-...
+LL |
LL | &(Either::Two(_t), Either::One(_u)) => (),
| -- ...and here -- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
|
-LL | (Either::One(_t), Either::Two(_u)) => (),
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&`
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
+help: consider removing the borrow
+ |
+LL - &(Either::Two(_t), Either::One(_u)) => (),
+LL + (Either::Two(_t), Either::One(_u)) => (),
|
-LL | (Either::Two(_t), Either::One(_u)) => (),
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:61:11
+ --> $DIR/duplicate-suggestions.rs:56:11
|
LL | match &(e.clone(), e.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^
| data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&`
+help: consider removing the borrow
|
-LL ~ (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~ | &(Either::Two(_t), Either::One(_u)) => (),
+LL - &(Either::One(_t), Either::Two(_u))
+LL + (Either::One(_t), Either::Two(_u))
|
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:70:11
+ --> $DIR/duplicate-suggestions.rs:64:11
|
LL | match &(e.clone(), e.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | &(Either::One(_t), Either::Two(_u)) => (),
- | -----------------------------------
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ...and here
+ | |
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:78:11
+ --> $DIR/duplicate-suggestions.rs:71:11
|
LL | match &(e.clone(), e.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | &(Either::One(_t), Either::Two(_u)) => (),
- | -----------------------------------
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ...and here
+ | |
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - &(Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:91:31
+ --> $DIR/duplicate-suggestions.rs:82:31
|
LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(X(_t), X(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+LL + let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:95:54
+ --> $DIR/duplicate-suggestions.rs:85:54
|
LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
- | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL + if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:99:57
+ --> $DIR/duplicate-suggestions.rs:88:57
|
LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
- | --------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+LL + while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:103:11
+ --> $DIR/duplicate-suggestions.rs:91:11
|
LL | match &mut (em.clone(), em.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| -- -- ...and here
| |
| data moved here
-...
+LL |
LL | &mut (Either::Two(_t), Either::One(_u)) => (),
| -- ...and here -- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
|
-LL | (Either::One(_t), Either::Two(_u)) => (),
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::Two(_t), Either::One(_u)) => (),
+LL + (Either::Two(_t), Either::One(_u)) => (),
|
-LL | (Either::Two(_t), Either::One(_u)) => (),
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:113:11
+ --> $DIR/duplicate-suggestions.rs:99:11
|
LL | match &mut (em.clone(), em.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
|
-LL ~ (Either::One(_t), Either::Two(_u))
-LL +
-LL +
-LL ~ | &mut (Either::Two(_t), Either::One(_u)) => (),
+LL - &mut (Either::One(_t), Either::Two(_u))
+LL + (Either::One(_t), Either::Two(_u))
|
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:122:11
+ --> $DIR/duplicate-suggestions.rs:107:11
|
LL | match &mut (em.clone(), em.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ---------------------------------------
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ...and here
+ | |
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:130:11
+ --> $DIR/duplicate-suggestions.rs:114:11
|
LL | match &mut (em.clone(), em.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ---------------------------------------
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ...and here
+ | |
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:138:11
+ --> $DIR/duplicate-suggestions.rs:121:11
|
LL | match &mut (em.clone(), em.clone()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ---------------------------------------
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+ | -- -- ...and here
+ | |
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - &mut (Either::One(_t), Either::Two(_u)) => (),
+LL + (Either::One(_t), Either::Two(_u)) => (),
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/duplicate-suggestions.rs:86:11
+ --> $DIR/duplicate-suggestions.rs:78:11
|
LL | fn f5(&(X(_t), X(_u)): &(X, X)) { }
| ^^^^--^^^^^--^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&`: `(X(_t), X(_u))`
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the borrow
+ |
+LL - fn f5(&(X(_t), X(_u)): &(X, X)) { }
+LL + fn f5((X(_t), X(_u)): &(X, X)) { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/duplicate-suggestions.rs:146:11
+ --> $DIR/duplicate-suggestions.rs:128:11
|
LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
| ^^^^^^^^--^^^^^--^^
- | | | |
- | | | ...and here
- | | data moved here
- | help: consider removing the `&mut`: `(X(_t), X(_u))`
+ | | |
+ | | ...and here
+ | data moved here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the mutable borrow
+ |
+LL - fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+LL + fn f6((X(_t), X(_u)): &mut (X, X)) { }
+ |
error: aborting due to 17 previous errors
let X(_t) = x;
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &x
if let Either::One(_t) = e { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
while let Either::One(_t) = e { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
match e {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
Either::One(_t)
| Either::Two(_t) => (),
}
match e {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
let X(mut _t) = x;
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &x
if let Either::One(mut _t) = em { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
while let Either::One(mut _t) = em { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
match em {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
Either::One(mut _t)
| Either::Two(mut _t) => (),
}
match em {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
Either::One(mut _t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
let X(_t) = x;
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &x
if let Either::One(_t) = e { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
while let Either::One(_t) = e { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
match e {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
Either::One(_t)
| Either::Two(_t) => (),
}
match e {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &e
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
let X(mut _t) = x;
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &x
if let Either::One(mut _t) = em { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
while let Either::One(mut _t) = em { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
match em {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
Either::One(mut _t)
| Either::Two(mut _t) => (),
}
match em {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
Either::One(mut _t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
match em {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &em
Either::One(mut _t) => (),
Either::Two(ref mut _t) => (),
// FIXME: should suggest removing `ref` too
LL | consume_fn(|| {
| -- captured by this `Fn` closure
LL | let X(_t) = x;
- | -- ^ help: consider borrowing here: `&x`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &x;
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:32:34
+ --> $DIR/move-into-closure.rs:31:34
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `Fn` closure
...
LL | if let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &e { }
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:36:37
+ --> $DIR/move-into-closure.rs:34:37
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `Fn` closure
...
LL | while let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &e { }
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:40:15
+ --> $DIR/move-into-closure.rs:37:15
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `Fn` closure
...
LL | match e {
- | ^ help: consider borrowing here: `&e`
+ | ^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:47:15
+ --> $DIR/move-into-closure.rs:43:15
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `Fn` closure
...
LL | match e {
- | ^ help: consider borrowing here: `&e`
+ | ^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:56:25
+ --> $DIR/move-into-closure.rs:51:25
|
LL | let x = X(Y);
| - captured outer variable
| -- captured by this `Fn` closure
...
LL | let X(mut _t) = x;
- | ------ ^ help: consider borrowing here: `&x`
+ | ------ ^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(mut _t) = &x;
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:60:38
+ --> $DIR/move-into-closure.rs:54:38
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `Fn` closure
...
LL | if let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
+ | ------ ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(mut _t) = &em { }
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:64:41
+ --> $DIR/move-into-closure.rs:57:41
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `Fn` closure
...
LL | while let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
+ | ------ ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(mut _t) = &em { }
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:68:15
+ --> $DIR/move-into-closure.rs:60:15
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `Fn` closure
...
LL | match em {
- | ^^ help: consider borrowing here: `&em`
+ | ^^
...
LL | Either::One(mut _t)
| ------
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
- --> $DIR/move-into-closure.rs:75:15
+ --> $DIR/move-into-closure.rs:66:15
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `Fn` closure
...
LL | match em {
- | ^^ help: consider borrowing here: `&em`
+ | ^^
...
LL | Either::One(mut _t) => (),
| ------
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:95:21
+ --> $DIR/move-into-closure.rs:85:21
|
LL | let x = X(Y);
| - captured outer variable
LL | consume_fnmut(|| {
| -- captured by this `FnMut` closure
LL | let X(_t) = x;
- | -- ^ help: consider borrowing here: `&x`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &x;
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:99:34
+ --> $DIR/move-into-closure.rs:88:34
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `FnMut` closure
...
LL | if let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &e { }
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:103:37
+ --> $DIR/move-into-closure.rs:91:37
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `FnMut` closure
...
LL | while let Either::One(_t) = e { }
- | -- ^ help: consider borrowing here: `&e`
+ | -- ^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &e { }
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:107:15
+ --> $DIR/move-into-closure.rs:94:15
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `FnMut` closure
...
LL | match e {
- | ^ help: consider borrowing here: `&e`
+ | ^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:114:15
+ --> $DIR/move-into-closure.rs:100:15
|
LL | let e = Either::One(X(Y));
| - captured outer variable
| -- captured by this `FnMut` closure
...
LL | match e {
- | ^ help: consider borrowing here: `&e`
+ | ^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &e {
+ | +
error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:123:25
+ --> $DIR/move-into-closure.rs:108:25
|
LL | let x = X(Y);
| - captured outer variable
| -- captured by this `FnMut` closure
...
LL | let X(mut _t) = x;
- | ------ ^ help: consider borrowing here: `&x`
+ | ------ ^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(mut _t) = &x;
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:127:38
+ --> $DIR/move-into-closure.rs:111:38
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `FnMut` closure
...
LL | if let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
+ | ------ ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(mut _t) = &em { }
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:131:41
+ --> $DIR/move-into-closure.rs:114:41
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `FnMut` closure
...
LL | while let Either::One(mut _t) = em { }
- | ------ ^^ help: consider borrowing here: `&em`
+ | ------ ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(mut _t) = &em { }
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:135:15
+ --> $DIR/move-into-closure.rs:117:15
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `FnMut` closure
...
LL | match em {
- | ^^ help: consider borrowing here: `&em`
+ | ^^
...
LL | Either::One(mut _t)
| ------
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:142:15
+ --> $DIR/move-into-closure.rs:123:15
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `FnMut` closure
...
LL | match em {
- | ^^ help: consider borrowing here: `&em`
+ | ^^
...
LL | Either::One(mut _t) => (),
| ------
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
- --> $DIR/move-into-closure.rs:150:15
+ --> $DIR/move-into-closure.rs:130:15
|
LL | let mut em = Either::One(X(Y));
| ------ captured outer variable
| -- captured by this `FnMut` closure
...
LL | match em {
- | ^^ help: consider borrowing here: `&em`
+ | ^^
...
LL | Either::One(mut _t) => (),
| ------
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &em {
+ | +
error: aborting due to 21 previous errors
let X(_t) = *s;
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION s
+ //~| HELP consider removing the dereference here
if let Either::One(_t) = *r { }
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION r
+ //~| HELP consider removing the dereference here
while let Either::One(_t) = *r { }
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION r
+ //~| HELP consider removing the dereference here
match *r {
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION r
+ //~| HELP consider removing the dereference here
Either::One(_t)
| Either::Two(_t) => (),
}
match *r {
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION r
+ //~| HELP consider removing the dereference here
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
let X(_t) = *sm;
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION sm
+ //~| HELP consider removing the dereference here
if let Either::One(_t) = *rm { }
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION rm
+ //~| HELP consider removing the dereference here
while let Either::One(_t) = *rm { }
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION rm
+ //~| HELP consider removing the dereference here
match *rm {
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION rm
+ //~| HELP consider removing the dereference here
Either::One(_t)
| Either::Two(_t) => (),
}
match *rm {
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION rm
+ //~| HELP consider removing the dereference here
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
}
match *rm {
//~^ ERROR cannot move
- //~| HELP consider borrowing here
- //~| SUGGESTION rm
+ //~| HELP consider removing the dereference here
Either::One(_t) => (),
Either::Two(ref mut _t) => (),
// FIXME: should suggest removing `ref` too
let X(_t) = vs[0];
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vs[0]
if let Either::One(_t) = vr[0] { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vr[0]
while let Either::One(_t) = vr[0] { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vr[0]
match vr[0] {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vr[0]
Either::One(_t)
| Either::Two(_t) => (),
}
match vr[0] {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vr[0]
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
let X(_t) = vsm[0];
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vsm[0]
if let Either::One(_t) = vrm[0] { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vrm[0]
while let Either::One(_t) = vrm[0] { }
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vrm[0]
match vrm[0] {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vrm[0]
Either::One(_t)
| Either::Two(_t) => (),
}
match vrm[0] {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vrm[0]
Either::One(_t) => (),
Either::Two(ref _t) => (),
// FIXME: should suggest removing `ref` too
match vrm[0] {
//~^ ERROR cannot move
//~| HELP consider borrowing here
- //~| SUGGESTION &vrm[0]
Either::One(_t) => (),
Either::Two(ref mut _t) => (),
// FIXME: should suggest removing `ref` too
let &X(_t) = s;
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
if let &Either::One(_t) = r { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
while let &Either::One(_t) = r { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
match r {
//~^ ERROR cannot move
&Either::One(_t)
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
| &Either::Two(_t) => (),
// FIXME: would really like a suggestion here too
}
match r {
//~^ ERROR cannot move
&Either::One(_t) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&Either::Two(ref _t) => (),
}
match r {
//~^ ERROR cannot move
&Either::One(_t) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
Either::Two(_t) => (),
}
fn f1(&X(_t): &X) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
let &mut X(_t) = sm;
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
if let &mut Either::One(_t) = rm { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
while let &mut Either::One(_t) = rm { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
match rm {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&mut Either::Two(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::Two(_t)
+ //~^ HELP consider removing
}
match rm {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&mut Either::Two(ref _t) => (),
}
match rm {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&mut Either::Two(ref mut _t) => (),
}
match rm {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
Either::Two(_t) => (),
}
fn f2(&mut X(_t): &mut X) { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
// move from tuple of &Either/&X
let (&X(_t),) = (&x.clone(),);
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
if let (&Either::One(_t),) = (&e.clone(),) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
while let (&Either::One(_t),) = (&e.clone(),) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
match (&e.clone(),) {
//~^ ERROR cannot move
(&Either::One(_t),)
+ //~^ HELP consider borrowing the pattern binding
| (&Either::Two(_t),) => (),
}
fn f3((&X(_t),): (&X,)) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
let (&mut X(_t),) = (&mut xm.clone(),);
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
match (&mut em.clone(),) {
//~^ ERROR cannot move
(&mut Either::One(_t),) => (),
+ //~^ HELP consider borrowing the pattern binding
(&mut Either::Two(_t),) => (),
+ //~^ HELP consider borrowing the pattern binding
}
fn f4((&mut X(_t),): (&mut X,)) { }
//~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
// move from &Either/&X value
let &X(_t) = &x;
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
if let &Either::One(_t) = &e { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
while let &Either::One(_t) = &e { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
match &e {
//~^ ERROR cannot move
&Either::One(_t)
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
| &Either::Two(_t) => (),
// FIXME: would really like a suggestion here too
}
match &e {
//~^ ERROR cannot move
&Either::One(_t) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&Either::Two(ref _t) => (),
}
match &e {
//~^ ERROR cannot move
&Either::One(_t) => (),
- //~^ HELP consider removing the `&`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
Either::Two(_t) => (),
}
let &mut X(_t) = &mut xm;
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION X(_t)
+ //~| HELP consider removing
if let &mut Either::One(_t) = &mut em { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
while let &mut Either::One(_t) = &mut em { }
//~^ ERROR cannot move
- //~| HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~| HELP consider removing
match &mut em {
//~^ ERROR cannot move
&mut Either::One(_t)
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
| &mut Either::Two(_t) => (),
// FIXME: would really like a suggestion here too
}
match &mut em {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&mut Either::Two(ref _t) => (),
}
match &mut em {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
&mut Either::Two(ref mut _t) => (),
}
match &mut em {
//~^ ERROR cannot move
&mut Either::One(_t) => (),
- //~^ HELP consider removing the `&mut`
- //~| SUGGESTION Either::One(_t)
+ //~^ HELP consider removing
Either::Two(_t) => (),
}
}
+
+struct Testing {
+ a: Option<String>
+}
+
+fn testing(a: &Testing) {
+ let Some(_s) = a.a else {
+ //~^ ERROR cannot move
+ //~| HELP consider borrowing the pattern binding
+ return;
+ };
+}
--> $DIR/simple.rs:38:17
|
LL | let X(_t) = *s;
- | -- ^^ help: consider borrowing here: `&*s`
+ | -- ^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let X(_t) = *s;
+LL + let X(_t) = s;
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:42:30
+ --> $DIR/simple.rs:41:30
|
LL | if let Either::One(_t) = *r { }
- | -- ^^ help: consider borrowing here: `&*r`
+ | -- ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - if let Either::One(_t) = *r { }
+LL + if let Either::One(_t) = r { }
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:46:33
+ --> $DIR/simple.rs:44:33
|
LL | while let Either::One(_t) = *r { }
- | -- ^^ help: consider borrowing here: `&*r`
+ | -- ^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - while let Either::One(_t) = *r { }
+LL + while let Either::One(_t) = r { }
+ |
error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
- --> $DIR/simple.rs:50:11
+ --> $DIR/simple.rs:47:11
|
LL | match *r {
- | ^^ help: consider borrowing here: `&*r`
+ | ^^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *r {
+LL + match r {
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:57:11
+ --> $DIR/simple.rs:53:11
|
LL | match *r {
- | ^^ help: consider borrowing here: `&*r`
+ | ^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *r {
+LL + match r {
+ |
error[E0507]: cannot move out of `sm` which is behind a mutable reference
- --> $DIR/simple.rs:66:17
+ --> $DIR/simple.rs:61:17
|
LL | let X(_t) = *sm;
- | -- ^^^ help: consider borrowing here: `&*sm`
+ | -- ^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - let X(_t) = *sm;
+LL + let X(_t) = sm;
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:70:30
+ --> $DIR/simple.rs:64:30
|
LL | if let Either::One(_t) = *rm { }
- | -- ^^^ help: consider borrowing here: `&*rm`
+ | -- ^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - if let Either::One(_t) = *rm { }
+LL + if let Either::One(_t) = rm { }
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:74:33
+ --> $DIR/simple.rs:67:33
|
LL | while let Either::One(_t) = *rm { }
- | -- ^^^ help: consider borrowing here: `&*rm`
+ | -- ^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - while let Either::One(_t) = *rm { }
+LL + while let Either::One(_t) = rm { }
+ |
error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
- --> $DIR/simple.rs:78:11
+ --> $DIR/simple.rs:70:11
|
LL | match *rm {
- | ^^^ help: consider borrowing here: `&*rm`
+ | ^^^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:85:11
+ --> $DIR/simple.rs:76:11
|
LL | match *rm {
- | ^^^ help: consider borrowing here: `&*rm`
+ | ^^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:93:11
+ --> $DIR/simple.rs:83:11
|
LL | match *rm {
- | ^^^ help: consider borrowing here: `&*rm`
+ | ^^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the dereference here
+ |
+LL - match *rm {
+LL + match rm {
+ |
error[E0507]: cannot move out of index of `Vec<X>`
- --> $DIR/simple.rs:102:17
+ --> $DIR/simple.rs:91:17
|
LL | let X(_t) = vs[0];
- | -- ^^^^^ help: consider borrowing here: `&vs[0]`
+ | -- ^^^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &vs[0];
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:106:30
+ --> $DIR/simple.rs:94:30
|
LL | if let Either::One(_t) = vr[0] { }
- | -- ^^^^^ help: consider borrowing here: `&vr[0]`
+ | -- ^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &vr[0] { }
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:110:33
+ --> $DIR/simple.rs:97:33
|
LL | while let Either::One(_t) = vr[0] { }
- | -- ^^^^^ help: consider borrowing here: `&vr[0]`
+ | -- ^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &vr[0] { }
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:114:11
+ --> $DIR/simple.rs:100:11
|
LL | match vr[0] {
- | ^^^^^ help: consider borrowing here: `&vr[0]`
+ | ^^^^^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vr[0] {
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:121:11
+ --> $DIR/simple.rs:106:11
|
LL | match vr[0] {
- | ^^^^^ help: consider borrowing here: `&vr[0]`
+ | ^^^^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vr[0] {
+ | +
error[E0507]: cannot move out of index of `Vec<X>`
- --> $DIR/simple.rs:130:17
+ --> $DIR/simple.rs:114:17
|
LL | let X(_t) = vsm[0];
- | -- ^^^^^^ help: consider borrowing here: `&vsm[0]`
+ | -- ^^^^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let X(_t) = &vsm[0];
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:134:30
+ --> $DIR/simple.rs:117:30
|
LL | if let Either::One(_t) = vrm[0] { }
- | -- ^^^^^^ help: consider borrowing here: `&vrm[0]`
+ | -- ^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | if let Either::One(_t) = &vrm[0] { }
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:138:33
+ --> $DIR/simple.rs:120:33
|
LL | while let Either::One(_t) = vrm[0] { }
- | -- ^^^^^^ help: consider borrowing here: `&vrm[0]`
+ | -- ^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | while let Either::One(_t) = &vrm[0] { }
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:142:11
+ --> $DIR/simple.rs:123:11
|
LL | match vrm[0] {
- | ^^^^^^ help: consider borrowing here: `&vrm[0]`
+ | ^^^^^^
...
LL | Either::One(_t)
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:149:11
+ --> $DIR/simple.rs:129:11
|
LL | match vrm[0] {
- | ^^^^^^ help: consider borrowing here: `&vrm[0]`
+ | ^^^^^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
error[E0507]: cannot move out of index of `Vec<Either>`
- --> $DIR/simple.rs:157:11
+ --> $DIR/simple.rs:136:11
|
LL | match vrm[0] {
- | ^^^^^^ help: consider borrowing here: `&vrm[0]`
+ | ^^^^^^
...
LL | Either::One(_t) => (),
| --
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | match &vrm[0] {
+ | +
error[E0507]: cannot move out of `s` which is behind a shared reference
- --> $DIR/simple.rs:168:18
+ --> $DIR/simple.rs:146:18
|
LL | let &X(_t) = s;
- | ------ ^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `X(_t)`
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &X(_t) = s;
+LL + let X(_t) = s;
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:172:31
+ --> $DIR/simple.rs:149:31
|
LL | if let &Either::One(_t) = r { }
- | ---------------- ^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let &Either::One(_t) = r { }
+LL + if let Either::One(_t) = r { }
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:176:34
+ --> $DIR/simple.rs:152:34
|
LL | while let &Either::One(_t) = r { }
- | ---------------- ^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | -- ^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - while let &Either::One(_t) = r { }
+LL + while let Either::One(_t) = r { }
+ |
error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference
- --> $DIR/simple.rs:180:11
+ --> $DIR/simple.rs:155:11
|
LL | match r {
| ^
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
-help: consider removing the `&`
+help: consider removing the borrow
|
-LL ~ Either::One(_t)
-LL +
-LL +
-LL ~ | &Either::Two(_t) => (),
+LL - &Either::One(_t)
+LL + Either::One(_t)
|
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:188:11
+ --> $DIR/simple.rs:162:11
|
LL | match r {
| ^
LL |
LL | &Either::One(_t) => (),
- | ----------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference
- --> $DIR/simple.rs:195:11
+ --> $DIR/simple.rs:168:11
|
LL | match r {
| ^
LL |
LL | &Either::One(_t) => (),
- | ----------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of `sm` which is behind a mutable reference
- --> $DIR/simple.rs:207:22
+ --> $DIR/simple.rs:178:22
|
LL | let &mut X(_t) = sm;
- | ---------- ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `X(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - let &mut X(_t) = sm;
+LL + let X(_t) = sm;
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:211:35
+ --> $DIR/simple.rs:181:35
|
LL | if let &mut Either::One(_t) = rm { }
- | -------------------- ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - if let &mut Either::One(_t) = rm { }
+LL + if let Either::One(_t) = rm { }
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:215:38
+ --> $DIR/simple.rs:184:38
|
LL | while let &mut Either::One(_t) = rm { }
- | -------------------- ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - while let &mut Either::One(_t) = rm { }
+LL + while let Either::One(_t) = rm { }
+ |
error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference
- --> $DIR/simple.rs:219:11
+ --> $DIR/simple.rs:187:11
|
LL | match rm {
| ^^
LL |
LL | &mut Either::One(_t) => (),
| -- data moved here
-...
+LL |
LL | &mut Either::Two(_t) => (),
| -- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
|
-LL | Either::One(_t) => (),
- | ~~~~~~~~~~~~~~~
-help: consider removing the `&mut`
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::Two(_t) => (),
+LL + Either::Two(_t) => (),
|
-LL | Either::Two(_t) => (),
- | ~~~~~~~~~~~~~~~
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:228:11
+ --> $DIR/simple.rs:194:11
|
LL | match rm {
| ^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:235:11
+ --> $DIR/simple.rs:200:11
|
LL | match rm {
| ^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference
- --> $DIR/simple.rs:242:11
+ --> $DIR/simple.rs:206:11
|
LL | match rm {
| ^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:258:21
+ --> $DIR/simple.rs:220:21
|
LL | let (&X(_t),) = (&x.clone(),);
| -- ^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let (&X(ref _t),) = (&x.clone(),);
+ | +++
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:260:34
+ --> $DIR/simple.rs:223:34
|
LL | if let (&Either::One(_t),) = (&e.clone(),) { }
| -- ^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | if let (&Either::One(ref _t),) = (&e.clone(),) { }
+ | +++
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:262:37
+ --> $DIR/simple.rs:226:37
|
LL | while let (&Either::One(_t),) = (&e.clone(),) { }
| -- ^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | while let (&Either::One(ref _t),) = (&e.clone(),) { }
+ | +++
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:264:11
+ --> $DIR/simple.rs:229:11
|
LL | match (&e.clone(),) {
| ^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (&Either::One(ref _t),)
+ | +++
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:272:25
+ --> $DIR/simple.rs:239:25
|
LL | let (&mut X(_t),) = (&mut xm.clone(),);
| -- ^^^^^^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let (&mut X(ref _t),) = (&mut xm.clone(),);
+ | +++
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:274:38
+ --> $DIR/simple.rs:242:38
|
LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
| -- ^^^^^^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+ | +++
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:276:41
+ --> $DIR/simple.rs:245:41
|
LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
| -- ^^^^^^^^^^^^^^^^^^
| |
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { }
+ | +++
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:278:11
+ --> $DIR/simple.rs:248:11
|
LL | match (&mut em.clone(),) {
| ^^^^^^^^^^^^^^^^^^
LL |
LL | (&mut Either::One(_t),) => (),
| -- data moved here
+LL |
LL | (&mut Either::Two(_t),) => (),
| -- ...and here
|
= note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider borrowing the pattern binding
+ |
+LL | (&mut Either::One(ref _t),) => (),
+ | +++
+help: consider borrowing the pattern binding
+ |
+LL | (&mut Either::Two(ref _t),) => (),
+ | +++
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:288:18
+ --> $DIR/simple.rs:261:18
|
LL | let &X(_t) = &x;
- | ------ ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `X(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - let &X(_t) = &x;
+LL + let X(_t) = &x;
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:292:31
+ --> $DIR/simple.rs:264:31
|
LL | if let &Either::One(_t) = &e { }
- | ---------------- ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - if let &Either::One(_t) = &e { }
+LL + if let Either::One(_t) = &e { }
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:296:34
+ --> $DIR/simple.rs:267:34
|
LL | while let &Either::One(_t) = &e { }
- | ---------------- ^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | -- ^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - while let &Either::One(_t) = &e { }
+LL + while let Either::One(_t) = &e { }
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:300:11
+ --> $DIR/simple.rs:270:11
|
LL | match &e {
| ^^
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
-help: consider removing the `&`
+help: consider removing the borrow
|
-LL ~ Either::One(_t)
-LL +
-LL +
-LL ~ | &Either::Two(_t) => (),
+LL - &Either::One(_t)
+LL + Either::One(_t)
|
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:308:11
+ --> $DIR/simple.rs:277:11
|
LL | match &e {
| ^^
LL |
LL | &Either::One(_t) => (),
- | ----------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:315:11
+ --> $DIR/simple.rs:283:11
|
LL | match &e {
| ^^
LL |
LL | &Either::One(_t) => (),
- | ----------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - &Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:323:22
+ --> $DIR/simple.rs:290:22
|
LL | let &mut X(_t) = &mut xm;
- | ---------- ^^^^^^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `X(_t)`
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - let &mut X(_t) = &mut xm;
+LL + let X(_t) = &mut xm;
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:327:35
+ --> $DIR/simple.rs:293:35
|
LL | if let &mut Either::One(_t) = &mut em { }
- | -------------------- ^^^^^^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - if let &mut Either::One(_t) = &mut em { }
+LL + if let Either::One(_t) = &mut em { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:331:38
+ --> $DIR/simple.rs:296:38
|
LL | while let &mut Either::One(_t) = &mut em { }
- | -------------------- ^^^^^^^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | -- ^^^^^^^
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - while let &mut Either::One(_t) = &mut em { }
+LL + while let Either::One(_t) = &mut em { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:335:11
+ --> $DIR/simple.rs:299:11
|
LL | match &mut em {
| ^^^^^^^
| data moved here
| move occurs because `_t` has type `X`, which does not implement the `Copy` trait
|
-help: consider removing the `&mut`
+help: consider removing the mutable borrow
|
-LL ~ Either::One(_t)
-LL +
-LL +
-LL ~ | &mut Either::Two(_t) => (),
+LL - &mut Either::One(_t)
+LL + Either::One(_t)
|
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:343:11
+ --> $DIR/simple.rs:306:11
|
LL | match &mut em {
| ^^^^^^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:350:11
+ --> $DIR/simple.rs:312:11
|
LL | match &mut em {
| ^^^^^^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:357:11
+ --> $DIR/simple.rs:318:11
|
LL | match &mut em {
| ^^^^^^^
LL |
LL | &mut Either::One(_t) => (),
- | --------------------
- | | |
- | | data moved here
- | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `Either::One(_t)`
+ | --
+ | |
+ | data moved here
+ | move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - &mut Either::One(_t) => (),
+LL + Either::One(_t) => (),
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:202:11
+ --> $DIR/simple.rs:174:11
|
LL | fn f1(&X(_t): &X) { }
| ^^^--^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&`: `X(_t)`
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the borrow
+ |
+LL - fn f1(&X(_t): &X) { }
+LL + fn f1(X(_t): &X) { }
+ |
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:249:11
+ --> $DIR/simple.rs:212:11
|
LL | fn f2(&mut X(_t): &mut X) { }
| ^^^^^^^--^
- | | |
- | | data moved here
- | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
- | help: consider removing the `&mut`: `X(_t)`
+ | |
+ | data moved here
+ | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider removing the mutable borrow
+ |
+LL - fn f2(&mut X(_t): &mut X) { }
+LL + fn f2(X(_t): &mut X) { }
+ |
error[E0507]: cannot move out of a shared reference
- --> $DIR/simple.rs:269:11
+ --> $DIR/simple.rs:235:11
|
LL | fn f3((&X(_t),): (&X,)) { }
| ^^^^--^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn f3((&X(ref _t),): (&X,)) { }
+ | +++
error[E0507]: cannot move out of a mutable reference
- --> $DIR/simple.rs:283:11
+ --> $DIR/simple.rs:255:11
|
LL | fn f4((&mut X(_t),): (&mut X,)) { }
| ^^^^^^^^--^^^
| |
| data moved here
| move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | fn f4((&mut X(ref _t),): (&mut X,)) { }
+ | +++
+
+error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference
+ --> $DIR/simple.rs:331:20
+ |
+LL | let Some(_s) = a.a else {
+ | -- ^^^
+ | |
+ | data moved here
+ | move occurs because `_s` has type `String`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | let Some(ref _s) = a.a else {
+ | +++
-error: aborting due to 60 previous errors
+error: aborting due to 61 previous errors
For more information about this error, try `rustc --explain E0507`.
--> $DIR/dont-suggest-try_into-in-macros.rs:2:5
|
LL | assert_eq!(10u64, 10usize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected `u64`, found `usize`
+ | expected because this is `u64`
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
found type parameter `F`
note: associated function defined here
--> $SRC_DIR/core/src/pin.rs:LL:COL
- |
-LL | pub const fn new(pointer: P) -> Pin<P> {
- | ^^^
error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
--> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
= note: consider using `Box::pin`
note: required by a bound in `Pin::<P>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL
- |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
- | ^^^^^ required by this bound in `Pin::<P>::new`
error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
--> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
= note: consider using `Box::pin`
note: required by a bound in `Pin::<P>::new`
--> $SRC_DIR/core/src/pin.rs:LL:COL
- |
-LL | impl<P: Deref<Target: Unpin>> Pin<P> {
- | ^^^^^ required by this bound in `Pin::<P>::new`
error[E0308]: mismatched types
--> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
note: function defined here
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
- | ^^^^^^^^^^^^^^^
help: you need to pin and box this expression
|
LL ~ Box::pin(async {
| `self.v` moved due to this implicit call to `.into_iter()`
| move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves `self.v`
+note: `into_iter` takes ownership of the receiver `self`, which moves `self.v`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
|
LL | for _ in &self.v {
| value moved due to this implicit call to `.into_iter()`
| move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves value
+note: `into_iter` takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
- |
-LL | fn into_iter(self) -> Self::IntoIter;
- | ^^^^
help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
|
LL | for loader in &*LOADERS {
|
LL | t.min().unwrap()
| ^^^
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
- ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
- |
-LL | Self: Sized,
- | ----- this has a `Sized` requirement
+ = note: this has a `Sized` requirement
|
= note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
|
LL | h.finish()
| ^^^^^^ method not found in `DefaultHasher`
+ --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
- |
-LL | fn finish(&self) -> u64;
- | ------ the method is available for `DefaultHasher` here
+ = note: the method is available for `DefaultHasher` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
| ^^^^^^^------ help: remove these generics
| |
| expected 0 generic arguments
- |
-note: associated function defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/ord.rs:LL:COL
- |
-LL | fn simd_gt(self, other: Self) -> Self::Mask;
- | ^^^^^^^
error[E0425]: cannot find function `simd_gt` in this scope
--> $DIR/issue-104287.rs:6:5
--- /dev/null
+trait Bar {}
+
+trait Foo {
+ fn f() {}
+}
+
+impl Foo for dyn Bar {}
+
+fn main() {
+ Foo::f();
+ //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
--- /dev/null
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/issue-104327.rs:10:5
+ |
+LL | fn f() {}
+ | --------- `Foo::f` defined here
+...
+LL | Foo::f();
+ | ^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | <(dyn Bar + 'static) as Foo>::f();
+ | +++++++++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
--- /dev/null
+#![feature(object_safe_for_dispatch)]
+
+trait Foo {
+ fn f() {}
+}
+
+impl Foo for dyn Sized {}
+
+fn main() {
+ Foo::f();
+ //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type
+}
--- /dev/null
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/issue-104328.rs:10:5
+ |
+LL | fn f() {}
+ | --------- `Foo::f` defined here
+...
+LL | Foo::f();
+ | ^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL | <(dyn Sized + 'static) as Foo>::f();
+ | +++++++++++++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
--- /dev/null
+use std::fmt;
+
+struct S {
+}
+
+impl S {
+ fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ //~^ ERROR non-item in item list
+ //~| ERROR associated function in `impl` without body
+ println!("val: {}", val);
+ }
+}
+
+impl S {
+ fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+ //~^ ERROR associated function in `impl` without body
+}
+
+fn main() {
+ let s = S{};
+ s.hello(&32);
+}
--- /dev/null
+error: non-item in item list
+ --> $DIR/issue-105226.rs:7:56
+ |
+LL | impl S {
+ | - item list starts here
+LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ | - ^ non-item starts here
+ | |
+ | help: consider removing this semicolon
+...
+LL | }
+ | - item list ends here
+
+error: associated function in `impl` without body
+ --> $DIR/issue-105226.rs:7:5
+ |
+LL | fn hello<P>(&self, val: &P) where P: fmt::Display; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+ | |
+ | help: provide a definition for the function: `{ <body> }`
+
+error: associated function in `impl` without body
+ --> $DIR/issue-105226.rs:15:5
+ |
+LL | fn hello_empty<P>(&self, val: &P) where P: fmt::Display;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+ | |
+ | help: provide a definition for the function: `{ <body> }`
+
+error: aborting due to 3 previous errors
+
= note: required for `String` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::find`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
- | ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::find`
help: consider borrowing here
|
LL | println!("{:?}", line.find(&pattern));
error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
- --> $DIR/issue-71394-no-from-impl.rs:3:20
+ --> $DIR/issue-71394-no-from-impl.rs:3:25
|
LL | let _: &[i8] = data.into();
- | ^^^^ ---- required by a bound introduced by this call
- | |
- | the trait `From<&[u8]>` is not implemented for `&[i8]`
+ | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
|
= help: the following other types implement trait `From<T>`:
<[T; LANES] as From<Simd<T, LANES>>>
LL | let _ = 42.into::<Option<_>>();
| ^^^^ expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
- |
-LL | fn into(self) -> T;
- | ^^^^
help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument
|
LL | let _ = Into::<Option<_>>::into(42);
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by a bound in `BufWriter::<W>::new`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
- |
-LL | impl<W: Write> BufWriter<W> {
- | ^^^^^ required by this bound in `BufWriter::<W>::new`
error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied
--> $DIR/mut-borrow-needed-by-trait.rs:17:14
= note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
note: required by a bound in `BufWriter`
--> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
- |
-LL | pub struct BufWriter<W: Write> {
- | ^^^^^ required by this bound in `BufWriter`
-error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn std::io::Write>`, but its trait bounds were not satisfied
+error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied
--> $DIR/mut-borrow-needed-by-trait.rs:21:5
|
LL | writeln!(fp, "hello world").unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn std::io::Write>` due to unsatisfied trait bounds
- |
- ::: $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL
|
-LL | pub struct BufWriter<W: Write> {
- | ------------------------------ doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
+ = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write`
|
= note: the following trait bounds were not satisfied:
`&dyn std::io::Write: std::io::Write`
| |
| data moved here
| move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing the pattern binding
+ |
+LL | (None, &ref c) => &c.unwrap(),
+ | +++
error: aborting due to previous error
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn unwrap(self) -> T {
- | ^^^^
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
--> $DIR/option-content-move.rs:27:20
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
|
-note: this function takes ownership of the receiver `self`, which moves `selection.1`
+note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub fn unwrap(self) -> T
- | ^^^^
error: aborting due to 2 previous errors
--> $DIR/option-to-bool.rs:4:16
|
LL | if true && x {}
- | ^ expected `bool`, found enum `Option`
+ | ---- ^ expected `bool`, found enum `Option`
+ | |
+ | expected because this is `bool`
|
= note: expected type `bool`
found enum `Option<i32>`
|
LL | struct Wrapper<T>(T);
| ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
-note: the following trait must be implemented
+note: the trait `Add` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Add<Rhs = Self> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn qux<T>(a: Wrapper<T>, b: T) -> T where Wrapper<T>: Add<T, Output = T> {
found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
note: associated function defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub const fn unwrap_or(self, default: T) -> T
- | ^^^^^^^^^
help: try calling `unwrap_or_else` instead
|
LL | let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
|
note: required by a bound in `BufReader::<R>::new`
--> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
- |
-LL | impl<R: Read> BufReader<R> {
- | ^^^^ required by this bound in `BufReader::<R>::new`
help: consider removing the leading `&`-reference
|
LL - let mut stream_reader = BufReader::new(&stream);
|
LL | stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed");
| ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds
+ --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
|
- ::: $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
- |
-LL | pub struct BufReader<R> {
- | ----------------------- doesn't satisfy `BufReader<&T>: BufRead`
+ = note: doesn't satisfy `BufReader<&T>: BufRead`
|
= note: the following trait bounds were not satisfied:
`&T: std::io::Read`
|
LL | let _i: i16 = 0_i32.try_into().unwrap();
| ^^^^^^^^ method not found in `i32`
+ --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
- ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
- |
-LL | fn try_into(self) -> Result<T, Self::Error>;
- | -------- the method is available for `i32` here
+ = note: the method is available for `i32` here
|
= help: items from traits can only be used if the trait is in scope
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
LL | let _: Vec<A:B> = A::B;
| ^^^ expected at least 1 generic argument
|
-note: struct defined here, with at least 1 generic parameter: `T`
- --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^^^ -
help: add missing generic argument
|
LL | let _: Vec<T, A:B> = A::B;
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
|
LL | let _: f64 = 0..10;
- | --- ^^^^^ expected `f64`, found struct `std::ops::Range`
+ | --- ^^^^^ expected `f64`, found struct `Range`
| |
| expected due to this
|
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
|
LL | let _: f64 = std::ops::Range { start: 0, end: 1 };
- | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `std::ops::Range`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
| |
| expected due to this
|
|
LL | struct Foo<T>(dyn SendEqAlias<T>);
| ^^^^^^^^^^^^^^ missing reference to `Rhs`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
|
- ::: $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
- | --------------------------------------- type parameter `Rhs` must be specified for this
+ = note: type parameter `Rhs` must be specified for this
|
= note: because of the default `Self` reference, type parameters must be specified on object types
|
LL | struct Bar<T>(dyn SendEqAlias<T>, T);
| ^^^^^^^^^^^^^^ missing reference to `Rhs`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
|
- ::: $SRC_DIR/core/src/cmp.rs:LL:COL
- |
-LL | pub trait PartialEq<Rhs: ?Sized = Self> {
- | --------------------------------------- type parameter `Rhs` must be specified for this
+ = note: type parameter `Rhs` must be specified for this
|
= note: because of the default `Self` reference, type parameters must be specified on object types
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
-LL | pub trait Eq: PartialEq<Self> {
- | ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
+ = note: the trait cannot be made into an object because it uses `Self` as a type parameter
error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
--> $DIR/object-fail.rs:9:17
impl Foo for IntoIter<i32> {
type Key = u32;
- //~^ ERROR expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+ //~^ ERROR expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
}
fn main() {}
-error[E0271]: expected `std::vec::IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
+error[E0271]: expected `IntoIter<i32>` to be an iterator that yields `u32`, but it yields `i32`
--> $DIR/assoc-type-in-superbad.rs:12:16
|
LL | type Key = u32;
|
LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/string.rs:LL:COL
- |
-LL | pub trait ToString {
- | ------------------ similarly named trait `ToString` defined here
+ = note: similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/string.rs:LL:COL
- |
-LL | pub trait ToString {
- | ------------------ similarly named trait `ToString` defined here
+ = note: similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/string.rs:LL:COL
- |
-LL | pub trait ToString {
- | ------------------ similarly named trait `ToString` defined here
+ = note: similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/string.rs:LL:COL
- |
-LL | pub trait ToString {
- | ------------------ similarly named trait `ToString` defined here
+ = note: similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
|
LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
| ^^^^^^ help: a trait with a similar name exists: `ToString`
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
|
- ::: $SRC_DIR/alloc/src/string.rs:LL:COL
- |
-LL | pub trait ToString {
- | ------------------ similarly named trait `ToString` defined here
+ = note: similarly named trait `ToString` defined here
error: aborting due to 6 previous errors
= help: the trait `Sized` is not implemented for `dyn Trait`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^ required by this bound in `Vec`
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/bad-sized.rs:4:37
= help: the trait `Sized` is not implemented for `dyn Trait`
note: required by a bound in `Vec::<T>::new`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | impl<T> Vec<T> {
- | ^ required by this bound in `Vec::<T>::new`
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/bad-sized.rs:4:37
= help: the trait `Sized` is not implemented for `dyn Trait`
note: required by a bound in `Vec`
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^ required by this bound in `Vec`
error: aborting due to 4 previous errors
|
= help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
= help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+ |
+LL | fn foo(_x: impl Foo + Send) {
+ | ++++
help: function arguments must have a statically known size, borrowed types always have a known size
|
LL | fn foo(_x: &Foo + Send) {
#![feature(rustc_attrs)]
#[rustc_must_implement_one_of(a, a)]
-//~^ Functions names are duplicated
+//~^ functions names are duplicated
trait Trait {
fn a() {}
}
#[rustc_must_implement_one_of(b, a, a, c, b, c)]
-//~^ Functions names are duplicated
-//~| Functions names are duplicated
-//~| Functions names are duplicated
+//~^ functions names are duplicated
+//~| functions names are duplicated
+//~| functions names are duplicated
trait Trait1 {
fn a() {}
fn b() {}
-error: Functions names are duplicated
+error: functions names are duplicated
--> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31
|
LL | #[rustc_must_implement_one_of(a, a)]
| ^ ^
|
- = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
-error: Functions names are duplicated
+error: functions names are duplicated
--> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34
|
LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
| ^ ^
|
- = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
-error: Functions names are duplicated
+error: functions names are duplicated
--> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31
|
LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
| ^ ^
|
- = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
-error: Functions names are duplicated
+error: functions names are duplicated
--> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40
|
LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
| ^ ^
|
- = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+ = note: all `#[rustc_must_implement_one_of]` arguments must be unique
error: aborting due to 4 previous errors
#![feature(rustc_attrs)]
#[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
-//~| Function not found in this trait
+//~^ function not found in this trait
+//~| function not found in this trait
trait Tr0 {}
#[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
+//~^ function not found in this trait
trait Tr1 {
fn a() {}
}
#[rustc_must_implement_one_of(A, B)]
trait Tr4 {
- const A: u8 = 1; //~ Not a function
+ const A: u8 = 1; //~ not a function
- type B; //~ Not a function
+ type B; //~ not a function
}
#[rustc_must_implement_one_of(a, b)]
trait Tr5 {
- fn a(); //~ This function doesn't have a default implementation
+ fn a(); //~ function doesn't have a default implementation
- fn b(); //~ This function doesn't have a default implementation
+ fn b(); //~ function doesn't have a default implementation
}
#[rustc_must_implement_one_of(abc, xyz)]
LL | struct Struct {}
| ---------------- not a trait
-error: Function not found in this trait
+error: function not found in this trait
--> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
|
LL | #[rustc_must_implement_one_of(a, b)]
| ^
-error: Function not found in this trait
+error: function not found in this trait
--> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
|
LL | #[rustc_must_implement_one_of(a, b)]
| ^
-error: Function not found in this trait
+error: function not found in this trait
--> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
|
LL | #[rustc_must_implement_one_of(a, b)]
LL | #[rustc_must_implement_one_of(a)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: Not a function
+error: not a function
--> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
|
LL | const A: u8 = 1;
|
LL | #[rustc_must_implement_one_of(A, B)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+ = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
-error: Not a function
+error: not a function
--> $DIR/rustc_must_implement_one_of_misuse.rs:28:5
|
LL | type B;
|
LL | #[rustc_must_implement_one_of(A, B)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+ = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
--> $DIR/rustc_must_implement_one_of_misuse.rs:33:5
|
LL | fn a();
LL | #[rustc_must_implement_one_of(a, b)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
--> $DIR/rustc_must_implement_one_of_misuse.rs:35:5
|
LL | fn b();
--- /dev/null
+trait A<T>: std::ops::Add<Self> + Sized {}
+trait B<T>: A<T> {}
+trait C<T>: A<dyn B<T, Output=usize>> {}
+//~^ ERROR the trait `B` cannot be made into an object
+
+fn main() {}
--- /dev/null
+error[E0038]: the trait `B` cannot be made into an object
+ --> $DIR/issue-38404.rs:3:15
+ |
+LL | trait C<T>: A<dyn B<T, Output=usize>> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38404.rs:1:13
+ |
+LL | trait A<T>: std::ops::Add<Self> + Sized {}
+ | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
+LL | trait B<T>: A<T> {}
+ | - this trait cannot be made into an object...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
--- /dev/null
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR `i32` is not an iterator
+
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR cannot find type `N` in this scope
+//~| ERROR `i32` is not an iterator
+
+fn main() {}
--- /dev/null
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:3:12
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -^ not found in this scope
+ | |
+ | help: you might be missing a type parameter: `<N>`
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:3:15
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:3:12
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -^ not found in this scope
+ | |
+ | help: you might be missing a type parameter: `<N>`
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:3:15
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | - ^^^^^^^^^^ not found in this scope
+ | |
+ | help: you might be missing a type parameter: `<NotDefined>`
+
+error[E0412]: cannot find type `N` in this scope
+ --> $DIR/issue-50480.rs:12:18
+ |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | - ^
+ | |
+ | similarly named type parameter `T` defined here
+ |
+help: a type parameter with a similar name exists
+ |
+LL | struct Bar<T>(T, T, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ~
+help: you might be missing a type parameter
+ |
+LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | +++
+
+error[E0412]: cannot find type `NotDefined` in this scope
+ --> $DIR/issue-50480.rs:12:21
+ |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^ not found in this scope
+
+error[E0277]: `i32` is not an iterator
+ --> $DIR/issue-50480.rs:3:27
+ |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `i32`
+ = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/issue-50480.rs:1:17
+ |
+LL | #[derive(Clone, Copy)]
+ | ^^^^
+LL |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -------- ------ this field does not implement `Copy`
+ | |
+ | this field does not implement `Copy`
+ |
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `i32` is not an iterator
+ --> $DIR/issue-50480.rs:12:33
+ |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `i32`
+ = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/issue-50480.rs:10:17
+ |
+LL | #[derive(Clone, Copy)]
+ | ^^^^
+LL |
+LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+ | -------- ------ this field does not implement `Copy`
+ | |
+ | this field does not implement `Copy`
+ |
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0204, E0277, E0412.
+For more information about an error, try `rustc --explain E0204`.
where T: ?Sized;
note: required by a bound in `HashMap::<K, V, S>::get`
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
- |
-LL | K: Borrow<Q>,
- | ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
help: consider specifying the generic argument
|
LL | opts.get::<Q>(opt.as_ref());
| |
| required by a bound introduced by this call
|
- = note: cannot satisfy `u32: From<_>`
+ = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+ - impl From<Ipv4Addr> for u32;
+ - impl From<NonZeroU32> for u32;
+ - impl From<bool> for u32;
+ - impl From<char> for u32;
+ - impl From<u16> for u32;
+ - impl From<u8> for u32;
+ - impl<T> From<!> for T;
+ - impl<T> From<T> for T;
help: try using a fully qualified path to specify the expected types
|
LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
LL | T: FnMut(&'a ()),
| ^^^^^^^^^^^^^
|
- = note: cannot satisfy `T: FnMut<(&'a (),)>`
+note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found
+ --> $DIR/issue-85735.rs:7:8
+ |
+LL | T: FnMut(&'a ()),
+ | ^^^^^^^^^^^^^
+LL |
+LL | T: FnMut(&'b ()),
+ | ^^^^^^^^^^^^^
error: aborting due to previous error
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
= note: required for `std::iter::Empty<()>` to implement `Iterator`
= note: 171 redundant requirements hidden
- = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+ = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
= note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
error: aborting due to previous error; 1 warning emitted
error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
- --> $DIR/issue-97576.rs:8:18
+ --> $DIR/issue-97576.rs:8:22
|
LL | bar: bar.into(),
- | ^^^ ---- required by a bound introduced by this call
- | |
- | the trait `From<impl ToString>` is not implemented for `String`
+ | ^^^^ the trait `From<impl ToString>` is not implemented for `String`
|
= note: required for `impl ToString` to implement `Into<String>`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`)
note: required by a bound in `Option`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub enum Option<T> {
- | ^ required by this bound in `Option`
error: aborting due to previous error
--- /dev/null
+// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333
+
+trait Animal<X>: 'static {}
+
+fn foo<Y, X>()
+where
+ Y: Animal<X> + ?Sized,
+{
+ // `Y` implements `Animal<X>` so `Y` is 'static.
+ baz::<Y>()
+}
+
+fn bar<'a>(_arg: &'a i32) {
+ foo::<dyn Animal<&'a i32>, &'a i32>() //~ ERROR: lifetime may not live long enough
+}
+
+fn baz<T: 'static + ?Sized>() {}
+
+fn main() {
+ let a = 5;
+ bar(&a);
+}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/issue-44454-1.rs:14:5
+ |
+LL | fn bar<'a>(_arg: &'a i32) {
+ | -- lifetime `'a` defined here
+LL | foo::<dyn Animal<&'a i32>, &'a i32>()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
--- /dev/null
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928
+
+trait Trait<ARG: 'static>: 'static {
+ type Assoc: AsRef<str>;
+}
+
+fn hr<T: ?Sized, ARG>(x: T::Assoc) -> Box<dyn AsRef<str> + 'static>
+where
+ T: Trait<ARG>
+{
+ Box::new(x)
+}
+
+fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+ type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+ hr::<DynTrait, _>(x) //~ ERROR: borrowed data escapes outside of function
+}
+
+fn main() {
+ let extended = extend_lt(&String::from("hello"));
+ println!("{}", extended.as_ref().as_ref());
+}
--- /dev/null
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/issue-44454-2.rs:16:5
+ |
+LL | fn extend_lt<'a>(x: &'a str) -> Box<dyn AsRef<str> + 'static> {
+ | -- - `x` is a reference that is only valid in the function body
+ | |
+ | lifetime `'a` defined here
+LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>;
+LL | hr::<DynTrait, _>(x)
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `x` escapes the function body here
+ | argument requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
--- /dev/null
+// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290
+
+use std::any::Any;
+
+trait Animal<X>: 'static {}
+
+trait Projector {
+ type Foo;
+}
+
+impl<X> Projector for dyn Animal<X> {
+ type Foo = X;
+}
+
+fn make_static<'a, T>(t: &'a T) -> &'static T {
+ let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+ let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+ //~^ ERROR: lifetime may not live long enough
+ any.downcast_ref::<&'static T>().unwrap()
+}
+
+fn generic<T: Projector + Animal<U> + ?Sized, U>(x: <T as Projector>::Foo) -> Box<dyn Any> {
+ make_static_any(x)
+}
+
+fn make_static_any<U: 'static>(u: U) -> Box<dyn Any> {
+ Box::new(u)
+}
+
+fn main() {
+ let a = make_static(&"salut".to_string());
+ println!("{}", *a);
+}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/issue-44454-3.rs:17:15
+ |
+LL | fn make_static<'a, T>(t: &'a T) -> &'static T {
+ | -- lifetime `'a` defined here
+LL | let x: <dyn Animal<&'a T> as Projector>::Foo = t;
+LL | let any = generic::<dyn Animal<&'a T>, &'a T>(x);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
|
help: use the fully-qualified path to the only available implementation
|
-LL | let _f: base::Foo = base::<Foo as HasNew>::new();
- | +++++++ +
+LL | let _f: base::Foo = <Foo as base::HasNew>::new();
+ | +++++++ +
error: aborting due to previous error
= note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
note: required by a bound in `TcpListener::bind`
--> $SRC_DIR/std/src/net/tcp.rs:LL:COL
- |
-LL | pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
- | ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
help: consider dereferencing here
|
LL | let _errors = TcpListener::bind(&*bad);
= note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
- |
-LL | pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
- | ^^^^^^^^^^^ required by this bound in `core::str::<impl str>::contains`
help: consider dereferencing here
|
LL | .filter(|c| "aeiou".contains(*c))
--- /dev/null
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+ fn from(_unchecked: usize) -> Self {
+ TargetStruct
+ }
+}
+
+fn main() {
+ let a = &3;
+ let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
--- /dev/null
+// run-rustfix
+
+struct TargetStruct;
+
+impl From<usize> for TargetStruct {
+ fn from(_unchecked: usize) -> Self {
+ TargetStruct
+ }
+}
+
+fn main() {
+ let a = &3;
+ let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+}
--- /dev/null
+error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied
+ --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30
+ |
+LL | let _b: TargetStruct = a.into();
+ | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`
+ |
+ = note: required for `&{integer}` to implement `Into<TargetStruct>`
+help: consider dereferencing here
+ |
+LL | let _b: TargetStruct = (*a).into();
+ | ++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
|
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn check<T: Iterator, U: ?Sized>() {
| ^^^^
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn check<T: Iterator, U: ?Sized>() {
= help: the trait `Sized` is not implemented for `[T]`
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
error[E0277]: the size for values of type `[&U]` cannot be known at compilation time
--> $DIR/suggest-where-clause.rs:31:20
= help: the trait `Sized` is not implemented for `[&U]`
note: required by a bound in `std::mem::size_of`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub const fn size_of<T>() -> usize {
- | ^ required by this bound in `std::mem::size_of`
error: aborting due to 7 previous errors
LL | | ASSUME_VALIDITY,
LL | | ASSUME_VISIBILITY,
| |_____________________________- help: remove these generic arguments
- |
-note: trait defined here, with at most 3 generic parameters: `Src`, `Context`, `ASSUME`
- --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
- |
-LL | pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
- | ^^^^^^^^^^^^^^^^^^^^^ --- ------- ------------------------------------------
error: aborting due to previous error
found struct `Vec<String>`
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub fn push(&mut self, value: T) {
- | ^^^^
help: remove the extra argument
|
LL | groups.push(/* (Vec<String>, Vec<Process>) */);
|
note: associated function defined here
--> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
- |
-LL | pub fn push_back(&mut self, value: T) {
- | ^^^^^^^^^
help: wrap these arguments in parentheses to construct a tuple
|
LL | self.acc.push_back((self.current_provides, self.current_requires));
|
help: consider giving this closure parameter an explicit type
|
-LL | |x: _| x.len()
- | +++
+LL | |x: /* Type */| x.len()
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/closures_in_branches.rs:21:10
|
help: consider giving this closure parameter an explicit type
|
-LL | |x: _| x.len()
- | +++
+LL | |x: /* Type */| x.len()
+ | ++++++++++++
error: aborting due to 2 previous errors
impl Foo for () {
type Bar = std::vec::IntoIter<u32>;
- //~^ ERROR expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+ //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
}
fn incoherent() {
-error[E0271]: expected `std::vec::IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
+error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
--> $DIR/issue-57961.rs:10:16
|
LL | type X = impl Sized;
--- /dev/null
+// check-pass
+
+#![warn(unused)]
+
+type Z = dyn for<'x> Send;
+//~^ WARN type alias `Z` is never used
+
+fn main() {}
--- /dev/null
+warning: type alias `Z` is never used
+ --> $DIR/issue-37515.rs:5:6
+ |
+LL | type Z = dyn for<'x> Send;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-37515.rs:3:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
+
+warning: 1 warning emitted
+
LL | input_cells: Vec::new()
| ^^^ expected at least 1 generic argument
|
-note: struct defined here, with at least 1 generic parameter: `T`
- --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
- | ^^^ -
help: add missing generic argument
|
LL | input_cells: Vec<T>::new()
|
LL | fn foo<T: Into<String>>(x: i32) {}
| ^^^^^^^^^^^^ required by this bound in `foo`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
|
LL | foo::<T>(42);
| +++++
|
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | pub fn with_capacity(capacity: usize) -> Self {
- | ^^^^^^^^^^^^^
help: remove the extra argument
|
LL | let x: Vec::with_capacity(10);
|
LL | struct Z;
| ^^^^^^^^ must implement `std::ops::Neg`
-note: the following trait must be implemented
+note: the trait `std::ops::Neg` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | pub trait Neg {
- | ^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:45:5
--> $DIR/type-ascription-precedence.rs:53:5
|
LL | (S .. S): S;
- | ^^^^^^^^ expected struct `S`, found struct `std::ops::Range`
+ | ^^^^^^^^ expected struct `S`, found struct `Range`
|
= note: expected struct `S`
found struct `std::ops::Range<S>`
--> $DIR/assignment-in-if.rs:44:18
|
LL | if x == x && x = x && x == x {
- | ^ expected `bool`, found `usize`
+ | ------ ^ expected `bool`, found `usize`
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:44:22
--> $DIR/assignment-in-if.rs:51:28
|
LL | if x == x && x == x && x = x {
- | ^ expected `bool`, found `usize`
+ | ---------------- ^ expected `bool`, found `usize`
+ | |
+ | expected because this is `bool`
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:51:8
LL | where &'a T : Foo,
| ^^^
|
- = note: cannot satisfy `&'a T: Foo`
+note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found
+ --> $DIR/issue-40294.rs:6:19
+ |
+LL | where &'a T : Foo,
+ | ^^^
+LL | &'b T : Foo
+ | ^^^
error: aborting due to previous error
|
help: consider giving this closure parameter an explicit type
|
-LL | let x = |_: _| {};
- | +++
+LL | let x = |_: /* Type */| {};
+ | ++++++++++++
error[E0282]: type annotations needed
--> $DIR/unknown_type_for_closure.rs:10:14
LL | fn broken_add<T>(&self, rhs: T) -> Self {
| - found type parameter
LL | *self + rhs
- | ^^^ expected type parameter `Self`, found type parameter `T`
+ | ----- ^^^ expected type parameter `Self`, found type parameter `T`
+ | |
+ | expected because this is `Self`
|
= note: expected type parameter `Self`
found type parameter `T`
|
help: consider giving this closure parameter an explicit type
|
-LL | let _ = |a: _, b: _| -> _ { 0 };
- | +++
+LL | let _ = |a: /* Type */, b: _| -> _ { 0 };
+ | ++++++++++++
error: aborting due to 5 previous errors
error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((..., ..., ...), ..., ...), ..., ...), ..., ...)>>`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
-LL | pub fn drop<T>(_x: T) {}
- | ^^^^^^^^^^^^^^^^^^^^^
- |
= help: consider adding a `#![type_length_limit="10"]` attribute to your crate
= note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
|
LL | nc.clone()
| ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+ |
+LL | #[derive(Clone)]
+ |
error: aborting due to previous error
--- /dev/null
+fn main(){
+ let my_var: String(String?);
+ //~^ ERROR: invalid `?` in type
+ //~| ERROR: parenthesized type parameters may only be used with a `Fn` trait
+}
--- /dev/null
+error: invalid `?` in type
+ --> $DIR/issue-104582.rs:2:30
+ |
+LL | let my_var: String(String?);
+ | ^ `?` is only allowed on expressions, not types
+ |
+help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
+ |
+LL | let my_var: String(Option<String>);
+ | +++++++ ~
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/issue-104582.rs:2:17
+ |
+LL | let my_var: String(String?);
+ | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses
+ |
+help: use angle brackets instead
+ |
+LL | let my_var: String<String?>;
+ | ~ ~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0214`.
| - this type parameter - expected `I` because of return type
...
LL | self.iter()
- | ^^^^^^^^^^^ expected type parameter `I`, found struct `std::slice::Iter`
+ | ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter`
|
= note: expected type parameter `I`
found struct `std::slice::Iter<'_, N>`
--- /dev/null
+fn main() {
+ let baz = ().foo(); //~ ERROR no method named `foo` found
+ <i32 as std::str::FromStr>::from_str(&baz); // No complaints about `str` being unsized
+}
--- /dev/null
+error[E0599]: no method named `foo` found for unit type `()` in the current scope
+ --> $DIR/issue-33575.rs:2:18
+ |
+LL | let baz = ().foo();
+ | ^^^ method not found in `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
found unit type `()`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
help: try wrapping the expression in `Some`
|
LL | fn main() { test(Ok(Some(()))); }
| |
| expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic argument
|
LL | pub fn run() -> Result<_, E> {
| |
| expected 2 generic arguments
|
-note: enum defined here, with 2 generic parameters: `T`, `E`
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | pub enum Result<T, E> {
- | ^^^^^^ - -
help: add missing generic argument
|
LL | pub fn interact(&mut self) -> Result<_, E> {
|
LL | impl F {
| ^ help: a trait with a similar name exists: `Fn`
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
- ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | -------------------------------------- similarly named trait `Fn` defined here
+ = note: similarly named trait `Fn` defined here
error[E0412]: cannot find type `TestResult` in this scope
--> $DIR/issue-83693.rs:9:22
found type `{integer}`
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
- | ^^^^^^^^^
error: aborting due to 2 previous errors
--- /dev/null
+//check-fail
+
+#![crate_type="lib"]
+
+fn r({) {
+ Ok { //~ ERROR mismatched types [E0308]
+ d..||_=m
+ }
+}
+//~^^^^^ ERROR expected parameter name, found `{`
+//~| ERROR expected one of `,`, `:`, or `}`, found `..`
+//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
+//~| ERROR cannot find value `m` in this scope [E0425]
+//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
--- /dev/null
+error: expected parameter name, found `{`
+ --> $DIR/issue-92481.rs:5:6
+ |
+LL | fn r({) {
+ | ^ expected parameter name
+
+error: expected one of `,`, `:`, or `}`, found `..`
+ --> $DIR/issue-92481.rs:5:6
+ |
+LL | fn r({) {
+ | ^ unclosed delimiter
+LL | Ok {
+LL | d..||_=m
+ | -^
+ | |
+ | help: `}` may belong here
+
+error[E0425]: cannot find value `d` in this scope
+ --> $DIR/issue-92481.rs:7:9
+ |
+LL | d..||_=m
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `m` in this scope
+ --> $DIR/issue-92481.rs:7:16
+ |
+LL | d..||_=m
+ | ^ not found in this scope
+
+error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
+ --> $DIR/issue-92481.rs:7:9
+ |
+LL | d..||_=m
+ | ^ field does not exist
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+ = note: `Result<_, _>::Ok` defined here
+ |
+help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
+ |
+LL | Result<_, _>::Ok(/* fields */)
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/issue-92481.rs:6:5
+ |
+LL | fn r({) {
+ | - help: a return type might be missing here: `-> _`
+LL | / Ok {
+LL | | d..||_=m
+LL | | }
+ | |_____^ expected `()`, found enum `Result`
+ |
+ = note: expected unit type `()`
+ found enum `Result<_, _>`
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0559.
+For more information about an error, try `rustc --explain E0308`.
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^^^
help: remove the extra argument
|
LL | let _ = Some(3);
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
help: remove the extra arguments
|
LL | let _ = Ok(3);
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
- |
-LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
- | ^^
help: provide the argument
|
LL | let _ = Ok(/* value */);
| ^^^^--- help: remove these generics
| |
| expected 0 generic arguments
- |
-note: trait defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
| ^^^^---------- help: remove these generics
| |
| expected 0 generic arguments
- |
-note: trait defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
| ^^^^--- help: remove these generics
| |
| expected 0 generic arguments
- |
-note: trait defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
| ^^^^---- help: remove these generics
| |
| expected 0 lifetime arguments
- |
-note: trait defined here, with 0 lifetime parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
| ^^^^ -- help: remove this lifetime argument
| |
| expected 0 lifetime arguments
- |
-note: trait defined here, with 0 lifetime parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
| ^^^^ - help: remove this generic argument
| |
| expected 0 generic arguments
- |
-note: trait defined here, with 0 generic parameters
- --> $SRC_DIR/core/src/marker.rs:LL:COL
- |
-LL | pub trait Copy: Clone {
- | ^^^^
error: aborting due to 6 previous errors
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^
help: change the type of the numeric literal from `u32` to `i32`
|
LL | <i32 as Add<i32>>::add(1i32, 2);
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
- |
-LL | fn add(self, rhs: Rhs) -> Self::Output;
- | ^^^
help: change the type of the numeric literal from `u32` to `i32`
|
LL | <i32 as Add<i32>>::add(1, 2i32);
|
note: required by a bound in `Fn`
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
- |
-LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
- | ^^^^^ required by this bound in `Fn`
error: aborting due to previous error
-error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
--> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
|
LL | mut_.call((0, ));
- | ^^^^ method not found in `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]`
+ | ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]`
error: aborting due to previous error
|
note: `Result<u32, &Void>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
|
-LL | pub enum Result<T, E> {
- | ---------------------
-...
-LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
- | ^^^ not covered
+ = note: not covered
= note: the matched value is of type `Result<u32, &Void>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
|
note: `Result<u32, Void>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
|
-LL | pub enum Result<T, E> {
- | ---------------------
-...
-LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
- | ^^^ not covered
+ = note: not covered
= note: the matched value is of type `Result<u32, Void>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Result<u32, Void>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
|
-LL | pub enum Result<T, E> {
- | ---------------------
-...
-LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
- | ^^^ not covered
+ = note: not covered
= note: the matched value is of type `Result<u32, Void>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
--> $DIR/union-borrow-move-parent-sibling.rs:62:13
|
LL | let a = u.x.0;
- | ^^^^^
- | |
- | move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&u.x.0`
+ | ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let a = &u.x.0;
+ | +
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:64:13
--> $DIR/union-borrow-move-parent-sibling.rs:76:13
|
LL | let a = (u.x.0).0;
- | ^^^^^^^^^
- | |
- | move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&(u.x.0).0`
+ | ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let a = &(u.x.0).0;
+ | +
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:78:13
--> $DIR/union-borrow-move-parent-sibling.rs:62:13
|
LL | let a = u.x.0;
- | ^^^^^
- | |
- | move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&u.x.0`
+ | ^^^^^ move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let a = &u.x.0;
+ | +
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:64:13
--> $DIR/union-borrow-move-parent-sibling.rs:76:13
|
LL | let a = (u.x.0).0;
- | ^^^^^^^^^
- | |
- | move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
- | help: consider borrowing here: `&(u.x.0).0`
+ | ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
+ |
+help: consider borrowing here
+ |
+LL | let a = &(u.x.0).0;
+ | +
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:78:13
|
note: required by a bound in `AssertParamIsCopy`
--> $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)
help: consider annotating `U1` with `#[derive(Copy)]`
|
|
note: required by a bound in `AssertParamIsCopy`
--> $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)
help: consider annotating `U1` with `#[derive(Copy)]`
|
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
|
|
note: required by a bound in `AssertParamIsEq`
--> $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)
help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
|
...
LL | let _z = y.clone();
| ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
- |
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
-LL | / pub struct Box<
-LL | | T: ?Sized,
-LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
- | |_- doesn't satisfy `Box<dyn Foo>: Clone`
+ = note: doesn't satisfy `Box<dyn Foo>: Clone`
|
= note: the following trait bounds were not satisfied:
`dyn Foo: Sized`
...
LL | let _j = i.clone();
| ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
- |
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
-LL | / pub struct Box<
-LL | | T: ?Sized,
-LL | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
-LL | | >(Unique<T>, A);
- | |_- doesn't satisfy `Box<R>: Clone`
+ = note: doesn't satisfy `Box<R>: Clone`
|
= note: the following trait bounds were not satisfied:
`R: Clone`
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn not(self) -> Self::Output;
- | ^^^^
help: consider cloning the value if the performance cost is acceptable
|
LL | !x.clone();
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
- |
-LL | fn not(self) -> Self::Output;
- | ^^^^
error[E0507]: cannot move out of `*n` which is behind a shared reference
--> $DIR/unop-move-semantics.rs:26:6
LL | println!("{}", &y);
| ^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
--> $DIR/borrow-after-move.rs:5:12
|
LL | fn foo(self) -> String;
LL | y.foo();
| ^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `y`
+note: `Foo::foo` takes ownership of the receiver `self`, which moves `y`
--> $DIR/double-move.rs:5:12
|
LL | fn foo(self) -> String;
error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
- --> $DIR/issue-71659.rs:30:13
+ --> $DIR/issue-71659.rs:30:15
|
LL | let x = x.cast::<[i32]>();
- | ^ ---- required by a bound introduced by this call
- | |
- | the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+ | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
|
note: required by a bound in `Cast::cast`
--> $DIR/issue-71659.rs:19:15
LL | return self.x;
| ^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
--> $DIR/use-after-move-self-based-on-type.rs:15:16
|
LL | pub fn bar(self) {}
LL | return *self.x;
| ^^^^^^^ value used here after move
|
-note: this function takes ownership of the receiver `self`, which moves `self`
+note: `S::bar` takes ownership of the receiver `self`, which moves `self`
--> $DIR/use-after-move-self.rs:13:16
|
LL | pub fn bar(self) {}
LL | println!("{}", start.test);
| ^^^^^^^^^^ value borrowed here after move
|
-note: this function takes ownership of the receiver `self`, which moves `start`
+note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start`
--> $DIR/walk-struct-literal-with.rs:7:28
|
LL | fn make_string_bar(mut self) -> Mine{
--- /dev/null
+// incremental
+
+trait Foo {
+ type V;
+}
+
+trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {}
+
+struct Bar<'a, T> {
+ callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+ //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied
+ //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+ //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+}
+
+impl<T: Foo> Bar<'_, Bar<'_, T>> {}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied
+ --> $DIR/hir-wf-canonicalized.rs:10:15
+ |
+LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>`
+
+error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
+ --> $DIR/hir-wf-canonicalized.rs:10:15
+ |
+LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+
+error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
+ --> $DIR/hir-wf-canonicalized.rs:10:15
+ |
+LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
+note: required by a bound in `Bar`
+ --> $DIR/hir-wf-canonicalized.rs:9:16
+ |
+LL | struct Bar<'a, T> {
+ | ^ required by this bound in `Bar`
+help: consider relaxing the implicit `Sized` restriction
+ |
+LL | struct Bar<'a, T: ?Sized> {
+ | ++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
= note: required for `&T` to implement `IntoIterator`
note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
- |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
- | ^^^^^^^^^^^^ required by this bound in `Flatten`
error[E0277]: `&T` is not an iterator
--> $DIR/hir-wf-check-erase-regions.rs:10:27
= note: required for `&T` to implement `IntoIterator`
note: required by a bound in `Flatten`
--> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
- |
-LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
- | ^^^^^^^^^^^^ required by this bound in `Flatten`
error: aborting due to 2 previous errors
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `Option`
--> $SRC_DIR/core/src/option.rs:LL:COL
- |
-LL | pub enum Option<T> {
- | ^ required by this bound in `Option`
error: aborting due to previous error
--> $DIR/wrong-mul-method-signature.rs:63:45
|
LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
- | ^^^ expected struct `Vec2`, found floating-point number
+ | ----------------------- ^^^ expected struct `Vec2`, found floating-point number
+ | |
+ | expected because this is `Vec2`
error[E0308]: mismatched types
--> $DIR/wrong-mul-method-signature.rs:63:19
-Subproject commit f6e737b1e3386adb89333bf06a01f68a91ac5306
+Subproject commit cc0a320879c17207bbfb96b5d778e28a2c62030d
with:
github_token: "${{ secrets.github_token }}"
- - name: Install dependencies (Linux-i686)
- run: |
- sudo dpkg --add-architecture i386
- sudo apt-get update
- sudo apt-get install gcc-multilib libssl-dev:i386 libgit2-dev:i386
- if: matrix.host == 'i686-unknown-linux-gnu'
-
- name: Checkout
uses: actions/checkout@v3.0.2
## Unreleased / Beta / In Rust Nightly
-[b52fb523...master](https://github.com/rust-lang/rust-clippy/compare/b52fb523...master)
+[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
+
+## Rust 1.66
+
+Current stable, released 2022-12-15
+
+[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
+
+### New Lints
+
+* [`manual_clamp`]
+ [#9484](https://github.com/rust-lang/rust-clippy/pull/9484)
+* [`missing_trait_methods`]
+ [#9670](https://github.com/rust-lang/rust-clippy/pull/9670)
+* [`unused_format_specs`]
+ [#9637](https://github.com/rust-lang/rust-clippy/pull/9637)
+* [`iter_kv_map`]
+ [#9409](https://github.com/rust-lang/rust-clippy/pull/9409)
+* [`manual_filter`]
+ [#9451](https://github.com/rust-lang/rust-clippy/pull/9451)
+* [`box_default`]
+ [#9511](https://github.com/rust-lang/rust-clippy/pull/9511)
+* [`implicit_saturating_add`]
+ [#9549](https://github.com/rust-lang/rust-clippy/pull/9549)
+* [`as_ptr_cast_mut`]
+ [#9572](https://github.com/rust-lang/rust-clippy/pull/9572)
+* [`disallowed_macros`]
+ [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`partial_pub_fields`]
+ [#9658](https://github.com/rust-lang/rust-clippy/pull/9658)
+* [`uninlined_format_args`]
+ [#9233](https://github.com/rust-lang/rust-clippy/pull/9233)
+* [`cast_nan_to_int`]
+ [#9617](https://github.com/rust-lang/rust-clippy/pull/9617)
+
+### Moves and Deprecations
+
+* `positional_named_format_parameters` was uplifted to rustc under the new name
+ `named_arguments_used_positionally`
+ [#8518](https://github.com/rust-lang/rust-clippy/pull/8518)
+* Moved [`implicit_saturating_sub`] to `style` (Now warn-by-default)
+ [#9584](https://github.com/rust-lang/rust-clippy/pull/9584)
+* Moved `derive_partial_eq_without_eq` to `nursery` (now allow-by-default)
+ [#9536](https://github.com/rust-lang/rust-clippy/pull/9536)
+
+### Enhancements
+
+* [`nonstandard_macro_braces`]: Now includes `matches!()` in the default lint config
+ [#9471](https://github.com/rust-lang/rust-clippy/pull/9471)
+* [`suboptimal_flops`]: Now supports multiplication and subtraction operations
+ [#9581](https://github.com/rust-lang/rust-clippy/pull/9581)
+* [`arithmetic_side_effects`]: Now detects cases with literals behind references
+ [#9587](https://github.com/rust-lang/rust-clippy/pull/9587)
+* [`upper_case_acronyms`]: Now also checks enum names
+ [#9580](https://github.com/rust-lang/rust-clippy/pull/9580)
+* [`needless_borrowed_reference`]: Now lints nested patterns
+ [#9573](https://github.com/rust-lang/rust-clippy/pull/9573)
+* [`unnecessary_cast`]: Now works for non-trivial non-literal expressions
+ [#9576](https://github.com/rust-lang/rust-clippy/pull/9576)
+* [`arithmetic_side_effects`]: Now detects operations with custom types
+ [#9559](https://github.com/rust-lang/rust-clippy/pull/9559)
+* [`disallowed_methods`], [`disallowed_types`]: Not correctly lints types, functions and macros
+ with the same path
+ [#9495](https://github.com/rust-lang/rust-clippy/pull/9495)
+* [`self_named_module_files`], [`mod_module_files`]: Now take remapped path prefixes into account
+ [#9475](https://github.com/rust-lang/rust-clippy/pull/9475)
+* [`bool_to_int_with_if`]: Now detects the inverse if case
+ [#9476](https://github.com/rust-lang/rust-clippy/pull/9476)
+
+### False Positive Fixes
+
+* [`arithmetic_side_effects`]: Now allows operations that can't overflow
+ [#9474](https://github.com/rust-lang/rust-clippy/pull/9474)
+* [`unnecessary_lazy_evaluations`]: No longer lints in external macros
+ [#9486](https://github.com/rust-lang/rust-clippy/pull/9486)
+* [`needless_borrow`], [`explicit_auto_deref`]: No longer lint on unions that require the reference
+ [#9490](https://github.com/rust-lang/rust-clippy/pull/9490)
+* [`almost_complete_letter_range`]: No longer lints in external macros
+ [#9467](https://github.com/rust-lang/rust-clippy/pull/9467)
+* [`drop_copy`]: No longer lints on idiomatic cases in match arms
+ [#9491](https://github.com/rust-lang/rust-clippy/pull/9491)
+* [`question_mark`]: No longer lints in const context
+ [#9487](https://github.com/rust-lang/rust-clippy/pull/9487)
+* [`collapsible_if`]: Suggestion now work in macros
+ [#9410](https://github.com/rust-lang/rust-clippy/pull/9410)
+* [`std_instead_of_core`]: No longer triggers on unstable modules
+ [#9545](https://github.com/rust-lang/rust-clippy/pull/9545)
+* [`unused_peekable`]: No longer lints, if the peak is done in a closure or function
+ [#9465](https://github.com/rust-lang/rust-clippy/pull/9465)
+* [`useless_attribute`]: No longer lints on `#[allow]` attributes for [`unsafe_removed_from_name`]
+ [#9593](https://github.com/rust-lang/rust-clippy/pull/9593)
+* [`unnecessary_lazy_evaluations`]: No longer suggest switching to early evaluation when type has
+ custom `Drop` implementation
+ [#9551](https://github.com/rust-lang/rust-clippy/pull/9551)
+* [`unnecessary_cast`]: No longer lints on negative hexadecimal literals when cast as floats
+ [#9609](https://github.com/rust-lang/rust-clippy/pull/9609)
+* [`use_self`]: No longer lints in proc macros
+ [#9454](https://github.com/rust-lang/rust-clippy/pull/9454)
+* [`never_loop`]: Now takes `let ... else` statements into consideration.
+ [#9496](https://github.com/rust-lang/rust-clippy/pull/9496)
+* [`default_numeric_fallback`]: Now ignores constants
+ [#9636](https://github.com/rust-lang/rust-clippy/pull/9636)
+* [`uninit_vec`]: No longer lints `Vec::set_len(0)`
+ [#9519](https://github.com/rust-lang/rust-clippy/pull/9519)
+* [`arithmetic_side_effects`]: Now ignores references to integer types
+ [#9507](https://github.com/rust-lang/rust-clippy/pull/9507)
+* [`large_stack_arrays`]: No longer lints inside static items
+ [#9466](https://github.com/rust-lang/rust-clippy/pull/9466)
+* [`ref_option_ref`]: No longer lints if the inner reference is mutable
+ [#9684](https://github.com/rust-lang/rust-clippy/pull/9684)
+* [`ptr_arg`]: No longer lints if the argument is used as an incomplete trait object
+ [#9645](https://github.com/rust-lang/rust-clippy/pull/9645)
+* [`should_implement_trait`]: Now also works for `default` methods
+ [#9546](https://github.com/rust-lang/rust-clippy/pull/9546)
+
+### Suggestion Fixes/Improvements
+
+* [`derivable_impls`]: The suggestion is now machine applicable
+ [#9429](https://github.com/rust-lang/rust-clippy/pull/9429)
+* [`match_single_binding`]: The suggestion now handles scrutinies with side effects better
+ [#9601](https://github.com/rust-lang/rust-clippy/pull/9601)
+* [`zero_prefixed_literal`]: Only suggests using octal numbers, if this is possible
+ [#9652](https://github.com/rust-lang/rust-clippy/pull/9652)
+* [`rc_buffer`]: The suggestion is no longer machine applicable to avoid semantic changes
+ [#9633](https://github.com/rust-lang/rust-clippy/pull/9633)
+* [`print_literal`], [`write_literal`], [`uninlined_format_args`]: The suggestion now ignores
+ comments after the macro call.
+ [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`expect_fun_call`]:Improved the suggestion for `format!` calls with captured variables
+ [#9586](https://github.com/rust-lang/rust-clippy/pull/9586)
+* [`nonstandard_macro_braces`]: The suggestion is now machine applicable and will no longer
+ replace brackets inside the macro argument.
+ [#9499](https://github.com/rust-lang/rust-clippy/pull/9499)
+* [`from_over_into`]: The suggestion is now a machine applicable and contains explanations
+ [#9649](https://github.com/rust-lang/rust-clippy/pull/9649)
+* [`needless_return`]: The automatic suggestion now removes all required semicolons
+ [#9497](https://github.com/rust-lang/rust-clippy/pull/9497)
+* [`to_string_in_format_args`]: The suggestion now keeps parenthesis around values
+ [#9590](https://github.com/rust-lang/rust-clippy/pull/9590)
+* [`manual_assert`]: The suggestion now preserves comments
+ [#9479](https://github.com/rust-lang/rust-clippy/pull/9479)
+* [`redundant_allocation`]: The suggestion applicability is now marked `MaybeIncorrect` to
+ avoid semantic changes
+ [#9634](https://github.com/rust-lang/rust-clippy/pull/9634)
+* [`assertions_on_result_states`]: The suggestion has been corrected, for cases where the
+ `assert!` is not in a statement.
+ [#9453](https://github.com/rust-lang/rust-clippy/pull/9453)
+* [`nonminimal_bool`]: The suggestion no longer expands macros
+ [#9457](https://github.com/rust-lang/rust-clippy/pull/9457)
+* [`collapsible_match`]: Now specifies field names, when a struct is destructed
+ [#9685](https://github.com/rust-lang/rust-clippy/pull/9685)
+* [`unnecessary_cast`]: The suggestion now adds parenthesis for negative numbers
+ [#9577](https://github.com/rust-lang/rust-clippy/pull/9577)
+* [`redundant_closure`]: The suggestion now works for `impl FnMut` arguments
+ [#9556](https://github.com/rust-lang/rust-clippy/pull/9556)
+
+### ICE Fixes
+
+* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
+ [#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
+* [`manual_range_contains`]: No longer ICEs on values behind references
+ [#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
+* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
+ [#9531](https://github.com/rust-lang/rust-clippy/pull/9531)
+* `*_interior_mutable_const` lints: no longer ICE on const unions containing `!Freeze` types
+ [#9539](https://github.com/rust-lang/rust-clippy/pull/9539)
+
+### Others
+
+* Released `rustc_tools_util` for version information on `Crates.io`. (Further adjustments will
+ not be published as part of this changelog)
## Rust 1.65
-Current stable, released 2022-11-03
+Released 2022-11-03
[3c7e7dbc...b52fb523](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...b52fb523)
[`alloc_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#alloc_instead_of_core
[`allow_attributes_without_reason`]: https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes_without_reason
[`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range
+[`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
[`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`semicolon_inside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block
+[`semicolon_outside_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block
[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
[package]
name = "clippy"
-version = "0.1.67"
+version = "0.1.68"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
[dependencies]
clippy_lints = { path = "clippy_lints" }
semver = "1.0"
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
tempfile = { version = "3.2", optional = true }
termize = "0.1"
rustc-semver = "1.1"
[build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
[features]
deny-warnings = ["clippy_lints/deny-warnings"]
# Clippy
-[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test%22+event%3Apush+branch%3Aauto)
+[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](https://github.com/rust-lang/rust-clippy#license)
A collection of lints to catch common mistakes and improve your
println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap());
// Don't rebuild even if nothing changed
println!("cargo:rerun-if-changed=build.rs");
- // forward git repo hashes we build at
- println!(
- "cargo:rustc-env=GIT_HASH={}",
- rustc_tools_util::get_commit_hash().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=COMMIT_DATE={}",
- rustc_tools_util::get_commit_date().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
- rustc_tools_util::get_channel()
- );
+ rustc_tools_util::setup_version_info!();
}
[package]
name = "clippy_lints"
-version = "0.1.67"
+version = "0.1.68"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
+++ /dev/null
-use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::{trim_span, walk_span_to_context};
-use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
-use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::Span;
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for ranges which almost include the entire range of letters from 'a' to 'z', but
- /// don't because they're a half open range.
- ///
- /// ### Why is this bad?
- /// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
- ///
- /// ### Example
- /// ```rust
- /// let _ = 'a'..'z';
- /// ```
- /// Use instead:
- /// ```rust
- /// let _ = 'a'..='z';
- /// ```
- #[clippy::version = "1.63.0"]
- pub ALMOST_COMPLETE_LETTER_RANGE,
- suspicious,
- "almost complete letter range"
-}
-impl_lint_pass!(AlmostCompleteLetterRange => [ALMOST_COMPLETE_LETTER_RANGE]);
-
-pub struct AlmostCompleteLetterRange {
- msrv: Msrv,
-}
-impl AlmostCompleteLetterRange {
- pub fn new(msrv: Msrv) -> Self {
- Self { msrv }
- }
-}
-impl EarlyLintPass for AlmostCompleteLetterRange {
- fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
- if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
- let ctxt = e.span.ctxt();
- let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
- && let Some(end) = walk_span_to_context(end.span, ctxt)
- && self.msrv.meets(msrvs::RANGE_INCLUSIVE)
- {
- Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
- } else {
- None
- };
- check_range(cx, e.span, start, end, sugg);
- }
- }
-
- fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
- if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
- && matches!(kind.node, RangeEnd::Excluded)
- {
- let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
- "..="
- } else {
- "..."
- };
- check_range(cx, p.span, start, end, Some((kind.span, sugg)));
- }
- }
-
- extract_msrv_attr!(EarlyContext);
-}
-
-fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
- if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
- && let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
- && matches!(
- (
- LitKind::from_token_lit(start_token_lit),
- LitKind::from_token_lit(end_token_lit),
- ),
- (
- Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
- Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
- )
- | (
- Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
- Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
- )
- )
- && !in_external_macro(cx.sess(), span)
- {
- span_lint_and_then(
- cx,
- ALMOST_COMPLETE_LETTER_RANGE,
- span,
- "almost complete ascii letter range",
- |diag| {
- if let Some((span, sugg)) = sugg {
- diag.span_suggestion(
- span,
- "use an inclusive range",
- sugg,
- Applicability::MaybeIncorrect,
- );
- }
- }
- );
- }
-}
--- /dev/null
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::source::{trim_span, walk_span_to_context};
+use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for ranges which almost include the entire range of letters from 'a' to 'z'
+ /// or digits from '0' to '9', but don't because they're a half open range.
+ ///
+ /// ### Why is this bad?
+ /// This (`'a'..'z'`) is almost certainly a typo meant to include all letters.
+ ///
+ /// ### Example
+ /// ```rust
+ /// let _ = 'a'..'z';
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let _ = 'a'..='z';
+ /// ```
+ #[clippy::version = "1.63.0"]
+ pub ALMOST_COMPLETE_RANGE,
+ suspicious,
+ "almost complete range"
+}
+impl_lint_pass!(AlmostCompleteRange => [ALMOST_COMPLETE_RANGE]);
+
+pub struct AlmostCompleteRange {
+ msrv: Msrv,
+}
+impl AlmostCompleteRange {
+ pub fn new(msrv: Msrv) -> Self {
+ Self { msrv }
+ }
+}
+impl EarlyLintPass for AlmostCompleteRange {
+ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
+ if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind {
+ let ctxt = e.span.ctxt();
+ let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
+ && let Some(end) = walk_span_to_context(end.span, ctxt)
+ && self.msrv.meets(msrvs::RANGE_INCLUSIVE)
+ {
+ Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
+ } else {
+ None
+ };
+ check_range(cx, e.span, start, end, sugg);
+ }
+ }
+
+ fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &Pat) {
+ if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
+ && matches!(kind.node, RangeEnd::Excluded)
+ {
+ let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
+ "..="
+ } else {
+ "..."
+ };
+ check_range(cx, p.span, start, end, Some((kind.span, sugg)));
+ }
+ }
+
+ extract_msrv_attr!(EarlyContext);
+}
+
+fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
+ if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
+ && let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
+ && matches!(
+ (
+ LitKind::from_token_lit(start_token_lit),
+ LitKind::from_token_lit(end_token_lit),
+ ),
+ (
+ Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
+ Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
+ )
+ | (
+ Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
+ Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
+ )
+ | (
+ Ok(LitKind::Byte(b'0') | LitKind::Char('0')),
+ Ok(LitKind::Byte(b'9') | LitKind::Char('9')),
+ )
+ )
+ && !in_external_macro(cx.sess(), span)
+ {
+ span_lint_and_then(
+ cx,
+ ALMOST_COMPLETE_RANGE,
+ span,
+ "almost complete ascii range",
+ |diag| {
+ if let Some((span, sugg)) = sugg {
+ diag.span_suggestion(
+ span,
+ "use an inclusive range",
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ );
+ }
+}
/// ```rust
/// let x: Box<String> = Box::default();
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub BOX_DEFAULT,
perf,
"Using Box::new(T::default()) instead of Box::default()"
/// ```rust,ignore
/// let _: = 0_u64;
/// ```
- #[clippy::version = "1.64.0"]
+ #[clippy::version = "1.66.0"]
pub CAST_NAN_TO_INT,
suspicious,
"casting a known floating-point NaN into an integer"
crate::utils::internal_lints::produce_ice::PRODUCE_ICE_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH_INFO,
- crate::almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE_INFO,
+ crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
crate::approx_const::APPROX_CONSTANT_INFO,
crate::as_conversions::AS_CONVERSIONS_INFO,
crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
crate::returns::NEEDLESS_RETURN_INFO,
crate::same_name_method::SAME_NAME_METHOD_INFO,
crate::self_named_constructors::SELF_NAMED_CONSTRUCTORS_INFO,
+ crate::semicolon_block::SEMICOLON_INSIDE_BLOCK_INFO,
+ crate::semicolon_block::SEMICOLON_OUTSIDE_BLOCK_INFO,
crate::semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED_INFO,
crate::serde_api::SERDE_API_MISUSE_INFO,
crate::shadow::SHADOW_REUSE_INFO,
let mut projection_ty = projection_predicate.projection_ty;
loop {
match projection_ty.self_ty().kind() {
- ty::Projection(inner_projection_ty) => {
+ ty::Alias(ty::Projection, inner_projection_ty) => {
projection_ty = *inner_projection_ty;
}
ty::Param(param_ty) => {
&& let Some(term_ty) = projection_predicate.term.ty()
&& let ty::Param(term_param_ty) = term_ty.kind()
{
- let item_def_id = projection_predicate.projection_ty.item_def_id;
+ let item_def_id = projection_predicate.projection_ty.def_id;
let assoc_item = cx.tcx.associated_item(item_def_id);
let projection = cx.tcx
.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
continue;
},
ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
- ty::Projection(_) if ty.has_non_region_param() => TyPosition::new_deref_stable_for_result(precedence, ty),
- ty::Infer(_) | ty::Error(_) | ty::Bound(..) | ty::Opaque(..) | ty::Placeholder(_) | ty::Dynamic(..) => {
- Position::ReborrowStable(precedence).into()
+ ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
+ TyPosition::new_deref_stable_for_result(precedence, ty)
},
+ ty::Infer(_)
+ | ty::Error(_)
+ | ty::Bound(..)
+ | ty::Alias(ty::Opaque, ..)
+ | ty::Placeholder(_)
+ | ty::Dynamic(..) => Position::ReborrowStable(precedence).into(),
ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
Position::ReborrowStable(precedence).into()
},
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)
- | ty::Projection(_) => {
+ | ty::Alias(ty::Projection, _) => {
Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
},
};
use rustc_middle::traits::Reveal;
use rustc_middle::ty::{
self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
- TraitRef, Ty, TyCtxt,
+ Ty, TyCtxt,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
- trait_ref: TraitRef::new(
- eq_trait_id,
- tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
- ),
+ trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
constness: BoundConstness::NotConst,
polarity: ImplPolarity::Positive,
}))))
/// value: usize,
/// }
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub DISALLOWED_MACROS,
style,
"use of a disallowed macro"
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::FormatParamKind::{Implicit, Named, NamedInline, Numbered, Starred};
use clippy_utils::macros::{
- is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage,
+ is_assert_macro, is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam,
+ FormatParamUsage,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
///
/// If a format string contains a numbered argument that cannot be inlined
/// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub UNINLINED_FORMAT_ARGS,
style,
"using non-inlined variables in `format!` calls"
if args.format_string.span.from_expansion() {
return;
}
- if call_site.edition() < Edition2021 && is_panic(cx, def_id) {
- // panic! before 2021 edition considers a single string argument as non-format
+ if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) {
+ // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as
+ // non-format
return;
}
TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::{hir::nested_filter::OnlyBodies, ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{kw, sym};
use rustc_span::{Span, Symbol};
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
&& let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
&& cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
+ && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _))
{
span_lint_and_then(
cx,
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
+use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
return;
}
let ret_ty = return_ty(cx, hir_id);
- if let Opaque(id, subst) = *ret_ty.kind() {
- let preds = cx.tcx.explicit_item_bounds(id);
+ if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
+ let preds = cx.tcx.explicit_item_bounds(def_id);
let mut is_future = false;
for &(p, _span) in preds {
- let p = EarlyBinder(p).subst(cx.tcx, subst);
+ let p = EarlyBinder(p).subst(cx.tcx, substs);
if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
is_future = true;
///
/// u = u.saturating_add(1);
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub IMPLICIT_SATURATING_ADD,
style,
"Perform saturating addition instead of implicitly checking max bound of data type"
//! lint on indexing and slicing operations
use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::higher;
use rustc_ast::ast::RangeLimits;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
/// ### What it does
"indexing/slicing usage"
}
-declare_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+impl_lint_pass!(IndexingSlicing => [INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING]);
+
+#[derive(Copy, Clone)]
+pub struct IndexingSlicing {
+ suppress_restriction_lint_in_const: bool,
+}
+
+impl IndexingSlicing {
+ pub fn new(suppress_restriction_lint_in_const: bool) -> Self {
+ Self {
+ suppress_restriction_lint_in_const,
+ }
+ }
+}
impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ if self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) {
return;
}
if let ExprKind::Index(array, index) = &expr.kind {
+ let note = "the suggestion might not be applicable in constant blocks";
let ty = cx.typeck_results().expr_ty(array).peel_refs();
if let Some(range) = higher::Range::hir(index) {
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
(None, None) => return, // [..] is ok.
};
- span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic", None, help_msg);
+ span_lint_and_then(cx, INDEXING_SLICING, expr.span, "slicing may panic", |diag| {
+ diag.help(help_msg);
+
+ if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ diag.note(note);
+ }
+ });
} else {
// Catchall non-range index, i.e., [n] or [n << m]
if let ty::Array(..) = ty.kind() {
}
}
- span_lint_and_help(
- cx,
- INDEXING_SLICING,
- expr.span,
- "indexing may panic",
- None,
- "consider using `.get(n)` or `.get_mut(n)` instead",
- );
+ span_lint_and_then(cx, INDEXING_SLICING, expr.span, "indexing may panic", |diag| {
+ diag.help("consider using `.get(n)` or `.get_mut(n)` instead");
+
+ if cx.tcx.hir().is_inside_const_context(expr.hir_id) {
+ diag.note(note);
+ }
+ });
}
}
}
if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) {
match &arg.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => {
- if let LitKind::ByteStr(bytes) = &lit
+ if let LitKind::ByteStr(bytes, _) = &lit
&& std::str::from_utf8(bytes).is_err()
{
lint(cx, expr.span);
then {
let len = match &lit.node {
// include_bytes
- LitKind::ByteStr(bstr) => bstr.len(),
+ LitKind::ByteStr(bstr, _) => bstr.len(),
// include_str
LitKind::Str(sym, _) => sym.as_str().len(),
_ => return,
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::{
def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item,
- ItemKind, Mutability, Node, TraitItemRef, TyKind,
+ ItemKind, Mutability, Node, TraitItemRef, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
source_map::{Span, Spanned, Symbol},
symbol::sym,
};
+use std::borrow::Cow;
declare_clippy_lint! {
/// ### What it does
fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
let mut applicability = Applicability::MachineApplicable;
+
+ let lit1 = peel_ref_operators(cx, lit1);
+ let mut lit_str = snippet_with_applicability(cx, lit1.span, "_", &mut applicability);
+
+ // Wrap the expression in parentheses if it's a deref expression. Otherwise operator precedence will
+ // cause the code to dereference boolean(won't compile).
+ if let ExprKind::Unary(UnOp::Deref, _) = lit1.kind {
+ lit_str = Cow::from(format!("({lit_str})"));
+ }
+
span_lint_and_sugg(
cx,
COMPARISON_TO_EMPTY,
span,
"comparison to empty slice",
&format!("using `{op}is_empty` is clearer and more explicit"),
- format!(
- "{op}{}.is_empty()",
- snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
- ),
+ format!("{op}{lit_str}.is_empty()"),
applicability,
);
}
.filter_by_name_unhygienic(is_empty)
.any(|item| is_is_empty(cx, item))
}),
- ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+ ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
ty::Array(..) | ty::Slice(..) | ty::Str => true,
_ => false,
mod renamed_lints;
// begin lints modules, do not remove this comment, it’s used in `update_lints`
-mod almost_complete_letter_range;
+mod almost_complete_range;
mod approx_const;
mod as_conversions;
mod asm_syntax;
mod returns;
mod same_name_method;
mod self_named_constructors;
+mod semicolon_block;
mod semicolon_if_nothing_returned;
mod serde_api;
mod shadow;
}
let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
+ let arithmetic_side_effects_allowed_binary = conf.arithmetic_side_effects_allowed_binary.clone();
+ let arithmetic_side_effects_allowed_unary = conf.arithmetic_side_effects_allowed_unary.clone();
store.register_late_pass(move |_| {
Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(
- arithmetic_side_effects_allowed.clone(),
+ arithmetic_side_effects_allowed
+ .iter()
+ .flat_map(|el| [[el.clone(), "*".to_string()], ["*".to_string(), el.clone()]])
+ .chain(arithmetic_side_effects_allowed_binary.clone())
+ .collect(),
+ arithmetic_side_effects_allowed
+ .iter()
+ .chain(arithmetic_side_effects_allowed_unary.iter())
+ .cloned()
+ .collect(),
))
});
store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
store.register_late_pass(|_| Box::new(needless_bool::NeedlessBool));
store.register_late_pass(|_| Box::new(needless_bool::BoolComparison));
store.register_late_pass(|_| Box::new(needless_for_each::NeedlessForEach));
- store.register_late_pass(|_| Box::new(misc::MiscLints));
+ store.register_late_pass(|_| Box::<misc::LintPass>::default());
store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
let allow_expect_in_tests = conf.allow_expect_in_tests;
let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
+ let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const;
store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
store.register_late_pass(move |_| {
Box::new(methods::Methods::new(
store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl));
store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
store.register_late_pass(|_| Box::new(unwrap::Unwrap));
- store.register_late_pass(|_| Box::new(indexing_slicing::IndexingSlicing));
+ store.register_late_pass(move |_| {
+ Box::new(indexing_slicing::IndexingSlicing::new(
+ suppress_restriction_lint_in_const,
+ ))
+ });
store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst));
store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone));
store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
- store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv())));
+ store.register_early_pass(move || Box::new(almost_complete_range::AlmostCompleteRange::new(msrv())));
store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
+ store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock));
// add lints here, do not remove this comment, it's used in `new_lint`
}
cx: &'a LateContext<'tcx>, // context reference
states: HirIdMap<IncrementVisitorVarState>, // incremented variables
depth: u32, // depth of conditional expressions
- done: bool,
}
impl<'a, 'tcx> IncrementVisitor<'a, 'tcx> {
cx,
states: HirIdMap::default(),
depth: 0,
- done: false,
}
}
impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
- if self.done {
- return;
- }
-
// If node is a variable
if let Some(def_id) = path_to_local(expr) {
if let Some(parent) = get_parent_expr(self.cx, expr) {
walk_expr(self, expr);
self.depth -= 1;
} else if let ExprKind::Continue(_) = expr.kind {
- self.done = true;
+ // If we see a `continue` block, then we increment depth so that the IncrementVisitor
+ // state will be set to DontWarn if we see the variable being modified anywhere afterwards.
+ self.depth += 1;
} else {
walk_expr(self, expr);
}
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{peel_blocks_with_stmt, span_extract_comment, sugg};
+use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
if cx.tcx.item_name(macro_call.def_id) == sym::panic;
if !cx.tcx.sess.source_map().is_multiline(cond.span);
if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn);
+ // Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
+ // shuffles the condition around.
+ // Should this have a config value?
+ if !is_else_clause(cx.tcx, expr);
then {
let mut applicability = Applicability::MachineApplicable;
let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::{diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, source::snippet};
+use clippy_utils::{diagnostics::span_lint_and_sugg, higher, in_constant, macros::root_macro_call, source::snippet};
+use rustc_ast::ast::RangeLimits;
use rustc_ast::LitKind::{Byte, Char};
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd};
+use rustc_hir::{BorrowKind, Expr, ExprKind, PatKind, RangeEnd};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{def_id::DefId, sym};
+use rustc_span::{def_id::DefId, sym, Span};
declare_clippy_lint! {
/// ### What it does
/// assert!(matches!(b'X', b'A'..=b'Z'));
/// assert!(matches!('2', '0'..='9'));
/// assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
+ ///
+ /// ('0'..='9').contains(&'0');
+ /// ('a'..='z').contains(&'a');
+ /// ('A'..='Z').contains(&'A');
/// }
/// ```
/// Use instead:
/// assert!(b'X'.is_ascii_uppercase());
/// assert!('2'.is_ascii_digit());
/// assert!('x'.is_ascii_alphabetic());
+ ///
+ /// '0'.is_ascii_digit();
+ /// 'a'.is_ascii_lowercase();
+ /// 'A'.is_ascii_uppercase();
/// }
/// ```
#[clippy::version = "1.66.0"]
return;
}
- let Some(macro_call) = root_macro_call(expr.span) else { return };
-
- if is_matches_macro(cx, macro_call.def_id) {
+ if let Some(macro_call) = root_macro_call(expr.span)
+ && is_matches_macro(cx, macro_call.def_id) {
if let ExprKind::Match(recv, [arm, ..], _) = expr.kind {
let range = check_pat(&arm.pat.kind);
-
- if let Some(sugg) = match range {
- CharRange::UpperChar => Some("is_ascii_uppercase"),
- CharRange::LowerChar => Some("is_ascii_lowercase"),
- CharRange::FullChar => Some("is_ascii_alphabetic"),
- CharRange::Digit => Some("is_ascii_digit"),
- CharRange::Otherwise => None,
- } {
- let default_snip = "..";
- // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
- // macro span, so we check applicability manually by comparing `recv` is not default.
- let recv = snippet(cx, recv.span, default_snip);
-
- let applicability = if recv == default_snip {
- Applicability::HasPlaceholders
- } else {
- Applicability::MachineApplicable
- };
-
- span_lint_and_sugg(
- cx,
- MANUAL_IS_ASCII_CHECK,
- macro_call.span,
- "manual check for common ascii range",
- "try",
- format!("{recv}.{sugg}()"),
- applicability,
- );
- }
+ check_is_ascii(cx, macro_call.span, recv, &range);
+ }
+ } else if let ExprKind::MethodCall(path, receiver, [arg], ..) = expr.kind
+ && path.ident.name == sym!(contains)
+ && let Some(higher::Range { start: Some(start), end: Some(end), limits: RangeLimits::Closed })
+ = higher::Range::hir(receiver) {
+ let range = check_range(start, end);
+ if let ExprKind::AddrOf(BorrowKind::Ref, _, e) = arg.kind {
+ check_is_ascii(cx, expr.span, e, &range);
+ } else {
+ check_is_ascii(cx, expr.span, arg, &range);
}
}
}
extract_msrv_attr!(LateContext);
}
+fn check_is_ascii(cx: &LateContext<'_>, span: Span, recv: &Expr<'_>, range: &CharRange) {
+ if let Some(sugg) = match range {
+ CharRange::UpperChar => Some("is_ascii_uppercase"),
+ CharRange::LowerChar => Some("is_ascii_lowercase"),
+ CharRange::FullChar => Some("is_ascii_alphabetic"),
+ CharRange::Digit => Some("is_ascii_digit"),
+ CharRange::Otherwise => None,
+ } {
+ let default_snip = "..";
+ // `snippet_with_applicability` may set applicability to `MaybeIncorrect` for
+ // macro span, so we check applicability manually by comparing `recv` is not default.
+ let recv = snippet(cx, recv.span, default_snip);
+
+ let applicability = if recv == default_snip {
+ Applicability::HasPlaceholders
+ } else {
+ Applicability::MachineApplicable
+ };
+
+ span_lint_and_sugg(
+ cx,
+ MANUAL_IS_ASCII_CHECK,
+ span,
+ "manual check for common ascii range",
+ "try",
+ format!("{recv}.{sugg}()"),
+ applicability,
+ );
+ }
+}
+
fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
match pat_kind {
PatKind::Or(pats) => {
} else {
format!("{{ {sn_else} }}")
};
- let sugg = format!("let {sn_pat} = {sn_expr} else {else_bl};");
+ let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
+ format!("({sn_pat})")
+ } else {
+ sn_pat.into_owned()
+ };
+ let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
diag.span_suggestion(span, "consider writing", sugg, app);
},
);
&& seg.args.is_none()
&& let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
&& let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
- && match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
+ && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id)
+ {
check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv);
// TODO: Handle negative integers. They're currently treated as a wild match.
ExprKind::Lit(lit) => match lit.node {
LitKind::Str(sym, _) => Self::LitStr(sym),
- LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes),
+ LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
LitKind::Byte(val) => Self::LitInt(val.into()),
LitKind::Char(val) => Self::LitInt(val.into()),
LitKind::Int(val, _) => Self::LitInt(val),
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::peel_mid_ty_refs;
+use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
use clippy_utils::{is_diag_item_method, is_diag_trait_item};
use if_chain::if_chain;
use rustc_errors::Applicability;
let (input_type, ref_count) = peel_mid_ty_refs(input_type);
if let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()));
if return_type == input_type;
+ if let Some(clone_trait) = cx.tcx.lang_items().clone_trait();
+ if implements_trait(cx, return_type, clone_trait, &[]);
then {
let mut app = Applicability::MachineApplicable;
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
/// let map: HashMap<u32, u32> = HashMap::new();
/// let values = map.values().collect::<Vec<_>>();
/// ```
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.66.0"]
pub ITER_KV_MAP,
complexity,
"iterating on map using `iter` when `keys` or `values` would do"
no_effect_replace::check(cx, expr, arg1, arg2);
// Check for repeated `str::replace` calls to perform `collapsible_str_replace` lint
- if name == "replace" && let Some(("replace", ..)) = method_call(recv) {
+ if self.msrv.meets(msrvs::PATTERN_TRAIT_CHAR_ARRAY)
+ && name == "replace"
+ && let Some(("replace", ..)) = method_call(recv)
+ {
collapsible_str_replace::check(cx, expr, arg1, arg2);
}
},
&& let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, item, [collect_ty])
&& let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
- cx.tcx.mk_projection(into_iter_item_proj.item_def_id, into_iter_item_proj.substs)
+ cx.tcx.mk_projection(into_iter_item_proj.def_id, into_iter_item_proj.substs)
)
{
iter_item_ty == into_iter_item_ty
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, match_def_path, paths};
+use clippy_utils::{get_trait_def_id, is_expr_used_or_unified, match_def_path, paths};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
// Get receiver type
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+ if is_expr_used_or_unified(cx.tcx, expr) {
+ return;
+ }
+
if let Some(seek_trait_id) = get_trait_def_id(cx, &paths::STD_IO_SEEK) &&
implements_trait(cx, ty, seek_trait_id, &[]) &&
let ExprKind::Call(func, args1) = arg.kind &&
Node::Expr(parent_expr) => {
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
{
- if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
- return false;
- }
-
let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
&& let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind()
+ // https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021
+ && (*param_index as usize) < call_substs.len()
{
if fn_sig
.inputs()
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
+use clippy_utils::{
+ get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+};
declare_clippy_lint! {
/// ### What it does
"using `0 as *{const, mut} T`"
}
-declare_lint_pass!(MiscLints => [
+pub struct LintPass {
+ std_or_core: &'static str,
+}
+impl Default for LintPass {
+ fn default() -> Self {
+ Self { std_or_core: "std" }
+ }
+}
+impl_lint_pass!(LintPass => [
TOPLEVEL_REF_ARG,
USED_UNDERSCORE_BINDING,
SHORT_CIRCUIT_STATEMENT,
ZERO_PTR,
]);
-impl<'tcx> LateLintPass<'tcx> for MiscLints {
+impl<'tcx> LateLintPass<'tcx> for LintPass {
+ fn check_crate(&mut self, cx: &LateContext<'_>) {
+ if is_no_std_crate(cx) {
+ self.std_or_core = "core";
+ }
+ }
+
fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Cast(e, ty) = expr.kind {
- check_cast(cx, expr.span, e, ty);
+ self.check_cast(cx, expr.span, e, ty);
return;
}
if in_attributes_expansion(expr) || expr.span.is_desugaring(DesugaringKind::Await) {
}
}
-fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
- if_chain! {
- if let TyKind::Ptr(ref mut_ty) = ty.kind;
- if is_integer_literal(e, 0);
- if !in_constant(cx, e.hir_id);
- then {
- let (msg, sugg_fn) = match mut_ty.mutbl {
- Mutability::Mut => ("`0 as *mut _` detected", "std::ptr::null_mut"),
- Mutability::Not => ("`0 as *const _` detected", "std::ptr::null"),
- };
+impl LintPass {
+ fn check_cast(&self, cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
+ if_chain! {
+ if let TyKind::Ptr(ref mut_ty) = ty.kind;
+ if is_integer_literal(e, 0);
+ if !in_constant(cx, e.hir_id);
+ then {
+ let (msg, sugg_fn) = match mut_ty.mutbl {
+ Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"),
+ Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
+ };
- let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
- (format!("{sugg_fn}()"), Applicability::MachineApplicable)
- } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
- (format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
- } else {
- // `MaybeIncorrect` as type inference may not work with the suggested code
- (format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
- };
- span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+ let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
+ (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MachineApplicable)
+ } else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
+ (format!("{}::{sugg_fn}::<{mut_ty_snip}>()", self.std_or_core), Applicability::MachineApplicable)
+ } else {
+ // `MaybeIncorrect` as type inference may not work with the suggested code
+ (format!("{}::{sugg_fn}()", self.std_or_core), Applicability::MaybeIncorrect)
+ };
+ span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
+ }
}
}
}
peel_hir_expr_refs,
};
use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::impl_lint_pass;
use rustc_span::source_map::{Span, Spanned};
-const HARD_CODED_ALLOWED: &[&str] = &[
- "&str",
- "f32",
- "f64",
- "std::num::Saturating",
- "std::num::Wrapping",
- "std::string::String",
+const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
+ ["f32", "f32"],
+ ["f64", "f64"],
+ ["std::num::Saturating", "std::num::Saturating"],
+ ["std::num::Wrapping", "std::num::Wrapping"],
+ ["std::string::String", "&str"],
];
+const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
#[derive(Debug)]
pub struct ArithmeticSideEffects {
- allowed: FxHashSet<String>,
+ allowed_binary: FxHashMap<String, FxHashSet<String>>,
+ allowed_unary: FxHashSet<String>,
// Used to check whether expressions are constants, such as in enum discriminants and consts
const_span: Option<Span>,
expr_span: Option<Span>,
impl ArithmeticSideEffects {
#[must_use]
- pub fn new(mut allowed: FxHashSet<String>) -> Self {
- allowed.extend(HARD_CODED_ALLOWED.iter().copied().map(String::from));
+ pub fn new(user_allowed_binary: Vec<[String; 2]>, user_allowed_unary: Vec<String>) -> Self {
+ let mut allowed_binary: FxHashMap<String, FxHashSet<String>> = <_>::default();
+ for [lhs, rhs] in user_allowed_binary.into_iter().chain(
+ HARD_CODED_ALLOWED_BINARY
+ .iter()
+ .copied()
+ .map(|[lhs, rhs]| [lhs.to_string(), rhs.to_string()]),
+ ) {
+ allowed_binary.entry(lhs).or_default().insert(rhs);
+ }
+ let allowed_unary = user_allowed_unary
+ .into_iter()
+ .chain(HARD_CODED_ALLOWED_UNARY.iter().copied().map(String::from))
+ .collect();
Self {
- allowed,
+ allowed_binary,
+ allowed_unary,
const_span: None,
expr_span: None,
}
}
- /// Checks if the given `expr` has any of the inner `allowed` elements.
- fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
- self.allowed
- .contains(ty.to_string().split('<').next().unwrap_or_default())
+ /// Checks if the lhs and the rhs types of a binary operation like "addition" or
+ /// "multiplication" are present in the inner set of allowed types.
+ fn has_allowed_binary(&self, lhs_ty: Ty<'_>, rhs_ty: Ty<'_>) -> bool {
+ let lhs_ty_string = lhs_ty.to_string();
+ let lhs_ty_string_elem = lhs_ty_string.split('<').next().unwrap_or_default();
+ let rhs_ty_string = rhs_ty.to_string();
+ let rhs_ty_string_elem = rhs_ty_string.split('<').next().unwrap_or_default();
+ if let Some(rhs_from_specific) = self.allowed_binary.get(lhs_ty_string_elem)
+ && {
+ let rhs_has_allowed_ty = rhs_from_specific.contains(rhs_ty_string_elem);
+ rhs_has_allowed_ty || rhs_from_specific.contains("*")
+ }
+ {
+ true
+ } else if let Some(rhs_from_glob) = self.allowed_binary.get("*") {
+ rhs_from_glob.contains(rhs_ty_string_elem)
+ } else {
+ false
+ }
+ }
+
+ /// Checks if the type of an unary operation like "negation" is present in the inner set of
+ /// allowed types.
+ fn has_allowed_unary(&self, ty: Ty<'_>) -> bool {
+ let ty_string = ty.to_string();
+ let ty_string_elem = ty_string.split('<').next().unwrap_or_default();
+ self.allowed_unary.contains(ty_string_elem)
}
// For example, 8i32 or &i64::MAX.
};
let lhs_ty = cx.typeck_results().expr_ty(lhs);
let rhs_ty = cx.typeck_results().expr_ty(rhs);
- let lhs_and_rhs_have_the_same_ty = lhs_ty == rhs_ty;
- if lhs_and_rhs_have_the_same_ty && self.is_allowed_ty(lhs_ty) && self.is_allowed_ty(rhs_ty) {
+ if self.has_allowed_binary(lhs_ty, rhs_ty) {
return;
}
let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
return;
}
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
- if self.is_allowed_ty(ty) {
+ if self.has_allowed_unary(ty) {
return;
}
let actual_un_expr = peel_hir_expr_refs(un_expr).0;
use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{clip, unsext};
+use clippy_utils::{clip, peel_hir_expr_refs, unsext};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
use rustc_lint::LateContext;
if !is_allowed(cx, op, left, right) {
match op {
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
- check_op(cx, left, 0, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
- check_op(cx, right, 0, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ right,
+ 0,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Mul => {
- check_op(cx, left, 1, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
- BinOpKind::Div => check_op(cx, right, 1, expr.span, left.span, Parens::Unneeded),
+ BinOpKind::Div => check_op(
+ cx,
+ right,
+ 1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ ),
BinOpKind::BitAnd => {
- check_op(cx, left, -1, expr.span, right.span, needs_parenthesis(cx, expr, right));
- check_op(cx, right, -1, expr.span, left.span, Parens::Unneeded);
+ check_op(
+ cx,
+ left,
+ -1,
+ expr.span,
+ peel_hir_expr_refs(right).0.span,
+ needs_parenthesis(cx, expr, right),
+ );
+ check_op(
+ cx,
+ right,
+ -1,
+ expr.span,
+ peel_hir_expr_refs(left).0.span,
+ Parens::Unneeded,
+ );
},
BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
_ => (),
/// use rust_decimal::Decimal;
/// let _n = Decimal::MAX + Decimal::MAX;
/// ```
- ///
- /// ### Allowed types
- /// Custom allowed types can be specified through the "arithmetic-side-effects-allowed" filter.
#[clippy::version = "1.64.0"]
pub ARITHMETIC_SIDE_EFFECTS,
restriction,
fn is_not_macro_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
if let ItemKind::Use(path, _) = item.kind {
- if path.res.iter().all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _))) {
+ if path
+ .res
+ .iter()
+ .all(|res| matches!(res, Res::Def(DefKind::Macro(MacroKind::Bang), _)))
+ {
return false;
}
} else if let ItemKind::Macro(..) = item.kind {
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
if lifetime.ident.name == rustc_span::symbol::kw::StaticLifetime {
let snip = snippet(cx, borrow_type.ty.span, "<type>");
- let sugg = format!("&{snip}");
+ let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str());
span_lint_and_then(
cx,
REDUNDANT_STATIC_LIFETIMES,
#[rustfmt::skip]
pub static RENAMED_LINTS: &[(&str, &str)] = &[
+ ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
("clippy::blacklisted_name", "clippy::disallowed_names"),
("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"),
("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"),
--- /dev/null
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Suggests moving the semicolon after a block to the inside of the block, after its last
+ /// expression.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+ /// and this lint suggests inside the block.
+ /// Take a look at `semicolon_outside_block` for the other alternative.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x) };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x); }
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub SEMICOLON_INSIDE_BLOCK,
+ restriction,
+ "add a semicolon inside the block"
+}
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Suggests moving the semicolon from a block's final expression outside of the block.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine
+ /// and this lint suggests outside the block.
+ /// Take a look at `semicolon_inside_block` for the other alternative.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x); }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # fn f(_: u32) {}
+ /// # let x = 0;
+ /// unsafe { f(x) };
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub SEMICOLON_OUTSIDE_BLOCK,
+ restriction,
+ "add a semicolon outside the block"
+}
+declare_lint_pass!(SemicolonBlock => [SEMICOLON_INSIDE_BLOCK, SEMICOLON_OUTSIDE_BLOCK]);
+
+impl LateLintPass<'_> for SemicolonBlock {
+ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+ match stmt.kind {
+ StmtKind::Expr(Expr {
+ kind: ExprKind::Block(block, _),
+ ..
+ }) if !block.span.from_expansion() => {
+ let Block {
+ expr: None,
+ stmts: [.., stmt],
+ ..
+ } = block else { return };
+ let &Stmt {
+ kind: StmtKind::Semi(expr),
+ span,
+ ..
+ } = stmt else { return };
+ semicolon_outside_block(cx, block, expr, span);
+ },
+ StmtKind::Semi(Expr {
+ kind: ExprKind::Block(block @ Block { expr: Some(tail), .. }, _),
+ ..
+ }) if !block.span.from_expansion() => semicolon_inside_block(cx, block, tail, stmt.span),
+ _ => (),
+ }
+ }
+}
+
+fn semicolon_inside_block(cx: &LateContext<'_>, block: &Block<'_>, tail: &Expr<'_>, semi_span: Span) {
+ let insert_span = tail.span.source_callsite().shrink_to_hi();
+ let remove_span = semi_span.with_lo(block.span.hi());
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_INSIDE_BLOCK,
+ semi_span,
+ "consider moving the `;` inside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+}
+
+fn semicolon_outside_block(cx: &LateContext<'_>, block: &Block<'_>, tail_stmt_expr: &Expr<'_>, semi_span: Span) {
+ let insert_span = block.span.with_lo(block.span.hi());
+ // account for macro calls
+ let semi_span = cx.sess().source_map().stmt_span(semi_span, block.span);
+ let remove_span = semi_span.with_lo(tail_stmt_expr.span.source_callsite().hi());
+
+ span_lint_and_then(
+ cx,
+ SEMICOLON_OUTSIDE_BLOCK,
+ block.span,
+ "consider moving the `;` outside the block for consistent formatting",
+ |diag| {
+ multispan_sugg_with_applicability(
+ diag,
+ "put the `;` here",
+ Applicability::MachineApplicable,
+ [(remove_span, String::new()), (insert_span, ";".to_owned())],
+ );
+ },
+ );
+}
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{get_expr_use_or_unification_node, peel_blocks, SpanlessEq};
use clippy_utils::{get_parent_expr, is_lint_allowed, match_function_call, method_calls, paths};
-use clippy_utils::{peel_blocks, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
-use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES, STRING_FROM_UTF8_AS_BYTES]);
impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
+ #[expect(clippy::too_many_lines)]
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
use rustc_ast::LitKind;
&& lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT
&& !receiver.span.from_expansion()
{
- span_lint_and_sugg(
- cx,
- STRING_LIT_AS_BYTES,
- e.span,
- "calling `as_bytes()` on a string literal",
- "consider using a byte string literal instead",
- format!(
- "b{}",
- snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
- ),
- applicability,
- );
+ if let Some((parent, id)) = get_expr_use_or_unification_node(cx.tcx, e)
+ && let Node::Expr(parent) = parent
+ && let ExprKind::Match(scrutinee, ..) = parent.kind
+ && scrutinee.hir_id == id
+ {
+ // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces
+ // `&[u8]`. This change would prevent matching with different sized slices.
+ } else {
+ span_lint_and_sugg(
+ cx,
+ STRING_LIT_AS_BYTES,
+ e.span,
+ "calling `as_bytes()` on a string literal",
+ "consider using a byte string literal instead",
+ format!(
+ "b{}",
+ snippet_with_applicability(cx, receiver.span, r#""foo""#, &mut applicability)
+ ),
+ applicability,
+ );
+ }
}
}
}
};
kind!("Float(_, {float_ty})");
},
- LitKind::ByteStr(ref vec) => {
+ LitKind::ByteStr(ref vec, _) => {
bind!(self, vec);
kind!("ByteStr(ref {vec})");
chain!(self, "let [{:?}] = **{vec}", vec.value);
}
define_Conf! {
- /// Lint: Arithmetic.
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
///
- /// Suppress checking of the passed type names.
+ /// Suppress checking of the passed type names in all types of operations.
+ ///
+ /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+ /// ```
+ ///
+ /// #### Noteworthy
+ ///
+ /// A type, say `SomeType`, listed in this configuration has the same behavior of `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
+ ///
+ /// Suppress checking of the passed type pair names in binary operations like addition or
+ /// multiplication.
+ ///
+ /// Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
+ /// of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
+ ///
+ /// Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
+ /// `["AnotherType", "SomeType"]`.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
+ /// ```
+ (arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default()),
+ /// Lint: ARITHMETIC_SIDE_EFFECTS.
+ ///
+ /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
+ /// ```
+ (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
/// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
///
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
(allow_mixed_uninlined_format_args: bool = true),
+ /// Lint: INDEXING_SLICING
+ ///
+ /// Whether to suppress a restriction lint in constant code. In same
+ /// cases the restructured operation might not be unavoidable, as the
+ /// suggested counterparts are unavailable in constant code. This
+ /// configuration will cause restriction lints to trigger even
+ /// if no suggestion can be made.
+ (suppress_restriction_lint_in_const: bool = false),
}
/// Search for the configuration file.
use rustc_hir::Item;
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, FloatTy};
+use rustc_middle::ty::{self, fast_reject::SimplifiedType, FloatTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;
let lang_items = cx.tcx.lang_items();
// This list isn't complete, but good enough for our current list of paths.
let incoherent_impls = [
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
- SimplifiedTypeGen::SliceSimplifiedType,
- SimplifiedTypeGen::StrSimplifiedType,
+ SimplifiedType::FloatSimplifiedType(FloatTy::F32),
+ SimplifiedType::FloatSimplifiedType(FloatTy::F64),
+ SimplifiedType::SliceSimplifiedType,
+ SimplifiedType::StrSimplifiedType,
]
.iter()
.flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
[package]
name = "clippy_utils"
-version = "0.1.67"
+version = "0.1.68"
edition = "2021"
publish = false
LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")),
LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")),
LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")),
- LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")),
+ LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")),
LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")),
LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")),
LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")),
match *lit {
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
LitKind::Byte(b) => Constant::Int(u128::from(b)),
- LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)),
+ LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n),
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
use rustc_middle::ty as rustc_ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::fast_reject::SimplifiedTypeGen::{
+use rustc_middle::ty::fast_reject::SimplifiedType::{
ArraySimplifiedType, BoolSimplifiedType, CharSimplifiedType, FloatSimplifiedType, IntSimplifiedType,
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
};
let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
match cx.tcx.hir().get_by_def_id(parent_id) {
Node::Item(&Item {
- kind: ItemKind::Const(..) | ItemKind::Static(..),
+ kind: ItemKind::Const(..) | ItemKind::Static(..) | ItemKind::Enum(..),
..
})
| Node::TraitItem(&TraitItem {
)
}
+/// Is `def_id` of `assert!` or `debug_assert!`
+pub fn is_assert_macro(cx: &LateContext<'_>, def_id: DefId) -> bool {
+ let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return false };
+ matches!(name, sym::assert_macro | sym::debug_assert_macro)
+}
+
pub enum PanicExpn<'a> {
/// No arguments - `panic!()`
Empty,
msrv_aliases! {
1,65,0 { LET_ELSE }
1,62,0 { BOOL_THEN_SOME }
- 1,58,0 { FORMAT_ARGS_CAPTURE }
+ 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
-pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"];
pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
ty::Ref(_, _, hir::Mutability::Mut) => {
return Err((span, "mutable references in const fn are unstable".into()));
},
- ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+ ty::Alias(ty::Opaque, ..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
return Err((span, "function pointers in const fn are unstable".into()));
},
check_operand(tcx, value, span, body)
},
- TerminatorKind::SwitchInt {
- discr,
- switch_ty: _,
- targets: _,
- } => check_operand(tcx, discr, span, body),
+ TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::ty::{
- self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
- ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
+ self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
+ PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
VariantDef, VariantDiscr,
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use crate::{match_def_path, path_res, paths};
-// Checks if the given type implements copy.
+/// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
}
/// This method also recurses into opaque type predicates, so call it with `impl Trait<U>` and `U`
/// will also return `true`.
pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, needle: Ty<'tcx>) -> bool {
- ty.walk().any(|inner| match inner.unpack() {
- GenericArgKind::Type(inner_ty) => {
- if inner_ty == needle {
- return true;
- }
+ fn contains_ty_adt_constructor_opaque_inner<'tcx>(
+ cx: &LateContext<'tcx>,
+ ty: Ty<'tcx>,
+ needle: Ty<'tcx>,
+ seen: &mut FxHashSet<DefId>,
+ ) -> bool {
+ ty.walk().any(|inner| match inner.unpack() {
+ GenericArgKind::Type(inner_ty) => {
+ if inner_ty == needle {
+ return true;
+ }
- if inner_ty.ty_adt_def() == needle.ty_adt_def() {
- return true;
- }
+ if inner_ty.ty_adt_def() == needle.ty_adt_def() {
+ return true;
+ }
- if let ty::Opaque(def_id, _) = *inner_ty.kind() {
- for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
- match predicate.kind().skip_binder() {
- // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
- // and check substituions to find `U`.
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
- if trait_predicate
- .trait_ref
- .substs
- .types()
- .skip(1) // Skip the implicit `Self` generic parameter
- .any(|ty| contains_ty_adt_constructor_opaque(cx, ty, needle))
- {
- return true;
- }
- },
- // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
- // so we check the term for `U`.
- ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
- if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
- if contains_ty_adt_constructor_opaque(cx, ty, needle) {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *inner_ty.kind() {
+ if !seen.insert(def_id) {
+ return false;
+ }
+
+ for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
+ match predicate.kind().skip_binder() {
+ // For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
+ // and check substituions to find `U`.
+ ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
+ if trait_predicate
+ .trait_ref
+ .substs
+ .types()
+ .skip(1) // Skip the implicit `Self` generic parameter
+ .any(|ty| contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen))
+ {
return true;
}
- };
- },
- _ => (),
+ },
+ // For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
+ // so we check the term for `U`.
+ ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
+ if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
+ if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
+ return true;
+ }
+ };
+ },
+ _ => (),
+ }
}
}
- }
- false
- },
- GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
- })
+ false
+ },
+ GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
+ })
+ }
+
+ // A hash set to ensure that the same opaque type (`impl Trait` in RPIT or TAIT) is not
+ // visited twice.
+ let mut seen = FxHashSet::default();
+ contains_ty_adt_constructor_opaque_inner(cx, ty, needle, &mut seen)
}
/// Resolves `<T as Iterator>::Item` for `T`
is_must_use_ty(cx, *ty)
},
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
- ty::Opaque(def_id, _) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
},
ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
- ty::Opaque(id, _) => sig_from_bounds(cx, ty, cx.tcx.item_bounds(id), cx.tcx.opt_parent(id)),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
+ sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id), cx.tcx.opt_parent(def_id))
+ },
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
ty::Dynamic(bounds, _, _) => {
let lang_items = cx.tcx.lang_items();
_ => None,
}
},
- ty::Projection(proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
+ ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
_ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
},
inputs = Some(i);
},
PredicateKind::Clause(ty::Clause::Projection(p))
- if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
- && p.projection_ty.self_ty() == ty =>
+ if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
{
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
inputs.map(|ty| ExprFnSig::Trait(ty, output, predicates_id))
}
-fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
+fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option<ExprFnSig<'tcx>> {
let mut inputs = None;
let mut output = None;
let lang_items = cx.tcx.lang_items();
for (pred, _) in cx
.tcx
- .bound_explicit_item_bounds(ty.item_def_id)
+ .bound_explicit_item_bounds(ty.def_id)
.subst_iter_copied(cx.tcx, ty.substs)
{
match pred.kind().skip_binder() {
inputs = Some(i);
},
PredicateKind::Clause(ty::Clause::Projection(p))
- if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
+ if Some(p.projection_ty.def_id) == lang_items.fn_once_output() =>
{
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
container_id: DefId,
assoc_ty: Symbol,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
-) -> Option<ProjectionTy<'tcx>> {
+) -> Option<AliasTy<'tcx>> {
fn helper<'tcx>(
tcx: TyCtxt<'tcx>,
container_id: DefId,
assoc_ty: Symbol,
substs: SubstsRef<'tcx>,
- ) -> Option<ProjectionTy<'tcx>> {
+ ) -> Option<AliasTy<'tcx>> {
let Some(assoc_item) = tcx
.associated_items(container_id)
.find_by_name_and_kind(tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, container_id)
}
}
- Some(ProjectionTy {
- substs,
- item_def_id: assoc_item.def_id,
- })
+ Some(tcx.mk_alias_ty(assoc_item.def_id, substs))
}
helper(
tcx,
assoc_ty: Symbol,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> Option<Ty<'tcx>> {
- fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: ProjectionTy<'tcx>) -> Option<Ty<'tcx>> {
+ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
#[cfg(debug_assertions)]
if let Some((i, subst)) = ty
.substs
);
return None;
}
- match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.item_def_id, ty.substs)) {
+ match tcx.try_normalize_erasing_regions(param_env, tcx.mk_projection(ty.def_id, ty.substs)) {
Ok(ty) => Some(ty),
Err(e) => {
debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
[package]
name = "declare_clippy_lint"
-version = "0.1.67"
+version = "0.1.68"
edition = "2021"
publish = false
[toolchain]
-channel = "nightly-2022-12-01"
+channel = "nightly-2022-12-17"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
--- /dev/null
+# Changelog
+
+## Version 0.3.0
+
+* Added `setup_version_info!();` macro for automated scripts.
+* `get_version_info!()` no longer requires the user to import `rustc_tools_util::VersionInfo` and `std::env`
[package]
name = "rustc_tools_util"
-version = "0.2.1"
+version = "0.3.0"
description = "small helper to generate version information for git packages"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
List rustc_tools_util as regular AND build dependency.
````toml
[dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
[build-dependencies]
-rustc_tools_util = "0.2.1"
+rustc_tools_util = "0.3.0"
````
In `build.rs`, generate the data in your `main()`
-````rust
+
+```rust
fn main() {
- println!(
- "cargo:rustc-env=GIT_HASH={}",
- rustc_tools_util::get_commit_hash().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=COMMIT_DATE={}",
- rustc_tools_util::get_commit_date().unwrap_or_default()
- );
- println!(
- "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
- rustc_tools_util::get_channel().unwrap_or_default()
- );
+ rustc_tools_util::setup_version_info!();
}
-
-````
+```
Use the version information in your main.rs
-````rust
-use rustc_tools_util::*;
+```rust
fn show_version() {
let version_info = rustc_tools_util::get_version_info!();
println!("{}", version_info);
}
-````
+```
+
This gives the following output in clippy:
-`clippy 0.0.212 (a416c5e 2018-12-14)`
+`clippy 0.1.66 (a28f3c8 2022-11-20)`
+
+## Repository
+
+This project is part of the rust-lang/rust-clippy repository. The source code
+can be found under `./rustc_tools_util/`.
+The changelog for `rustc_tools_util` is available under:
+[`rustc_tools_util/CHANGELOG.md`](https://github.com/rust-lang/rust-clippy/blob/master/rustc_tools_util/CHANGELOG.md)
## License
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-use std::env;
-
+/// This macro creates the version string during compilation from the
+/// current environment
#[macro_export]
macro_rules! get_version_info {
() => {{
- let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
- let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
- let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
- let crate_name = String::from(env!("CARGO_PKG_NAME"));
+ let major = std::env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
+ let minor = std::env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
+ let patch = std::env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
+ let crate_name = String::from(std::env!("CARGO_PKG_NAME"));
- let host_compiler = option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
- let commit_hash = option_env!("GIT_HASH").map(str::to_string);
- let commit_date = option_env!("COMMIT_DATE").map(str::to_string);
+ let host_compiler = std::option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
+ let commit_hash = std::option_env!("GIT_HASH").map(str::to_string);
+ let commit_date = std::option_env!("COMMIT_DATE").map(str::to_string);
- VersionInfo {
+ $crate::VersionInfo {
major,
minor,
patch,
}};
}
+/// This macro can be used in `build.rs` to automatically set the needed
+/// environment values, namely `GIT_HASH`, `COMMIT_DATE` and
+/// `RUSTC_RELEASE_CHANNEL`
+#[macro_export]
+macro_rules! setup_version_info {
+ () => {{
+ println!(
+ "cargo:rustc-env=GIT_HASH={}",
+ $crate::get_commit_hash().unwrap_or_default()
+ );
+ println!(
+ "cargo:rustc-env=COMMIT_DATE={}",
+ $crate::get_commit_date().unwrap_or_default()
+ );
+ println!("cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}", $crate::get_channel());
+ }};
+}
+
// some code taken and adapted from RLS and cargo
pub struct VersionInfo {
pub major: u8,
#[must_use]
pub fn get_channel() -> String {
- match env::var("CFG_RELEASE_CHANNEL") {
+ match std::env::var("CFG_RELEASE_CHANNEL") {
Ok(channel) => channel,
Err(_) => {
// if that failed, try to ask rustc -V, do some parsing and find out
fn test_struct_local() {
let vi = get_version_info!();
assert_eq!(vi.major, 0);
- assert_eq!(vi.minor, 2);
- assert_eq!(vi.patch, 1);
+ assert_eq!(vi.minor, 3);
+ assert_eq!(vi.patch, 0);
assert_eq!(vi.crate_name, "rustc_tools_util");
// hard to make positive tests for these since they will always change
assert!(vi.commit_hash.is_none());
#[test]
fn test_display_local() {
let vi = get_version_info!();
- assert_eq!(vi.to_string(), "rustc_tools_util 0.2.1");
+ assert_eq!(vi.to_string(), "rustc_tools_util 0.3.0");
}
#[test]
let s = format!("{vi:?}");
assert_eq!(
s,
- "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 1 }"
+ "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 3, patch: 0 }"
);
}
}
use rustc_interface::interface;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::Symbol;
-use rustc_tools_util::VersionInfo;
use std::borrow::Cow;
use std::env;
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
-use rustc_tools_util::VersionInfo;
use std::env;
use std::path::PathBuf;
use std::process::{self, Command};
= help: convert all references to use `sym::Deref`
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
-error: hardcoded path to a diagnostic item
- --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
- |
-LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: convert all references to use `sym::deref_method`
-
error: hardcoded path to a language item
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
|
= help: convert all references to use `LangItem::DerefMut`
+error: hardcoded path to a diagnostic item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+ |
+LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `sym::deref_method`
+
error: aborting due to 3 previous errors
use core::ops::{Add, Neg};
-#[derive(Clone, Copy)]
-struct Point {
- x: i32,
- y: i32,
+macro_rules! create {
+ ($name:ident) => {
+ #[allow(clippy::arithmetic_side_effects)]
+ #[derive(Clone, Copy)]
+ struct $name;
+
+ impl Add<$name> for $name {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<i32> for $name {
+ type Output = $name;
+ fn add(self, other: i32) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<$name> for i32 {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<i64> for $name {
+ type Output = $name;
+ fn add(self, other: i64) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Add<$name> for i64 {
+ type Output = $name;
+ fn add(self, other: $name) -> Self::Output {
+ todo!()
+ }
+ }
+
+ impl Neg for $name {
+ type Output = $name;
+ fn neg(self) -> Self::Output {
+ todo!()
+ }
+ }
+ };
}
-impl Add for Point {
- type Output = Self;
+create!(Foo);
+create!(Bar);
+create!(Baz);
+create!(OutOfNames);
- fn add(self, other: Self) -> Self {
- todo!()
- }
+fn lhs_and_rhs_are_equal() {
+ // is explicitly on the list
+ let _ = OutOfNames + OutOfNames;
+ // is explicitly on the list
+ let _ = Foo + Foo;
+ // is implicitly on the list
+ let _ = Bar + Bar;
+ // not on the list
+ let _ = Baz + Baz;
}
-impl Neg for Point {
- type Output = Self;
+fn lhs_is_different() {
+ // is explicitly on the list
+ let _ = 1i32 + OutOfNames;
+ // is explicitly on the list
+ let _ = 1i32 + Foo;
+ // is implicitly on the list
+ let _ = 1i32 + Bar;
+ // not on the list
+ let _ = 1i32 + Baz;
- fn neg(self) -> Self::Output {
- todo!()
- }
+ // not on the list
+ let _ = 1i64 + Foo;
+ // is implicitly on the list
+ let _ = 1i64 + Bar;
+ // not on the list
+ let _ = 1i64 + Baz;
}
-fn main() {
- let _ = Point { x: 1, y: 0 } + Point { x: 2, y: 3 };
+fn rhs_is_different() {
+ // is explicitly on the list
+ let _ = OutOfNames + 1i32;
+ // is explicitly on the list
+ let _ = Foo + 1i32;
+ // is implicitly on the list
+ let _ = Bar + 1i32;
+ // not on the list
+ let _ = Baz + 1i32;
+
+ // not on the list
+ let _ = Foo + 1i64;
+ // is implicitly on the list
+ let _ = Bar + 1i64;
+ // not on the list
+ let _ = Baz + 1i64;
+}
- let point: Point = Point { x: 1, y: 0 };
- let _ = point + point;
- let _ = -point;
+fn unary() {
+ // is explicitly on the list
+ let _ = -OutOfNames;
+ // is specifically on the list
+ let _ = -Foo;
+ // not on the list
+ let _ = -Bar;
+ // not on the list
+ let _ = -Baz;
}
+
+fn main() {}
--- /dev/null
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:68:13
+ |
+LL | let _ = Baz + Baz;
+ | ^^^^^^^^^
+ |
+ = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:79:13
+ |
+LL | let _ = 1i32 + Baz;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:82:13
+ |
+LL | let _ = 1i64 + Foo;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:86:13
+ |
+LL | let _ = 1i64 + Baz;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:97:13
+ |
+LL | let _ = Baz + 1i32;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:100:13
+ |
+LL | let _ = Foo + 1i64;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:104:13
+ |
+LL | let _ = Baz + 1i64;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:113:13
+ |
+LL | let _ = -Bar;
+ | ^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects_allowed.rs:115:13
+ |
+LL | let _ = -Baz;
+ | ^^^^
+
+error: aborting due to 9 previous errors
+
-arithmetic-side-effects-allowed = ["Point"]
+arithmetic-side-effects-allowed = [
+ "OutOfNames"
+]
+arithmetic-side-effects-allowed-binary = [
+ ["Foo", "Foo"],
+ ["Foo", "i32"],
+ ["i32", "Foo"],
+ ["Bar", "*"],
+ ["*", "Bar"],
+]
+arithmetic-side-effects-allowed-unary = ["Foo"]
--- /dev/null
+suppress-restriction-lint-in-const = true
--- /dev/null
+#![feature(inline_const)]
+#![warn(clippy::indexing_slicing)]
+// We also check the out_of_bounds_indexing lint here, because it lints similar things and
+// we want to avoid false positives.
+#![warn(clippy::out_of_bounds_indexing)]
+#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+
+const ARR: [i32; 2] = [1, 2];
+const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+
+const fn idx() -> usize {
+ 1
+}
+const fn idx4() -> usize {
+ 4
+}
+
+fn main() {
+ let x = [1, 2, 3, 4];
+ let index: usize = 1;
+ x[index];
+ x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+
+ x[0]; // Ok, should not produce stderr.
+ x[3]; // Ok, should not produce stderr.
+ x[const { idx() }]; // Ok, should not produce stderr.
+ x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+
+ let y = &x;
+ y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
+ y[4]; // Ok, rustc will handle references too.
+
+ let v = vec![0; 5];
+ v[0];
+ v[10];
+ v[1 << 3];
+
+ const N: usize = 15; // Out of bounds
+ const M: usize = 3; // In bounds
+ x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
+ x[M]; // Ok, should not produce stderr.
+ v[N];
+ v[M];
+}
+
+/// An opaque integer representation
+pub struct Integer<'a> {
+ /// The underlying data
+ value: &'a [u8],
+}
+impl<'a> Integer<'a> {
+ // Check whether `self` holds a negative number or not
+ pub const fn is_negative(&self) -> bool {
+ self.value[0] & 0b1000_0000 != 0
+ }
+}
--- /dev/null
+error[E0080]: evaluation of `main::{constant#3}` failed
+ --> $DIR/test.rs:31:14
+ |
+LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+note: erroneous constant used
+ --> $DIR/test.rs:31:5
+ |
+LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: indexing may panic
+ --> $DIR/test.rs:22:5
+ |
+LL | x[index];
+ | ^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/test.rs:38:5
+ |
+LL | v[0];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:39:5
+ |
+LL | v[10];
+ | ^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:40:5
+ |
+LL | v[1 << 3];
+ | ^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:46:5
+ |
+LL | v[N];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error: indexing may panic
+ --> $DIR/test.rs:47:5
+ |
+LL | v[M];
+ | ^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/test.rs:10:24
+ |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+ | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
allow-unwrap-in-tests
allowed-scripts
arithmetic-side-effects-allowed
+ arithmetic-side-effects-allowed-binary
+ arithmetic-side-effects-allowed-unary
array-size-threshold
avoid-breaking-exported-api
await-holding-invalid-types
pass-by-value-size-limit
single-char-binding-names-threshold
standard-macro-braces
+ suppress-restriction-lint-in-const
third-party
too-large-for-stack
too-many-arguments-threshold
+++ /dev/null
-// run-rustfix
-// edition:2018
-// aux-build:macro_rules.rs
-
-#![feature(exclusive_range_pattern)]
-#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
-#![allow(ellipsis_inclusive_range_patterns)]
-#![allow(clippy::needless_parens_on_range_literals)]
-
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
- () => {
- 'a'
- };
-}
-
-macro_rules! b {
- () => {
- let _ = 'a'..='z';
- };
-}
-
-fn main() {
- #[rustfmt::skip]
- {
- let _ = ('a') ..='z';
- let _ = 'A' ..= ('Z');
- }
-
- let _ = 'b'..'z';
- let _ = 'B'..'Z';
-
- let _ = (b'a')..=(b'z');
- let _ = b'A'..=b'Z';
-
- let _ = b'b'..b'z';
- let _ = b'B'..b'Z';
-
- let _ = a!()..='z';
-
- let _ = match 0u8 {
- b'a'..=b'z' if true => 1,
- b'A'..=b'Z' if true => 2,
- b'b'..b'z' => 3,
- b'B'..b'Z' => 4,
- _ => 5,
- };
-
- let _ = match 'x' {
- 'a'..='z' if true => 1,
- 'A'..='Z' if true => 2,
- 'b'..'z' => 3,
- 'B'..'Z' => 4,
- _ => 5,
- };
-
- almost_complete_letter_range!();
- b!();
-}
-
-#[clippy::msrv = "1.25"]
-fn _under_msrv() {
- let _ = match 'a' {
- 'a'...'z' => 1,
- _ => 2,
- };
-}
-
-#[clippy::msrv = "1.26"]
-fn _meets_msrv() {
- let _ = 'a'..='z';
- let _ = match 'a' {
- 'a'..='z' => 1,
- _ => 2,
- };
-}
+++ /dev/null
-// run-rustfix
-// edition:2018
-// aux-build:macro_rules.rs
-
-#![feature(exclusive_range_pattern)]
-#![feature(stmt_expr_attributes)]
-#![warn(clippy::almost_complete_letter_range)]
-#![allow(ellipsis_inclusive_range_patterns)]
-#![allow(clippy::needless_parens_on_range_literals)]
-
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
- () => {
- 'a'
- };
-}
-
-macro_rules! b {
- () => {
- let _ = 'a'..'z';
- };
-}
-
-fn main() {
- #[rustfmt::skip]
- {
- let _ = ('a') ..'z';
- let _ = 'A' .. ('Z');
- }
-
- let _ = 'b'..'z';
- let _ = 'B'..'Z';
-
- let _ = (b'a')..(b'z');
- let _ = b'A'..b'Z';
-
- let _ = b'b'..b'z';
- let _ = b'B'..b'Z';
-
- let _ = a!()..'z';
-
- let _ = match 0u8 {
- b'a'..b'z' if true => 1,
- b'A'..b'Z' if true => 2,
- b'b'..b'z' => 3,
- b'B'..b'Z' => 4,
- _ => 5,
- };
-
- let _ = match 'x' {
- 'a'..'z' if true => 1,
- 'A'..'Z' if true => 2,
- 'b'..'z' => 3,
- 'B'..'Z' => 4,
- _ => 5,
- };
-
- almost_complete_letter_range!();
- b!();
-}
-
-#[clippy::msrv = "1.25"]
-fn _under_msrv() {
- let _ = match 'a' {
- 'a'..'z' => 1,
- _ => 2,
- };
-}
-
-#[clippy::msrv = "1.26"]
-fn _meets_msrv() {
- let _ = 'a'..'z';
- let _ = match 'a' {
- 'a'..'z' => 1,
- _ => 2,
- };
-}
+++ /dev/null
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:29:17
- |
-LL | let _ = ('a') ..'z';
- | ^^^^^^--^^^
- | |
- | help: use an inclusive range: `..=`
- |
- = note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:30:17
- |
-LL | let _ = 'A' .. ('Z');
- | ^^^^--^^^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:36:13
- |
-LL | let _ = (b'a')..(b'z');
- | ^^^^^^--^^^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:37:13
- |
-LL | let _ = b'A'..b'Z';
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:42:13
- |
-LL | let _ = a!()..'z';
- | ^^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:45:9
- |
-LL | b'a'..b'z' if true => 1,
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:46:9
- |
-LL | b'A'..b'Z' if true => 2,
- | ^^^^--^^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:53:9
- |
-LL | 'a'..'z' if true => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:54:9
- |
-LL | 'A'..'Z' if true => 2,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:22:17
- |
-LL | let _ = 'a'..'z';
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-...
-LL | b!();
- | ---- in this macro invocation
- |
- = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:67:9
- |
-LL | 'a'..'z' => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `...`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:74:13
- |
-LL | let _ = 'a'..'z';
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:76:9
- |
-LL | 'a'..'z' => 1,
- | ^^^--^^^
- | |
- | help: use an inclusive range: `..=`
-
-error: aborting due to 13 previous errors
-
--- /dev/null
+// run-rustfix
+// edition:2018
+// aux-build:macro_rules.rs
+
+#![feature(exclusive_range_pattern)]
+#![feature(stmt_expr_attributes)]
+#![warn(clippy::almost_complete_range)]
+#![allow(ellipsis_inclusive_range_patterns)]
+#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! a {
+ () => {
+ 'a'
+ };
+}
+macro_rules! A {
+ () => {
+ 'A'
+ };
+}
+macro_rules! zero {
+ () => {
+ '0'
+ };
+}
+
+macro_rules! b {
+ () => {
+ let _ = 'a'..='z';
+ let _ = 'A'..='Z';
+ let _ = '0'..='9';
+ };
+}
+
+fn main() {
+ #[rustfmt::skip]
+ {
+ let _ = ('a') ..='z';
+ let _ = 'A' ..= ('Z');
+ let _ = ((('0'))) ..= ('9');
+ }
+
+ let _ = 'b'..'z';
+ let _ = 'B'..'Z';
+ let _ = '1'..'9';
+
+ let _ = (b'a')..=(b'z');
+ let _ = b'A'..=b'Z';
+ let _ = b'0'..=b'9';
+
+ let _ = b'b'..b'z';
+ let _ = b'B'..b'Z';
+ let _ = b'1'..b'9';
+
+ let _ = a!()..='z';
+ let _ = A!()..='Z';
+ let _ = zero!()..='9';
+
+ let _ = match 0u8 {
+ b'a'..=b'z' if true => 1,
+ b'A'..=b'Z' if true => 2,
+ b'0'..=b'9' if true => 3,
+ b'b'..b'z' => 4,
+ b'B'..b'Z' => 5,
+ b'1'..b'9' => 6,
+ _ => 7,
+ };
+
+ let _ = match 'x' {
+ 'a'..='z' if true => 1,
+ 'A'..='Z' if true => 2,
+ '0'..='9' if true => 3,
+ 'b'..'z' => 4,
+ 'B'..'Z' => 5,
+ '1'..'9' => 6,
+ _ => 7,
+ };
+
+ almost_complete_range!();
+ b!();
+}
+
+#[clippy::msrv = "1.25"]
+fn _under_msrv() {
+ let _ = match 'a' {
+ 'a'...'z' => 1,
+ 'A'...'Z' => 2,
+ '0'...'9' => 3,
+ _ => 4,
+ };
+}
+
+#[clippy::msrv = "1.26"]
+fn _meets_msrv() {
+ let _ = 'a'..='z';
+ let _ = 'A'..='Z';
+ let _ = '0'..='9';
+ let _ = match 'a' {
+ 'a'..='z' => 1,
+ 'A'..='Z' => 1,
+ '0'..='9' => 3,
+ _ => 4,
+ };
+}
--- /dev/null
+// run-rustfix
+// edition:2018
+// aux-build:macro_rules.rs
+
+#![feature(exclusive_range_pattern)]
+#![feature(stmt_expr_attributes)]
+#![warn(clippy::almost_complete_range)]
+#![allow(ellipsis_inclusive_range_patterns)]
+#![allow(clippy::needless_parens_on_range_literals)]
+#![allow(clippy::double_parens)]
+
+#[macro_use]
+extern crate macro_rules;
+
+macro_rules! a {
+ () => {
+ 'a'
+ };
+}
+macro_rules! A {
+ () => {
+ 'A'
+ };
+}
+macro_rules! zero {
+ () => {
+ '0'
+ };
+}
+
+macro_rules! b {
+ () => {
+ let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
+ };
+}
+
+fn main() {
+ #[rustfmt::skip]
+ {
+ let _ = ('a') ..'z';
+ let _ = 'A' .. ('Z');
+ let _ = ((('0'))) .. ('9');
+ }
+
+ let _ = 'b'..'z';
+ let _ = 'B'..'Z';
+ let _ = '1'..'9';
+
+ let _ = (b'a')..(b'z');
+ let _ = b'A'..b'Z';
+ let _ = b'0'..b'9';
+
+ let _ = b'b'..b'z';
+ let _ = b'B'..b'Z';
+ let _ = b'1'..b'9';
+
+ let _ = a!()..'z';
+ let _ = A!()..'Z';
+ let _ = zero!()..'9';
+
+ let _ = match 0u8 {
+ b'a'..b'z' if true => 1,
+ b'A'..b'Z' if true => 2,
+ b'0'..b'9' if true => 3,
+ b'b'..b'z' => 4,
+ b'B'..b'Z' => 5,
+ b'1'..b'9' => 6,
+ _ => 7,
+ };
+
+ let _ = match 'x' {
+ 'a'..'z' if true => 1,
+ 'A'..'Z' if true => 2,
+ '0'..'9' if true => 3,
+ 'b'..'z' => 4,
+ 'B'..'Z' => 5,
+ '1'..'9' => 6,
+ _ => 7,
+ };
+
+ almost_complete_range!();
+ b!();
+}
+
+#[clippy::msrv = "1.25"]
+fn _under_msrv() {
+ let _ = match 'a' {
+ 'a'..'z' => 1,
+ 'A'..'Z' => 2,
+ '0'..'9' => 3,
+ _ => 4,
+ };
+}
+
+#[clippy::msrv = "1.26"]
+fn _meets_msrv() {
+ let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
+ let _ = match 'a' {
+ 'a'..'z' => 1,
+ 'A'..'Z' => 1,
+ '0'..'9' => 3,
+ _ => 4,
+ };
+}
--- /dev/null
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:42:17
+ |
+LL | let _ = ('a') ..'z';
+ | ^^^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+ |
+ = note: `-D clippy::almost-complete-range` implied by `-D warnings`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:43:17
+ |
+LL | let _ = 'A' .. ('Z');
+ | ^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:44:17
+ |
+LL | let _ = ((('0'))) .. ('9');
+ | ^^^^^^^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:51:13
+ |
+LL | let _ = (b'a')..(b'z');
+ | ^^^^^^--^^^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:52:13
+ |
+LL | let _ = b'A'..b'Z';
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:53:13
+ |
+LL | let _ = b'0'..b'9';
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:59:13
+ |
+LL | let _ = a!()..'z';
+ | ^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:60:13
+ |
+LL | let _ = A!()..'Z';
+ | ^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:61:13
+ |
+LL | let _ = zero!()..'9';
+ | ^^^^^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:64:9
+ |
+LL | b'a'..b'z' if true => 1,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:65:9
+ |
+LL | b'A'..b'Z' if true => 2,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:66:9
+ |
+LL | b'0'..b'9' if true => 3,
+ | ^^^^--^^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:74:9
+ |
+LL | 'a'..'z' if true => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:75:9
+ |
+LL | 'A'..'Z' if true => 2,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:76:9
+ |
+LL | '0'..'9' if true => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:33:17
+ |
+LL | let _ = 'a'..'z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:34:17
+ |
+LL | let _ = 'A'..'Z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:35:17
+ |
+LL | let _ = '0'..'9';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:90:9
+ |
+LL | 'a'..'z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:91:9
+ |
+LL | 'A'..'Z' => 2,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:92:9
+ |
+LL | '0'..'9' => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `...`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:99:13
+ |
+LL | let _ = 'a'..'z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:100:13
+ |
+LL | let _ = 'A'..'Z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:101:13
+ |
+LL | let _ = '0'..'9';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:103:9
+ |
+LL | 'a'..'z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:104:9
+ |
+LL | 'A'..'Z' => 1,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: almost complete ascii range
+ --> $DIR/almost_complete_range.rs:105:9
+ |
+LL | '0'..'9' => 3,
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+
+error: aborting due to 27 previous errors
+
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:78:13
- |
-LL | let _ = String::new() + "";
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
-
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:86:27
- |
-LL | let inferred_string = string + "";
- | ^^^^^^^^^^^
-
-error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:90:13
- |
-LL | let _ = inferred_string + "";
- | ^^^^^^^^^^^^^^^^^^^^
-
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:165:5
|
LL | _n += 1;
| ^^^^^^^
+ |
+ = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
error: arithmetic operation that can potentially result in unexpected side-effects
--> $DIR/arithmetic_side_effects.rs:166:5
LL | _n = -&_n;
| ^^^^
-error: aborting due to 58 previous errors
+error: aborting due to 55 previous errors
}
#[macro_export]
-macro_rules! almost_complete_letter_range {
+macro_rules! almost_complete_range {
() => {
let _ = 'a'..'z';
+ let _ = 'A'..'Z';
+ let _ = '0'..'9';
};
}
}
}
}
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+ A = u32::MAX as i64 + 1,
+}
}
}
}
+
+#[derive(PartialEq, Debug)]
+#[repr(i64)]
+enum Test {
+ A = u32::MAX as i64 + 1,
+}
// run-rustfix
+#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
fn get_filter() -> char {
.replace('u', iter.next().unwrap())
.replace('s', iter.next().unwrap());
}
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+ let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+ let _ = "".replace(['a', 'b'], "1.58");
+}
// run-rustfix
+#![allow(unused)]
#![warn(clippy::collapsible_str_replace)]
fn get_filter() -> char {
.replace('u', iter.next().unwrap())
.replace('s', iter.next().unwrap());
}
+
+#[clippy::msrv = "1.57"]
+fn msrv_1_57() {
+ let _ = "".replace('a', "1.57").replace('b', "1.57");
+}
+
+#[clippy::msrv = "1.58"]
+fn msrv_1_58() {
+ let _ = "".replace('a', "1.58").replace('b', "1.58");
+}
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:19:27
+ --> $DIR/collapsible_str_replace.rs:20:27
|
LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
= note: `-D clippy::collapsible-str-replace` implied by `-D warnings`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:21:27
+ --> $DIR/collapsible_str_replace.rs:22:27
|
LL | let _ = "hesuo worpd".replace('s', l).replace('u', l);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], l)`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:23:27
+ --> $DIR/collapsible_str_replace.rs:24:27
|
LL | let _ = "hesuo worpd".replace('s', "l").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:26:10
+ --> $DIR/collapsible_str_replace.rs:27:10
|
LL | .replace('s', "l")
| __________^
| |__________________________^ help: replace with: `replace(['s', 'u', 'p', 'd'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:31:27
+ --> $DIR/collapsible_str_replace.rs:32:27
|
LL | let _ = "hesuo world".replace(s, "l").replace('u', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:33:27
+ --> $DIR/collapsible_str_replace.rs:34:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, 'u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:35:27
+ --> $DIR/collapsible_str_replace.rs:36:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:37:27
+ --> $DIR/collapsible_str_replace.rs:38:27
|
LL | let _ = "hesuo worpd".replace(s, "l").replace(u, "l").replace(p, "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([s, u, p], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:39:27
+ --> $DIR/collapsible_str_replace.rs:40:27
|
LL | let _ = "hesuo worlp".replace('s', "l").replace('u', "l").replace('p', "d");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['s', 'u'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:41:45
+ --> $DIR/collapsible_str_replace.rs:42:45
|
LL | let _ = "hesuo worpd".replace('s', "x").replace('u', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['u', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:44:47
+ --> $DIR/collapsible_str_replace.rs:45:47
|
LL | let _ = "hesudo worpd".replace("su", "l").replace('d', "l").replace('p', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['d', 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:46:28
+ --> $DIR/collapsible_str_replace.rs:47:28
|
LL | let _ = "hesudo worpd".replace(d, "l").replace('p', "l").replace("su", "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([d, 'p'], "l")`
error: used consecutive `str::replace` call
- --> $DIR/collapsible_str_replace.rs:48:27
+ --> $DIR/collapsible_str_replace.rs:49:27
|
LL | let _ = "hesuo world".replace(get_filter(), "l").replace('s', "l");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace([get_filter(), 's'], "l")`
-error: aborting due to 13 previous errors
+error: used consecutive `str::replace` call
+ --> $DIR/collapsible_str_replace.rs:86:16
+ |
+LL | let _ = "".replace('a', "1.58").replace('b', "1.58");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `replace(['a', 'b'], "1.58")`
+
+error: aborting due to 14 previous errors
}
}
}
+
+mod issue_10058 {
+ pub fn test() {
+ // should not lint since we are increasing counter potentially more than once in the loop
+ let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+ let mut counter = 0;
+ for value in values {
+ counter += 1;
+
+ if value == 0 {
+ continue;
+ }
+
+ counter += 1;
+ }
+ }
+
+ pub fn test2() {
+ // should not lint since we are increasing counter potentially more than once in the loop
+ let values = [0, 1, 0, 1, 1, 1, 0, 1, 0, 1];
+ let mut counter = 0;
+ for value in values {
+ counter += 1;
+
+ if value != 0 {
+ counter += 1;
+ }
+ }
+ }
+}
// run-rustfix
+#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
#![allow(unused)]
}
}
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+ fn into(self) -> Opaque {}
+}
+
fn main() {}
// run-rustfix
+#![feature(type_alias_impl_trait)]
#![warn(clippy::from_over_into)]
#![allow(unused)]
}
}
+type Opaque = impl Sized;
+struct IntoOpaque;
+impl Into<Opaque> for IntoOpaque {
+ fn into(self) -> Opaque {}
+}
+
fn main() {}
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:9:1
+ --> $DIR/from_over_into.rs:10:1
|
LL | impl Into<StringWrapper> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:17:1
+ --> $DIR/from_over_into.rs:18:1
|
LL | impl Into<SelfType> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:32:1
+ --> $DIR/from_over_into.rs:33:1
|
LL | impl Into<SelfKeywords> for X {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:44:1
+ --> $DIR/from_over_into.rs:45:1
|
LL | impl core::convert::Into<bool> for crate::ExplicitPaths {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:77:5
+ --> $DIR/from_over_into.rs:78:5
|
LL | impl<T> Into<FromOverInto<T>> for Vec<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42;
1;
42;
- &x;
+ x;
x;
let mut a = A(String::new());
2 * { a };
(({ a } + 4));
1;
+
+ // Issue #9904
+ let x = 0i32;
+ let _: i32 = x;
}
pub fn decide(a: bool, b: bool) -> u32 {
2 * (0 + { a });
1 * ({ a } + 4);
1 * 1;
+
+ // Issue #9904
+ let x = 0i32;
+ let _: i32 = &x + 0;
}
pub fn decide(a: bool, b: bool) -> u32 {
--> $DIR/identity_op.rs:68:5
|
LL | &x >> 0;
- | ^^^^^^^ help: consider reducing it to: `&x`
+ | ^^^^^^^ help: consider reducing it to: `x`
error: this operation has no effect
--> $DIR/identity_op.rs:69:5
| ^^^^^ help: consider reducing it to: `1`
error: this operation has no effect
- --> $DIR/identity_op.rs:118:5
+ --> $DIR/identity_op.rs:118:18
+ |
+LL | let _: i32 = &x + 0;
+ | ^^^^^^ help: consider reducing it to: `x`
+
+error: this operation has no effect
+ --> $DIR/identity_op.rs:122:5
|
LL | 0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })`
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
let _ = (**pathbuf_ref).clone();
+
+ struct NoClone;
+ impl ToOwned for NoClone {
+ type Owned = Self;
+ fn to_owned(&self) -> Self {
+ NoClone
+ }
+ }
+ let no_clone = &NoClone;
+ let _ = no_clone.to_owned();
}
let pathbuf_ref = &pathbuf_ref;
let _ = pathbuf_ref.to_owned(); // Don't lint. Returns `&&PathBuf`
let _ = pathbuf_ref.to_path_buf();
+
+ struct NoClone;
+ impl ToOwned for NoClone {
+ type Owned = Self;
+ fn to_owned(&self) -> Self {
+ NoClone
+ }
+ }
+ let no_clone = &NoClone;
+ let _ = no_clone.to_owned();
}
#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
const ARR: [i32; 2] = [1, 2];
-const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr.
+const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
const fn idx() -> usize {
x[3]; // Ok, should not produce stderr.
x[const { idx() }]; // Ok, should not produce stderr.
x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
- const { &ARR[idx()] }; // Ok, should not produce stderr.
- const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+ const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
let y = &x;
y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:9:20
+ |
+LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:10:24
+ |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+ | ^^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+
error[E0080]: evaluation of `main::{constant#3}` failed
--> $DIR/indexing_slicing_index.rs:31:14
|
-LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
note: erroneous constant used
--> $DIR/indexing_slicing_index.rs:31:5
|
-LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
| ^^^^^^^^^^^^^^^^^^^^^^
error: indexing may panic
| ^^^^^^^^
|
= help: consider using `.get(n)` or `.get_mut(n)` instead
- = note: `-D clippy::indexing-slicing` implied by `-D warnings`
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:30:14
+ |
+LL | const { &ARR[idx()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
+
+error: indexing may panic
+ --> $DIR/indexing_slicing_index.rs:31:14
+ |
+LL | const { &ARR[idx4()] }; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
+ | ^^^^^^^^^^^
+ |
+ = help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: the suggestion might not be applicable in constant blocks
error: indexing may panic
--> $DIR/indexing_slicing_index.rs:38:5
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
-error: aborting due to 8 previous errors
+error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0080`.
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
+extern crate core;
+use core::ops::Deref;
+
pub struct One;
struct Wither;
}
}
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+ type Target = DerefToString;
+
+ fn deref(&self) -> &Self::Target {
+ &DerefToString {}
+ }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "Hello, world!"
+ }
+}
+
fn main() {
let x = [1, 2];
if x.is_empty() {
if "".is_empty() {}
+ let s = "Hello, world!";
+ let s1 = &s;
+ let s2 = &s1;
+ let s3 = &s2;
+ let s4 = &s3;
+ let s5 = &s4;
+ let s6 = &s5;
+ println!("{}", s1.is_empty());
+ println!("{}", s2.is_empty());
+ println!("{}", s3.is_empty());
+ println!("{}", s4.is_empty());
+ println!("{}", s5.is_empty());
+ println!("{}", (s6).is_empty());
+
+ let d2s = DerefToDerefToString {};
+ println!("{}", (**d2s).is_empty());
+
let y = One;
if y.len() == 0 {
// No error; `One` does not have `.is_empty()`.
#![warn(clippy::len_zero)]
#![allow(dead_code, unused, clippy::len_without_is_empty)]
+extern crate core;
+use core::ops::Deref;
+
pub struct One;
struct Wither;
}
}
+struct DerefToDerefToString;
+
+impl Deref for DerefToDerefToString {
+ type Target = DerefToString;
+
+ fn deref(&self) -> &Self::Target {
+ &DerefToString {}
+ }
+}
+
+struct DerefToString;
+
+impl Deref for DerefToString {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ "Hello, world!"
+ }
+}
+
fn main() {
let x = [1, 2];
if x.len() == 0 {
if "".len() == 0 {}
+ let s = "Hello, world!";
+ let s1 = &s;
+ let s2 = &s1;
+ let s3 = &s2;
+ let s4 = &s3;
+ let s5 = &s4;
+ let s6 = &s5;
+ println!("{}", *s1 == "");
+ println!("{}", **s2 == "");
+ println!("{}", ***s3 == "");
+ println!("{}", ****s4 == "");
+ println!("{}", *****s5 == "");
+ println!("{}", ******(s6) == "");
+
+ let d2s = DerefToDerefToString {};
+ println!("{}", &**d2s == "");
+
let y = One;
if y.len() == 0 {
// No error; `One` does not have `.is_empty()`.
error: length comparison to zero
- --> $DIR/len_zero.rs:61:8
+ --> $DIR/len_zero.rs:84:8
|
LL | if x.len() == 0 {
| ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `x.is_empty()`
= note: `-D clippy::len-zero` implied by `-D warnings`
error: length comparison to zero
- --> $DIR/len_zero.rs:65:8
+ --> $DIR/len_zero.rs:88:8
|
LL | if "".len() == 0 {}
| ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `"".is_empty()`
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:97:20
+ |
+LL | println!("{}", *s1 == "");
+ | ^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s1.is_empty()`
+ |
+ = note: `-D clippy::comparison-to-empty` implied by `-D warnings`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:98:20
+ |
+LL | println!("{}", **s2 == "");
+ | ^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s2.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:99:20
+ |
+LL | println!("{}", ***s3 == "");
+ | ^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s3.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:100:20
+ |
+LL | println!("{}", ****s4 == "");
+ | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s4.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:101:20
+ |
+LL | println!("{}", *****s5 == "");
+ | ^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `s5.is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:102:20
+ |
+LL | println!("{}", ******(s6) == "");
+ | ^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(s6).is_empty()`
+
+error: comparison to empty slice
+ --> $DIR/len_zero.rs:105:20
+ |
+LL | println!("{}", &**d2s == "");
+ | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `(**d2s).is_empty()`
+
error: length comparison to zero
- --> $DIR/len_zero.rs:80:8
+ --> $DIR/len_zero.rs:120:8
|
LL | if has_is_empty.len() == 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:83:8
+ --> $DIR/len_zero.rs:123:8
|
LL | if has_is_empty.len() != 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:86:8
+ --> $DIR/len_zero.rs:126:8
|
LL | if has_is_empty.len() > 0 {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:89:8
+ --> $DIR/len_zero.rs:129:8
|
LL | if has_is_empty.len() < 1 {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:92:8
+ --> $DIR/len_zero.rs:132:8
|
LL | if has_is_empty.len() >= 1 {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:103:8
+ --> $DIR/len_zero.rs:143:8
|
LL | if 0 == has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:106:8
+ --> $DIR/len_zero.rs:146:8
|
LL | if 0 != has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:109:8
+ --> $DIR/len_zero.rs:149:8
|
LL | if 0 < has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:112:8
+ --> $DIR/len_zero.rs:152:8
|
LL | if 1 <= has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()`
error: length comparison to one
- --> $DIR/len_zero.rs:115:8
+ --> $DIR/len_zero.rs:155:8
|
LL | if 1 > has_is_empty.len() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `has_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:129:8
+ --> $DIR/len_zero.rs:169:8
|
LL | if with_is_empty.len() == 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `with_is_empty.is_empty()`
error: length comparison to zero
- --> $DIR/len_zero.rs:142:8
+ --> $DIR/len_zero.rs:182:8
|
LL | if b.len() != 0 {}
| ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()`
-error: aborting due to 14 previous errors
+error: aborting due to 21 previous errors
panic!("panic5");
}
assert!(!a.is_empty(), "with expansion {}", one!());
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
assert!(!(b.is_empty() || a.is_empty()), "panic4");
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:73:5
+ --> $DIR/manual_assert.rs:78:5
|
LL | / if a > 2 {
LL | | // comment
if a.is_empty() {
panic!("with expansion {}", one!())
}
+ if a.is_empty() {
+ let _ = 0;
+ } else if a.len() == 1 {
+ panic!("panic6");
+ }
}
fn issue7730(a: u8) {
assert!('x'.is_ascii_alphabetic());
assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+ b'0'.is_ascii_digit();
+ b'a'.is_ascii_lowercase();
+ b'A'.is_ascii_uppercase();
+
+ '0'.is_ascii_digit();
+ 'a'.is_ascii_lowercase();
+ 'A'.is_ascii_uppercase();
+
+ let cool_letter = &'g';
+ cool_letter.is_ascii_digit();
+ cool_letter.is_ascii_lowercase();
+ cool_letter.is_ascii_uppercase();
}
#[clippy::msrv = "1.23"]
assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
assert!(matches!('x', 'A'..='Z' | 'a'..='z' | '_'));
+
+ (b'0'..=b'9').contains(&b'0');
+ (b'a'..=b'z').contains(&b'a');
+ (b'A'..=b'Z').contains(&b'A');
+
+ ('0'..='9').contains(&'0');
+ ('a'..='z').contains(&'a');
+ ('A'..='Z').contains(&'A');
+
+ let cool_letter = &'g';
+ ('0'..='9').contains(cool_letter);
+ ('a'..='z').contains(cool_letter);
+ ('A'..='Z').contains(cool_letter);
}
#[clippy::msrv = "1.23"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:29:13
+ --> $DIR/manual_is_ascii_check.rs:19:5
+ |
+LL | (b'0'..=b'9').contains(&b'0');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:20:5
+ |
+LL | (b'a'..=b'z').contains(&b'a');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:21:5
+ |
+LL | (b'A'..=b'Z').contains(&b'A');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:23:5
+ |
+LL | ('0'..='9').contains(&'0');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'0'.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:24:5
+ |
+LL | ('a'..='z').contains(&'a');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'a'.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:25:5
+ |
+LL | ('A'..='Z').contains(&'A');
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'A'.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:28:5
+ |
+LL | ('0'..='9').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_digit()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:29:5
+ |
+LL | ('a'..='z').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_lowercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:30:5
+ |
+LL | ('A'..='Z').contains(cool_letter);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cool_letter.is_ascii_uppercase()`
+
+error: manual check for common ascii range
+ --> $DIR/manual_is_ascii_check.rs:42:13
|
LL | assert!(matches!(b'1', b'0'..=b'9'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `b'1'.is_ascii_digit()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:30:13
+ --> $DIR/manual_is_ascii_check.rs:43:13
|
LL | assert!(matches!('X', 'A'..='Z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'X'.is_ascii_uppercase()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:31:13
+ --> $DIR/manual_is_ascii_check.rs:44:13
|
LL | assert!(matches!('x', 'A'..='Z' | 'a'..='z'));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_alphabetic()`
error: manual check for common ascii range
- --> $DIR/manual_is_ascii_check.rs:41:23
+ --> $DIR/manual_is_ascii_check.rs:54:23
|
LL | const FOO: bool = matches!('x', '0'..='9');
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'x'.is_ascii_digit()`
-error: aborting due to 11 previous errors
+error: aborting due to 20 previous errors
Ok(v) => v,
Err(()) => return,
};
+
+ let f = Variant::Bar(1);
+
+ let _value = match f {
+ Variant::Bar(_) | Variant::Baz(_) => (),
+ _ => return,
+ };
}
fn not_fire() {
LL | | (Some(_), Some(_)) | (None, None) => continue,
LL | | (Some(v), None) | (None, Some(v)) => v,
LL | | };
- | |__________^ help: consider writing: `let (Some(v), None) | (None, Some(v)) = h() else { continue };`
+ | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:49:9
LL | | _ => continue,
LL | | Variant::Bar(v) | Variant::Baz(v) => v,
LL | | };
- | |__________^ help: consider writing: `let Variant::Bar(v) | Variant::Baz(v) = build_enum() else { continue };`
+ | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:57:5
LL | | };
| |______^ help: consider writing: `let Ok(v) = f().map_err(|_| ()) else { return };`
-error: aborting due to 6 previous errors
+error: this could be rewritten as `let...else`
+ --> $DIR/manual_let_else_match.rs:70:5
+ |
+LL | / let _value = match f {
+LL | | Variant::Bar(_) | Variant::Baz(_) => (),
+LL | | _ => return,
+LL | | };
+ | |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
+
+error: aborting due to 7 previous errors
// edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
fn main() {
let _ = 'a'..='z';
// edition:2018
#![warn(clippy::needless_parens_on_range_literals)]
-#![allow(clippy::almost_complete_letter_range)]
+#![allow(clippy::almost_complete_range)]
fn main() {
let _ = ('a')..=('z');
+#![feature(type_alias_impl_trait)]
#![warn(clippy::new_ret_no_self)]
#![allow(dead_code)]
}
}
}
+
+mod issue10041 {
+ struct Bomb;
+
+ impl Bomb {
+ // Hidden <Rhs = Self> default generic paramter.
+ pub fn new() -> impl PartialOrd {
+ 0i32
+ }
+ }
+
+ // TAIT with self-referencing bounds
+ type X = impl std::ops::Add<Output = X>;
+
+ struct Bomb2;
+
+ impl Bomb2 {
+ pub fn new() -> X {
+ 0i32
+ }
+ }
+}
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:49:5
+ --> $DIR/new_ret_no_self.rs:50:5
|
LL | / pub fn new(_: String) -> impl R<Item = u32> {
LL | | S3
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:81:5
+ --> $DIR/new_ret_no_self.rs:82:5
|
LL | / pub fn new() -> u32 {
LL | | unimplemented!();
| |_____^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:90:5
+ --> $DIR/new_ret_no_self.rs:91:5
|
LL | / pub fn new(_: String) -> u32 {
LL | | unimplemented!();
| |_____^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:126:5
+ --> $DIR/new_ret_no_self.rs:127:5
|
LL | / pub fn new() -> (u32, u32) {
LL | | unimplemented!();
| |_____^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:153:5
+ --> $DIR/new_ret_no_self.rs:154:5
|
LL | / pub fn new() -> *mut V {
LL | | unimplemented!();
| |_____^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:171:5
+ --> $DIR/new_ret_no_self.rs:172:5
|
LL | / pub fn new() -> Option<u32> {
LL | | unimplemented!();
| |_____^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:224:9
+ --> $DIR/new_ret_no_self.rs:225:9
|
LL | fn new() -> String;
| ^^^^^^^^^^^^^^^^^^^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:236:9
+ --> $DIR/new_ret_no_self.rs:237:9
|
LL | fn new(_: String) -> String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:271:9
+ --> $DIR/new_ret_no_self.rs:272:9
|
LL | / fn new() -> (u32, u32) {
LL | | unimplemented!();
| |_________^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:298:9
+ --> $DIR/new_ret_no_self.rs:299:9
|
LL | / fn new() -> *mut V {
LL | | unimplemented!();
| |_________^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:368:9
+ --> $DIR/new_ret_no_self.rs:369:9
|
LL | / fn new(t: T) -> impl Into<i32> {
LL | | 1
| |_________^
error: methods called `new` usually return `Self`
- --> $DIR/new_ret_no_self.rs:389:9
+ --> $DIR/new_ret_no_self.rs:390:9
|
LL | / fn new(t: T) -> impl Trait2<(), i32> {
LL | | unimplemented!()
LL | | }
| |_________^
-error: aborting due to 12 previous errors
+error: methods called `new` usually return `Self`
+ --> $DIR/new_ret_no_self.rs:410:9
+ |
+LL | / pub fn new() -> impl PartialOrd {
+LL | | 0i32
+LL | | }
+ | |_________^
+
+error: methods called `new` usually return `Self`
+ --> $DIR/new_ret_no_self.rs:421:9
+ |
+LL | / pub fn new() -> X {
+LL | | 0i32
+LL | | }
+ | |_________^
+
+error: aborting due to 14 previous errors
static STATIC_VAR_ARRAY: &[u8; 1] = b"T"; // ERROR Consider removing 'static.
+static mut STATIC_MUT_SLICE: &mut [u32] = &mut [0];
+
fn main() {
let false_positive: &'static str = "test";
+
+ unsafe {
+ STATIC_MUT_SLICE[0] = 0;
+ }
}
trait Bar {
static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
+static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+
fn main() {
let false_positive: &'static str = "test";
+
+ unsafe {
+ STATIC_MUT_SLICE[0] = 0;
+ }
}
trait Bar {
| -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:65:16
+ --> $DIR/redundant_static_lifetimes.rs:42:31
+ |
+LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
+ | -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]`
+
+error: statics have by default a `'static` lifetime
+ --> $DIR/redundant_static_lifetimes.rs:71:16
|
LL | static V: &'static u8 = &17;
| -^^^^^^^--- help: consider removing `'static`: `&u8`
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
// run-rustfix
+#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
#![allow(clippy::blocks_in_if_conditions)]
#![allow(clippy::box_collection)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
+#![warn(clippy::almost_complete_range)]
#![warn(clippy::disallowed_names)]
#![warn(clippy::blocks_in_if_conditions)]
#![warn(clippy::blocks_in_if_conditions)]
// run-rustfix
+#![allow(clippy::almost_complete_range)]
#![allow(clippy::disallowed_names)]
#![allow(clippy::blocks_in_if_conditions)]
#![allow(clippy::box_collection)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
+#![warn(clippy::almost_complete_letter_range)]
#![warn(clippy::blacklisted_name)]
#![warn(clippy::block_in_if_condition_expr)]
#![warn(clippy::block_in_if_condition_stmt)]
+error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
+ --> $DIR/rename.rs:41:9
+ |
+LL | #![warn(clippy::almost_complete_letter_range)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
+ |
+ = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
- --> $DIR/rename.rs:40:9
+ --> $DIR/rename.rs:42:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
- |
- = note: `-D renamed-and-removed-lints` implied by `-D warnings`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:41:9
+ --> $DIR/rename.rs:43:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:42:9
+ --> $DIR/rename.rs:44:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
- --> $DIR/rename.rs:43:9
+ --> $DIR/rename.rs:45:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> $DIR/rename.rs:44:9
+ --> $DIR/rename.rs:46:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> $DIR/rename.rs:45:9
+ --> $DIR/rename.rs:47:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
- --> $DIR/rename.rs:46:9
+ --> $DIR/rename.rs:48:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
- --> $DIR/rename.rs:47:9
+ --> $DIR/rename.rs:49:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
- --> $DIR/rename.rs:48:9
+ --> $DIR/rename.rs:50:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> $DIR/rename.rs:49:9
+ --> $DIR/rename.rs:51:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> $DIR/rename.rs:50:9
+ --> $DIR/rename.rs:52:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> $DIR/rename.rs:51:9
+ --> $DIR/rename.rs:53:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> $DIR/rename.rs:52:9
+ --> $DIR/rename.rs:54:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> $DIR/rename.rs:53:9
+ --> $DIR/rename.rs:55:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:54:9
+ --> $DIR/rename.rs:56:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:55:9
+ --> $DIR/rename.rs:57:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:56:9
+ --> $DIR/rename.rs:58:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:57:9
+ --> $DIR/rename.rs:59:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> $DIR/rename.rs:58:9
+ --> $DIR/rename.rs:60:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:59:9
+ --> $DIR/rename.rs:61:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:60:9
+ --> $DIR/rename.rs:62:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:61:9
+ --> $DIR/rename.rs:63:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
- --> $DIR/rename.rs:62:9
+ --> $DIR/rename.rs:64:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> $DIR/rename.rs:63:9
+ --> $DIR/rename.rs:65:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
- --> $DIR/rename.rs:64:9
+ --> $DIR/rename.rs:66:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
- --> $DIR/rename.rs:65:9
+ --> $DIR/rename.rs:67:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> $DIR/rename.rs:66:9
+ --> $DIR/rename.rs:68:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:67:9
+ --> $DIR/rename.rs:69:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:68:9
+ --> $DIR/rename.rs:70:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
- --> $DIR/rename.rs:69:9
+ --> $DIR/rename.rs:71:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> $DIR/rename.rs:70:9
+ --> $DIR/rename.rs:72:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> $DIR/rename.rs:71:9
+ --> $DIR/rename.rs:73:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> $DIR/rename.rs:72:9
+ --> $DIR/rename.rs:74:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
- --> $DIR/rename.rs:73:9
+ --> $DIR/rename.rs:75:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> $DIR/rename.rs:74:9
+ --> $DIR/rename.rs:76:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> $DIR/rename.rs:75:9
+ --> $DIR/rename.rs:77:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> $DIR/rename.rs:76:9
+ --> $DIR/rename.rs:78:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> $DIR/rename.rs:77:9
+ --> $DIR/rename.rs:79:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> $DIR/rename.rs:78:9
+ --> $DIR/rename.rs:80:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> $DIR/rename.rs:79:9
+ --> $DIR/rename.rs:81:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
-error: aborting due to 40 previous errors
+error: aborting due to 41 previous errors
t.seek(SeekFrom::End(0));
}
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+ let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
fn main() {
let mut f = OpenOptions::new()
.write(true)
t.seek(SeekFrom::End(0));
}
+// This should NOT trigger clippy warning because
+// expr is used here
+fn seek_to_start_in_let<T: Seek>(t: &mut T) {
+ let a = t.seek(SeekFrom::Start(0)).unwrap();
+}
+
fn main() {
let mut f = OpenOptions::new()
.write(true)
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
error: used `seek` to go to the start of the stream
- --> $DIR/seek_to_start_instead_of_rewind.rs:128:7
+ --> $DIR/seek_to_start_instead_of_rewind.rs:134:7
|
LL | f.seek(SeekFrom::Start(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
--- /dev/null
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()); }
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
--- /dev/null
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_inside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
--- /dev/null
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:39:5
+ |
+LL | { unit_fn_block() };
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-inside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block() };
+LL + { unit_fn_block(); }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:40:5
+ |
+LL | unsafe { unit_fn_block() };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block() };
+LL + unsafe { unit_fn_block(); }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:48:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block()
+LL | | };
+ | |______^
+ |
+help: put the `;` here
+ |
+LL ~ unit_fn_block();
+LL ~ }
+ |
+
+error: consider moving the `;` inside the block for consistent formatting
+ --> $DIR/semicolon_inside_block.rs:61:5
+ |
+LL | { m!(()) };
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()) };
+LL + { m!(()); }
+ |
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()) };
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
--- /dev/null
+// run-rustfix
+#![allow(
+ unused,
+ clippy::unused_unit,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::single_element_loop
+)]
+#![warn(clippy::semicolon_outside_block)]
+
+macro_rules! m {
+ (()) => {
+ ()
+ };
+ (0) => {{
+ 0
+ };};
+ (1) => {{
+ 1;
+ }};
+ (2) => {{
+ 2;
+ }};
+}
+
+fn unit_fn_block() {
+ ()
+}
+
+#[rustfmt::skip]
+fn main() {
+ { unit_fn_block() }
+ unsafe { unit_fn_block() }
+
+ {
+ unit_fn_block()
+ }
+
+ { unit_fn_block() };
+ unsafe { unit_fn_block() };
+
+ { unit_fn_block(); }
+ unsafe { unit_fn_block(); }
+
+ { unit_fn_block(); };
+ unsafe { unit_fn_block(); };
+
+ {
+ unit_fn_block();
+ unit_fn_block()
+ };
+ {
+ unit_fn_block();
+ unit_fn_block();
+ }
+ {
+ unit_fn_block();
+ unit_fn_block();
+ };
+
+ { m!(()) };
+ { m!(()); }
+ { m!(()); };
+ m!(0);
+ m!(1);
+ m!(2);
+
+ for _ in [()] {
+ unit_fn_block();
+ }
+ for _ in [()] {
+ unit_fn_block()
+ }
+
+ let _d = || {
+ unit_fn_block();
+ };
+ let _d = || {
+ unit_fn_block()
+ };
+
+ { unit_fn_block(); };
+
+ unit_fn_block()
+}
--- /dev/null
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:42:5
+ |
+LL | { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::semicolon-outside-block` implied by `-D warnings`
+help: put the `;` here
+ |
+LL - { unit_fn_block(); }
+LL + { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:43:5
+ |
+LL | unsafe { unit_fn_block(); }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - unsafe { unit_fn_block(); }
+LL + unsafe { unit_fn_block() };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:52:5
+ |
+LL | / {
+LL | | unit_fn_block();
+LL | | unit_fn_block();
+LL | | }
+ | |_____^
+ |
+help: put the `;` here
+ |
+LL ~ unit_fn_block()
+LL ~ };
+ |
+
+error: consider moving the `;` outside the block for consistent formatting
+ --> $DIR/semicolon_outside_block.rs:62:5
+ |
+LL | { m!(()); }
+ | ^^^^^^^^^^^
+ |
+help: put the `;` here
+ |
+LL - { m!(()); }
+LL + { m!(()) };
+ |
+
+error: aborting due to 4 previous errors
+
let includestr = include_bytes!("string_lit_as_bytes.rs");
let _ = b"string with newline\t\n";
+
+ let _ = match "x".as_bytes() {
+ b"xx" => 0,
+ [b'x', ..] => 1,
+ _ => 2,
+ };
}
fn main() {}
let includestr = include_str!("string_lit_as_bytes.rs").as_bytes();
let _ = "string with newline\t\n".as_bytes();
+
+ let _ = match "x".as_bytes() {
+ b"xx" => 0,
+ [b'x', ..] => 1,
+ _ => 2,
+ };
}
fn main() {}
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {}", var);
+ debug_assert!(var == 1, "p6 {}", var);
}
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {var}");
+ debug_assert!(var == 1, "p6 {var}");
}
LL + panic!("p3 {var}");
|
-error: aborting due to 4 previous errors
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:30:5
+ |
+LL | assert!(var == 1, "p5 {}", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - assert!(var == 1, "p5 {}", var);
+LL + assert!(var == 1, "p5 {var}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:31:5
+ |
+LL | debug_assert!(var == 1, "p6 {}", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - debug_assert!(var == 1, "p6 {}", var);
+LL + debug_assert!(var == 1, "p6 {var}");
+ |
+
+error: aborting due to 6 previous errors
panic!("p4 {var}");
}
}
+
+ assert!(var == 1, "p5 {}", var);
+ debug_assert!(var == 1, "p6 {}", var);
}
Key(v.to_vec())
}
}
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+ #![allow(unused)]
+
+ pub struct Iri<T>(T);
+
+ impl<T: AsRef<str>> Iri<T> {
+ pub fn parse(iri: T) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+
+ pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+ let base_iri = Iri::parse(url.to_owned())?;
+ Ok(())
+ }
+}
Key(v.to_vec())
}
}
+
+// This is a watered down version of the code in: https://github.com/oxigraph/rio
+// The ICE is triggered by the call to `to_owned` on this line:
+// https://github.com/oxigraph/rio/blob/66635b9ff8e5423e58932353fa40d6e64e4820f7/testsuite/src/parser_evaluator.rs#L116
+mod issue_10021 {
+ #![allow(unused)]
+
+ pub struct Iri<T>(T);
+
+ impl<T: AsRef<str>> Iri<T> {
+ pub fn parse(iri: T) -> Result<Self, ()> {
+ unimplemented!()
+ }
+ }
+
+ pub fn parse_w3c_rdf_test_file(url: &str) -> Result<(), ()> {
+ let base_iri = Iri::parse(url.to_owned())?;
+ Ok(())
+ }
+}
--- /dev/null
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _ = core::ptr::null::<usize>();
+ let _ = core::ptr::null_mut::<f64>();
+ let _: *const u8 = core::ptr::null();
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
--- /dev/null
+// run-rustfix
+
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![deny(clippy::zero_ptr)]
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _ = 0 as *const usize;
+ let _ = 0 as *mut f64;
+ let _: *const u8 = 0 as *const _;
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
--- /dev/null
+error: `0 as *const _` detected
+ --> $DIR/zero_ptr_no_std.rs:9:13
+ |
+LL | let _ = 0 as *const usize;
+ | ^^^^^^^^^^^^^^^^^ help: try: `core::ptr::null::<usize>()`
+ |
+note: the lint level is defined here
+ --> $DIR/zero_ptr_no_std.rs:5:9
+ |
+LL | #![deny(clippy::zero_ptr)]
+ | ^^^^^^^^^^^^^^^^
+
+error: `0 as *mut _` detected
+ --> $DIR/zero_ptr_no_std.rs:10:13
+ |
+LL | let _ = 0 as *mut f64;
+ | ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::<f64>()`
+
+error: `0 as *const _` detected
+ --> $DIR/zero_ptr_no_std.rs:11:24
+ |
+LL | let _: *const u8 = 0 as *const _;
+ | ^^^^^^^^^^^^^ help: try: `core::ptr::null()`
+
+error: aborting due to 3 previous errors
+
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(clippy::single_match_else)]
-use rustc_tools_util::VersionInfo;
use std::fs;
#[test]
[relabel]
allow-unauthenticated = [
"A-*", "C-*", "E-*", "I-*", "L-*", "P-*", "S-*", "T-*",
- "good-first-issue"
+ "good-first-issue", "beta-nominated"
]
# Allows shortcuts like `@rustbot ready`
let has_asm_support = config.has_asm_support();
let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
+ let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
&& config.parse_name_directive(ln, "needs-sanitizer-support");
ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
ignore |= !has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi");
+ ignore |= !has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi");
ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
rustc.args(&["--json", "future-incompat"]);
}
rustc.arg("-Ccodegen-units=1");
+ // Hide line numbers to reduce churn
rustc.arg("-Zui-testing");
+ // Hide libstd sources from ui tests to make sure we generate the stderr
+ // output that users will see.
+ // Without this, we may be producing good diagnostics in-tree but users
+ // will not see half the information.
+ rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+ rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
rustc.arg("-Zdeduplicate-diagnostics=no");
// FIXME: use this for other modes too, for perf?
rustc.arg("-Cstrip=debuginfo");
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
// Virtual `/rustc/$sha` coming from download-rustc:
std::env::var_os("FAKE_DOWNLOAD_RUSTC_PREFIX").map(PathBuf::from),
+ // Tests using -Zsimulate-remapped-rust-src-base should use this fake path
+ Some("/rustc/FAKE_PREFIX".into()),
];
for base_dir in source_bases {
if let Some(base_dir) = base_dir {
"x86_64-unknown-netbsd",
];
+pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"];
+
pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
// FIXME: currently broken, see #88132
// "aarch64-apple-darwin",
use crate::*;
pub mod stacked_borrows;
-use stacked_borrows::diagnostics::RetagCause;
pub type CallId = NonZeroU64;
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
- fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+ fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
let this = self.eval_context_mut();
let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
match method {
- BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place),
+ BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
+ }
+ }
+
+ fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+ let this = self.eval_context_mut();
+ let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+ match method {
+ BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
}
}
Operation::Dealloc(_) => format!(" due to deallocation"),
Operation::Access(AccessOp { kind, tag, .. }) =>
format!(" due to {kind:?} access for {tag:?}"),
- Operation::Retag(RetagOp { orig_tag, permission, .. }) => {
+ Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
let permission = permission
.expect("start_grant should set the current permission before popping a tag");
- format!(" due to {permission:?} retag from {orig_tag:?}")
+ format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
}
};
//! Implements "Stacked Borrows". See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
//! for further information.
+pub mod diagnostics;
+mod item;
+mod stack;
+
use log::trace;
use std::cmp;
-use std::fmt::{self, Write};
+use std::fmt::Write;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::{Mutability, RetagKind};
use crate::borrow_tracker::{
stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
- AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields,
+ AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
};
use crate::*;
-mod item;
+use diagnostics::RetagCause;
pub use item::{Item, Permission};
-mod stack;
pub use stack::Stack;
-pub mod diagnostics;
pub type AllocState = Stacks;
modified_since_last_gc: bool,
}
-/// Indicates which kind of reference is being created.
-/// Used by high-level `reborrow` to compute which permissions to grant to the
-/// new pointer.
-#[derive(Copy, Clone, Hash, PartialEq, Eq)]
-enum RefKind {
- /// `Box`.
- Box,
- /// `&mut`.
- Unique { two_phase: bool },
- /// `&` with or without interior mutability.
- Shared,
- /// `*mut`/`*const` (raw pointers).
- Raw { mutable: bool },
+/// Indicates which permissions to grant to the retagged pointer.
+#[derive(Clone, Debug)]
+enum NewPermission {
+ Uniform {
+ perm: Permission,
+ access: Option<AccessKind>,
+ protector: Option<ProtectorKind>,
+ },
+ FreezeSensitive {
+ freeze_perm: Permission,
+ freeze_access: Option<AccessKind>,
+ freeze_protector: Option<ProtectorKind>,
+ nonfreeze_perm: Permission,
+ nonfreeze_access: Option<AccessKind>,
+ // nonfreeze_protector must always be None
+ },
}
-impl fmt::Display for RefKind {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl NewPermission {
+ /// A key function: determine the permissions to grant at a retag for the given kind of
+ /// reference/pointer.
+ fn from_ref_ty<'tcx>(
+ ty: ty::Ty<'tcx>,
+ kind: RetagKind,
+ cx: &crate::MiriInterpCx<'_, 'tcx>,
+ ) -> Self {
+ let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+ match ty.kind() {
+ ty::Ref(_, pointee, Mutability::Mut) => {
+ if kind == RetagKind::TwoPhase {
+ // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers.
+ assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase.
+ NewPermission::Uniform {
+ perm: Permission::SharedReadWrite,
+ access: None,
+ protector: None,
+ }
+ } else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
+ // A regular full mutable reference.
+ NewPermission::Uniform {
+ perm: Permission::Unique,
+ access: Some(AccessKind::Write),
+ protector,
+ }
+ } else {
+ NewPermission::Uniform {
+ perm: Permission::SharedReadWrite,
+ // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+ // should do fake accesses here. But then we run into
+ // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+ // we don't do that.
+ access: None,
+ protector,
+ }
+ }
+ }
+ ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => {
+ assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+ // Mutable raw pointer. No access, not protected.
+ NewPermission::Uniform {
+ perm: Permission::SharedReadWrite,
+ access: None,
+ protector: None,
+ }
+ }
+ ty::Ref(_, _pointee, Mutability::Not) => {
+ NewPermission::FreezeSensitive {
+ freeze_perm: Permission::SharedReadOnly,
+ freeze_access: Some(AccessKind::Read),
+ freeze_protector: protector,
+ nonfreeze_perm: Permission::SharedReadWrite,
+ // Inside UnsafeCell, this does *not* count as an access, as there
+ // might actually be mutable references further up the stack that
+ // we have to keep alive.
+ nonfreeze_access: None,
+ // We do not protect inside UnsafeCell.
+ // This fixes https://github.com/rust-lang/rust/issues/55005.
+ }
+ }
+ ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => {
+ assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+ // `*const T`, when freshly created, are read-only in the frozen part.
+ NewPermission::FreezeSensitive {
+ freeze_perm: Permission::SharedReadOnly,
+ freeze_access: Some(AccessKind::Read),
+ freeze_protector: None,
+ nonfreeze_perm: Permission::SharedReadWrite,
+ nonfreeze_access: None,
+ }
+ }
+ _ => unreachable!(),
+ }
+ }
+
+ fn protector(&self) -> Option<ProtectorKind> {
match self {
- RefKind::Box => write!(f, "Box"),
- RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
- RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
- RefKind::Shared => write!(f, "shared reference"),
- RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"),
- RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"),
+ NewPermission::Uniform { protector, .. } => *protector,
+ NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector,
}
}
}
&mut self,
place: &MPlaceTy<'tcx, Provenance>,
size: Size,
- kind: RefKind,
- retag_cause: RetagCause, // What caused this retag, for diagnostics only
+ new_perm: NewPermission,
new_tag: BorTag,
- protect: Option<ProtectorKind>,
+ retag_cause: RetagCause, // What caused this retag, for diagnostics only
) -> InterpResult<'tcx, Option<AllocId>> {
let this = self.eval_context_mut();
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
let ty = place.layout.ty;
if global.tracked_pointer_tags.contains(&new_tag) {
- let mut kind_str = format!("{kind}");
- match kind {
- RefKind::Unique { two_phase: false }
- if !ty.is_unpin(*this.tcx, this.param_env()) =>
- {
- write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
- },
- RefKind::Shared
- if !ty.is_freeze(*this.tcx, this.param_env()) =>
- {
- write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
- },
- _ => write!(kind_str, " (pointee type {ty})").unwrap(),
- };
+ let mut kind_str = String::new();
+ match new_perm {
+ NewPermission::Uniform { perm, .. } =>
+ write!(kind_str, "{perm:?} permission").unwrap(),
+ NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) =>
+ write!(kind_str, "{freeze_perm:?} permission").unwrap(),
+ NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } =>
+ write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),
+ }
+ write!(kind_str, " (pointee type {ty})").unwrap();
this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
new_tag.inner(),
Some(kind_str),
);
let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
dcx.log_creation();
- if protect.is_some() {
+ if new_perm.protector().is_some() {
dcx.log_protector();
}
},
if size == Size::ZERO {
trace!(
- "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
- kind,
+ "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
new_tag,
place.ptr,
place.layout.ty,
}
trace!(
- "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
- kind,
+ "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
new_tag,
orig_tag,
place.layout.ty,
size.bytes()
);
- if let Some(protect) = protect {
+ if let Some(protect) = new_perm.protector() {
// See comment in `Stack::item_invalidated` for why we store the tag twice.
this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
this.machine
.insert(new_tag, protect);
}
- // Update the stacks.
- // Make sure that raw pointers and mutable shared references are reborrowed "weak":
- // There could be existing unique pointers reborrowed from them that should remain valid!
- let (perm, access) = match kind {
- RefKind::Unique { two_phase } => {
- // Permission is Unique only if the type is `Unpin` and this is not twophase
- if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
- (Permission::Unique, Some(AccessKind::Write))
- } else {
- // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
- // should do fake accesses here. But then we run into
- // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
- // we don't do that.
- (Permission::SharedReadWrite, None)
+ // Update the stacks, according to the new permission information we are given.
+ match new_perm {
+ NewPermission::Uniform { perm, access, protector } => {
+ assert!(perm != Permission::SharedReadOnly);
+ // Here we can avoid `borrow()` calls because we have mutable references.
+ // Note that this asserts that the allocation is mutable -- but since we are creating a
+ // mutable pointer, that seems reasonable.
+ let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
+ let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
+ let item = Item::new(new_tag, perm, protector.is_some());
+ let range = alloc_range(base_offset, size);
+ let global = machine.borrow_tracker.as_ref().unwrap().borrow();
+ let dcx = DiagnosticCxBuilder::retag(
+ machine,
+ retag_cause,
+ new_tag,
+ orig_tag,
+ alloc_range(base_offset, size),
+ );
+ stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
+ stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
+ })?;
+ drop(global);
+ if let Some(access) = access {
+ assert_eq!(access, AccessKind::Write);
+ // Make sure the data race model also knows about this.
+ if let Some(data_race) = alloc_extra.data_race.as_mut() {
+ data_race.write(alloc_id, range, machine)?;
+ }
}
}
- RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
- RefKind::Raw { mutable: true } => {
- // Creating a raw ptr does not count as an access
- (Permission::SharedReadWrite, None)
- }
- RefKind::Shared | RefKind::Raw { mutable: false } => {
- // Shared references and *const are a whole different kind of game, the
- // permission is not uniform across the entire range!
+ NewPermission::FreezeSensitive {
+ freeze_perm,
+ freeze_access,
+ freeze_protector,
+ nonfreeze_perm,
+ nonfreeze_access,
+ } => {
+ // The permission is not uniform across the entire range!
// We need a frozen-sensitive reborrow.
// We have to use shared references to alloc/memory_extra here since
// `visit_freeze_sensitive` needs to access the global state.
// Adjust range.
range.start += base_offset;
// We are only ever `SharedReadOnly` inside the frozen bits.
- let (perm, access) = if frozen {
- (Permission::SharedReadOnly, Some(AccessKind::Read))
- } else {
- // Inside UnsafeCell, this does *not* count as an access, as there
- // might actually be mutable references further up the stack that
- // we have to keep alive.
- (Permission::SharedReadWrite, None)
- };
- let protected = if frozen {
- protect.is_some()
+ let (perm, access, protector) = if frozen {
+ (freeze_perm, freeze_access, freeze_protector)
} else {
- // We do not protect inside UnsafeCell.
- // This fixes https://github.com/rust-lang/rust/issues/55005.
- false
+ (nonfreeze_perm, nonfreeze_access, None)
};
- let item = Item::new(new_tag, perm, protected);
+ let item = Item::new(new_tag, perm, protector.is_some());
let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
let dcx = DiagnosticCxBuilder::retag(
&this.machine,
}
Ok(())
})?;
- return Ok(Some(alloc_id));
- }
- };
-
- // Here we can avoid `borrow()` calls because we have mutable references.
- // Note that this asserts that the allocation is mutable -- but since we are creating a
- // mutable pointer, that seems reasonable.
- let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
- let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
- let item = Item::new(new_tag, perm, protect.is_some());
- let range = alloc_range(base_offset, size);
- let global = machine.borrow_tracker.as_ref().unwrap().borrow();
- let dcx = DiagnosticCxBuilder::retag(
- machine,
- retag_cause,
- new_tag,
- orig_tag,
- alloc_range(base_offset, size),
- );
- stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
- stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
- })?;
- drop(global);
- if let Some(access) = access {
- assert_eq!(access, AccessKind::Write);
- // Make sure the data race model also knows about this.
- if let Some(data_race) = alloc_extra.data_race.as_mut() {
- data_race.write(alloc_id, range, machine)?;
}
}
fn sb_retag_reference(
&mut self,
val: &ImmTy<'tcx, Provenance>,
- kind: RefKind,
- retag_cause: RetagCause, // What caused this retag, for diagnostics only
- protect: Option<ProtectorKind>,
+ new_perm: NewPermission,
+ cause: RetagCause, // What caused this retag, for diagnostics only
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
let this = self.eval_context_mut();
// We want a place for where the ptr *points to*, so we get one.
let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
// Reborrow.
- let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?;
+ let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
// Adjust pointer.
let new_place = place.map_provenance(|p| {
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
- fn sb_retag(
+ fn sb_retag_ptr_value(
+ &mut self,
+ kind: RetagKind,
+ val: &ImmTy<'tcx, Provenance>,
+ ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+ let this = self.eval_context_mut();
+ let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
+ let retag_cause = match kind {
+ RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+ RetagKind::FnEntry => unreachable!(),
+ RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+ };
+ this.sb_retag_reference(&val, new_perm, retag_cause)
+ }
+
+ fn sb_retag_place_contents(
&mut self,
kind: RetagKind,
place: &PlaceTy<'tcx, Provenance>,
let this = self.eval_context_mut();
let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
let retag_cause = match kind {
- RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+ RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value`
RetagKind::FnEntry => RetagCause::FnEntry,
- RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+ RetagKind::Default => RetagCause::Normal,
};
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
return visitor.visit_value(place);
}
impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
#[inline(always)] // yes this helps in our benchmarks
- fn retag_place(
+ fn retag_ptr_inplace(
&mut self,
place: &PlaceTy<'tcx, Provenance>,
- ref_kind: RefKind,
+ new_perm: NewPermission,
retag_cause: RetagCause,
- protector: Option<ProtectorKind>,
) -> InterpResult<'tcx> {
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
- let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?;
+ let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
self.ecx.write_immediate(*val, place)?;
Ok(())
}
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
// Boxes get a weak protectors, since they may be deallocated.
- self.retag_place(
- place,
- RefKind::Box,
- self.retag_cause,
- /*protector*/
- (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
- )
+ let new_perm = NewPermission::Uniform {
+ perm: Permission::Unique,
+ access: Some(AccessKind::Write),
+ protector: (self.kind == RetagKind::FnEntry)
+ .then_some(ProtectorKind::WeakProtector),
+ };
+ self.retag_ptr_inplace(place, new_perm, self.retag_cause)
}
fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
// Check the type of this value to see what to do with it (retag, or recurse).
match place.layout.ty.kind() {
- ty::Ref(_, _, mutbl) => {
- let ref_kind = match mutbl {
- Mutability::Mut =>
- RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
- Mutability::Not => RefKind::Shared,
- };
- self.retag_place(
- place,
- ref_kind,
- self.retag_cause,
- /*protector*/
- (self.kind == RetagKind::FnEntry)
- .then_some(ProtectorKind::StrongProtector),
- )?;
+ ty::Ref(..) => {
+ let new_perm =
+ NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
+ self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
}
- ty::RawPtr(tym) => {
- // We definitely do *not* want to recurse into raw pointers -- wide raw
- // pointers have fields, and for dyn Trait pointees those can have reference
- // type!
- if self.kind == RetagKind::Raw {
- // Raw pointers need to be enabled.
- self.retag_place(
- place,
- RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
- self.retag_cause,
- /*protector*/ None,
- )?;
- }
+ ty::RawPtr(..) => {
+ // We do *not* want to recurse into raw pointers -- wide raw pointers have
+ // fields, and for dyn Trait pointees those can have reference type!
}
- _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
+ ty::Adt(adt, _) if adt.is_box() => {
// Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
// (Yes this means we technically also recursively retag the allocator itself
// even if field retagging is not enabled. *shrug*)
let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
// Reborrow it. With protection! That is part of the point.
- let val = this.sb_retag_reference(
- &val,
- RefKind::Unique { two_phase: false },
- RetagCause::FnReturn,
- /*protector*/ Some(ProtectorKind::StrongProtector),
- )?;
+ let new_perm = NewPermission::Uniform {
+ perm: Permission::Unique,
+ access: Some(AccessKind::Write),
+ protector: Some(ProtectorKind::StrongProtector),
+ };
+ let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
// And use reborrowed pointer for return place.
let return_place = this.ref_to_mplace(&val)?;
this.frame_mut().return_place = return_place.into();
/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
- /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
+ /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
///
- /// new_kind is `None` for base tags.
+ /// new_perm is `None` for base tags.
CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
/// This `Item` was popped from the borrow stack. The string explains the reason.
PoppedPointerTag(Item, String),
if is_local && idx > 0 {
err.span_note(frame_info.span, &frame_info.to_string());
} else {
- err.note(&frame_info.to_string());
+ let sm = sess.source_map();
+ let span = sm.span_to_embeddable_string(frame_info.span);
+ err.note(format!("{frame_info} at {span}"));
}
}
let msg = match &e {
CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
- CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
- CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
+ CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+ CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
format!(
- "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
+ "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
),
PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
CreatedCallId(id) => format!("function call with id {id}"),
};
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Symbol;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Size, Align};
use rustc_target::spec::abi::Abi;
+use rustc_const_eval::const_eval::CheckAlignment;
use crate::{
concurrency::{data_race, weak_memory},
const PANIC_ON_ALLOC_FAIL: bool = false;
#[inline(always)]
- fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
- ecx.machine.check_alignment != AlignmentCheck::None
+ fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> CheckAlignment {
+ if ecx.machine.check_alignment == AlignmentCheck::None {
+ CheckAlignment::No
+ } else {
+ CheckAlignment::Error
+ }
}
#[inline(always)]
ecx.machine.check_alignment == AlignmentCheck::Int
}
+ fn alignment_check_failed(
+ _ecx: &InterpCx<'mir, 'tcx, Self>,
+ has: Align,
+ required: Align,
+ _check: CheckAlignment,
+ ) -> InterpResult<'tcx, ()> {
+ throw_ub!(AlignmentCheckFailed { has, required })
+ }
+
#[inline(always)]
fn enforce_validity(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
ecx.machine.validate
ptr: Pointer<Self::Provenance>,
) -> InterpResult<'tcx> {
match ptr.provenance {
- Provenance::Concrete { alloc_id, tag } =>
- intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+ Provenance::Concrete { alloc_id, tag } => {
+ intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
+ }
Provenance::Wildcard => {
// No need to do anything for wildcard pointers as
// their provenances have already been previously exposed.
}
#[inline(always)]
- fn retag(
+ fn retag_ptr_value(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ kind: mir::RetagKind,
+ val: &ImmTy<'tcx, Provenance>,
+ ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+ if ecx.machine.borrow_tracker.is_some() {
+ ecx.retag_ptr_value(kind, val)
+ } else {
+ Ok(val.clone())
+ }
+ }
+
+ #[inline(always)]
+ fn retag_place_contents(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
kind: mir::RetagKind,
place: &PlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx> {
if ecx.machine.borrow_tracker.is_some() {
- ecx.retag(kind, place)?;
+ ecx.retag_place_contents(kind, place)?;
}
Ok(())
}
| |_^ the program aborted execution
|
= note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
-note: inside `main` at $DIR/abort-terminator.rs:LL:CC
+note: inside `main`
--> $DIR/abort-terminator.rs:LL:CC
|
LL | panic_abort();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-alignment.rs:LL:CC
+note: inside `main`
--> $DIR/deallocate-bad-alignment.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 2));
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-size.rs:LL:CC
+note: inside `main`
--> $DIR/deallocate-bad-size.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(2, 1));
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-twice.rs:LL:CC
+note: inside `main`
--> $DIR/deallocate-twice.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
= note: BACKTRACE:
= note: inside `std::sys::PLATFORM::alloc::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/PLATFORM/alloc.rs:LL:CC
= note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/global_system_mixup.rs:LL:CC
+note: inside `main`
--> $DIR/global_system_mixup.rs:LL:CC
|
LL | System.deallocate(ptr, l);
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-bad-size.rs:LL:CC
+note: inside `main`
--> $DIR/reallocate-bad-size.rs:LL:CC
|
LL | let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-dangling.rs:LL:CC
+note: inside `main`
--> $DIR/reallocate-dangling.rs:LL:CC
|
LL | let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
= note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside `main` at $DIR/stack_free.rs:LL:CC
+note: inside `main`
--> $DIR/stack_free.rs:LL:CC
|
LL | drop(bad_box);
| ^^^
= note: BACKTRACE:
= note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
-note: inside `main` at $DIR/box-cell-alias.rs:LL:CC
+note: inside `main`
--> $DIR/box-cell-alias.rs:LL:CC
|
LL | let res = helper(val, ptr);
= note: inside `std::sys::PLATFORM::thread::Thread::join` at RUSTLIB/std/src/sys/PLATFORM/thread.rs:LL:CC
= note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
= note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
-note: inside `main` at $DIR/windows_join_detached.rs:LL:CC
+note: inside `main`
--> $DIR/windows_join_detached.rs:LL:CC
|
LL | thread.join().unwrap();
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
= note: BACKTRACE:
-note: inside `main` at $DIR/tokio_mvp.rs:LL:CC
+note: inside `main`
--> $DIR/tokio_mvp.rs:LL:CC
|
LL | #[tokio::main]
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `evil` at $DIR/storage_dead_dangling.rs:LL:CC
-note: inside `main` at $DIR/storage_dead_dangling.rs:LL:CC
+note: inside `main`
--> $DIR/storage_dead_dangling.rs:LL:CC
|
LL | evil();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
-note: inside `main` at $DIR/stack_pop_race.rs:LL:CC
+note: inside `main`
--> $DIR/stack_pop_race.rs:LL:CC
|
LL | race(0);
| |_^ the program aborted execution
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | unsafe { nounwind() }
| |_^ the program aborted execution
|
= note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
--> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
|
LL | unsafe { nounwind() }
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
-note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next`
--> $DIR/generator-pinned-moved.rs:LL:CC
|
LL | match me.resume(()) {
| ^^^^^^^^^^^^^
= note: inside `<std::boxed::Box<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `main`
--> $DIR/generator-pinned-moved.rs:LL:CC
|
LL | generator_iterator_2.next(); // and use moved value
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::simd::Simd::<f32, 2>::to_int_unchecked::<i32>` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-float-to-int.rs:LL:CC
+note: inside `main`
--> $DIR/simd-float-to-int.rs:LL:CC
|
LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::simd::Simd::<i8, 4>::gather_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-gather.rs:LL:CC
+note: inside `main`
--> $DIR/simd-gather.rs:LL:CC
|
LL | let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::simd::Simd::<i8, 4>::scatter_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-scatter.rs:LL:CC
+note: inside `main`
--> $DIR/simd-scatter.rs:LL:CC
|
LL | / Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `FunnyPointer::from_data_ptr` at $DIR/issue-miri-1112.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1112.rs:LL:CC
+note: inside `main`
--> $DIR/issue-miri-1112.rs:LL:CC
|
LL | let _raw: &FunnyPointer = FunnyPointer::from_data_ptr(&hello, &meta as *const _);
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `m::f` at $DIR/never_transmute_void.rs:LL:CC
-note: inside `main` at $DIR/never_transmute_void.rs:LL:CC
+note: inside `main`
--> $DIR/never_transmute_void.rs:LL:CC
|
LL | m::f(v);
= note: inside `std::panicking::r#try::do_call::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panicking::r#try::<(), [closure@$DIR/bad_unwind.rs:LL:CC]>` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::panic::catch_unwind::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panic.rs:LL:CC
-note: inside `main` at $DIR/bad_unwind.rs:LL:CC
+note: inside `main`
--> $DIR/bad_unwind.rs:LL:CC
|
LL | std::panic::catch_unwind(|| unwind()).unwrap_err();
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `<Foo as std::ops::Drop>::drop` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `<Foo as std::ops::Drop>::drop`
--> $DIR/double_panic.rs:LL:CC
|
LL | panic!("second");
| ^
= note: inside `std::ptr::drop_in_place::<Foo> - shim(Some(Foo))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
-note: inside `main` at $DIR/double_panic.rs:LL:CC
+note: inside `main`
--> $DIR/double_panic.rs:LL:CC
|
LL | }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the program aborted execution
|
= note: inside `panic_handler` at $DIR/no_std.rs:LL:CC
-note: inside `start` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `start`
--> $DIR/no_std.rs:LL:CC
|
LL | panic!("blarg I am dead")
= note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
--> $DIR/panic_abort1.rs:LL:CC
|
LL | std::panic!("panicking from libstd");
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
--> $DIR/panic_abort2.rs:LL:CC
|
LL | std::panic!("{}-panicking from libstd", 42);
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
--> $DIR/panic_abort3.rs:LL:CC
|
LL | core::panic!("panicking from libcore");
= note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
= note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
= note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
-note: inside `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
--> $DIR/panic_abort4.rs:LL:CC
|
LL | core::panic!("{}-panicking from libcore", 42);
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `deref` at $DIR/provenance_transmute.rs:LL:CC
-note: inside `main` at $DIR/provenance_transmute.rs:LL:CC
+note: inside `main`
--> $DIR/provenance_transmute.rs:LL:CC
|
LL | deref(ptr1, ptr2.with_addr(ptr1.addr()));
= note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC
= note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC
= note: inside `std::fs::File::open::<&str>` at RUSTLIB/std/src/fs.rs:LL:CC
-note: inside `main` at $DIR/isolated_file.rs:LL:CC
+note: inside `main`
--> $DIR/isolated_file.rs:LL:CC
|
LL | let _file = std::fs::File::open("file.txt").unwrap();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `test_mkstemp_immutable_arg` at $DIR/mkstemp_immutable_arg.rs:LL:CC
-note: inside `main` at $DIR/mkstemp_immutable_arg.rs:LL:CC
+note: inside `main`
--> $DIR/mkstemp_immutable_arg.rs:LL:CC
|
LL | test_mkstemp_immutable_arg();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `test_file_open_missing_needed_mode` at $DIR/unix_open_missing_required_mode.rs:LL:CC
-note: inside `main` at $DIR/unix_open_missing_required_mode.rs:LL:CC
+note: inside `main`
--> $DIR/unix_open_missing_required_mode.rs:LL:CC
|
LL | test_file_open_missing_needed_mode();
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `test_cpp20_rwc_syncs` at $DIR/cpp20_rwc_syncs.rs:LL:CC
-note: inside `main` at $DIR/cpp20_rwc_syncs.rs:LL:CC
+note: inside `main`
--> $DIR/cpp20_rwc_syncs.rs:LL:CC
|
LL | test_cpp20_rwc_syncs();
| ^^
= note: BACKTRACE:
= note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut1.rs:LL:CC
+note: inside `main`
--> $DIR/aliasing_mut1.rs:LL:CC
|
LL | safe_raw(xraw, xraw);
| ^^
= note: BACKTRACE:
= note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut2.rs:LL:CC
+note: inside `main`
--> $DIR/aliasing_mut2.rs:LL:CC
|
LL | safe_raw(xshr, xraw);
| ^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut3.rs:LL:CC
+note: inside `main`
--> $DIR/aliasing_mut3.rs:LL:CC
|
LL | safe_raw(xraw, xshr);
| ^^
= note: BACKTRACE:
= note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut4.rs:LL:CC
+note: inside `main`
--> $DIR/aliasing_mut4.rs:LL:CC
|
LL | safe_raw(xshr, xraw as *mut _);
| ^^^^^^^^
= note: BACKTRACE:
= note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
-note: inside `demo_box_advanced_unique` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `demo_box_advanced_unique`
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
LL | unknown_code_2();
| ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `main`
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
LL | demo_box_advanced_unique(Box::new(0));
| ^^^^^
= note: BACKTRACE:
= note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
-note: inside `main` at $DIR/box_noalias_violation.rs:LL:CC
+note: inside `main`
--> $DIR/box_noalias_violation.rs:LL:CC
|
LL | test(Box::from_raw(ptr), ptr);
= note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside closure
--> $DIR/deallocate_against_protector1.rs:LL:CC
|
LL | drop(unsafe { Box::from_raw(raw) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `<[closure@$DIR/deallocate_against_protector1.rs:LL:CC] as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `inner`
--> $DIR/deallocate_against_protector1.rs:LL:CC
|
LL | f(x)
| ^^^^
-note: inside `main` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `main`
--> $DIR/deallocate_against_protector1.rs:LL:CC
|
LL | / inner(Box::leak(Box::new(0)), |x| {
= note: inside `alloc::alloc::box_free::<NotUnpin, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<NotUnpin>> - shim(Some(std::boxed::Box<NotUnpin>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: inside `std::mem::drop::<std::boxed::Box<NotUnpin>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside closure
--> $DIR/deallocate_against_protector2.rs:LL:CC
|
LL | drop(unsafe { Box::from_raw(raw) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: inside `<[closure@$DIR/deallocate_against_protector2.rs:LL:CC] as std::ops::FnOnce<(&mut NotUnpin,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `inner`
--> $DIR/deallocate_against_protector2.rs:LL:CC
|
LL | f(x)
| ^^^^
-note: inside `main` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `main`
--> $DIR/deallocate_against_protector2.rs:LL:CC
|
LL | / inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
| ^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/illegal_deALLOC.rs:LL:CC
+note: inside `main`
--> $DIR/illegal_deALLOC.rs:LL:CC
|
LL | dealloc(ptr2, Layout::from_size_align_unchecked(1, 1));
| ^
= note: BACKTRACE:
= note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
-note: inside `main` at $DIR/illegal_write6.rs:LL:CC
+note: inside `main`
--> $DIR/illegal_write6.rs:LL:CC
|
LL | foo(x, p);
| ^^
= note: BACKTRACE:
= note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector1.rs:LL:CC
+note: inside `main`
--> $DIR/invalidate_against_protector1.rs:LL:CC
|
LL | inner(xraw, xref);
| ^^
= note: BACKTRACE:
= note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector2.rs:LL:CC
+note: inside `main`
--> $DIR/invalidate_against_protector2.rs:LL:CC
|
LL | inner(xraw, xref);
| ^^
= note: BACKTRACE:
= note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector3.rs:LL:CC
+note: inside `main`
--> $DIR/invalidate_against_protector3.rs:LL:CC
|
LL | inner(ptr, &*ptr);
= note: BACKTRACE:
= note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-1.rs:LL:CC
+note: inside `main`
--> $DIR/issue-miri-1050-1.rs:LL:CC
|
LL | drop(Box::from_raw(ptr as *mut u32));
= note: BACKTRACE:
= note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-2.rs:LL:CC
+note: inside `main`
--> $DIR/issue-miri-1050-2.rs:LL:CC
|
LL | drop(Box::from_raw(ptr.as_ptr()));
| ^^^^^^^^
= note: BACKTRACE:
= note: inside `unknown_code_2` at $DIR/mut_exclusive_violation1.rs:LL:CC
-note: inside `demo_mut_advanced_unique` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `demo_mut_advanced_unique`
--> $DIR/mut_exclusive_violation1.rs:LL:CC
|
LL | unknown_code_2();
| ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `main`
--> $DIR/mut_exclusive_violation1.rs:LL:CC
|
LL | demo_mut_advanced_unique(&mut 0);
= note: BACKTRACE:
= note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside closure
--> $DIR/newtype_pair_retagging.rs:LL:CC
|
LL | || drop(Box::from_raw(ptr)),
| ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>`
--> $DIR/newtype_pair_retagging.rs:LL:CC
|
LL | dealloc();
| ^^^^^^^^^
-note: inside `main` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `main`
--> $DIR/newtype_pair_retagging.rs:LL:CC
|
LL | / dealloc_while_running(
= note: BACKTRACE:
= note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_retagging.rs:LL:CC
+note: inside closure
--> $DIR/newtype_retagging.rs:LL:CC
|
LL | || drop(Box::from_raw(ptr)),
| ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>`
--> $DIR/newtype_retagging.rs:LL:CC
|
LL | dealloc();
| ^^^^^^^^^
-note: inside `main` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `main`
--> $DIR/newtype_retagging.rs:LL:CC
|
LL | / dealloc_while_running(
| ^^^^^^^^
= note: BACKTRACE:
= note: inside `fun2` at $DIR/pointer_smuggling.rs:LL:CC
-note: inside `main` at $DIR/pointer_smuggling.rs:LL:CC
+note: inside `main`
--> $DIR/pointer_smuggling.rs:LL:CC
|
LL | fun2(); // if they now use a raw ptr they break our reference
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `thread_2` at $DIR/retag_data_race_read.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_read.rs:LL:CC
+note: inside closure
--> $DIR/retag_data_race_read.rs:LL:CC
|
LL | let t2 = std::thread::spawn(move || thread_2(p));
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `thread_2` at $DIR/retag_data_race_write.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_write.rs:LL:CC
+note: inside closure
--> $DIR/retag_data_race_write.rs:LL:CC
|
LL | let t2 = std::thread::spawn(move || thread_2(p));
| ^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_mut.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_mut.rs:LL:CC
|
LL | foo(&mut (1, 2));
| ^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_option.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_mut_option.rs:LL:CC
|
LL | match foo(&mut (1, 2)) {
| ^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_tuple.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_mut_tuple.rs:LL:CC
|
LL | foo(&mut (1, 2)).0;
| ^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_shr.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_shr.rs:LL:CC
|
LL | foo(&mut (1, 2));
| ^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_option.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_shr_option.rs:LL:CC
|
LL | match foo(&mut (1, 2)) {
| ^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_tuple.rs:LL:CC
+note: inside `main`
--> $DIR/return_invalid_shr_tuple.rs:LL:CC
|
LL | foo(&mut (1, 2)).0;
| ^
= note: BACKTRACE:
= note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
-note: inside `foo` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `foo`
--> $DIR/shr_frozen_violation1.rs:LL:CC
|
LL | unknown_code(&*x);
| ^^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `main`
--> $DIR/shr_frozen_violation1.rs:LL:CC
|
LL | println!("{}", foo(&mut 0));
| ^^^^^^^^^^^^^^^^^^
= note: BACKTRACE:
= note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
-note: inside `main` at $DIR/zst_slice.rs:LL:CC
+note: inside `main`
--> $DIR/zst_slice.rs:LL:CC
|
LL | assert_eq!(*s.get_unchecked(1), 2);
= note: BACKTRACE:
= note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
= note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer.rs:LL:CC
+note: inside `main`
--> $DIR/uninit_buffer.rs:LL:CC
|
LL | drop(slice1.cmp(slice2));
= note: BACKTRACE:
= note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
= note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer_with_provenance.rs:LL:CC
+note: inside `main`
--> $DIR/uninit_buffer_with_provenance.rs:LL:CC
|
LL | drop(slice1.cmp(slice2));
= help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
= note: BACKTRACE:
= note: inside `into_raw` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
--> $DIR/box.rs:LL:CC
|
LL | into_raw();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
|
= note: inside `into_unique` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
--> $DIR/box.rs:LL:CC
|
LL | into_unique();
struct Config {
verbose: bool,
sequential: bool,
+ batch: bool,
bind: SocketAddr,
}
Config {
verbose: false,
sequential: false,
+ batch: false,
bind: if cfg!(target_os = "android") || cfg!(windows) {
([0, 0, 0, 0], 12345).into()
} else {
}
"--bind" => next_is_bind = true,
"--sequential" => config.sequential = true,
+ "--batch" => config.batch = true,
"--verbose" | "-v" => config.verbose = true,
"--help" | "-h" => {
show_help();
OPTIONS:
--bind <IP>:<PORT> Specify IP address and port to listen for requests, e.g. "0.0.0.0:12345"
--sequential Run only one test at a time
+ --batch Send stdout and stderr in batch instead of streaming
-v, --verbose Show status messages
-h, --help Show this help screen
"#,
// Some tests assume RUST_TEST_TMPDIR exists
cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());
- // Spawn the child and ferry over stdout/stderr to the socket in a framed
- // fashion (poor man's style)
- let mut child =
- t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
- drop(lock);
- let mut stdout = child.stdout.take().unwrap();
- let mut stderr = child.stderr.take().unwrap();
let socket = Arc::new(Mutex::new(reader.into_inner()));
- let socket2 = socket.clone();
- let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
- my_copy(&mut stderr, 1, &*socket);
- thread.join().unwrap();
- // Finally send over the exit status.
- let status = t!(child.wait());
+ let status = if config.batch {
+ let child =
+ t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).output());
+ batch_copy(&child.stdout, 0, &*socket);
+ batch_copy(&child.stderr, 1, &*socket);
+ child.status
+ } else {
+ // Spawn the child and ferry over stdout/stderr to the socket in a framed
+ // fashion (poor man's style)
+ let mut child =
+ t!(cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn());
+ drop(lock);
+ let mut stdout = child.stdout.take().unwrap();
+ let mut stderr = child.stderr.take().unwrap();
+ let socket2 = socket.clone();
+ let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
+ my_copy(&mut stderr, 1, &*socket);
+ thread.join().unwrap();
+ t!(child.wait())
+ };
+ // Finally send over the exit status.
let (which, code) = get_status_code(&status);
t!(socket.lock().unwrap().write_all(&[
}
}
+fn batch_copy(buf: &[u8], which: u8, dst: &Mutex<dyn Write>) {
+ let n = buf.len();
+ let mut dst = dst.lock().unwrap();
+ t!(dst.write_all(&[which, (n >> 24) as u8, (n >> 16) as u8, (n >> 8) as u8, (n >> 0) as u8,]));
+ if n > 0 {
+ t!(dst.write_all(buf));
+ // Marking buf finished
+ t!(dst.write_all(&[which, 0, 0, 0, 0,]));
+ }
+}
+
fn read_u32(r: &mut dyn Read) -> u32 {
let mut len = [0; 4];
t!(r.read_exact(&mut len));
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match self {
ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
- ast::NestedMetaItem::Lit(ref l) => rewrite_literal(context, l.token_lit, l.span, shape),
+ ast::NestedMetaItem::Lit(ref l) => {
+ rewrite_literal(context, l.as_token_lit(), l.span, shape)
+ }
}
}
}
}),
)?
}
- ast::MetaItemKind::NameValue(ref literal) => {
+ ast::MetaItemKind::NameValue(ref lit) => {
let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
// 3 = ` = `
let lit_shape = shape.shrink_left(path.len() + 3)?;
- // `rewrite_literal` returns `None` when `literal` exceeds max
+ // `rewrite_literal` returns `None` when `lit` exceeds max
// width. Since a literal is basically unformattable unless it
// is a string literal (and only if `format_strings` is set),
// we might be better off ignoring the fact that the attribute
// is longer than the max width and continue on formatting.
// See #2479 for example.
- let value = rewrite_literal(context, literal.token_lit, literal.span, lit_shape)
- .unwrap_or_else(|| context.snippet(literal.span).to_owned());
+ let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
+ .unwrap_or_else(|| context.snippet(lit.span).to_owned());
format!("{} = {}", path, value)
}
})
("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
+ ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"),
("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
("mach", "BSD-2-Clause"),
("regalloc2", "Apache-2.0 WITH LLVM-exception"),
("target-lexicon", "Apache-2.0 WITH LLVM-exception"),
+ ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"),
];
const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
"snap",
"stable_deref_trait",
"stacker",
+ "static_assertions",
"syn",
"synstructure",
"tempfile",
"tracing-log",
"tracing-subscriber",
"tracing-tree",
+ "twox-hash",
"type-map",
"typenum",
"unic-char-property",
"cranelift-codegen",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
+ "cranelift-egraph",
"cranelift-entity",
"cranelift-frontend",
"cranelift-isle",
"cranelift-native",
"cranelift-object",
"crc32fast",
+ "fallible-iterator",
"fxhash",
"getrandom",
"gimli",
"region",
"slice-group-by",
"smallvec",
+ "stable_deref_trait",
"target-lexicon",
"version_check",
"wasi",
+ "wasmtime-jit-icache-coherence",
"winapi",
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
let bad = std::sync::Arc::new(AtomicBool::new(false));
+ let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
+ // poll all threads for completion before awaiting the oldest one
+ for i in (0..handles.len()).rev() {
+ if handles[i].is_finished() {
+ handles.swap_remove_back(i).unwrap().join().unwrap();
+ }
+ }
+
+ while handles.len() >= concurrency.get() {
+ handles.pop_front().unwrap().join().unwrap();
+ }
+ };
+
scope(|s| {
let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
VecDeque::with_capacity(concurrency.get());
macro_rules! check {
($p:ident $(, $args:expr)* ) => {
- while handles.len() >= concurrency.get() {
- handles.pop_front().unwrap().join().unwrap();
- }
+ drain_handles(&mut handles);
let handle = s.spawn(|| {
let mut flag = false;
check!(alphabetical, &library_path);
let collected = {
- while handles.len() >= concurrency.get() {
- handles.pop_front().unwrap().join().unwrap();
- }
+ drain_handles(&mut handles);
+
let mut flag = false;
let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose);
if flag {
//! `// ignore-tidy-CHECK-NAME`.
use crate::walk::{filter_dirs, walk};
-use regex::Regex;
+use regex::{Regex, RegexSet};
use std::path::Path;
/// Error code markdown is restricted to 80 columns because they can be
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v)))
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
.collect();
+ let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap();
walk(path, &mut skip, &mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
let mut trailing_new_lines = 0;
let mut lines = 0;
let mut last_safety_comment = false;
+ let is_test = file.components().any(|c| c.as_os_str() == "tests");
+ // scanning the whole file for multiple needles at once is more efficient than
+ // executing lines times needles separate searches.
+ let any_problematic_line = problematic_regex.is_match(contents);
for (i, line) in contents.split('\n').enumerate() {
+ if line.is_empty() {
+ if i == 0 {
+ leading_new_lines = true;
+ }
+ trailing_new_lines += 1;
+ continue;
+ } else {
+ trailing_new_lines = 0;
+ }
+
+ let trimmed = line.trim();
+
+ if !trimmed.starts_with("//") {
+ lines += 1;
+ }
+
let mut err = |msg: &str| {
tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
};
suppressible_tidy_err!(err, skip_cr, "CR character");
}
if filename != "style.rs" {
- if line.contains("TODO") {
+ if trimmed.contains("TODO") {
err("TODO is deprecated; use FIXME")
}
- if line.contains("//") && line.contains(" XXX") {
+ if trimmed.contains("//") && trimmed.contains(" XXX") {
err("XXX is deprecated; use FIXME")
}
- for s in problematic_consts_strings.iter() {
- if line.contains(s) {
- err("Don't use magic numbers that spell things (consider 0x12345678)");
+ if any_problematic_line {
+ for s in problematic_consts_strings.iter() {
+ if trimmed.contains(s) {
+ err("Don't use magic numbers that spell things (consider 0x12345678)");
+ }
}
}
}
- let is_test = || file.components().any(|c| c.as_os_str() == "tests");
// for now we just check libcore
- if line.contains("unsafe {") && !line.trim().starts_with("//") && !last_safety_comment {
- if file.components().any(|c| c.as_os_str() == "core") && !is_test() {
+ if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment {
+ if file.components().any(|c| c.as_os_str() == "core") && !is_test {
suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe");
}
}
- if line.contains("// SAFETY:") {
+ if trimmed.contains("// SAFETY:") {
last_safety_comment = true;
- } else if line.trim().starts_with("//") || line.trim().is_empty() {
+ } else if trimmed.starts_with("//") || trimmed.is_empty() {
// keep previous value
} else {
last_safety_comment = false;
if (line.starts_with("// Copyright")
|| line.starts_with("# Copyright")
|| line.starts_with("Copyright"))
- && (line.contains("Rust Developers") || line.contains("Rust Project Developers"))
+ && (trimmed.contains("Rust Developers")
+ || trimmed.contains("Rust Project Developers"))
{
suppressible_tidy_err!(
err,
if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
err(LLVM_UNREACHABLE_INFO);
}
- if line.is_empty() {
- if i == 0 {
- leading_new_lines = true;
- }
- trailing_new_lines += 1;
- } else {
- trailing_new_lines = 0;
- }
-
- if !line.trim().starts_with("//") {
- lines += 1;
- }
}
if leading_new_lines {
let mut err = |_| {
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 2070;
+const ISSUES_ENTRY_LIMIT: usize = 2040;
fn check_entries(path: &Path, bad: &mut bool) {
for dir in Walk::new(&path.join("test/ui")) {
-//! Run `x.py` from any subdirectory of a rust compiler checkout.
+//! Run bootstrap from any subdirectory of a rust compiler checkout.
//!
//! We prefer `exec`, to avoid adding an extra process in the process tree.
//! However, since `exec` isn't available on Windows, we indirect through
//! `exec_or_status`, which will call `exec` on unix and `status` on Windows.
//!
-//! We use `python`, `python3`, or `python2` as the python interpreter to run
-//! `x.py`, in that order of preference.
+//! We use `powershell.exe x.ps1` on Windows, and `sh -c x` on Unix, those are
+//! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard.
+//! We also don't use `pwsh` on Windows, because it is not installed by default;
use std::{
- env::{self, consts::EXE_EXTENSION},
- io,
+ env, io,
+ path::Path,
process::{self, Command, ExitStatus},
};
-const PYTHON: &str = "python";
-const PYTHON2: &str = "python2";
-const PYTHON3: &str = "python3";
-
-fn python() -> &'static str {
- let val = match env::var_os("PATH") {
- Some(val) => val,
- None => return PYTHON,
- };
-
- let mut python2 = false;
- let mut python3 = false;
-
- for dir in env::split_paths(&val) {
- // `python` should always take precedence over python2 / python3 if it exists
- if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
- return PYTHON;
- }
+#[cfg(windows)]
+fn x_command(dir: &Path) -> Command {
+ let mut cmd = Command::new("powershell.exe");
+ cmd.args([
+ "-NoLogo",
+ "-NoProfile",
+ "-NonInteractive",
+ "-ExecutionPolicy",
+ "RemoteSigned",
+ "-Command",
+ "./x.ps1",
+ ])
+ .current_dir(dir);
+ cmd
+}
- python2 |= dir.join(PYTHON2).with_extension(EXE_EXTENSION).exists();
- python3 |= dir.join(PYTHON3).with_extension(EXE_EXTENSION).exists();
- }
+#[cfg(unix)]
+fn x_command(dir: &Path) -> Command {
+ Command::new(dir.join("x"))
+}
- // try 3 before 2
- if python3 {
- PYTHON3
- } else if python2 {
- PYTHON2
- } else {
- // Python was not found on path, so exit
- eprintln!("Unable to find python in your PATH. Please check it is installed.");
- process::exit(1);
- }
+#[cfg(not(any(windows, unix)))]
+fn x_command(_dir: &Path) -> Command {
+ compile_error!("Unsupported platform");
}
#[cfg(unix)]
let candidate = dir.join("x.py");
if candidate.exists() {
- let mut python = Command::new(python());
+ let mut cmd = x_command(dir);
- python.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
+ cmd.args(env::args().skip(1)).current_dir(dir);
- let result = exec_or_status(&mut python);
+ let result = exec_or_status(&mut cmd);
match result {
Err(error) => {
- eprintln!("Failed to invoke `{}`: {}", candidate.display(), error);
+ eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
}
Ok(status) => {
process::exit(status.code().unwrap_or(1));
"@compiler-errors",
"@eholk",
"@jackh726",
- "@fee1-dead",
"@TaKO8Ki",
+ "@Nilstrieb",
]
compiler = [
"compiler-team",