- name: disable git crlf conversion
run: git config --global core.autocrlf false
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
- name: configure the PR in which the error message will be posted
- name: disable git crlf conversion
run: git config --global core.autocrlf false
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
- name: configure the PR in which the error message will be posted
- name: disable git crlf conversion
run: git config --global core.autocrlf false
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
- name: configure the PR in which the error message will be posted
if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'"
steps:
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
- name: publish toolstate
"humantime 2.0.1",
"ignore",
"im-rc",
+ "indexmap",
"itertools",
"jobserver",
"lazy_static",
"serde_ignored",
"serde_json",
"shell-escape",
+ "snapbox",
"strip-ansi-escapes",
"tar",
"tempfile",
"atty",
"bitflags",
"indexmap",
+ "lazy_static",
"os_str_bytes",
"strsim 0.10.0",
"termcolor",
"textwrap 0.14.2",
]
+[[package]]
+name = "clap_complete"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
+dependencies = [
+ "clap 3.1.1",
+]
+
[[package]]
name = "clippy"
version = "0.1.62"
"winapi",
]
+[[package]]
+name = "concolor"
+version = "0.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "015267563b1df20adccdd00cb05257b1dfbea70a04928e9cf88ffb850c1a40af"
+dependencies = [
+ "atty",
+ "bitflags",
+ "concolor-query",
+]
+
+[[package]]
+name = "concolor-query"
+version = "0.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6417fe6fc03a8b533fd2177742eeb39a90c7233eedec7bac96d4d6b69a09449"
+
+[[package]]
+name = "content_inspector"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "core"
version = "0.0.0"
"rustc-std-workspace-core",
]
+[[package]]
+name = "dunce"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
+
[[package]]
name = "either"
version = "1.6.0"
[[package]]
name = "mdbook"
-version = "0.4.15"
+version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6"
+checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
dependencies = [
"ammonia",
"anyhow",
"chrono",
- "clap 2.34.0",
+ "clap 3.1.1",
+ "clap_complete",
"elasticlunr-rs",
"env_logger 0.7.1",
"handlebars",
"version_check",
]
+[[package]]
+name = "normalize-line-endings"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
+
[[package]]
name = "ntapi"
version = "0.3.6"
[[package]]
name = "once_cell"
-version = "1.7.2"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
[[package]]
name = "opaque-debug"
[[package]]
name = "openssl"
-version = "0.10.35"
+version = "0.10.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
+checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
[[package]]
name = "openssl-sys"
-version = "0.9.65"
+version = "0.9.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d"
+checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
dependencies = [
"autocfg",
"cc",
name = "proc_macro"
version = "0.0.0"
dependencies = [
+ "core",
"std",
]
checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
dependencies = [
"bitflags",
- "getopts",
"memchr",
"unicase",
]
[[package]]
name = "regex"
-version = "1.5.4"
+version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick",
"memchr",
"rustc_infer",
"rustc_middle",
"rustc_parse_format",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"expect-test",
"itertools",
"minifier",
+ "once_cell",
"pulldown-cmark",
"rayon",
"regex",
"libc",
]
+[[package]]
+name = "similar"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
+
[[package]]
name = "siphasher"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
+[[package]]
+name = "snapbox"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f212b806d6f56d19838e36a0aaa7e79a0bc9ca177e873fb87651ad92f983e2"
+dependencies = [
+ "concolor",
+ "content_inspector",
+ "dunce",
+ "filetime",
+ "normalize-line-endings",
+ "similar",
+ "snapbox-macros",
+ "tempfile",
+ "walkdir",
+ "yansi",
+]
+
+[[package]]
+name = "snapbox-macros"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930"
+
[[package]]
name = "socket2"
version = "0.4.1"
[[package]]
name = "walkdir"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"linked-hash-map",
]
+[[package]]
+name = "yansi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+
[[package]]
name = "yansi-term"
version = "0.1.2"
}
}
-impl<CTX> HashStable<CTX> for Path {
+impl<CTX: rustc_span::HashStableContext> HashStable<CTX> for Path {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
- segment.ident.name.hash_stable(hcx, hasher);
+ segment.ident.hash_stable(hcx, hasher);
}
}
}
}
}
+/// Inline assembly symbol operands get their own AST node that is somewhat
+/// similar to `AnonConst`.
+///
+/// The main difference is that we specifically don't assign it `DefId` in
+/// `DefCollector`. Instead this is deferred until AST lowering where we
+/// lower it to an `AnonConst` (for functions) or a `Path` (for statics)
+/// depending on what the path resolves to.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct InlineAsmSym {
+ pub id: NodeId,
+ pub qself: Option<QSelf>,
+ pub path: Path,
+}
+
/// Inline assembly operand.
///
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
anon_const: AnonConst,
},
Sym {
- expr: P<Expr>,
+ sym: InlineAsmSym,
},
}
use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
use crate::tokenstream::{DelimSpan, Spacing, TokenTree, TreeAndSpacing};
use crate::tokenstream::{LazyTokenStream, TokenStream};
+use crate::util::comments;
use rustc_index::bit_set::GrowableBitSet;
use rustc_span::source_map::BytePos;
}
}
+ pub fn may_have_doc_links(&self) -> bool {
+ self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
+ }
+
pub fn get_normal_item(&self) -> &AttrItem {
match self.kind {
AttrKind::Normal(ref item, _) => item,
fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
noop_flat_map_pat_field(fp, self)
}
+
+ fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
+ noop_visit_inline_asm(asm, self)
+ }
+
+ fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
+ noop_visit_inline_asm_sym(sym, self)
+ }
}
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
}
}
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
- ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
+ ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
ItemKind::TyAlias(box TyAlias {
defaultness, generics, where_clauses, bounds, ty, ..
}) => {
vis.visit_expr(value);
}
-fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
+pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
for (op, _) in &mut asm.operands {
match op {
InlineAsmOperand::In { expr, .. }
| InlineAsmOperand::Out { expr: Some(expr), .. }
- | InlineAsmOperand::InOut { expr, .. }
- | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
+ | InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr),
InlineAsmOperand::Out { expr: None, .. } => {}
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
vis.visit_expr(in_expr);
vis.visit_expr(out_expr);
}
}
- InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const),
+ InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
+ InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
}
}
}
+pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
+ InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
+ vis: &mut T,
+) {
+ vis.visit_id(id);
+ vis.visit_qself(qself);
+ vis.visit_path(path);
+}
+
pub fn noop_visit_expr<T: MutVisitor>(
Expr { kind, id, span, attrs, tokens }: &mut Expr,
vis: &mut T,
ExprKind::Ret(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
- ExprKind::InlineAsm(asm) => noop_visit_inline_asm(asm, vis),
+ ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
let StructExpr { qself, path, fields, rest } = se.deref_mut();
TokenTree::Token(Token::new(kind, span))
}
- /// Returns the opening delimiter as a token tree.
- pub fn open_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
- TokenTree::token(token::OpenDelim(delim), span.open)
- }
-
- /// Returns the closing delimiter as a token tree.
- pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree {
- TokenTree::token(token::CloseDelim(delim), span.close)
- }
-
pub fn uninterpolate(self) -> TokenTree {
match self {
TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
Cursor { stream, index: 0 }
}
+ #[inline]
pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> {
- if self.index < self.stream.len() {
+ self.stream.0.get(self.index).map(|tree| {
self.index += 1;
- Some(self.stream.0[self.index - 1].clone())
- } else {
- None
- }
+ tree.clone()
+ })
+ }
+
+ #[inline]
+ pub fn next_with_spacing_ref(&mut self) -> Option<&TreeAndSpacing> {
+ self.stream.0.get(self.index).map(|tree| {
+ self.index += 1;
+ tree
+ })
}
pub fn index(&self) -> usize {
pub pos: BytePos,
}
+/// A fast conservative estimate on whether the string can contain documentation links.
+/// A pair of square brackets `[]` must exist in the string, but we only search for the
+/// opening bracket because brackets always go in pairs in practice.
+#[inline]
+pub fn may_have_doc_links(s: &str) -> bool {
+ s.contains('[')
+}
+
/// Makes a doc string more presentable to users.
/// Used by rustdoc and perhaps other tools, but not by rustc.
pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
#[derive(Copy, Clone, Debug)]
pub enum FnKind<'a> {
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
- Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
+ Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
/// E.g., `|x, y| body`.
Closure(&'a FnDecl, &'a Expr),
impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&'a FnHeader> {
match *self {
- FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
+ FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
FnKind::Closure(_, _) => None,
}
}
pub fn decl(&self) -> &'a FnDecl {
match self {
- FnKind::Fn(_, _, sig, _, _) => &sig.decl,
+ FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
FnKind::Closure(decl, _) => decl,
}
}
fn visit_crate(&mut self, krate: &'ast Crate) {
walk_crate(self, krate)
}
+ fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
+ walk_inline_asm(self, asm)
+ }
+ fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
+ walk_inline_asm_sym(self, sym)
+ }
}
#[macro_export]
walk_list!(visitor, visit_expr, expr);
}
ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
- visitor.visit_generics(generics);
- let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+ let kind =
+ FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
visitor.visit_fn(kind, item.span, item.id)
}
ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind {
walk_list!(visitor, visit_expr, expr);
}
ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
- visitor.visit_generics(generics);
- let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
+ let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
match kind {
- FnKind::Fn(_, _, sig, _, body) => {
+ FnKind::Fn(_, _, sig, _, generics, body) => {
+ visitor.visit_generics(generics);
visitor.visit_fn_header(&sig.header);
walk_fn_decl(visitor, &sig.decl);
walk_list!(visitor, visit_block, body);
walk_list!(visitor, visit_expr, expr);
}
AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
- visitor.visit_generics(generics);
- let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
+ let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_expr(&constant.value);
}
-fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
+pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
for (op, _) in &asm.operands {
match op {
InlineAsmOperand::In { expr, .. }
| InlineAsmOperand::Out { expr: Some(expr), .. }
- | InlineAsmOperand::InOut { expr, .. }
- | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+ | InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr),
InlineAsmOperand::Out { expr: None, .. } => {}
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
visitor.visit_expr(in_expr);
}
}
InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
+ InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
}
}
}
+pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) {
+ if let Some(ref qself) = sym.qself {
+ visitor.visit_ty(&qself.ty);
+ }
+ visitor.visit_path(&sym.path, sym.id);
+}
+
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
walk_list!(visitor, visit_attribute, expression.attrs.iter());
+use crate::{ImplTraitContext, ImplTraitPosition, ParamMode};
+
use super::LoweringContext;
+use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::definitions::DefPathData;
use rustc_session::parse::feature_err;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, ExpnId, Span};
use rustc_target::asm;
use std::collections::hash_map::Entry;
use std::fmt::Write;
anon_const: self.lower_anon_const(anon_const),
}
}
- InlineAsmOperand::Sym { ref expr } => {
+ InlineAsmOperand::Sym { ref sym } => {
if !self.sess.features_untracked().asm_sym {
feature_err(
&self.sess.parse_sess,
)
.emit();
}
- hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
+
+ let static_def_id = self
+ .resolver
+ .get_partial_res(sym.id)
+ .filter(|res| res.unresolved_segments() == 0)
+ .and_then(|res| {
+ if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
+ Some(def_id)
+ } else {
+ None
+ }
+ });
+
+ if let Some(def_id) = static_def_id {
+ let path = self.lower_qpath(
+ sym.id,
+ &sym.qself,
+ &sym.path,
+ ParamMode::Optional,
+ ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+ );
+ hir::InlineAsmOperand::SymStatic { path, def_id }
+ } else {
+ // Replace the InlineAsmSym AST node with an
+ // Expr using the name node id.
+ let expr = Expr {
+ id: sym.id,
+ kind: ExprKind::Path(sym.qself.clone(), sym.path.clone()),
+ span: *op_sp,
+ attrs: AttrVec::new(),
+ tokens: None,
+ };
+
+ // Wrap the expression in an AnonConst.
+ let parent_def_id = self.current_hir_id_owner;
+ let node_id = self.resolver.next_node_id();
+ self.resolver.create_def(
+ parent_def_id,
+ node_id,
+ DefPathData::AnonConst,
+ ExpnId::root(),
+ *op_sp,
+ );
+ let anon_const = AnonConst { id: node_id, value: P(expr) };
+ hir::InlineAsmOperand::SymFn {
+ anon_const: self.lower_anon_const(&anon_const),
+ }
+ }
}
};
(op, self.lower_span(*op_sp))
err.span_label(op_sp, "argument");
err.emit();
}
- hir::InlineAsmOperand::Sym { .. } => {
+ hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {
let mut err = sess.struct_span_err(
placeholder_span,
"asm template modifiers are not allowed for `sym` arguments",
hir::InlineAsmOperand::InOut { .. }
| hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
- hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
+ hir::InlineAsmOperand::Const { .. }
+ | hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {
unreachable!()
}
};
self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
}
- fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) {
- match visibility.node {
- VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {}
- VisibilityKind::Restricted { hir_id, .. } => {
- self.insert(visibility.span, hir_id, Node::Visibility(visibility));
- self.with_parent(hir_id, |this| {
- intravisit::walk_vis(this, visibility);
- });
- }
- }
- }
-
fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) {
self.insert(v.span, v.id, Node::Variant(v));
self.with_parent(v.id, |this| {
use rustc_index::vec::{Idx, IndexVec};
use rustc_session::utils::NtToTokenstream;
use rustc_session::Session;
-use rustc_span::source_map::{respan, DesugaringKind};
+use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use rustc_target::spec::abi;
fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let mut ident = i.ident;
- let mut vis = self.lower_visibility(&i.vis);
+ let vis_span = self.lower_span(i.vis.span);
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
- let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
+ let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
- vis,
+ vis_span,
span: self.lower_span(i.span),
};
self.arena.alloc(item)
hir_id: hir::HirId,
ident: &mut Ident,
attrs: Option<&'hir [Attribute]>,
- vis: &mut hir::Visibility<'hir>,
+ vis_span: Span,
i: &ItemKind,
) -> hir::ItemKind<'hir> {
match *i {
// Start with an empty prefix.
let prefix = Path { segments: vec![], span: use_tree.span, tokens: None };
- self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
+ self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
}
ItemKind::Static(ref t, m, ref e) => {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
tree: &UseTree,
prefix: &Path,
id: NodeId,
- vis: &mut hir::Visibility<'hir>,
+ vis_span: Span,
ident: &mut Ident,
attrs: Option<&'hir [Attribute]>,
) -> hir::ItemKind<'hir> {
debug!("lower_use_tree(tree={:?})", tree);
- debug!("lower_use_tree: vis = {:?}", vis);
let path = &tree.prefix;
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
let res = this.lower_res(res);
let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
- let vis = this.rebuild_vis(&vis);
if let Some(attrs) = attrs {
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
}
def_id: new_id,
ident: this.lower_ident(ident),
kind,
- vis,
+ vis_span,
span: this.lower_span(span),
};
hir::OwnerNode::Item(this.arena.alloc(item))
// own its own names, we have to adjust the owner before
// lowering the rest of the import.
self.with_hir_id_owner(id, |this| {
- let mut vis = this.rebuild_vis(&vis);
let mut ident = *ident;
let kind =
- this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
+ this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
if let Some(attrs) = attrs {
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
}
def_id: new_hir_id,
ident: this.lower_ident(ident),
kind,
- vis,
+ vis_span,
span: this.lower_span(use_tree.span),
};
hir::OwnerNode::Item(this.arena.alloc(item))
});
}
- // Subtle and a bit hacky: we lower the privacy level
- // of the list stem to "private" most of the time, but
- // not for "restricted" paths. The key thing is that
- // we don't want it to stay as `pub` (with no caveats)
- // because that affects rustdoc and also the lints
- // about `pub` items. But we can't *always* make it
- // private -- particularly not for restricted paths --
- // because it contains node-ids that would then be
- // unused, failing the check that HirIds are "densely
- // assigned".
- match vis.node {
- hir::VisibilityKind::Public
- | hir::VisibilityKind::Crate(_)
- | hir::VisibilityKind::Inherited => {
- *vis = respan(
- self.lower_span(prefix.span.shrink_to_lo()),
- hir::VisibilityKind::Inherited,
- );
- }
- hir::VisibilityKind::Restricted { .. } => {
- // Do nothing here, as described in the comment on the match.
- }
- }
-
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
let res = self.lower_res(res);
let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
}
}
- /// Paths like the visibility path in `pub(super) use foo::{bar, baz}` are repeated
- /// many times in the HIR tree; for each occurrence, we need to assign distinct
- /// `NodeId`s. (See, e.g., #56128.)
- fn rebuild_use_path(&mut self, path: &hir::Path<'hir>) -> &'hir hir::Path<'hir> {
- debug!("rebuild_use_path(path = {:?})", path);
- let segments =
- self.arena.alloc_from_iter(path.segments.iter().map(|seg| hir::PathSegment {
- ident: seg.ident,
- hir_id: seg.hir_id.map(|_| self.next_id()),
- res: seg.res,
- args: None,
- infer_args: seg.infer_args,
- }));
- self.arena.alloc(hir::Path { span: path.span, res: path.res, segments })
- }
-
- fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir> {
- let vis_kind = match vis.node {
- hir::VisibilityKind::Public => hir::VisibilityKind::Public,
- hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
- hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
- hir::VisibilityKind::Restricted { ref path, hir_id: _ } => {
- hir::VisibilityKind::Restricted {
- path: self.rebuild_use_path(path),
- hir_id: self.next_id(),
- }
- }
- };
- respan(self.lower_span(vis.span), vis_kind)
- }
-
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
},
- vis: self.lower_visibility(&i.vis),
+ vis_span: self.lower_span(i.vis.span),
span: self.lower_span(i.span),
};
self.arena.alloc(item)
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), self.lower_span(f.span)),
},
- vis: self.lower_visibility(&f.vis),
+ vis_span: self.lower_span(f.vis.span),
ty,
}
}
def_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
- vis: self.lower_visibility(&i.vis),
kind,
+ vis_span: self.lower_span(i.vis.span),
span: self.lower_span(i.span),
};
self.arena.alloc(item)
}
}
- /// If an `explicit_owner` is given, this method allocates the `HirId` in
- /// the address space of that item instead of the item currently being
- /// lowered. This can happen during `lower_impl_item_ref()` where we need to
- /// lower a `Visibility` value although we haven't lowered the owning
- /// `ImplItem` in question yet.
- fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> {
- let node = match v.kind {
- VisibilityKind::Public => hir::VisibilityKind::Public,
- VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
- VisibilityKind::Restricted { ref path, id } => {
- debug!("lower_visibility: restricted path id = {:?}", id);
- let lowered_id = self.lower_node_id(id);
- hir::VisibilityKind::Restricted {
- path: self.lower_path(id, path, ParamMode::Explicit),
- hir_id: lowered_id,
- }
- }
- VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
- };
- respan(self.lower_span(v.span), node)
- }
-
fn lower_defaultness(
&self,
d: Defaultness,
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
use rustc_session::Session;
use rustc_span::hygiene::{ExpnId, MacroKind};
-use rustc_span::source_map::{respan, DesugaringKind};
+use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
/// an "elided" or "underscore" lifetime name. In the future, we probably want to move
/// everything into HIR lowering.
#[derive(Copy, Clone, Debug)]
-enum AnonymousLifetimeMode {
+pub enum AnonymousLifetimeMode {
/// For **Modern** cases, create a new anonymous region parameter
/// and reference that.
///
def_id: opaque_ty_id,
ident: Ident::empty(),
kind: opaque_ty_item_kind,
- vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
+ vis_span: self.lower_span(span.shrink_to_lo()),
span: self.lower_span(opaque_ty_span),
};
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
// Output lifetime like `'_`:
for (span, node_id) in lifetimes_to_define {
let param = this.fresh_lifetime_to_generic_param(span, node_id);
- lifetime_params.push((span, hir::LifetimeName::Implicit(false)));
+ lifetime_params.push((span, hir::LifetimeName::Implicit));
generic_params.push(param);
}
let generic_params = this.arena.alloc_from_iter(generic_params);
});
let param_name = match lt.name {
hir::LifetimeName::Param(param_name) => param_name,
- hir::LifetimeName::Implicit(_)
- | hir::LifetimeName::Underscore
- | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
+ hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+ hir::ParamName::Plain(lt.name.ident())
+ }
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
self.sess.diagnostic().span_bug(
param.ident.span,
"object-lifetime-default should not occur here",
);
}
- hir::LifetimeName::Error => ParamName::Error,
+ hir::LifetimeName::Static | hir::LifetimeName::Error => ParamName::Error,
};
let kind =
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span),
- AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false),
+ AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span),
}
}
/// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
/// return an "error lifetime".
fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
- let (id, msg, label) = match id {
- Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
-
- None => (
- self.resolver.next_node_id(),
- "`&` without an explicit lifetime name cannot be used here",
- "explicit lifetime name needed here",
- ),
- };
-
- let mut err = struct_span_err!(self.sess, span, E0637, "{}", msg,);
- err.span_label(span, label);
- err.emit();
-
+ let id = id.unwrap_or_else(|| self.resolver.next_node_id());
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
}
&'s mut self,
span: Span,
count: usize,
- param_mode: ParamMode,
) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> {
- (0..count).map(move |_| self.elided_path_lifetime(span, param_mode))
+ (0..count).map(move |_| self.elided_path_lifetime(span))
}
- fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime {
+ fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime {
match self.anonymous_lifetime_mode {
AnonymousLifetimeMode::CreateParameter => {
// We should have emitted E0726 when processing this path above
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
// later, at which point a suitable error will be emitted.
AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => {
- self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit)
+ self.new_implicit_lifetime(span)
}
}
}
r
}
- fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime {
+ fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
hir::Lifetime {
hir_id: self.next_id(),
span: self.lower_span(span),
- name: hir::LifetimeName::Implicit(missing),
+ name: hir::LifetimeName::Implicit,
}
}
}
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
let name = match lifetime.name {
- hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => {
+ hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`.
generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
};
generic_args.args = self
- .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode)
+ .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes)
.map(GenericArg::Lifetime)
.chain(generic_args.args.into_iter())
.collect();
- // In create-parameter mode we error here because we don't want to support
- // deprecated impl elision in new features like impl elision and `async fn`,
- // both of which work using the `CreateParameter` mode:
- //
- // impl Foo for std::cell::Ref<u32> // note lack of '_
- // async fn foo(_: std::cell::Ref<u32>) { ... }
if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
(param_mode, self.anonymous_lifetime_mode)
{
- let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
- let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
- let no_bindings = generic_args.bindings.is_empty();
- let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings {
- // If there are no generic args, our suggestion can include the angle brackets.
- (true, format!("<{}>", anon_lt_suggestion))
- } else {
- // Otherwise we'll insert a `'_, ` right after the opening bracket.
- (false, format!("{}, ", anon_lt_suggestion))
- };
- let insertion_sp = elided_lifetime_span.shrink_to_hi();
- let mut err = struct_span_err!(
- self.sess,
- path_span,
- E0726,
- "implicit elided lifetime not allowed here"
- );
- rustc_errors::add_elided_lifetime_in_path_suggestion(
- &self.sess.source_map(),
- &mut err,
- expected_lifetimes,
- path_span,
- incl_angl_brckt,
- insertion_sp,
- suggestion,
- );
- err.note("assuming a `'static` lifetime...");
- err.emit();
+ // Late resolver should have issued the error.
+ self.sess
+ .delay_span_bug(elided_lifetime_span, "implicit lifetime not allowed here");
}
}
self.is_impl_trait_banned = old;
}
- fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_tilde_const_allowed, true);
+ fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
+ let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
f(self);
self.is_tilde_const_allowed = old;
}
+ fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
+ self.with_tilde_const(true, f)
+ }
+
fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_tilde_const_allowed, false);
- f(self);
- self.is_tilde_const_allowed = old;
+ self.with_tilde_const(false, f)
}
fn with_let_management(
}
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
- if let Const::Yes(_) = sig.header.constness {
- self.with_tilde_const_allowed(|this| this.visit_generics(generics));
- } else {
- self.visit_generics(generics);
- }
- let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+ let kind =
+ FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
self.visit_fn(kind, item.span, item.id);
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. },
_,
_,
+ _,
) = fk
{
self.maybe_lint_missing_abi(*sig_span, id);
}
// Functions without bodies cannot have patterns.
- if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
+ if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
let (code, msg, label) = match ctxt {
FnCtxt::Foreign => (
});
}
- visit::walk_fn(self, fk, span);
+ let tilde_const_allowed =
+ matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
+ || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
+
+ self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk, span));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
{
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
- self.with_tilde_const_allowed(|this| this.visit_generics(generics));
- let kind =
- FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
+ let kind = FnKind::Fn(
+ FnCtxt::Assoc(ctxt),
+ item.ident,
+ sig,
+ &item.vis,
+ generics,
+ body.as_deref(),
+ );
self.visit_fn(kind, item.span, item.id);
}
_ => self
}
impl<'a> PostExpansionVisitor<'a> {
- fn check_abi(&self, abi: ast::StrLit) {
+ fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
let ast::StrLit { symbol_unescaped, span, .. } = abi;
+ if let ast::Const::Yes(_) = constness {
+ match symbol_unescaped.as_str() {
+ // Stable
+ "Rust" | "C" => {}
+ abi => gate_feature_post!(
+ &self,
+ const_extern_fn,
+ span,
+ &format!("`{}` as a `const fn` ABI is unstable", abi)
+ ),
+ }
+ }
+
match symbol_unescaped.as_str() {
// Stable
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
}
}
- fn check_extern(&self, ext: ast::Extern) {
+ fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
if let ast::Extern::Explicit(abi) = ext {
- self.check_abi(abi);
+ self.check_abi(abi, constness);
}
}
match i.kind {
ast::ItemKind::ForeignMod(ref foreign_module) => {
if let Some(abi) = foreign_module.abi {
- self.check_abi(abi);
+ self.check_abi(abi, ast::Const::No);
}
}
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match ty.kind {
ast::TyKind::BareFn(ref bare_fn_ty) => {
- self.check_extern(bare_fn_ty.ext);
+ // Function pointers cannot be `const`
+ self.check_extern(bare_fn_ty.ext, ast::Const::No);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let Some(header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below.
- self.check_extern(header.ext);
-
- if let (ast::Const::Yes(_), ast::Extern::Implicit)
- | (ast::Const::Yes(_), ast::Extern::Explicit(_)) = (header.constness, header.ext)
- {
- gate_feature_post!(
- &self,
- const_extern_fn,
- span,
- "`const extern fn` definitions are unstable"
- );
- }
+ self.check_extern(header.ext, header.constness);
}
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
self.word_space("=");
match term {
Term::Ty(ty) => self.print_type(ty),
- Term::Const(c) => self.print_expr_anon_const(c),
+ Term::Const(c) => self.print_expr_anon_const(c, &[]),
}
}
ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds),
s.space();
s.print_expr(&anon_const.value);
}
- InlineAsmOperand::Sym { expr } => {
+ InlineAsmOperand::Sym { sym } => {
s.word("sym");
s.space();
- s.print_expr(expr);
+ if let Some(qself) = &sym.qself {
+ s.print_qpath(&sym.path, qself, true);
+ } else {
+ s.print_path(&sym.path, true, 0);
+ }
}
}
}
self.end();
}
- pub(super) fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) {
+ pub(super) fn print_expr_anon_const(
+ &mut self,
+ expr: &ast::AnonConst,
+ attrs: &[ast::Attribute],
+ ) {
self.ibox(INDENT_UNIT);
self.word("const");
- self.print_expr(&expr.value);
+ self.nbsp();
+ if let ast::ExprKind::Block(block, None) = &expr.value.kind {
+ self.cbox(0);
+ self.ibox(0);
+ self.print_block_with_attrs(block, attrs);
+ } else {
+ self.print_expr(&expr.value);
+ }
self.end();
}
self.print_expr_vec(exprs);
}
ast::ExprKind::ConstBlock(ref anon_const) => {
- self.print_expr_anon_const(anon_const);
+ self.print_expr_anon_const(anon_const, attrs);
}
ast::ExprKind::Repeat(ref element, ref count) => {
self.print_expr_repeat(element, count);
sup: self.static_region,
sub: next_static_idx.into(),
locations: Locations::All(DUMMY_SP),
+ span: DUMMY_SP,
category: ConstraintCategory::Internal,
variance_info: VarianceDiagInfo::default(),
})
/// Given a region `R`, iterate over all regions `R1` such that
/// there exists a constraint `R: R1`.
- crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, 'tcx, D> {
+ crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'s, 'tcx, D> {
Successors {
edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
}
}
}
-impl<'s, 'graph, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph>
- for RegionGraph<'s, 'tcx, D>
-{
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'_> for RegionGraph<'s, 'tcx, D> {
type Item = RegionVid;
- // FIXME - why can't this be `'graph, 'tcx`
- type Iter = Successors<'graph, 'graph, D>;
+ type Iter = Successors<'s, 'tcx, D>;
}
use rustc_index::vec::IndexVec;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
+use rustc_span::Span;
use std::fmt;
use std::ops::Index;
/// Where did this constraint arise?
pub locations: Locations,
+ /// The `Span` associated with the creation of this constraint.
+ /// This should be used in preference to obtaining the span from
+ /// `locations`, since the `locations` may give a poor span
+ /// in some cases (e.g. converting a constraint from a promoted).
+ pub span: Span,
+
/// What caused this constraint?
pub category: ConstraintCategory,
use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
+use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
+use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
use crate::diagnostics::find_all_local_uses;
use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
err.span_suggestion_hidden(
return_span,
"use `.collect()` to allocate the iterator",
- format!("{}{}", snippet, ".collect::<Vec<_>>()"),
+ format!("{snippet}.collect::<Vec<_>>()"),
Applicability::MaybeIncorrect,
);
}
fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
let tcx = self.infcx.tcx;
- match place.last_projection() {
- None => StorageDeadOrDrop::LocalStorageDead,
- Some((place_base, elem)) => {
- // FIXME(spastorino) make this iterate
- let base_access = self.classify_drop_access_kind(place_base);
- match elem {
- ProjectionElem::Deref => match base_access {
- StorageDeadOrDrop::LocalStorageDead
- | StorageDeadOrDrop::BoxedStorageDead => {
- assert!(
- place_base.ty(self.body, tcx).ty.is_box(),
- "Drop of value behind a reference or raw pointer"
- );
- StorageDeadOrDrop::BoxedStorageDead
- }
- StorageDeadOrDrop::Destructor(_) => base_access,
- },
- ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
- let base_ty = place_base.ty(self.body, tcx).ty;
- match base_ty.kind() {
- ty::Adt(def, _) if def.has_dtor(tcx) => {
- // Report the outermost adt with a destructor
- match base_access {
- StorageDeadOrDrop::Destructor(_) => base_access,
- StorageDeadOrDrop::LocalStorageDead
- | StorageDeadOrDrop::BoxedStorageDead => {
- StorageDeadOrDrop::Destructor(base_ty)
+ let (kind, _place_ty) = place.projection.iter().fold(
+ (LocalStorageDead, PlaceTy::from_ty(self.body.local_decls[place.local].ty)),
+ |(kind, place_ty), &elem| {
+ (
+ match elem {
+ ProjectionElem::Deref => match kind {
+ StorageDeadOrDrop::LocalStorageDead
+ | StorageDeadOrDrop::BoxedStorageDead => {
+ assert!(
+ place_ty.ty.is_box(),
+ "Drop of value behind a reference or raw pointer"
+ );
+ StorageDeadOrDrop::BoxedStorageDead
+ }
+ StorageDeadOrDrop::Destructor(_) => kind,
+ },
+ ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
+ match place_ty.ty.kind() {
+ ty::Adt(def, _) if def.has_dtor(tcx) => {
+ // Report the outermost adt with a destructor
+ match kind {
+ StorageDeadOrDrop::Destructor(_) => kind,
+ StorageDeadOrDrop::LocalStorageDead
+ | StorageDeadOrDrop::BoxedStorageDead => {
+ StorageDeadOrDrop::Destructor(place_ty.ty)
+ }
}
}
+ _ => kind,
}
- _ => base_access,
}
- }
- ProjectionElem::ConstantIndex { .. }
- | ProjectionElem::Subslice { .. }
- | ProjectionElem::Index(_) => base_access,
- }
- }
- }
+ ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::Subslice { .. }
+ | ProjectionElem::Index(_) => kind,
+ },
+ place_ty.projection_ty(tcx, elem),
+ )
+ },
+ );
+ kind
}
/// Describe the reason for the fake borrow that was assigned to `place`.
use rustc_infer::infer::{
error_reporting::nice_region_error::NiceRegionError,
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
+ RelateParamBound,
};
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
let type_test_span = type_test.locations.span(&self.body);
if let Some(lower_bound_region) = lower_bound_region {
+ let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
+ let origin = RelateParamBound(type_test_span, generic_ty, None);
self.buffer_error(self.infcx.construct_generic_bound_failure(
type_test_span,
- None,
+ Some(origin),
type_test.generic_kind,
lower_bound_region,
+ self.body.source.def_id().as_local(),
));
} else {
// FIXME. We should handle this case better. It
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
}
- hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => {
+ hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
// In this case, the user left off the lifetime; so
// they wrote something like:
//
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort_by_key(|c| (c.sup, c.sub));
for constraint in &constraints {
- let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint;
+ let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
+ constraint;
let (name, arg) = match locations {
Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
}
Locations::Single(loc) => ("Single", format!("{:?}", loc)),
};
- with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?;
+ with_msg(&format!(
+ "{:?}: {:?} due to {:?} at {}({}) ({:?}",
+ sup, sub, category, name, arg, span
+ ))?;
}
Ok(())
crate fn retrieve_closure_constraint_info(
&self,
- body: &Body<'tcx>,
+ _body: &Body<'tcx>,
constraint: &OutlivesConstraint<'tcx>,
) -> BlameConstraint<'tcx> {
let loc = match constraint.locations {
.unwrap_or(BlameConstraint {
category: constraint.category,
from_closure: false,
- cause: ObligationCause::dummy_with_span(body.source_info(loc).span),
+ cause: ObligationCause::dummy_with_span(constraint.span),
variance_info: constraint.variance_info,
})
}
sup: r,
sub: constraint.min_choice,
locations: Locations::All(p_c.definition_span),
+ span: p_c.definition_span,
category: ConstraintCategory::OpaqueType,
variance_info: ty::VarianceDiagInfo::default(),
};
category: constraint.category,
from_closure: false,
cause: ObligationCause::new(
- constraint.locations.span(body),
+ constraint.span,
CRATE_HIR_ID,
cause_code.clone(),
),
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
use crate::{
constraints::OutlivesConstraint,
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
+ span: Span,
category: ConstraintCategory,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
}
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
+ span: Span,
category: ConstraintCategory,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
) -> Self {
implicit_region_bound,
param_env,
locations,
+ span,
category,
constraints,
}
self.constraints.outlives_constraints.push(OutlivesConstraint {
locations: self.locations,
category: self.category,
+ span: self.span,
sub,
sup,
variance_info: ty::VarianceDiagInfo::default(),
self.implicit_region_bound,
self.param_env,
Locations::All(DUMMY_SP),
+ DUMMY_SP,
ConstraintCategory::Internal,
&mut self.constraints,
)
Some(self.implicit_region_bound),
self.param_env,
Locations::All(DUMMY_SP),
+ DUMMY_SP,
ConstraintCategory::Internal,
&mut self.borrowck_context.constraints,
)
Some(self.implicit_region_bound),
self.param_env,
locations,
+ locations.span(self.body),
category,
&mut self.borrowck_context.constraints,
)
sup: ref_region.to_region_vid(),
sub: borrow_region.to_region_vid(),
locations: location.to_locations(),
+ span: location.to_locations().span(body),
category,
variance_info: ty::VarianceDiagInfo::default(),
});
sup,
sub,
locations: self.locations,
+ span: self.locations.span(self.type_checker.body),
category: self.category,
variance_info: info,
},
} else if p.eat_keyword(kw::Const) {
let anon_const = p.parse_anon_const_expr()?;
ast::InlineAsmOperand::Const { anon_const }
- } else if !is_global_asm && p.eat_keyword(sym::sym) {
+ } else if p.eat_keyword(sym::sym) {
let expr = p.parse_expr()?;
- match expr.kind {
- ast::ExprKind::Path(..) => {}
- _ => {
- let err = diag
- .struct_span_err(expr.span, "argument to `sym` must be a path expression");
- return Err(err);
- }
- }
- ast::InlineAsmOperand::Sym { expr }
+ let ast::ExprKind::Path(qself, path) = &expr.kind else {
+ let err = diag
+ .struct_span_err(expr.span, "expected a path for argument to `sym`");
+ return Err(err);
+ };
+ let sym = ast::InlineAsmSym {
+ id: ast::DUMMY_NODE_ID,
+ qself: qself.clone(),
+ path: path.clone(),
+ };
+ ast::InlineAsmOperand::Sym { sym }
} else if allow_templates {
let template = p.parse_expr()?;
// If it can't possibly expand to a string, provide diagnostics here to include other
[[package]]
name = "cranelift-bforest"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d16922317bd7dd104d509a373887822caa0242fc1def00de66abb538db221db4"
+checksum = "ed44413e7e2fe3260d0ed73e6956ab188b69c10ee92b892e401e0f4f6808c68b"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b80bf40380256307b68a3dcbe1b91cac92a533e212b5b635abc3e4525781a0a"
+checksum = "0b5d83f0f26bf213f971f45589d17e5b65e4861f9ed22392b0cbb6eaa5bd329c"
dependencies = [
"cranelift-bforest",
"cranelift-codegen-meta",
[[package]]
name = "cranelift-codegen-meta"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703d0ed7d3bc6c7a814ca12858175bf4e93167a3584127858c686e4b5dd6e432"
+checksum = "6800dc386177df6ecc5a32680607ed8ba1fa0d31a2a59c8c61fbf44826b8191d"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80f52311e1c90de12dcf8c4b9999c6ebfd1ed360373e88c357160936844511f6"
+checksum = "c961f85070985ebc8fcdb81b838a5cf842294d1e6ed4852446161c7e246fd455"
[[package]]
name = "cranelift-entity"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66bc82ef522c1f643baf7d4d40b7c52643ee4549d8960b0e6a047daacb83f897"
+checksum = "2347b2b8d1d5429213668f2a8e36c85ee3c73984a2f6a79007e365d3e575e7ed"
[[package]]
name = "cranelift-frontend"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cc35e4251864b17515845ba47447bca88fec9ca1a4186b19fe42526e36140e8"
+checksum = "4cbcdbf7bed29e363568b778649b69dabc3d727256d5d25236096ef693757654"
dependencies = [
"cranelift-codegen",
"log",
[[package]]
name = "cranelift-jit"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c66d594ad3bfe4e58b1fbd8d17877a7c6564a5f2d6f78cbbf4b0182af1927f"
+checksum = "7c769d4e0d76f59c8b2a3bf0477d89ee149bb0731b53fbb245ee081d49063095"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "cranelift-module"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf356697c40232aa09e1e3fb8a350ee894e849ccecc4eac56ff0570a4575c325"
+checksum = "0ab57d399a2401074bb0cc40b3031e420f3d66d46ec0cf21eeae53ac04bd73e2"
dependencies = [
"anyhow",
"cranelift-codegen",
[[package]]
name = "cranelift-native"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b882b2251c9845d509d92aebfdb6c8bb3b3b48e207ac951f21fbd20cfe7f90b3"
+checksum = "8f4cdf93552e5ceb2e3c042829ebb4de4378492705f769eadc6a7c6c5251624c"
dependencies = [
"cranelift-codegen",
"libc",
[[package]]
name = "cranelift-object"
-version = "0.82.1"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d3f1a88e654e567d2591169239ed157ab290811a729a6468f53999c01001263"
+checksum = "cf8e65f4839c26e6237fc0744911d79b0a2ac5e76b4e4eebd14db2b8d849fd31"
dependencies = [
"anyhow",
"cranelift-codegen",
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.82.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.82.1"
-cranelift-module = "0.82.1"
-cranelift-native = "0.82.1"
-cranelift-jit = { version = "0.82.1", optional = true }
-cranelift-object = "0.82.1"
+cranelift-codegen = { version = "0.83.0", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.83.0"
+cranelift-module = "0.83.0"
+cranelift-native = "0.83.0"
+cranelift-jit = { version = "0.83.0", optional = true }
+cranelift-object = "0.83.0"
target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
[[package]]
name = "compiler_builtins"
-version = "0.1.71"
+version = "0.1.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "163437f05ca8f29d7e9128ea728dedf5eb620e445fbca273641d3a3050305f23"
+checksum = "afdbb35d279238cf77f0c9e8d90ad50d6c7bff476ab342baafa29440f0f10bff"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "libc"
-version = "0.2.121"
+version = "0.2.124"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
+checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
dependencies = [
"rustc-std-workspace-core",
]
name = "proc_macro"
version = "0.0.0"
dependencies = [
+ "core",
"std",
]
--- /dev/null
+// Copied from https://github.com/rust-lang/rust/blob/3fe3b89cd57229343eeca753fdd8c63d9b03c65c/src/test/ui/simd/intrinsic/float-minmax-pass.rs
+// run-pass
+// ignore-emscripten
+
+// Test that the simd_f{min,max} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+extern "platform-intrinsic" {
+ fn simd_fmin<T>(x: T, y: T) -> T;
+ fn simd_fmax<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+ let x = f32x4(1.0, 2.0, 3.0, 4.0);
+ let y = f32x4(2.0, 1.0, 4.0, 3.0);
+
+ #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+ let nan = f32::NAN;
+ // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit.
+ // See https://github.com/rust-lang/rust/issues/52746.
+ #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+ let nan = f32::from_bits(f32::NAN.to_bits() - 1);
+
+ let n = f32x4(nan, nan, nan, nan);
+
+ unsafe {
+ let min0 = simd_fmin(x, y);
+ let min1 = simd_fmin(y, x);
+ assert_eq!(min0, min1);
+ let e = f32x4(1.0, 1.0, 3.0, 3.0);
+ assert_eq!(min0, e);
+ let minn = simd_fmin(x, n);
+ assert_eq!(minn, x);
+ let minn = simd_fmin(y, n);
+ assert_eq!(minn, y);
+
+ let max0 = simd_fmax(x, y);
+ let max1 = simd_fmax(y, x);
+ assert_eq!(max0, max1);
+ let e = f32x4(2.0, 2.0, 4.0, 4.0);
+ assert_eq!(max0, e);
+ let maxn = simd_fmax(x, n);
+ assert_eq!(maxn, x);
+ let maxn = simd_fmax(y, n);
+ assert_eq!(maxn, y);
+ }
+}
#[lang = "sized"]
pub trait Sized {}
+#[lang = "destruct"]
+pub trait Destruct {}
+
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
fn deref(&self) -> &Self::Target;
}
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+#[rustc_nonnull_optimization_guaranteed]
+pub struct NonNull<T: ?Sized>(pub *mut T);
+
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+
pub struct Unique<T: ?Sized> {
- pub pointer: *const T,
+ pub pointer: NonNull<T>,
pub _marker: PhantomData<T>,
}
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
-
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
#[lang = "owned_box"]
#[lang = "box_free"]
unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, alloc: ()) {
- libc::free(ptr.pointer as *mut u8);
+ libc::free(ptr.pointer.0 as *mut u8);
}
#[lang = "drop"]
#[allow(unreachable_code)] // FIXME false positive
fn main() {
take_unique(Unique {
- pointer: 0 as *const (),
+ pointer: unsafe { NonNull(1 as *mut ()) },
_marker: PhantomData,
});
take_f32(0.1);
assert!(intrinsics::needs_drop::<NoisyDrop>());
Unique {
- pointer: 0 as *const &str,
+ pointer: NonNull(1 as *mut &str),
_marker: PhantomData,
} as Unique<dyn SomeTrait>;
-#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
+use std::hint::black_box;
use std::io::Write;
use std::ops::Generator;
assert_eq!(houndred_f64 as i128, 100);
assert_eq!(1u128.rotate_left(2), 4);
+ assert_eq!(black_box(f32::NAN) as i128, 0);
+ assert_eq!(black_box(f32::NAN) as u128, 0);
+
// Test signed 128bit comparing
let max = usize::MAX as i128;
if 100i128 < 0i128 || 100i128 > max {
}
}
}
-diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs
-index 31b7ee2..bd04b3c 100644
---- a/crates/core_simd/tests/ops_macros.rs
-+++ b/crates/core_simd/tests/ops_macros.rs
-@@ -567,6 +567,7 @@ macro_rules! impl_float_tests {
- });
- }
-
-+ /*
- fn horizontal_max<const LANES: usize>() {
- test_helpers::test_1(&|x| {
- let vmax = Vector::<LANES>::from_array(x).horizontal_max();
-@@ -590,6 +591,7 @@ macro_rules! impl_float_tests {
- Ok(())
- });
- }
-+ */
- }
-
- #[cfg(feature = "std")]
-@@ -604,6 +606,7 @@ macro_rules! impl_float_tests {
- )
- }
-
-+ /*
- fn mul_add<const LANES: usize>() {
- test_helpers::test_ternary_elementwise(
- &Vector::<LANES>::mul_add,
-@@ -611,6 +614,7 @@ macro_rules! impl_float_tests {
- &|_, _, _| true,
- )
- }
-+ */
- }
- }
- }
--
2.26.2.7.g19db9cfb68
[toolchain]
-channel = "nightly-2022-03-19"
+channel = "nightly-2022-04-21"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
-#!/bin/bash
+#!/usr/bin/env bash
#![forbid(unsafe_code)]/* This line is ignored by bash
# This block is ignored by rustc
pushd $(dirname "$0")/../
-#!/bin/bash
+#!/usr/bin/env bash
set -e
./y.rs build --no-unstable-features
-#!/bin/bash
+#!/usr/bin/env bash
set -e
cd $(dirname "$0")/../
command -v rg >/dev/null 2>&1 || cargo install ripgrep
rm -r src/test/ui/{extern/,unsized-locals/,lto/,linkage*} || true
-for test in $(rg --files-with-matches "asm!|lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do
+for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" src/test/{ui,incremental}); do
rm $test
done
# ================
# requires stack unwinding
-rm src/test/ui/backtrace.rs
-rm src/test/ui/process/multi-panic.rs
-rm src/test/ui/numbers-arithmetic/issue-8460.rs
rm src/test/incremental/change_crate_dep_kind.rs
rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101)
-rm src/test/ui/panic-while-printing.rs
-rm src/test/ui/test-attrs/test-panic-while-printing.rs
-rm src/test/ui/test-attrs/test-type.rs
# requires compiling with -Cpanic=unwind
rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
# giving different but possibly correct results
# =============================================
-rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result
-rm src/test/ui/simd/intrinsic/float-minmax-pass.rs # same
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/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
+rm src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs # wrong result from `Location::caller()`
+
# bugs in the test suite
# ======================
-rm src/test/ui/unsafe/union.rs # has UB caught by cg_clif. see rust-lang/rust#95075
+rm src/test/ui/backtrace.rs # TODO warning
+rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support
+rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
+rm src/test/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
echo "[TEST] rustc test suite"
RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental}
$MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
$RUN_WRAPPER ./target/out/track-caller-attribute
+ echo "[AOT] float-minmax-pass"
+ $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
+ $RUN_WRAPPER ./target/out/float-minmax-pass
+
echo "[AOT] mod_bench"
$MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
$RUN_WRAPPER ./target/out/mod_bench
if cplace.layout().ty.is_box() {
cplace = cplace
.place_field(fx, Field::new(0)) // Box<T> -> Unique<T>
- .place_field(fx, Field::new(0)) // Unique<T> -> *const T
+ .place_field(fx, Field::new(0)) // Unique<T> -> NonNull<T>
+ .place_field(fx, Field::new(0)) // NonNull<T> -> *mut T
.place_deref(fx);
} else {
cplace = cplace.place_deref(fx);
fx.bcx.ins().fcvt_from_uint(to_ty, from)
}
} else if from_ty.is_float() && to_ty.is_int() {
- if to_ty == types::I128 {
+ let val = if to_ty == types::I128 {
// _____sssf___
// __fix sfti: f32 -> i128
// __fix dfti: f64 -> i128
let to_rust_ty = if to_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
- return fx
- .easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
- .load_scalar(fx);
- }
-
- // float -> int-like
- if to_ty == types::I8 || to_ty == types::I16 {
+ fx.easy_call(&name, &[CValue::by_val(from, fx.layout_of(from_rust_ty))], to_rust_ty)
+ .load_scalar(fx)
+ } else if to_ty == types::I8 || to_ty == types::I16 {
// FIXME implement fcvt_to_*int_sat.i8/i16
let val = if to_signed {
fx.bcx.ins().fcvt_to_sint_sat(types::I32, from)
fx.bcx.ins().fcvt_to_sint_sat(to_ty, from)
} else {
fx.bcx.ins().fcvt_to_uint_sat(to_ty, from)
+ };
+
+ if let Some(false) = fx.tcx.sess.opts.debugging_opts.saturating_float_casts {
+ return val;
+ }
+
+ let is_not_nan = fx.bcx.ins().fcmp(FloatCC::Equal, from, from);
+ if to_ty == types::I128 {
+ // FIXME(bytecodealliance/wasmtime#3963): select.i128 on fcmp eq miscompiles
+ let (lsb, msb) = fx.bcx.ins().isplit(val);
+ let zero = fx.bcx.ins().iconst(types::I64, 0);
+ let lsb = fx.bcx.ins().select(is_not_nan, lsb, zero);
+ let msb = fx.bcx.ins().select(is_not_nan, msb, zero);
+ fx.bcx.ins().iconcat(lsb, msb)
+ } else {
+ let zero = fx.bcx.ins().iconst(to_ty, 0);
+ fx.bcx.ins().select(is_not_nan, val, zero)
}
} else if from_ty.is_float() && to_ty.is_float() {
// float -> float
/// Can be set using `-Cllvm-args=display_cg_time=...`.
pub display_cg_time: bool,
- /// The register allocator to use.
- ///
- /// Defaults to the value of `CG_CLIF_REGALLOC` or `backtracking` otherwise. Can be set using
- /// `-Cllvm-args=regalloc=...`.
- pub regalloc: String,
-
/// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run
/// once before passing the clif ir to Cranelift for compilation.
///
args.split(' ').map(|arg| arg.to_string()).collect()
},
display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"),
- regalloc: std::env::var("CG_CLIF_REGALLOC")
- .unwrap_or_else(|_| "backtracking".to_string()),
enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
}
match name {
"mode" => config.codegen_mode = value.parse()?,
"display_cg_time" => config.display_cg_time = parse_bool(name, value)?,
- "regalloc" => config.regalloc = value.to_string(),
"enable_verifier" => config.enable_verifier = parse_bool(name, value)?,
"disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?,
_ => return Err(format!("Unknown option `{}`", name)),
let relative_discr = if niche_start == 0 {
tag
} else {
- // FIXME handle niche_start > i64::MAX
- fx.bcx.ins().iadd_imm(tag, -i64::try_from(niche_start).unwrap())
+ 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);
+ let msb =
+ fx.bcx.ins().iconst(types::I64, (niche_start >> 64) as u64 as i64);
+ fx.bcx.ins().iconcat(lsb, msb)
+ }
+ 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 = {
ret.write_cvalue(fx, old);
};
- // In Rust floating point min and max don't propagate NaN. In Cranelift they do however.
- // For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*`
- // and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing
- // a float against itself. Only in case of NaN is it not equal to itself.
minnumf32, (v a, v b) {
- let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
- let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
- let temp = fx.bcx.ins().select(a_ge_b, b, a);
- let val = fx.bcx.ins().select(a_is_nan, b, temp);
+ let val = crate::num::codegen_float_min(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
ret.write_cvalue(fx, val);
};
minnumf64, (v a, v b) {
- let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
- let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
- let temp = fx.bcx.ins().select(a_ge_b, b, a);
- let val = fx.bcx.ins().select(a_is_nan, b, temp);
+ let val = crate::num::codegen_float_min(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
ret.write_cvalue(fx, val);
};
maxnumf32, (v a, v b) {
- let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
- let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
- let temp = fx.bcx.ins().select(a_le_b, b, a);
- let val = fx.bcx.ins().select(a_is_nan, b, temp);
+ let val = crate::num::codegen_float_max(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
ret.write_cvalue(fx, val);
};
maxnumf64, (v a, v b) {
- let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
- let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
- let temp = fx.bcx.ins().select(a_le_b, b, a);
- let val = fx.bcx.ins().select(a_is_nan, b, temp);
+ let val = crate::num::codegen_float_max(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
ret.write_cvalue(fx, val);
};
}
assert_eq!(a.layout(), b.layout());
assert_eq!(a.layout(), c.layout());
- let layout = a.layout();
+ assert_eq!(a.layout(), ret.layout());
- let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
- let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
- assert_eq!(lane_count, ret_lane_count);
- let ret_lane_layout = fx.layout_of(ret_lane_ty);
+ let layout = a.layout();
+ let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
for lane in 0..lane_count {
- let a_lane = a.value_lane(fx, lane).load_scalar(fx);
- let b_lane = b.value_lane(fx, lane).load_scalar(fx);
- let c_lane = c.value_lane(fx, lane).load_scalar(fx);
+ let a_lane = a.value_lane(fx, lane);
+ let b_lane = b.value_lane(fx, lane);
+ let c_lane = c.value_lane(fx, lane);
- let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane);
- let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout);
+ let res_lane = match lane_ty.kind() {
+ ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty),
+ ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty),
+ _ => unreachable!(),
+ };
ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
}
_ => unreachable!("{:?}", lane_ty),
}
match intrinsic {
- sym::simd_fmin => fx.bcx.ins().fmin(x_lane, y_lane),
- sym::simd_fmax => fx.bcx.ins().fmax(x_lane, y_lane),
+ sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane),
+ sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane),
_ => unreachable!(),
}
});
let lt = match ty.kind() {
ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b),
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b),
- ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b),
+ ty::Float(_) => return crate::num::codegen_float_min(fx, a, b),
_ => unreachable!(),
};
fx.bcx.ins().select(lt, a, b)
let gt = match ty.kind() {
ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b),
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b),
- ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b),
+ ty::Float(_) => return crate::num::codegen_float_max(fx, a, b),
_ => unreachable!(),
};
fx.bcx.ins().select(gt, a, b)
flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();
- flags_builder.set("regalloc", &backend_config.regalloc).unwrap();
-
use rustc_session::config::OptLevel;
match sess.opts.optimize {
OptLevel::No => {
CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
}
}
+
+// In Rust floating point min and max don't propagate NaN. In Cranelift they do however.
+// For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*`
+// and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing
+// a float against itself. Only in case of NaN is it not equal to itself.
+pub(crate) fn codegen_float_min(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value {
+ let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
+ let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
+ let temp = fx.bcx.ins().select(a_ge_b, b, a);
+ fx.bcx.ins().select(a_is_nan, b, temp)
+}
+
+pub(crate) fn codegen_float_max(fx: &mut FunctionCx<'_, '_, '_>, a: Value, b: Value) -> Value {
+ let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
+ let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
+ let temp = fx.bcx.ins().select(a_le_b, b, a);
+ fx.bcx.ins().select(a_is_nan, b, temp)
+}
}
InlineAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
constants_len += self.tcx.symbol_name(instance).name.len();
}
InlineAsmOperandRef::SymStatic { def_id } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
}
}
}
InlineAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
}
InlineAsmOperandRef::SymStatic { def_id } => {
- // TODO(@Commeownist): This may not be sufficient for all kinds of statics.
- // Some statics may need the `@plt` suffix, like thread-local vars.
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
let instance = Instance::mono(self.tcx, def_id);
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => unimplemented!(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
InlineAsmRegClass::X86(
X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => cx.type_i16(),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
}
-impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> {
- fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef], options: InlineAsmOptions, _line_spans: &[Span]) {
+impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+ fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span]) {
let asm_arch = self.tcx.sess.asm_arch.unwrap();
// Default to Intel syntax on x86
// here unlike normal inline assembly.
template_str.push_str(string);
}
+
+ GlobalAsmOperandRef::SymFn { instance } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O)
+ // or byte count suffixes (x86 Windows).
+ let name = self.tcx.symbol_name(instance).name;
+ template_str.push_str(name);
+ }
+
+ GlobalAsmOperandRef::SymStatic { def_id } => {
+ // TODO(@Amanieu): Additional mangling is needed on
+ // some targets to add a leading underscore (Mach-O).
+ let instance = Instance::mono(self.tcx, def_id);
+ let name = self.tcx.symbol_name(instance).name;
+ template_str.push_str(name);
+ }
}
}
}
_ => unreachable!(),
},
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
+ InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None,
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
unreachable!("clobber-only")
}
use crate::{GccCodegenBackend, GccContext};
pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_handler: &Handler, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
- let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]);
+ let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);
{
let context = &module.module_llvm.context;
}
}
-impl AsmMethods for CodegenCx<'_, '_> {
+impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> {
fn codegen_global_asm(
&self,
template: &[InlineAsmTemplatePiece],
- operands: &[GlobalAsmOperandRef],
+ operands: &[GlobalAsmOperandRef<'tcx>],
options: InlineAsmOptions,
_line_spans: &[Span],
) {
// here unlike normal inline assembly.
template_str.push_str(string);
}
+ GlobalAsmOperandRef::SymFn { instance } => {
+ let llval = self.get_fn(instance);
+ self.add_compiler_used_global(llval);
+ let symbol = llvm::build_string(|s| unsafe {
+ llvm::LLVMRustGetMangledName(llval, s);
+ })
+ .expect("symbol is not valid UTF-8");
+ template_str.push_str(&symbol);
+ }
+ GlobalAsmOperandRef::SymStatic { def_id } => {
+ let llval = self
+ .renamed_statics
+ .borrow()
+ .get(&def_id)
+ .copied()
+ .unwrap_or_else(|| self.get_static(def_id));
+ self.add_compiler_used_global(llval);
+ let symbol = llvm::build_string(|s| unsafe {
+ llvm::LLVMRustGetMangledName(llval, s);
+ })
+ .expect("symbol is not valid UTF-8");
+ template_str.push_str(&symbol);
+ }
}
}
}
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
InlineAsmRegClass::X86(
- X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
+ X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::kreg0,
) => unreachable!("clobber-only"),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
_ => unreachable!(),
},
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
- InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::kreg0,
+ ) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
- InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::kreg0,
+ ) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
for (bc_decoded, name) in serialized_modules {
let _timer = cgcx
.prof
- .generic_activity_with_arg("LLVM_fat_lto_link_module", format!("{:?}", name));
+ .generic_activity_with_arg_recorder("LLVM_fat_lto_link_module", |recorder| {
+ recorder.record_arg(format!("{:?}", name))
+ });
info!("linking {:?}", name);
let data = bc_decoded.data();
linker.add(data).map_err(|()| {
let mut linker = Linker::new(first.module_llvm.llmod());
for module in elements {
- let _timer =
- cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name));
+ let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
linker.add(buffer.data()).map_err(|()| {
let msg = format!("failed to serialize module {:?}", module.name);
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
let cgu = tcx.codegen_unit(cgu_name);
- let _prof_timer = tcx.prof.generic_activity_with_args(
- "codegen_module",
- &[cgu_name.to_string(), cgu.size_estimate().to_string()],
- );
+ let _prof_timer =
+ tcx.prof.generic_activity_with_arg_recorder("codegen_module", |recorder| {
+ recorder.record_arg(cgu_name.to_string());
+ recorder.record_arg(cgu.size_estimate().to_string());
+ });
// Instantiate monomorphizations without filling out definitions yet...
let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str());
{
attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
}
- // Run replace-all-uses-with for statics that need it
- for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
- unsafe {
- let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
- llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
- llvm::LLVMDeleteGlobal(old_g);
- }
- }
-
// Finalize code coverage by injecting the coverage map. Note, the coverage map will
// also be added to the `llvm.compiler.used` variable, created next.
if cx.sess().instrument_coverage() {
cx.create_compiler_used_variable()
}
+ // Run replace-all-uses-with for statics that need it. This must
+ // happen after the llvm.used variables are created.
+ for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
+ unsafe {
+ let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
+ llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
+ llvm::LLVMDeleteGlobal(old_g);
+ }
+ }
+
// Finalize debuginfo
if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize();
llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
+ // The old global has had its name removed but is returned by
+ // get_static since it is in the instance cache. Provide an
+ // alternative lookup that points to the new global so that
+ // global_asm! can compute the correct mangled symbol name
+ // for the global.
+ self.renamed_statics.borrow_mut().insert(def_id, new_g);
+
// To avoid breaking any invariants, we leave around the old
// global for the moment; we'll replace all references to it
// with the new global later. (See base::codegen_backend.)
use rustc_data_structures::base_n;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
/// A counter that is used for generating local symbol names
local_gen_sym_counter: Cell<usize>,
+
+ /// `codegen_static` will sometimes create a second global variable with a
+ /// different type and clear the symbol name of the original global.
+ /// `global_asm!` needs to be able to find this new global so that it can
+ /// compute the correct mangled symbol name to insert into the asm.
+ pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
}
pub struct TypeLowering<'ll> {
rust_try_fn: Cell::new(None),
intrinsics: Default::default(),
local_gen_sym_counter: Cell::new(0),
+ renamed_statics: Default::default(),
}
}
let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
- DINodeCreationResult::new(build_basic_type_di_node(cx, t), false)
- }
- ty::Tuple(elements) if elements.is_empty() => {
- DINodeCreationResult::new(build_basic_type_di_node(cx, t), false)
+ build_basic_type_di_node(cx, t)
}
+ ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t),
ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
}
}
-fn build_basic_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
+fn build_basic_type_di_node<'ll, 'tcx>(
+ cx: &CodegenCx<'ll, 'tcx>,
+ t: Ty<'tcx>,
+) -> DINodeCreationResult<'ll> {
debug!("build_basic_type_di_node: {:?}", t);
// When targeting MSVC, emit MSVC style type names for compatibility with
let (name, encoding) = match t.kind() {
ty::Never => ("!", DW_ATE_unsigned),
- ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned),
+ ty::Tuple(elements) if elements.is_empty() => {
+ if cpp_like_debuginfo {
+ return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t));
+ } else {
+ ("()", DW_ATE_unsigned)
+ }
+ }
ty::Bool => ("bool", DW_ATE_boolean),
ty::Char => ("char", DW_ATE_UTF),
ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
};
if !cpp_like_debuginfo {
- return ty_di_node;
+ return DINodeCreationResult::new(ty_di_node, false);
}
let typedef_name = match t.kind() {
ty::Int(int_ty) => int_ty.name_str(),
ty::Uint(uint_ty) => uint_ty.name_str(),
ty::Float(float_ty) => float_ty.name_str(),
- _ => return ty_di_node,
+ _ => return DINodeCreationResult::new(ty_di_node, false),
};
let typedef_di_node = unsafe {
)
};
- typedef_di_node
+ DINodeCreationResult::new(typedef_di_node, false)
}
fn build_foreign_type_di_node<'ll, 'tcx>(
// Build the type node for each field.
let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
- .clone()
.map(|variant_index| {
let variant_struct_type_di_node = super::build_generator_variant_struct_type_di_node(
cx,
simd_neg: Int => neg, Float => fneg;
}
+ if name == sym::simd_arith_offset {
+ // This also checks that the first operand is a ptr type.
+ let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
+ span_bug!(span, "must be called with a vector of pointer types as first argument")
+ });
+ let layout = bx.layout_of(pointee.ty);
+ let ptrs = args[0].immediate();
+ // The second argument must be a ptr-sized integer.
+ // (We don't care about the signedness, this is wrapping anyway.)
+ let (_offsets_len, offsets_elem) = arg_tys[1].simd_size_and_type(bx.tcx());
+ if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) {
+ span_bug!(
+ span,
+ "must be called with a vector of pointer-sized integers as second argument"
+ );
+ }
+ let offsets = args[1].immediate();
+
+ return Ok(bx.gep(bx.backend_type(layout), ptrs, &[offsets]));
+ }
+
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
let lhs = args[0].immediate();
let rhs = args[1].immediate();
remark_passes_len: usize,
);
+ #[allow(improper_ctypes)]
+ pub fn LLVMRustGetMangledName(V: &Value, out: &RustString);
}
// On MSVC packed debug information is produced by the linker itself so
// there's no need to do anything else here.
- SplitDebuginfo::Packed if sess.target.is_like_msvc => {}
+ SplitDebuginfo::Packed if sess.target.is_like_windows => {}
// ... and otherwise we're processing a `*.dwp` packed dwarf file.
//
use std::collections::hash_map::Entry::*;
use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
-use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::Node;
-use rustc_index::vec::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
- let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = {
- let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO, cnums.len() + 1);
-
- for &cnum in cnums.iter() {
- cnum_stable_ids[cnum] =
- tcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).0;
- }
-
- cnum_stable_ids
- };
-
let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
for &cnum in cnums.iter() {
// If there are multiple monomorphizations available,
// we select one deterministically.
let other_cnum = *e.get();
- if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
+ if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) {
e.insert(cnum);
}
}
// a box with a non-zst allocator should not be directly dereferenced
if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
- let ptr = cg_base.extract_field(bx, 0).extract_field(bx, 0);
+ // Extract `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
+ let ptr =
+ cg_base.extract_field(bx, 0).extract_field(bx, 0).extract_field(bx, 0);
ptr.deref(bx.cx())
} else {
mir::ProjectionElem::Deref => {
// a box with a non-zst allocator should not be directly dereferenced
if cg_base.layout.ty.is_box() && !cg_base.layout.field(cx, 1).is_zst() {
- let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
+ // Project `Box<T>` -> `Unique<T>` -> `NonNull<T>` -> `*const T`
+ let ptr =
+ cg_base.project_field(bx, 0).project_field(bx, 0).project_field(bx, 0);
bx.load_operand(ptr).deref(bx.cx())
} else {
use rustc_hir as hir;
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
+use rustc_middle::ty;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::Instance;
pub trait MonoItemExt<'a, 'tcx> {
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
);
GlobalAsmOperandRef::Const { string }
}
- _ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
+ hir::InlineAsmOperand::SymFn { ref anon_const } => {
+ let ty = cx
+ .tcx()
+ .typeck_body(anon_const.body)
+ .node_type(anon_const.hir_id);
+ let instance = match ty.kind() {
+ &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+ _ => span_bug!(*op_sp, "asm sym is not a function"),
+ };
+
+ GlobalAsmOperandRef::SymFn { instance }
+ }
+ hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+ GlobalAsmOperandRef::SymStatic { def_id }
+ }
+ hir::InlineAsmOperand::In { .. }
+ | hir::InlineAsmOperand::Out { .. }
+ | hir::InlineAsmOperand::InOut { .. }
+ | hir::InlineAsmOperand::SplitInOut { .. } => {
+ span_bug!(*op_sp, "invalid operand type for global_asm!")
+ }
})
.collect();
}
#[derive(Debug)]
-pub enum GlobalAsmOperandRef {
+pub enum GlobalAsmOperandRef<'tcx> {
Const { string: String },
+ SymFn { instance: Instance<'tcx> },
+ SymStatic { def_id: DefId },
}
pub trait AsmBuilderMethods<'tcx>: BackendTypes {
);
}
-pub trait AsmMethods {
+pub trait AsmMethods<'tcx> {
fn codegen_global_asm(
&self,
template: &[InlineAsmTemplatePiece],
- operands: &[GlobalAsmOperandRef],
+ operands: &[GlobalAsmOperandRef<'tcx>],
options: InlineAsmOptions,
line_spans: &[Span],
);
+ StaticMethods
+ CoverageInfoMethods<'tcx>
+ DebugInfoMethods<'tcx>
- + AsmMethods
+ + AsmMethods<'tcx>
+ PreDefineMethods<'tcx>
+ HasParamEnv<'tcx>
+ HasTyCtxt<'tcx>
+ StaticMethods
+ CoverageInfoMethods<'tcx>
+ DebugInfoMethods<'tcx>
- + AsmMethods
+ + AsmMethods<'tcx>
+ PreDefineMethods<'tcx>
+ HasParamEnv<'tcx>
+ HasTyCtxt<'tcx>
}
}
+#[instrument(skip(tcx), level = "debug")]
fn turn_into_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
constant: ConstAlloc<'tcx>,
!is_static || cid.promoted.is_some(),
"the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
);
+
// Turn this into a proper constant.
op_to_const(&ecx, &mplace.into())
}
use std::convert::TryFrom;
use rustc_hir::Mutability;
+use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{
mir::{self, interpret::ConstAlloc},
ty::ScalarInt,
};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_target::abi::VariantIdx;
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
bug!("intern_const_alloc_recursive should not error in this case")
}
- ConstValue::Scalar(Scalar::from_pointer(loc_place.ptr.into_pointer_or_addr().unwrap(), &tcx))
+ ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
}
/// Convert an evaluated constant to a type level constant
const_to_valtree_inner(&ecx, &place)
}
-fn const_to_valtree_inner<'tcx>(
+#[instrument(skip(ecx), level = "debug")]
+fn branches<'tcx>(
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
place: &MPlaceTy<'tcx>,
+ n: usize,
+ variant: Option<VariantIdx>,
) -> Option<ty::ValTree<'tcx>> {
- let branches = |n, variant| {
- let place = match variant {
- Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
- None => *place,
- };
- let variant =
- variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
- let fields = (0..n).map(|i| {
- let field = ecx.mplace_field(&place, i).unwrap();
- const_to_valtree_inner(ecx, &field)
- });
- // For enums, we preped their variant index before the variant's fields so we can figure out
- // the variant again when just seeing a valtree.
- let branches = variant.into_iter().chain(fields);
- Some(ty::ValTree::Branch(
- ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?),
- ))
+ let place = match variant {
+ Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
+ None => *place,
};
+ let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32()))));
+ debug!(?place, ?variant);
+
+ let fields = (0..n).map(|i| {
+ let field = ecx.mplace_field(&place, i).unwrap();
+ const_to_valtree_inner(ecx, &field)
+ });
+ // For enums, we prepend their variant index before the variant's fields so we can figure out
+ // the variant again when just seeing a valtree.
+ let branches = variant.into_iter().chain(fields);
+ Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
+}
+
+fn slice_branches<'tcx>(
+ ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
+ place: &MPlaceTy<'tcx>,
+) -> Option<ty::ValTree<'tcx>> {
+ let n = place.len(&ecx.tcx()).expect(&format!("expected to use len of place {:?}", place));
+ let branches = (0..n).map(|i| {
+ let place_elem = ecx.mplace_index(place, i).unwrap();
+ const_to_valtree_inner(ecx, &place_elem)
+ });
+
+ Some(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches.collect::<Option<Vec<_>>>()?)))
+}
+
+#[instrument(skip(ecx), level = "debug")]
+fn const_to_valtree_inner<'tcx>(
+ ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
+ place: &MPlaceTy<'tcx>,
+) -> Option<ty::ValTree<'tcx>> {
match place.layout.ty.kind() {
ty::FnDef(..) => Some(ty::ValTree::zst()),
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
// agree with runtime equality tests.
ty::FnPtr(_) | ty::RawPtr(_) => None,
- ty::Ref(..) => unimplemented!("need to use deref_const"),
+ ty::Ref(_, _, _) => {
+ let derefd_place = ecx.deref_operand(&place.into()).unwrap_or_else(|e| bug!("couldn't deref {:?}, error: {:?}", place, e));
+ debug!(?derefd_place);
+
+ const_to_valtree_inner(ecx, &derefd_place)
+ }
+
+ ty::Str | ty::Slice(_) | ty::Array(_, _) => {
+ let valtree = slice_branches(ecx, place);
+ debug!(?valtree);
+
+ valtree
+ }
// Trait objects are not allowed in type level constants, as we have no concept for
// resolving their backing type, even if we can do that at const eval time. We may
// hypothetically be able to allow `dyn StructuralEq` trait objects in the future,
// but it is unclear if this is useful.
ty::Dynamic(..) => None,
- ty::Slice(_) | ty::Str => {
- unimplemented!("need to find the backing data of the slice/str and recurse on that")
- }
- ty::Tuple(substs) => branches(substs.len(), None),
- ty::Array(_, len) => branches(usize::try_from(len.eval_usize(ecx.tcx.tcx, ecx.param_env)).unwrap(), None),
+ ty::Tuple(substs) => branches(ecx, place, substs.len(), None),
ty::Adt(def, _) => {
if def.variants().is_empty() {
let variant = ecx.read_discriminant(&place.into()).unwrap().1;
- branches(def.variant(variant).fields.len(), def.is_enum().then_some(variant))
+ branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
}
ty::Never
return_place: Option<&PlaceTy<'tcx, M::PointerTag>>,
return_to_block: StackPopCleanup,
) -> InterpResult<'tcx> {
- debug!("body: {:#?}", body);
+ trace!("body: {:#?}", body);
// first push a stack frame so we have access to the local substs
let pre_frame = Frame {
body,
return Ok(());
}
- debug!("locals: {:#?}", frame.locals);
+ trace!("locals: {:#?}", frame.locals);
// Cleanup: deallocate all locals that are backed by an allocation.
for local in &frame.locals {
/// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to.
type PointerTag: Provenance + Eq + Hash + 'static;
+ /// When getting the AllocId of a pointer, some extra data is also obtained from the tag
+ /// that is passed to memory access hooks so they can do things with it.
+ type TagExtra: Copy + 'static;
+
/// Machines can define extra (non-instance) things that represent values of function pointers.
/// For example, Miri uses this to return a function pointer from `dlsym`
/// that can later be called to execute the right thing.
/// Whether, when checking alignment, we should `force_int` and thus support
/// custom alignment logic based on whatever the integer address happens to be.
+ ///
+ /// Requires PointerTag::OFFSET_IS_ADDR to be true.
fn force_int_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
/// Whether to enforce the validity invariant
addr: u64,
) -> Pointer<Option<Self::PointerTag>>;
- /// Convert a pointer with provenance into an allocation-offset pair.
+ /// Convert a pointer with provenance into an allocation-offset pair
+ /// and extra provenance info.
+ ///
+ /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`.
fn ptr_get_alloc(
ecx: &InterpCx<'mir, 'tcx, Self>,
ptr: Pointer<Self::PointerTag>,
- ) -> (AllocId, Size);
+ ) -> (AllocId, Size, Self::TagExtra);
/// Called to initialize the "extra" state of an allocation and make the pointers
/// it contains (in relocations) tagged. The way we construct allocations is
_tcx: TyCtxt<'tcx>,
_machine: &Self,
_alloc_extra: &Self::AllocExtra,
- _tag: Self::PointerTag,
+ _tag: (AllocId, Self::TagExtra),
_range: AllocRange,
) -> InterpResult<'tcx> {
Ok(())
_tcx: TyCtxt<'tcx>,
_machine: &mut Self,
_alloc_extra: &mut Self::AllocExtra,
- _tag: Self::PointerTag,
+ _tag: (AllocId, Self::TagExtra),
_range: AllocRange,
) -> InterpResult<'tcx> {
Ok(())
_tcx: TyCtxt<'tcx>,
_machine: &mut Self,
_alloc_extra: &mut Self::AllocExtra,
- _tag: Self::PointerTag,
+ _tag: (AllocId, Self::TagExtra),
_range: AllocRange,
) -> InterpResult<'tcx> {
Ok(())
// (CTFE and ConstProp) use the same instance. Here, we share that code.
pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type PointerTag = AllocId;
+ type TagExtra = ();
+
type ExtraFnVal = !;
type MemoryMap =
}
#[inline(always)]
- fn ptr_get_alloc(_ecx: &InterpCx<$mir, $tcx, Self>, ptr: Pointer<AllocId>) -> (AllocId, Size) {
+ fn ptr_get_alloc(
+ _ecx: &InterpCx<$mir, $tcx, Self>,
+ ptr: Pointer<AllocId>,
+ ) -> (AllocId, Size, Self::TagExtra) {
// We know `offset` is relative to the allocation, so we can use `into_parts`.
let (alloc_id, offset) = ptr.into_parts();
- (alloc_id, offset)
+ (alloc_id, offset, ())
}
}
&self,
ptr: Pointer<AllocId>,
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
- // We know `offset` is relative to the allocation, so we can use `into_parts`.
- let (alloc_id, offset) = ptr.into_parts();
+ let alloc_id = ptr.provenance;
// We need to handle `extern static`.
match self.tcx.get_global_alloc(alloc_id) {
Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => {
_ => {}
}
// And we need to get the tag.
- Ok(M::tag_alloc_base_pointer(self, Pointer::new(alloc_id, offset)))
+ Ok(M::tag_alloc_base_pointer(self, ptr))
}
pub fn create_fn_alloc_ptr(
new_align: Align,
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
- let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
if offset.bytes() != 0 {
throw_ub_format!(
"reallocating {:?} which does not point to the beginning of an object",
};
// This will also call the access hooks.
self.mem_copy(
- ptr.into(),
+ ptr,
Align::ONE,
new_ptr.into(),
Align::ONE,
old_size.min(new_size),
/*nonoverlapping*/ true,
)?;
- self.deallocate_ptr(ptr.into(), old_size_and_align, kind)?;
+ self.deallocate_ptr(ptr, old_size_and_align, kind)?;
Ok(new_ptr)
}
old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx> {
- let (alloc_id, offset, ptr) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, tag) = self.ptr_get_alloc_id(ptr)?;
trace!("deallocating: {}", alloc_id);
if offset.bytes() != 0 {
*self.tcx,
&mut self.machine,
&mut alloc.extra,
- ptr.provenance,
+ (alloc_id, tag),
alloc_range(Size::ZERO, size),
)?;
ptr: Pointer<Option<M::PointerTag>>,
size: Size,
align: Align,
- ) -> InterpResult<'tcx, Option<(AllocId, Size, Pointer<M::PointerTag>)>> {
+ ) -> InterpResult<'tcx, Option<(AllocId, Size, M::TagExtra)>> {
let align = M::enforce_alignment(&self).then_some(align);
self.check_and_deref_ptr(
ptr,
size,
align,
CheckInAllocMsg::MemoryAccessTest,
- |alloc_id, offset, ptr| {
+ |alloc_id, offset, tag| {
let (size, align) =
self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
- Ok((size, align, (alloc_id, offset, ptr)))
+ Ok((size, align, (alloc_id, offset, tag)))
},
)
}
size: Size,
align: Option<Align>,
msg: CheckInAllocMsg,
- alloc_size: impl FnOnce(
- AllocId,
- Size,
- Pointer<M::PointerTag>,
- ) -> InterpResult<'tcx, (Size, Align, T)>,
+ alloc_size: impl FnOnce(AllocId, Size, M::TagExtra) -> InterpResult<'tcx, (Size, Align, T)>,
) -> InterpResult<'tcx, Option<T>> {
fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
if offset % align.bytes() == 0 {
}
None
}
- Ok((alloc_id, offset, ptr)) => {
- let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, ptr)?;
+ Ok((alloc_id, offset, tag)) => {
+ let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, tag)?;
// Test bounds. This also ensures non-null.
// It is sufficient to check this for the end pointer. Also check for overflow!
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
// we want the error to be about the bounds.
if let Some(align) = align {
if M::force_int_for_alignment_check(self) {
- let addr = Scalar::from_pointer(ptr, &self.tcx)
- .to_machine_usize(&self.tcx)
- .expect("ptr-to-int cast for align check should never fail");
- check_offset_align(addr, align)?;
+ // `force_int_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
+ check_offset_align(ptr.addr().bytes(), align)?;
} else {
// Check allocation alignment and offset alignment.
if alloc_align.bytes() < align.bytes() {
size,
align,
CheckInAllocMsg::MemoryAccessTest,
- |alloc_id, offset, ptr| {
+ |alloc_id, offset, tag| {
let alloc = self.get_alloc_raw(alloc_id)?;
- Ok((alloc.size(), alloc.align, (alloc_id, offset, ptr, alloc)))
+ Ok((alloc.size(), alloc.align, (alloc_id, offset, tag, alloc)))
},
)?;
- if let Some((alloc_id, offset, ptr, alloc)) = ptr_and_alloc {
+ if let Some((alloc_id, offset, tag, alloc)) = ptr_and_alloc {
let range = alloc_range(offset, size);
- M::memory_read(*self.tcx, &self.machine, &alloc.extra, ptr.provenance, range)?;
+ M::memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, tag), range)?;
Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id }))
} else {
// Even in this branch we have to be sure that we actually access the allocation, in
align: Align,
) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::PointerTag, M::AllocExtra>>> {
let parts = self.get_ptr_access(ptr, size, align)?;
- if let Some((alloc_id, offset, ptr)) = parts {
+ if let Some((alloc_id, offset, tag)) = parts {
let tcx = *self.tcx;
// FIXME: can we somehow avoid looking up the allocation twice here?
// We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
let range = alloc_range(offset, size);
- M::memory_written(tcx, machine, &mut alloc.extra, ptr.provenance, range)?;
+ M::memory_written(tcx, machine, &mut alloc.extra, (alloc_id, tag), range)?;
Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id }))
} else {
Ok(None)
ptr: Pointer<Option<M::PointerTag>>,
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
trace!("get_fn({:?})", ptr);
- let (alloc_id, offset, _ptr) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
if offset.bytes() != 0 {
throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset)))
}
range: AllocRange,
val: ScalarMaybeUninit<Tag>,
) -> InterpResult<'tcx> {
+ let range = self.range.subrange(range);
+ debug!(
+ "write_scalar in {} at {:#x}, size {}: {:?}",
+ self.alloc_id,
+ range.start.bytes(),
+ range.size.bytes(),
+ val
+ );
Ok(self
.alloc
- .write_scalar(&self.tcx, self.range.subrange(range), val)
+ .write_scalar(&self.tcx, range, val)
.map_err(|e| e.to_interp_error(self.alloc_id))?)
}
}
/// Mark the entire referenced range as uninitalized
- pub fn write_uninit(&mut self) {
- self.alloc.mark_init(self.range, false);
+ pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
+ Ok(self
+ .alloc
+ .write_uninit(&self.tcx, self.range)
+ .map_err(|e| e.to_interp_error(self.alloc_id))?)
}
}
impl<'tcx, 'a, Tag: Provenance, Extra> AllocRef<'a, 'tcx, Tag, Extra> {
pub fn read_scalar(&self, range: AllocRange) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
- Ok(self
+ let range = self.range.subrange(range);
+ let res = self
.alloc
- .read_scalar(&self.tcx, self.range.subrange(range))
- .map_err(|e| e.to_interp_error(self.alloc_id))?)
+ .read_scalar(&self.tcx, range)
+ .map_err(|e| e.to_interp_error(self.alloc_id))?;
+ debug!(
+ "read_scalar in {} at {:#x}, size {}: {:?}",
+ self.alloc_id,
+ range.start.bytes(),
+ range.size.bytes(),
+ res
+ );
+ Ok(res)
}
pub fn read_ptr_sized(&self, offset: Size) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
// and once below to get the underlying `&[mut] Allocation`.
// Source alloc preparations and access hooks.
- let Some((src_alloc_id, src_offset, src)) = src_parts else {
+ let Some((src_alloc_id, src_offset, src_tag)) = src_parts else {
// Zero-sized *source*, that means dst is also zero-sized and we have nothing to do.
return Ok(());
};
let src_alloc = self.get_alloc_raw(src_alloc_id)?;
let src_range = alloc_range(src_offset, size);
- M::memory_read(*tcx, &self.machine, &src_alloc.extra, src.provenance, src_range)?;
+ M::memory_read(*tcx, &self.machine, &src_alloc.extra, (src_alloc_id, src_tag), src_range)?;
// We need the `dest` ptr for the next operation, so we get it now.
// We already did the source checks and called the hooks so we are good to return early.
- let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else {
+ let Some((dest_alloc_id, dest_offset, dest_tag)) = dest_parts else {
// Zero-sized *destination*.
return Ok(());
};
// Destination alloc preparations and access hooks.
let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?;
let dest_range = alloc_range(dest_offset, size * num_copies);
- M::memory_written(*tcx, extra, &mut dest_alloc.extra, dest.provenance, dest_range)?;
+ M::memory_written(
+ *tcx,
+ extra,
+ &mut dest_alloc.extra,
+ (dest_alloc_id, dest_tag),
+ dest_range,
+ )?;
let dest_bytes = dest_alloc
.get_bytes_mut_ptr(&tcx, dest_range)
.map_err(|e| e.to_interp_error(dest_alloc_id))?
// This also avoids writing to the target bytes so that the backing allocation is never
// touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary
// operating system this can avoid physically allocating the page.
- dest_alloc.mark_init(dest_range, false); // `Size` multiplication
- dest_alloc.mark_relocation_range(relocations);
+ dest_alloc
+ .write_uninit(&tcx, dest_range)
+ .map_err(|e| e.to_interp_error(dest_alloc_id))?;
+ // We can forget about the relocations, this is all not initialized anyway.
return Ok(());
}
pub fn ptr_try_get_alloc_id(
&self,
ptr: Pointer<Option<M::PointerTag>>,
- ) -> Result<(AllocId, Size, Pointer<M::PointerTag>), u64> {
+ ) -> Result<(AllocId, Size, M::TagExtra), u64> {
match ptr.into_pointer_or_addr() {
Ok(ptr) => {
- let (alloc_id, offset) = M::ptr_get_alloc(self, ptr);
- Ok((alloc_id, offset, ptr))
+ let (alloc_id, offset, extra) = M::ptr_get_alloc(self, ptr);
+ Ok((alloc_id, offset, extra))
}
Err(addr) => Err(addr.bytes()),
}
pub fn ptr_get_alloc_id(
&self,
ptr: Pointer<Option<M::PointerTag>>,
- ) -> InterpResult<'tcx, (AllocId, Size, Pointer<M::PointerTag>)> {
+ ) -> InterpResult<'tcx, (AllocId, Size, M::TagExtra)> {
self.ptr_try_get_alloc_id(ptr).map_err(|offset| {
err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
})
}
#[inline]
- pub(super) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
+ pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
if self.layout.is_unsized() {
// We need to consult `meta` metadata
match self.layout.ty.kind() {
// Zero-sized access
return Ok(());
};
- alloc.write_uninit();
+ alloc.write_uninit()?;
Ok(())
}
self.write_immediate(*val, &dest)?;
}
- Aggregate(ref kind, ref operands) => {
- // active_field_index is for union initialization.
- let (dest, active_field_index) = match **kind {
- mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- self.write_discriminant(variant_index, &dest)?;
- if self.tcx.adt_def(adt_did).is_enum() {
- assert!(active_field_index.is_none());
- (self.place_downcast(&dest, variant_index)?, None)
- } else {
- if active_field_index.is_some() {
- assert_eq!(operands.len(), 1);
- }
- (dest, active_field_index)
- }
- }
- _ => (dest, None),
- };
+ Aggregate(box ref kind, ref operands) => {
+ assert!(matches!(kind, mir::AggregateKind::Array(..)));
- for (i, operand) in operands.iter().enumerate() {
+ for (field_index, operand) in operands.iter().enumerate() {
let op = self.eval_operand(operand, None)?;
- let field_index = active_field_index.unwrap_or(i);
let field_dest = self.place_field(&dest, field_index)?;
self.copy_op(&op, &field_dest)?;
}
if let Some(ref mut ref_tracking) = self.ref_tracking {
// Proceed recursively even for ZST, no reason to skip them!
// `!` is a ZST and we want to validate it.
- if let Ok((alloc_id, _offset, _ptr)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
+ if let Ok((alloc_id, _offset, _tag)) = self.ecx.ptr_try_get_alloc_id(place.ptr) {
// Special handling for pointers to statics (irrespective of their type).
let alloc_kind = self.ecx.tcx.get_global_alloc(alloc_id);
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
// This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
- if self.tcx.sess.opts.debugging_opts.validate_mir {
+ if self.tcx.sess.opts.debugging_opts.validate_mir && self.mir_phase < MirPhase::DropsLowered
+ {
// `Operand::Copy` is only supposed to be used with `Copy` types.
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
| ty::FnPtr(..)
)
}
- // None of the possible types have lifetimes, so we can just compare
- // directly
- if a != b {
+ // The function pointer types can have lifetimes
+ if !self.mir_assign_valid_types(a, b) {
self.fail(
location,
format!("Cannot compare unequal types {:?} and {:?}", a, b),
};
// since CopyNonOverlapping is parametrized by 1 type,
// we only need to check that they are equal and not keep an extra parameter.
- if op_src_ty != op_dst_ty {
+ if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
self.fail(location, format!("bad arg ({:?} != {:?})", op_src_ty, op_dst_ty));
}
#![allow(non_camel_case_types)]
#![allow(nonstandard_style)]
-use std::fs::{File, OpenOptions};
-use std::io;
-use std::path::Path;
-
cfg_if! {
- // We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
- // `fcntl`-style advisory locks properly (rust-lang/rust#72157).
- //
- // For other Unix targets we still use `fcntl` because it's more portable than
- // `flock`.
if #[cfg(target_os = "linux")] {
- use std::os::unix::prelude::*;
-
- #[derive(Debug)]
- pub struct Lock {
- _file: File,
- }
-
- impl Lock {
- pub fn new(p: &Path,
- wait: bool,
- create: bool,
- exclusive: bool)
- -> io::Result<Lock> {
- let file = OpenOptions::new()
- .read(true)
- .write(true)
- .create(create)
- .mode(libc::S_IRWXU as u32)
- .open(p)?;
-
- let mut operation = if exclusive {
- libc::LOCK_EX
- } else {
- libc::LOCK_SH
- };
- if !wait {
- operation |= libc::LOCK_NB
- }
-
- let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
- if ret == -1 {
- Err(io::Error::last_os_error())
- } else {
- Ok(Lock { _file: file })
- }
- }
-
- pub fn error_unsupported(err: &io::Error) -> bool {
- matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
- }
- }
-
- // Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
- // `flock` is associated with the file descriptor and closing the file release it
- // automatically.
+ mod linux;
+ use linux as imp;
} else if #[cfg(unix)] {
- use std::mem;
- use std::os::unix::prelude::*;
-
- #[derive(Debug)]
- pub struct Lock {
- file: File,
- }
-
- impl Lock {
- pub fn new(p: &Path,
- wait: bool,
- create: bool,
- exclusive: bool)
- -> io::Result<Lock> {
- let file = OpenOptions::new()
- .read(true)
- .write(true)
- .create(create)
- .mode(libc::S_IRWXU as u32)
- .open(p)?;
-
- let lock_type = if exclusive {
- libc::F_WRLCK
- } else {
- libc::F_RDLCK
- };
-
- let mut flock: libc::flock = unsafe { mem::zeroed() };
- flock.l_type = lock_type as libc::c_short;
- flock.l_whence = libc::SEEK_SET as libc::c_short;
- flock.l_start = 0;
- flock.l_len = 0;
-
- let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
- let ret = unsafe {
- libc::fcntl(file.as_raw_fd(), cmd, &flock)
- };
- if ret == -1 {
- Err(io::Error::last_os_error())
- } else {
- Ok(Lock { file })
- }
- }
-
- pub fn error_unsupported(err: &io::Error) -> bool {
- matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
- }
- }
-
- impl Drop for Lock {
- fn drop(&mut self) {
- let mut flock: libc::flock = unsafe { mem::zeroed() };
- flock.l_type = libc::F_UNLCK as libc::c_short;
- flock.l_whence = libc::SEEK_SET as libc::c_short;
- flock.l_start = 0;
- flock.l_len = 0;
-
- unsafe {
- libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
- }
- }
- }
+ mod unix;
+ use unix as imp;
} else if #[cfg(windows)] {
- use std::mem;
- use std::os::windows::prelude::*;
-
- use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
- use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
- use winapi::um::fileapi::LockFileEx;
- use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
-
- #[derive(Debug)]
- pub struct Lock {
- _file: File,
- }
-
- impl Lock {
- pub fn new(p: &Path,
- wait: bool,
- create: bool,
- exclusive: bool)
- -> io::Result<Lock> {
- assert!(p.parent().unwrap().exists(),
- "Parent directory of lock-file must exist: {}",
- p.display());
-
- let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
-
- let mut open_options = OpenOptions::new();
- open_options.read(true)
- .share_mode(share_mode);
-
- if create {
- open_options.create(true)
- .write(true);
- }
-
- debug!("attempting to open lock file `{}`", p.display());
- let file = match open_options.open(p) {
- Ok(file) => {
- debug!("lock file opened successfully");
- file
- }
- Err(err) => {
- debug!("error opening lock file: {}", err);
- return Err(err)
- }
- };
-
- let ret = unsafe {
- let mut overlapped: OVERLAPPED = mem::zeroed();
-
- let mut dwFlags = 0;
- if !wait {
- dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
- }
-
- if exclusive {
- dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- }
-
- debug!("attempting to acquire lock on lock file `{}`",
- p.display());
- LockFileEx(file.as_raw_handle(),
- dwFlags,
- 0,
- 0xFFFF_FFFF,
- 0xFFFF_FFFF,
- &mut overlapped)
- };
- if ret == 0 {
- let err = io::Error::last_os_error();
- debug!("failed acquiring file lock: {}", err);
- Err(err)
- } else {
- debug!("successfully acquired lock");
- Ok(Lock { _file: file })
- }
- }
-
- pub fn error_unsupported(err: &io::Error) -> bool {
- err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
- }
- }
-
- // Note that we don't need a Drop impl on the Windows: The file is unlocked
- // automatically when it's closed.
+ mod windows;
+ use windows as imp;
} else {
- #[derive(Debug)]
- pub struct Lock(());
-
- impl Lock {
- pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
- -> io::Result<Lock>
- {
- let msg = "file locks not supported on this platform";
- Err(io::Error::new(io::ErrorKind::Other, msg))
- }
-
- pub fn error_unsupported(_err: &io::Error) -> bool {
- true
- }
- }
+ mod unsupported;
+ use unsupported as imp;
}
}
+
+pub use imp::Lock;
--- /dev/null
+//! We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
+//! `fcntl`-style advisory locks properly (rust-lang/rust#72157). For other Unix
+//! targets we still use `fcntl` because it's more portable than `flock`.
+
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::os::unix::prelude::*;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock {
+ _file: File,
+}
+
+impl Lock {
+ pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+ let file = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(create)
+ .mode(libc::S_IRWXU as u32)
+ .open(p)?;
+
+ let mut operation = if exclusive { libc::LOCK_EX } else { libc::LOCK_SH };
+ if !wait {
+ operation |= libc::LOCK_NB
+ }
+
+ let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
+ if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { _file: file }) }
+ }
+
+ pub fn error_unsupported(err: &io::Error) -> bool {
+ matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
+ }
+}
+
+// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. A lock acquired by
+// `flock` is associated with the file descriptor and closing the file releases it
+// automatically.
--- /dev/null
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::mem;
+use std::os::unix::prelude::*;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock {
+ file: File,
+}
+
+impl Lock {
+ pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+ let file = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(create)
+ .mode(libc::S_IRWXU as u32)
+ .open(p)?;
+
+ let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK };
+
+ let mut flock: libc::flock = unsafe { mem::zeroed() };
+ flock.l_type = lock_type as libc::c_short;
+ flock.l_whence = libc::SEEK_SET as libc::c_short;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
+ let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) };
+ if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) }
+ }
+
+ pub fn error_unsupported(err: &io::Error) -> bool {
+ matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
+ }
+}
+
+impl Drop for Lock {
+ fn drop(&mut self) {
+ let mut flock: libc::flock = unsafe { mem::zeroed() };
+ flock.l_type = libc::F_UNLCK as libc::c_short;
+ flock.l_whence = libc::SEEK_SET as libc::c_short;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ unsafe {
+ libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
+ }
+ }
+}
--- /dev/null
+use std::io;
+use std::path::Path;
+
+#[derive(Debug)]
+pub struct Lock(());
+
+impl Lock {
+ pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) -> io::Result<Lock> {
+ let msg = "file locks not supported on this platform";
+ Err(io::Error::new(io::ErrorKind::Other, msg))
+ }
+
+ pub fn error_unsupported(_err: &io::Error) -> bool {
+ true
+ }
+}
--- /dev/null
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::mem;
+use std::os::windows::prelude::*;
+use std::path::Path;
+
+use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
+use winapi::um::fileapi::LockFileEx;
+use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, OVERLAPPED};
+use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
+
+#[derive(Debug)]
+pub struct Lock {
+ _file: File,
+}
+
+impl Lock {
+ pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
+ assert!(
+ p.parent().unwrap().exists(),
+ "Parent directory of lock-file must exist: {}",
+ p.display()
+ );
+
+ let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ let mut open_options = OpenOptions::new();
+ open_options.read(true).share_mode(share_mode);
+
+ if create {
+ open_options.create(true).write(true);
+ }
+
+ debug!("attempting to open lock file `{}`", p.display());
+ let file = match open_options.open(p) {
+ Ok(file) => {
+ debug!("lock file opened successfully");
+ file
+ }
+ Err(err) => {
+ debug!("error opening lock file: {}", err);
+ return Err(err);
+ }
+ };
+
+ let ret = unsafe {
+ let mut overlapped: OVERLAPPED = mem::zeroed();
+
+ let mut dwFlags = 0;
+ if !wait {
+ dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
+ }
+
+ if exclusive {
+ dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+
+ debug!("attempting to acquire lock on lock file `{}`", p.display());
+ LockFileEx(file.as_raw_handle(), dwFlags, 0, 0xFFFF_FFFF, 0xFFFF_FFFF, &mut overlapped)
+ };
+ if ret == 0 {
+ let err = io::Error::last_os_error();
+ debug!("failed acquiring file lock: {}", err);
+ Err(err)
+ } else {
+ debug!("successfully acquired lock");
+ Ok(Lock { _file: file })
+ }
+ }
+
+ pub fn error_unsupported(err: &io::Error) -> bool {
+ err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
+ }
+}
+
+// Note that we don't need a Drop impl on Windows: The file is unlocked
+// automatically when it's closed.
#![feature(control_flow_enum)]
#![feature(core_intrinsics)]
#![feature(extend_one)]
+#![feature(generator_trait)]
+#![feature(generators)]
#![feature(let_else)]
#![feature(hash_raw_entry)]
#![feature(maybe_uninit_uninit_array)]
#![feature(thread_id_value)]
#![feature(vec_into_raw_parts)]
#![allow(rustc::default_hash_types)]
-#![deny(unaligned_references)]
#![allow(rustc::potential_query_instability)]
#[macro_use]
pub use ena::undo_log;
pub use ena::unify;
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
pub struct OnDrop<F: Fn()>(pub F);
impl<F: Fn()> OnDrop<F> {
}
}
+struct IterFromGenerator<G>(G);
+
+impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
+ type Item = G::Yield;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match Pin::new(&mut self.0).resume(()) {
+ GeneratorState::Yielded(n) => Some(n),
+ GeneratorState::Complete(_) => None,
+ }
+ }
+}
+
+/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`.
+pub fn iter_from_generator<G: Generator<Return = ()> + Unpin>(
+ generator: G,
+) -> impl Iterator<Item = G::Yield> {
+ IterFromGenerator(generator)
+}
+
// See comments in src/librustc_middle/lib.rs
#[doc(hidden)]
pub fn __noop_fix_for_27438() {}
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
use parking_lot::RwLock;
+use smallvec::SmallVec;
bitflags::bitflags! {
struct EventFilter: u32 {
}
}
- // This shim makes sure that calls only get executed if the filter mask
- // lets them pass. It also contains some trickery to make sure that
- // code is optimized for non-profiling compilation sessions, i.e. anything
- // past the filter check is never inlined so it doesn't clutter the fast
- // path.
+ /// This shim makes sure that calls only get executed if the filter mask
+ /// lets them pass. It also contains some trickery to make sure that
+ /// code is optimized for non-profiling compilation sessions, i.e. anything
+ /// past the filter check is never inlined so it doesn't clutter the fast
+ /// path.
#[inline(always)]
fn exec<F>(&self, event_filter: EventFilter, f: F) -> TimingGuard<'_>
where
})
}
+ /// Start profiling a generic activity, allowing costly arguments to be recorded. Profiling
+ /// continues until the `TimingGuard` returned from this call is dropped.
+ ///
+ /// If the arguments to a generic activity are cheap to create, use `generic_activity_with_arg`
+ /// or `generic_activity_with_args` for their simpler API. However, if they are costly or
+ /// require allocation in sufficiently hot contexts, then this allows for a closure to be called
+ /// only when arguments were asked to be recorded via `-Z self-profile-events=args`.
+ ///
+ /// In this case, the closure will be passed a `&mut EventArgRecorder`, to help with recording
+ /// one or many arguments within the generic activity being profiled, by calling its
+ /// `record_arg` method for example.
+ ///
+ /// This `EventArgRecorder` may implement more specific traits from other rustc crates, e.g. for
+ /// richer handling of rustc-specific argument types, while keeping this single entry-point API
+ /// for recording arguments.
+ ///
+ /// Note: recording at least one argument is *required* for the self-profiler to create the
+ /// `TimingGuard`. A panic will be triggered if that doesn't happen. This function exists
+ /// explicitly to record arguments, so it fails loudly when there are none to record.
+ ///
+ #[inline(always)]
+ pub fn generic_activity_with_arg_recorder<F>(
+ &self,
+ event_label: &'static str,
+ mut f: F,
+ ) -> TimingGuard<'_>
+ where
+ F: FnMut(&mut EventArgRecorder<'_>),
+ {
+ // Ensure this event will only be recorded when self-profiling is turned on.
+ self.exec(EventFilter::GENERIC_ACTIVITIES, |profiler| {
+ let builder = EventIdBuilder::new(&profiler.profiler);
+ let event_label = profiler.get_or_alloc_cached_string(event_label);
+
+ // Ensure the closure to create event arguments will only be called when argument
+ // recording is turned on.
+ let event_id = if profiler.event_filter_mask.contains(EventFilter::FUNCTION_ARGS) {
+ // Set up the builder and call the user-provided closure to record potentially
+ // costly event arguments.
+ let mut recorder = EventArgRecorder { profiler, args: SmallVec::new() };
+ f(&mut recorder);
+
+ // It is expected that the closure will record at least one argument. If that
+ // doesn't happen, it's a bug: we've been explicitly called in order to record
+ // arguments, so we fail loudly when there are none to record.
+ if recorder.args.is_empty() {
+ panic!(
+ "The closure passed to `generic_activity_with_arg_recorder` needs to \
+ record at least one argument"
+ );
+ }
+
+ builder.from_label_and_args(event_label, &recorder.args)
+ } else {
+ builder.from_label(event_label)
+ };
+ TimingGuard::start(profiler, profiler.generic_activity_event_kind, event_id)
+ })
+ }
+
/// Record the size of an artifact that the compiler produces
///
/// `artifact_kind` is the class of artifact (e.g., query_cache, object_file, etc.)
}
}
+/// A helper for recording costly arguments to self-profiling events. Used with
+/// `SelfProfilerRef::generic_activity_with_arg_recorder`.
+pub struct EventArgRecorder<'p> {
+ /// The `SelfProfiler` used to intern the event arguments that users will ask to record.
+ profiler: &'p SelfProfiler,
+
+ /// The interned event arguments to be recorded in the generic activity event.
+ ///
+ /// The most common case, when actually recording event arguments, is to have one argument. Then
+ /// followed by recording two, in a couple places.
+ args: SmallVec<[StringId; 2]>,
+}
+
+impl EventArgRecorder<'_> {
+ /// Records a single argument within the current generic activity being profiled.
+ ///
+ /// Note: when self-profiling with costly event arguments, at least one argument
+ /// needs to be recorded. A panic will be triggered if that doesn't happen.
+ pub fn record_arg<A>(&mut self, event_arg: A)
+ where
+ A: Borrow<str> + Into<String>,
+ {
+ let event_arg = self.profiler.get_or_alloc_cached_string(event_arg);
+ self.args.push(event_arg);
+ }
+}
+
pub struct SelfProfiler {
profiler: Profiler,
event_filter_mask: EventFilter,
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
}
-// Implement HashStable by just calling `Hash::hash()`. This works fine for
-// self-contained values that don't depend on the hashing context `CTX`.
-#[macro_export]
+/// Implement HashStable by just calling `Hash::hash()`.
+///
+/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
+/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
+/// for examples). Therefore this macro is not exported and should only be used in the limited cases
+/// here in this module.
+///
+/// Use `#[derive(HashStable_Generic)]` instead.
macro_rules! impl_stable_hash_via_hash {
($t:ty) => {
impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
}
impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
+ #[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.get().hash_stable(ctx, hasher)
}
}
impl<CTX> HashStable<CTX> for ::std::num::NonZeroUsize {
+ #[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
self.get().hash_stable(ctx, hasher)
}
}
impl<CTX> HashStable<CTX> for ::std::cmp::Ordering {
+ #[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
(*self as i8).hash_stable(ctx, hasher);
}
}
impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
+ #[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
let (ref _0,) = *self;
_0.hash_stable(ctx, hasher);
/// Returns `true` if any of the primary spans are displayable.
pub fn has_primary_spans(&self) -> bool {
- self.primary_spans.iter().any(|sp| !sp.is_dummy())
+ !self.is_dummy()
}
/// Returns `true` if this contains only a dummy primary span with any hygienic context.
pub fn is_dummy(&self) -> bool {
- let mut is_dummy = true;
- for span in &self.primary_spans {
- if !span.is_dummy() {
- is_dummy = false;
- }
- }
- is_dummy
+ self.primary_spans.iter().all(|sp| sp.is_dummy())
}
/// Replaces all occurrences of one Span with another. Used to move `Span`s in areas that don't
use crate::snippet::Style;
use crate::{
CodeSuggestion, DiagnosticMessage, Level, MultiSpan, Substitution, SubstitutionPart,
- SuggestionStyle, ToolMetadata,
+ SuggestionStyle,
};
use rustc_data_structures::stable_map::FxHashMap;
use rustc_error_messages::FluentValue;
use rustc_lint_defs::{Applicability, LintExpectationId};
-use rustc_serialize::json::Json;
use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
msg: msg.into(),
style,
applicability,
- tool_metadata: Default::default(),
});
self
}
msg: msg.into(),
style: SuggestionStyle::CompletelyHidden,
applicability,
- tool_metadata: Default::default(),
});
self
}
msg: msg.into(),
style,
applicability,
- tool_metadata: Default::default(),
});
self
}
msg: msg.into(),
style: SuggestionStyle::ShowCode,
applicability,
- tool_metadata: Default::default(),
});
self
}
msg: msg.into(),
style: SuggestionStyle::ShowCode,
applicability,
- tool_metadata: Default::default(),
});
self
}
self
}
- /// Adds a suggestion intended only for a tool. The intent is that the metadata encodes
- /// the suggestion in a tool-specific way, as it may not even directly involve Rust code.
- pub fn tool_only_suggestion_with_metadata(
- &mut self,
- msg: impl Into<DiagnosticMessage>,
- applicability: Applicability,
- tool_metadata: Json,
- ) {
- self.push_suggestion(CodeSuggestion {
- substitutions: vec![],
- msg: msg.into(),
- style: SuggestionStyle::CompletelyHidden,
- applicability,
- tool_metadata: ToolMetadata::new(tool_metadata),
- })
- }
-
pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
self.span = sp.into();
if let Some(span) = self.span.primary_span() {
use crate::emitter::{Emitter, HumanReadableErrorType};
use crate::registry::Registry;
use crate::DiagnosticId;
-use crate::ToolMetadata;
use crate::{
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
};
use std::vec;
use rustc_serialize::json::{as_json, as_pretty_json};
-use rustc_serialize::{Encodable, Encoder};
#[cfg(test)]
mod tests;
// The following data types are provided just for serialisation.
-// NOTE: this has a manual implementation of Encodable which needs to be updated in
-// parallel.
+#[derive(Encodable)]
struct Diagnostic {
/// The primary error message.
message: String,
children: Vec<Diagnostic>,
/// The message as rustc would render it.
rendered: Option<String>,
- /// Extra tool metadata
- tool_metadata: ToolMetadata,
-}
-
-macro_rules! encode_fields {
- (
- $enc:expr, // encoder
- $idx:expr, // starting field index
- $struct:expr, // struct we're serializing
- $struct_name:ident, // struct name
- [ $($name:ident),+$(,)? ], // fields to encode
- [ $($ignore:ident),+$(,)? ] // fields we're skipping
- ) => {
- {
- // Pattern match to make sure all fields are accounted for
- let $struct_name { $($name,)+ $($ignore: _,)+ } = $struct;
- let mut idx = $idx;
- $(
- $enc.emit_struct_field(
- stringify!($name),
- idx == 0,
- |enc| $name.encode(enc),
- )?;
- idx += 1;
- )+
- idx
- }
- };
-}
-
-// Special-case encoder to skip tool_metadata if not set
-impl<E: Encoder> Encodable<E> for Diagnostic {
- fn encode(&self, s: &mut E) -> Result<(), E::Error> {
- s.emit_struct(false, |s| {
- let mut idx = 0;
-
- idx = encode_fields!(
- s,
- idx,
- self,
- Self,
- [message, code, level, spans, children, rendered],
- [tool_metadata]
- );
- if self.tool_metadata.is_set() {
- idx = encode_fields!(
- s,
- idx,
- self,
- Self,
- [tool_metadata],
- [message, code, level, spans, children, rendered]
- );
- }
-
- let _ = idx;
- Ok(())
- })
- }
}
#[derive(Encodable)]
spans: DiagnosticSpan::from_suggestion(sugg, &args, je),
children: vec![],
rendered: None,
- tool_metadata: sugg.tool_metadata.clone(),
}
});
.chain(sugg)
.collect(),
rendered: Some(output),
- tool_metadata: ToolMetadata::default(),
}
}
.unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, args, je)),
children: vec![],
rendered: None,
- tool_metadata: ToolMetadata::default(),
}
}
}
LazyFallbackBundle, MultiSpan, SpanLabel, DEFAULT_LOCALE_RESOURCES,
};
pub use rustc_lint_defs::{pluralize, Applicability};
-use rustc_serialize::json::Json;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::source_map::SourceMap;
+use rustc_span::HashStableContext;
use rustc_span::{Loc, Span};
use std::borrow::Cow;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
use std::num::NonZeroUsize;
use std::panic;
use std::path::Path;
}
}
-#[derive(Clone, Debug, PartialEq, Default)]
-pub struct ToolMetadata(pub Option<Json>);
-
-impl ToolMetadata {
- fn new(json: Json) -> Self {
- ToolMetadata(Some(json))
- }
-
- fn is_set(&self) -> bool {
- self.0.is_some()
- }
-}
-
-impl Hash for ToolMetadata {
- fn hash<H: Hasher>(&self, _state: &mut H) {}
-}
-
-// Doesn't really need to round-trip
-impl<D: Decoder> Decodable<D> for ToolMetadata {
- fn decode(_d: &mut D) -> Self {
- ToolMetadata(None)
- }
-}
-
-impl<S: Encoder> Encodable<S> for ToolMetadata {
- fn encode(&self, e: &mut S) -> Result<(), S::Error> {
- match &self.0 {
- None => e.emit_unit(),
- Some(json) => json.encode(e),
- }
- }
-}
-
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub struct CodeSuggestion {
/// Each substitute can have multiple variants due to multiple
/// which are useful for users but not useful for
/// tools like rustfix
pub applicability: Applicability,
- /// Tool-specific metadata
- pub tool_metadata: ToolMetadata,
}
#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
(0, 0) => return,
(0, _) => self.emitter.emit_diagnostic(&Diagnostic::new(
Level::Warning,
- DiagnosticMessage::Str(warnings.to_owned()),
+ DiagnosticMessage::Str(warnings),
)),
(_, 0) => {
let _ = self.fatal(&errors);
path_span: Span,
incl_angl_brckt: bool,
insertion_span: Span,
- anon_lts: String,
) {
- let (replace_span, suggestion) = if incl_angl_brckt {
- (insertion_span, anon_lts)
- } else {
- // When possible, prefer a suggestion that replaces the whole
- // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
- // at a point (which makes for an ugly/confusing label)
- if let Ok(snippet) = source_map.span_to_snippet(path_span) {
- // But our spans can get out of whack due to macros; if the place we think
- // we want to insert `'_` isn't even within the path expression's span, we
- // should bail out of making any suggestion rather than panicking on a
- // subtract-with-overflow or string-slice-out-out-bounds (!)
- // FIXME: can we do better?
- if insertion_span.lo().0 < path_span.lo().0 {
- return;
- }
- let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
- if insertion_index > snippet.len() {
- return;
- }
- let (before, after) = snippet.split_at(insertion_index);
- (path_span, format!("{}{}{}", before, anon_lts, after))
- } else {
- (insertion_span, anon_lts)
- }
- };
- diag.span_suggestion(
- replace_span,
+ diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
+ if source_map.span_to_snippet(insertion_span).is_err() {
+ // Do not try to suggest anything if generated by a proc-macro.
+ return;
+ }
+ let anon_lts = vec!["'_"; n].join(", ");
+ let suggestion =
+ if incl_angl_brckt { format!("<{}>", anon_lts) } else { format!("{}, ", anon_lts) };
+ diag.span_suggestion_verbose(
+ insertion_span.shrink_to_hi(),
&format!("indicate the anonymous lifetime{}", pluralize!(n)),
suggestion,
Applicability::MachineApplicable,
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(HashStable_Generic)]
pub struct ErrorGuaranteed(());
impl ErrorGuaranteed {
ErrorGuaranteed(())
}
}
-
-rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);
(_, 0) => {
// Dump all possible `next_mps` into `cur_mps` for the next iteration. Then
// process the next token.
- self.cur_mps.extend(self.next_mps.drain(..));
+ self.cur_mps.append(&mut self.next_mps);
parser.to_mut().bump();
}
use rustc_errors::ErrorGuaranteed;
use rustc_parse::nt_to_tokenstream;
use rustc_parse::parser::ForceCollect;
+use rustc_span::profiling::SpannedEventArgRecorder;
use rustc_span::{Span, DUMMY_SP};
const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
input: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
let _timer =
- ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+ ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+ recorder.record_arg_with_span(ecx.expansion_descr(), span);
+ });
+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
let server = proc_macro_server::Rustc::new(ecx);
self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| {
annotated: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
let _timer =
- ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+ ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+ recorder.record_arg_with_span(ecx.expansion_descr(), span);
+ });
+
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
let server = proc_macro_server::Rustc::new(ecx);
self.client
let stream = {
let _timer =
- ecx.sess.prof.generic_activity_with_arg("expand_proc_macro", ecx.expansion_descr());
+ ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
+ recorder.record_arg_with_span(ecx.expansion_descr(), span);
+ });
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
let server = proc_macro_server::Rustc::new(ecx);
match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) {
-use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_id::DefId;
use crate::hir;
use rustc_ast as ast;
pub fn descr(self, def_id: DefId) -> &'static str {
match self {
DefKind::Fn => "function",
- DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
- "crate"
- }
+ DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",
DefKind::Mod => "module",
DefKind::Static(..) => "static",
DefKind::Enum => "enum",
}
}
- /// Retrieves the root definition.
- pub fn get_root_def(&self) -> LocalDefId {
- LocalDefId { local_def_index: CRATE_DEF_INDEX }
- }
-
/// Adds a definition with a parent definition.
pub fn create_def(
&mut self,
use crate::intravisit::FnKind;
use crate::LangItem;
+use rustc_ast as ast;
use rustc_ast::util::parser::ExprPrecedence;
-use rustc_ast::{self as ast, CrateSugar};
use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability};
/// User wrote nothing (e.g., the lifetime in `&u32`).
///
/// The bool indicates whether the user should have written something.
- Implicit(bool),
+ Implicit,
/// Implicit lifetime in a context like `dyn Foo`. This is
/// distinguished from implicit lifetimes elsewhere because the
pub fn ident(&self) -> Ident {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault
- | LifetimeName::Implicit(_)
+ | LifetimeName::Implicit
| LifetimeName::Error => Ident::empty(),
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
pub fn is_elided(&self) -> bool {
match self {
LifetimeName::ImplicitObjectLifetimeDefault
- | LifetimeName::Implicit(_)
+ | LifetimeName::Implicit
| LifetimeName::Underscore => true,
// It might seem surprising that `Fresh(_)` counts as
pub struct ImplItem<'hir> {
pub ident: Ident,
pub def_id: LocalDefId,
- pub vis: Visibility<'hir>,
pub generics: Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub span: Span,
+ pub vis_span: Span,
}
impl ImplItem<'_> {
Const {
anon_const: AnonConst,
},
- Sym {
- expr: Expr<'hir>,
+ SymFn {
+ anon_const: AnonConst,
+ },
+ SymStatic {
+ path: QPath<'hir>,
+ def_id: DefId,
},
}
| Self::Out { reg, .. }
| Self::InOut { reg, .. }
| Self::SplitInOut { reg, .. } => Some(reg),
- Self::Const { .. } | Self::Sym { .. } => None,
+ Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
}
}
pub span: Span,
}
-pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
-
-#[derive(Copy, Clone, Debug, HashStable_Generic)]
-pub enum VisibilityKind<'hir> {
- Public,
- Crate(CrateSugar),
- Restricted { path: &'hir Path<'hir>, hir_id: HirId },
- Inherited,
-}
-
-impl VisibilityKind<'_> {
- pub fn is_pub(&self) -> bool {
- matches!(*self, VisibilityKind::Public)
- }
-
- pub fn is_pub_restricted(&self) -> bool {
- match *self {
- VisibilityKind::Public | VisibilityKind::Inherited => false,
- VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true,
- }
- }
-}
-
#[derive(Debug, HashStable_Generic)]
pub struct FieldDef<'hir> {
pub span: Span,
+ pub vis_span: Span,
pub ident: Ident,
- pub vis: Visibility<'hir>,
pub hir_id: HirId,
pub ty: &'hir Ty<'hir>,
}
pub ident: Ident,
pub def_id: LocalDefId,
pub kind: ItemKind<'hir>,
- pub vis: Visibility<'hir>,
pub span: Span,
+ pub vis_span: Span,
}
impl Item<'_> {
pub kind: ForeignItemKind<'hir>,
pub def_id: LocalDefId,
pub span: Span,
- pub vis: Visibility<'hir>,
+ pub vis_span: Span,
}
impl ForeignItem<'_> {
Lifetime(&'hir Lifetime),
GenericParam(&'hir GenericParam<'hir>),
- Visibility(&'hir Visibility<'hir>),
Crate(&'hir Mod<'hir>),
| Node::Binding(..)
| Node::Arm(..)
| Node::Local(..)
- | Node::Visibility(..)
| Node::Crate(..)
| Node::Ty(..)
| Node::TraitRef(..)
match self {
Node::Item(i) => match i.kind {
ItemKind::Fn(ref sig, ref generics, _) => {
- Some(FnKind::ItemFn(i.ident, generics, sig.header, &i.vis))
+ Some(FnKind::ItemFn(i.ident, generics, sig.header))
}
_ => None,
},
Node::TraitItem(ti) => match ti.kind {
TraitItemKind::Fn(ref sig, TraitFn::Provided(_)) => {
- Some(FnKind::Method(ti.ident, sig, None))
+ Some(FnKind::Method(ti.ident, sig))
}
_ => None,
},
Node::ImplItem(ii) => match ii.kind {
- ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig, Some(&ii.vis))),
+ ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)),
_ => None,
},
Node::Expr(e) => match e.kind {
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
- rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
+ rustc_data_structures::static_assert_size!(super::Item<'static>, 160);
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
- rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 144);
- rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 136);
+ rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 120);
+ rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 112);
}
-use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
+use crate::def_id::{LocalDefId, CRATE_DEF_ID};
use std::fmt;
/// Uniquely identifies a node in the HIR of the current crate. It is
/// integers starting at zero, so a mapping that maps all or most nodes within
/// an "item-like" to something else can be implemented by a `Vec` instead of a
/// tree or hash map.
+ #[derive(HashStable_Generic)]
pub struct ItemLocalId { .. }
}
-rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
+
impl ItemLocalId {
/// Signal local id which should never be used.
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
}
-/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
-pub const CRATE_HIR_ID: HirId = HirId {
- owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
- local_id: ItemLocalId::from_u32(0),
-};
+/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
+pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) };
#[derive(Copy, Clone, Debug)]
pub enum FnKind<'a> {
/// `#[xxx] pub async/const/extern "Abi" fn foo()`
- ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>),
+ ItemFn(Ident, &'a Generics<'a>, FnHeader),
/// `fn foo(&self)`
- Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>),
+ Method(Ident, &'a FnSig<'a>),
/// `|x, y| {}`
Closure,
impl<'a> FnKind<'a> {
pub fn header(&self) -> Option<&FnHeader> {
match *self {
- FnKind::ItemFn(_, _, ref header, _) => Some(header),
- FnKind::Method(_, ref sig, _) => Some(&sig.header),
+ FnKind::ItemFn(_, _, ref header) => Some(header),
+ FnKind::Method(_, ref sig) => Some(&sig.header),
FnKind::Closure => None,
}
}
walk_assoc_type_binding(self, type_binding)
}
fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
- fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
- walk_vis(self, vis)
- }
fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) {
walk_associated_item_kind(self, kind);
}
fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
walk_defaultness(self, defaultness);
}
+ fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) {
+ walk_inline_asm(self, asm, id);
+ }
}
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
| LifetimeName::Param(ParamName::Error)
| LifetimeName::Static
| LifetimeName::Error
- | LifetimeName::Implicit(_)
+ | LifetimeName::Implicit
| LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Underscore => {}
}
}
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
- visitor.visit_vis(&item.vis);
visitor.visit_ident(item.ident);
match item.kind {
ItemKind::ExternCrate(orig_name) => {
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
- FnKind::ItemFn(item.ident, generics, sig.header, &item.vis),
+ FnKind::ItemFn(item.ident, generics, sig.header),
&sig.decl,
body_id,
item.span,
}
ItemKind::GlobalAsm(asm) => {
visitor.visit_id(item.hir_id());
- walk_inline_asm(visitor, asm);
+ visitor.visit_inline_asm(asm, item.hir_id());
}
ItemKind::TyAlias(ref ty, ref generics) => {
visitor.visit_id(item.hir_id());
}
}
-fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>) {
- for (op, _op_sp) in asm.operands {
+pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
+ for (op, op_sp) in asm.operands {
match op {
- InlineAsmOperand::In { expr, .. }
- | InlineAsmOperand::InOut { expr, .. }
- | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+ InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
+ visitor.visit_expr(expr)
+ }
InlineAsmOperand::Out { expr, .. } => {
if let Some(expr) = expr {
visitor.visit_expr(expr);
visitor.visit_expr(out_expr);
}
}
- InlineAsmOperand::Const { anon_const } => visitor.visit_anon_const(anon_const),
+ InlineAsmOperand::Const { anon_const, .. }
+ | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
+ InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
}
}
}
pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
visitor.visit_id(foreign_item.hir_id());
- visitor.visit_vis(&foreign_item.vis);
visitor.visit_ident(foreign_item.ident);
match foreign_item.kind {
}
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
visitor.visit_fn(
- FnKind::Method(trait_item.ident, sig, None),
+ FnKind::Method(trait_item.ident, sig),
&sig.decl,
body_id,
trait_item.span,
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let ImplItem { def_id: _, ident, ref vis, ref generics, ref kind, span: _ } = *impl_item;
+ let ImplItem { def_id: _, ident, ref generics, ref kind, span: _, vis_span: _ } = *impl_item;
visitor.visit_ident(ident);
- visitor.visit_vis(vis);
visitor.visit_generics(generics);
match *kind {
ImplItemKind::Const(ref ty, body) => {
}
ImplItemKind::Fn(ref sig, body_id) => {
visitor.visit_fn(
- FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)),
+ FnKind::Method(impl_item.ident, sig),
&sig.decl,
body_id,
impl_item.span,
pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) {
visitor.visit_id(field.hir_id);
- visitor.visit_vis(&field.vis);
visitor.visit_ident(field.ident);
visitor.visit_ty(&field.ty);
}
walk_list!(visitor, visit_expr, optional_expression);
}
ExprKind::InlineAsm(ref asm) => {
- walk_inline_asm(visitor, asm);
+ visitor.visit_inline_asm(asm, expression.hir_id);
}
ExprKind::Yield(ref subexpression, _) => {
visitor.visit_expr(subexpression);
visitor.visit_expr(&arm.body);
}
-pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) {
- if let VisibilityKind::Restricted { ref path, hir_id } = vis.node {
- visitor.visit_id(hir_id);
- visitor.visit_path(path, hir_id)
- }
-}
-
pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) {
// No visitable content here: this fn exists so you can call it if
// the right thing to do, should content be added in the future,
use crate::hir;
use crate::{Item, ItemKind, TraitItem, TraitItemKind};
+use crate::def::DefKind;
use std::fmt::{self, Display};
#[derive(Copy, Clone, PartialEq, Debug)]
}
}
+ // FIXME: For now, should only be used with def_kinds from ItemIds
+ pub fn from_def_kind(def_kind: DefKind) -> Target {
+ match def_kind {
+ DefKind::ExternCrate => Target::ExternCrate,
+ DefKind::Use => Target::Use,
+ DefKind::Static(..) => Target::Static,
+ DefKind::Const => Target::Const,
+ DefKind::Fn => Target::Fn,
+ DefKind::Macro(..) => Target::MacroDef,
+ DefKind::Mod => Target::Mod,
+ DefKind::ForeignMod => Target::ForeignMod,
+ DefKind::GlobalAsm => Target::GlobalAsm,
+ DefKind::TyAlias => Target::TyAlias,
+ DefKind::OpaqueTy => Target::OpaqueTy,
+ DefKind::Enum => Target::Enum,
+ DefKind::Struct => Target::Struct,
+ DefKind::Union => Target::Union,
+ DefKind::Trait => Target::Trait,
+ DefKind::TraitAlias => Target::TraitAlias,
+ DefKind::Impl => Target::Impl,
+ _ => panic!("impossible case reached"),
+ }
+ }
+
pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
match trait_item.kind {
TraitItemKind::Const(..) => Target::AssocConst,
use rustc_hir as hir;
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
-use rustc_span::source_map::{SourceMap, Spanned};
+use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
use rustc_span::{self, FileName};
use rustc_target::spec::abi::Abi;
-use std::borrow::Cow;
use std::cell::Cell;
use std::vec;
self.print_block(&a)
}
Node::Lifetime(a) => self.print_lifetime(&a),
- Node::Visibility(a) => self.print_visibility(&a),
Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
Node::Field(_) => panic!("cannot print Node::Field"),
// These cases do not carry enough information in the
printer.s.eof()
}
-pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_>, w: S) -> String {
- to_string(NO_ANN, |s| {
- s.print_visibility(vis);
- s.word(w)
- })
-}
-
pub fn generic_params_to_string(generic_params: &[GenericParam<'_>]) -> String {
to_string(NO_ANN, |s| s.print_generic_params(generic_params))
}
header: hir::FnHeader,
name: Option<Symbol>,
generics: &hir::Generics<'_>,
- vis: &hir::Visibility<'_>,
arg_names: &[Ident],
body_id: Option<hir::BodyId>,
) -> String {
- to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, vis, arg_names, body_id))
+ to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, arg_names, body_id))
}
pub fn enum_def_to_string(
generics: &hir::Generics<'_>,
name: Symbol,
span: rustc_span::Span,
- visibility: &hir::Visibility<'_>,
) -> String {
- to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span, visibility))
+ to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span))
}
impl<'a> State<'a> {
},
Some(item.ident.name),
generics,
- &item.vis,
arg_names,
None,
);
self.end() // end the outer fn box
}
hir::ForeignItemKind::Static(ref t, m) => {
- self.head(visibility_qualified(&item.vis, "static"));
+ self.head("static");
if m == hir::Mutability::Mut {
self.word_space("mut");
}
self.end() // end the outer cbox
}
hir::ForeignItemKind::Type => {
- self.head(visibility_qualified(&item.vis, "type"));
+ self.head("type");
self.print_ident(item.ident);
self.word(";");
self.end(); // end the head-ibox
ident: Ident,
ty: &hir::Ty<'_>,
default: Option<hir::BodyId>,
- vis: &hir::Visibility<'_>,
) {
- self.word(visibility_qualified(vis, ""));
+ self.head("");
self.word_space("const");
self.print_ident(ident);
self.word_space(":");
generics: &hir::Generics<'_>,
inner: impl Fn(&mut Self),
) {
- self.head(visibility_qualified(&item.vis, "type"));
+ self.head("type");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
self.end(); // end the inner ibox
self.ann.pre(self, AnnNode::Item(item));
match item.kind {
hir::ItemKind::ExternCrate(orig_name) => {
- self.head(visibility_qualified(&item.vis, "extern crate"));
+ self.head("extern crate");
if let Some(orig_name) = orig_name {
self.print_name(orig_name);
self.space();
self.end(); // end outer head-block
}
hir::ItemKind::Use(ref path, kind) => {
- self.head(visibility_qualified(&item.vis, "use"));
+ self.head("use");
self.print_path(path, false);
match kind {
self.end(); // end outer head-block
}
hir::ItemKind::Static(ref ty, m, expr) => {
- self.head(visibility_qualified(&item.vis, "static"));
+ self.head("static");
if m == hir::Mutability::Mut {
self.word_space("mut");
}
self.end(); // end the outer cbox
}
hir::ItemKind::Const(ref ty, expr) => {
- self.head(visibility_qualified(&item.vis, "const"));
+ self.head("const");
self.print_ident(item.ident);
self.word_space(":");
self.print_type(&ty);
sig.header,
Some(item.ident.name),
param_names,
- &item.vis,
&[],
Some(body),
);
self.ann.nested(self, Nested::Body(body));
}
hir::ItemKind::Macro(ref macro_def, _) => {
- self.print_mac_def(macro_def, &item.ident, item.span, |state| {
- state.print_visibility(&item.vis)
- });
+ self.print_mac_def(macro_def, &item.ident, item.span, |_| {});
}
hir::ItemKind::Mod(ref _mod) => {
- self.head(visibility_qualified(&item.vis, "mod"));
+ self.head("mod");
self.print_ident(item.ident);
self.nbsp();
self.bopen();
self.bclose(item.span);
}
hir::ItemKind::GlobalAsm(ref asm) => {
- self.head(visibility_qualified(&item.vis, "global_asm!"));
+ self.head("global_asm!");
self.print_inline_asm(asm);
self.end()
}
});
}
hir::ItemKind::Enum(ref enum_definition, ref params) => {
- self.print_enum_def(enum_definition, params, item.ident.name, item.span, &item.vis);
+ self.print_enum_def(enum_definition, params, item.ident.name, item.span);
}
hir::ItemKind::Struct(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "struct"));
+ self.head("struct");
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Union(ref struct_def, ref generics) => {
- self.head(visibility_qualified(&item.vis, "union"));
+ self.head("union");
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
}
hir::ItemKind::Impl(hir::Impl {
items,
}) => {
self.head("");
- self.print_visibility(&item.vis);
self.print_defaultness(defaultness);
self.print_unsafety(unsafety);
self.word_nbsp("impl");
}
hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, trait_items) => {
self.head("");
- self.print_visibility(&item.vis);
self.print_is_auto(is_auto);
self.print_unsafety(unsafety);
self.word_nbsp("trait");
self.bclose(item.span);
}
hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
- self.head(visibility_qualified(&item.vis, "trait"));
+ self.head("trait");
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
generics: &hir::Generics<'_>,
name: Symbol,
span: rustc_span::Span,
- visibility: &hir::Visibility<'_>,
) {
- self.head(visibility_qualified(visibility, "enum"));
+ self.head("enum");
self.print_name(name);
self.print_generic_params(&generics.params);
self.print_where_clause(&generics.where_clause);
self.bclose(span)
}
- pub fn print_visibility(&mut self, vis: &hir::Visibility<'_>) {
- match vis.node {
- hir::VisibilityKind::Public => self.word_nbsp("pub"),
- hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"),
- hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"),
- hir::VisibilityKind::Restricted { ref path, .. } => {
- self.word("pub(");
- if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super {
- // Special case: `super` can print like `pub(super)`.
- self.word("super");
- } else {
- // Everything else requires `in` at present.
- self.word_nbsp("in");
- self.print_path(path, false);
- }
- self.word_nbsp(")");
- }
- hir::VisibilityKind::Inherited => (),
- }
- }
-
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
match defaultness {
hir::Defaultness::Default { .. } => self.word_nbsp("default"),
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo());
s.print_outer_attributes(s.attrs(field.hir_id));
- s.print_visibility(&field.vis);
s.print_type(&field.ty)
});
self.pclose();
self.hardbreak_if_not_bol();
self.maybe_print_comment(field.span.lo());
self.print_outer_attributes(self.attrs(field.hir_id));
- self.print_visibility(&field.vis);
self.print_ident(field.ident);
self.word_nbsp(":");
self.print_type(&field.ty);
ident: Ident,
m: &hir::FnSig<'_>,
generics: &hir::Generics<'_>,
- vis: &hir::Visibility<'_>,
arg_names: &[Ident],
body_id: Option<hir::BodyId>,
) {
- self.print_fn(&m.decl, m.header, Some(ident.name), generics, vis, arg_names, body_id)
+ self.print_fn(&m.decl, m.header, Some(ident.name), generics, arg_names, body_id)
}
pub fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
self.print_outer_attributes(self.attrs(ti.hir_id()));
match ti.kind {
hir::TraitItemKind::Const(ref ty, default) => {
- let vis =
- Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
- self.print_associated_const(ti.ident, &ty, default, &vis);
+ self.print_associated_const(ti.ident, &ty, default);
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => {
- let vis =
- Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
- self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None);
+ self.print_method_sig(ti.ident, sig, &ti.generics, arg_names, None);
self.word(";");
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
- let vis =
- Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited };
self.head("");
- self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body));
+ self.print_method_sig(ti.ident, sig, &ti.generics, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
match ii.kind {
hir::ImplItemKind::Const(ref ty, expr) => {
- self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis);
+ self.print_associated_const(ii.ident, &ty, Some(expr));
}
hir::ImplItemKind::Fn(ref sig, body) => {
self.head("");
- self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body));
+ self.print_method_sig(ii.ident, sig, &ii.generics, &[], Some(body));
self.nbsp();
self.end(); // need to close a box
self.end(); // need to close a box
s.space();
s.print_anon_const(anon_const);
}
- hir::InlineAsmOperand::Sym { expr } => {
- s.word("sym");
+ hir::InlineAsmOperand::SymFn { anon_const } => {
+ s.word("sym_fn");
s.space();
- s.print_expr(expr);
+ s.print_anon_const(anon_const);
+ }
+ hir::InlineAsmOperand::SymStatic { path, def_id: _ } => {
+ s.word("sym_static");
+ s.space();
+ s.print_qpath(path, true);
}
},
AsmArg::Options(opts) => {
header: hir::FnHeader,
name: Option<Symbol>,
generics: &hir::Generics<'_>,
- vis: &hir::Visibility<'_>,
arg_names: &[Ident],
body_id: Option<hir::BodyId>,
) {
- self.print_fn_header_info(header, vis);
+ self.print_fn_header_info(header);
if let Some(name) = name {
self.nbsp();
},
name,
&generics,
- &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited },
arg_names,
None,
);
self.end();
}
- pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) {
- self.word(visibility_qualified(vis, ""));
-
+ pub fn print_fn_header_info(&mut self, header: hir::FnHeader) {
match header.constness {
hir::Constness::NotConst => {}
hir::Constness::Const => self.word_nbsp("const"),
let targets = node_set(&query, &edge_filter.target);
filter_nodes(&query, &sources, &targets)
}
- Err(_) => query.nodes().into_iter().collect(),
+ Err(_) => query.nodes().into_iter().map(|n| n.kind).collect(),
};
let edges = filter_edges(&query, &nodes);
}
#[allow(missing_docs)]
-pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>);
+pub struct GraphvizDepGraph(FxHashSet<DepKind>, Vec<(DepKind, DepKind)>);
-impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> {
- type Node = &'q DepNode;
- type Edge = (&'q DepNode, &'q DepNode);
- fn nodes(&self) -> dot::Nodes<'_, &'q DepNode> {
+impl<'a> dot::GraphWalk<'a> for GraphvizDepGraph {
+ type Node = DepKind;
+ type Edge = (DepKind, DepKind);
+ fn nodes(&self) -> dot::Nodes<'_, DepKind> {
let nodes: Vec<_> = self.0.iter().cloned().collect();
nodes.into()
}
- fn edges(&self) -> dot::Edges<'_, (&'q DepNode, &'q DepNode)> {
+ fn edges(&self) -> dot::Edges<'_, (DepKind, DepKind)> {
self.1[..].into()
}
- fn source(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode {
+ fn source(&self, edge: &(DepKind, DepKind)) -> DepKind {
edge.0
}
- fn target(&self, edge: &(&'q DepNode, &'q DepNode)) -> &'q DepNode {
+ fn target(&self, edge: &(DepKind, DepKind)) -> DepKind {
edge.1
}
}
-impl<'a, 'q> dot::Labeller<'a> for GraphvizDepGraph<'q> {
- type Node = &'q DepNode;
- type Edge = (&'q DepNode, &'q DepNode);
+impl<'a> dot::Labeller<'a> for GraphvizDepGraph {
+ type Node = DepKind;
+ type Edge = (DepKind, DepKind);
fn graph_id(&self) -> dot::Id<'_> {
dot::Id::new("DependencyGraph").unwrap()
}
- fn node_id(&self, n: &&'q DepNode) -> dot::Id<'_> {
+ fn node_id(&self, n: &DepKind) -> dot::Id<'_> {
let s: String = format!("{:?}", n)
.chars()
.map(|c| if c == '_' || c.is_alphanumeric() { c } else { '_' })
debug!("n={:?} s={:?}", n, s);
dot::Id::new(s).unwrap()
}
- fn node_label(&self, n: &&'q DepNode) -> dot::LabelText<'_> {
+ fn node_label(&self, n: &DepKind) -> dot::LabelText<'_> {
dot::LabelText::label(format!("{:?}", n))
}
}
query: &'q DepGraphQuery,
sources: &Option<FxHashSet<&'q DepNode>>,
targets: &Option<FxHashSet<&'q DepNode>>,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
if let Some(sources) = sources {
if let Some(targets) = targets {
walk_between(query, sources, targets)
} else if let Some(targets) = targets {
walk_nodes(query, targets, INCOMING)
} else {
- query.nodes().into_iter().collect()
+ query.nodes().into_iter().map(|n| n.kind).collect()
}
}
query: &'q DepGraphQuery,
starts: &FxHashSet<&'q DepNode>,
direction: Direction,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
let mut set = FxHashSet::default();
for &start in starts {
debug!("walk_nodes: start={:?} outgoing?={:?}", start, direction == OUTGOING);
- if set.insert(start) {
+ if set.insert(start.kind) {
let mut stack = vec![query.indices[start]];
while let Some(index) = stack.pop() {
for (_, edge) in query.graph.adjacent_edges(index, direction) {
let neighbor_index = edge.source_or_target(direction);
let neighbor = query.graph.node_data(neighbor_index);
- if set.insert(neighbor) {
+ if set.insert(neighbor.kind) {
stack.push(neighbor_index);
}
}
query: &'q DepGraphQuery,
sources: &FxHashSet<&'q DepNode>,
targets: &FxHashSet<&'q DepNode>,
-) -> FxHashSet<&'q DepNode> {
+) -> FxHashSet<DepKind> {
// This is a bit tricky. We want to include a node only if it is:
// (a) reachable from a source and (b) will reach a target. And we
// have to be careful about cycles etc. Luckily efficiency is not
let index = query.indices[n];
node_states[index.0] == State::Included
})
+ .map(|n| n.kind)
.collect();
fn recurse(query: &DepGraphQuery, node_states: &mut [State], node: NodeIndex) -> bool {
fn filter_edges<'q>(
query: &'q DepGraphQuery,
- nodes: &FxHashSet<&'q DepNode>,
-) -> Vec<(&'q DepNode, &'q DepNode)> {
- query
+ nodes: &FxHashSet<DepKind>,
+) -> Vec<(DepKind, DepKind)> {
+ let uniq: FxHashSet<_> = query
.edges()
.into_iter()
- .filter(|&(source, target)| nodes.contains(source) && nodes.contains(target))
- .collect()
+ .map(|(s, t)| (s.kind, t.kind))
+ .filter(|(source, target)| nodes.contains(source) && nodes.contains(target))
+ .collect();
+ uniq.into_iter().collect()
}
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::Node as HirNode;
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
tcx.dep_graph.with_ignore(|| {
let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
- tcx.hir().visit_all_item_likes(&mut dirty_clean_visitor);
+
+ let crate_items = tcx.hir_crate_items(());
+
+ for id in crate_items.items() {
+ dirty_clean_visitor.check_item(id.def_id);
+ }
+
+ for id in crate_items.trait_items() {
+ dirty_clean_visitor.check_item(id.def_id);
+ }
+
+ for id in crate_items.impl_items() {
+ dirty_clean_visitor.check_item(id.def_id);
+ }
+
+ for id in crate_items.foreign_items() {
+ dirty_clean_visitor.check_item(id.def_id);
+ }
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
tcx.hir().walk_attributes(&mut all_attrs);
}
}
- fn check_item(&mut self, item_id: LocalDefId, item_span: Span) {
+ fn check_item(&mut self, item_id: LocalDefId) {
+ let item_span = self.tcx.def_span(item_id.to_def_id());
let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
let Some(assertion) = self.assertion_maybe(item_id, attr) else {
}
}
-impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
- fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.check_item(item.def_id, item.span);
- }
-
- fn visit_trait_item(&mut self, item: &hir::TraitItem<'_>) {
- self.check_item(item.def_id, item.span);
- }
-
- fn visit_impl_item(&mut self, item: &hir::ImplItem<'_>) {
- self.check_item(item.def_id, item.span);
- }
-
- fn visit_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
- self.check_item(item.def_id, item.span);
- }
-}
-
/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have
/// a cfg flag called `foo`.
fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
// Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles
// (e.g., #41849).
- relate::relate_substs(self, None, a_subst, b_subst)
+ relate::relate_substs(self, a_subst, b_subst)
} else {
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
- relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst)
+ relate::relate_substs_with_variances(
+ self,
+ item_def_id,
+ &opt_variances,
+ a_subst,
+ b_subst,
+ )
}
}
// performing trait matching (which then performs equality
// unification).
- relate::relate_substs(self, None, a_subst, b_subst)
+ relate::relate_substs(self, a_subst, b_subst)
}
fn relate_with_variance<T: Relate<'tcx>>(
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Item, ItemKind, Node};
use rustc_middle::dep_graph::DepContext;
mut values: Option<ValuePairs<'tcx>>,
terr: &TypeError<'tcx>,
swap_secondary_and_primary: bool,
+ force_label: bool,
) {
let span = cause.span(self.tcx);
debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
TypeError::ObjectUnsafeCoercion(_) => {}
_ => {
let mut label_or_note = |span: Span, msg: &str| {
- if &[span] == diag.span.primary_spans() {
+ if force_label || &[span] == diag.span.primary_spans() {
diag.span_label(span, msg);
} else {
diag.span_note(span, msg);
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
}
};
- self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false);
+ self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
diag
}
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
) {
- self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
+ let owner =
+ self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
+ self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
}
pub fn construct_generic_bound_failure(
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
+ owner: Option<LocalDefId>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let hir = self.tcx.hir();
// Attempt to obtain the span of the parameter so we can
// suggest adding an explicit lifetime bound to it.
- let generics = self
- .in_progress_typeck_results
- .map(|typeck_results| typeck_results.borrow().hir_owner)
- .map(|owner| {
- let hir_id = hir.local_def_id_to_hir_id(owner);
- let parent_id = hir.get_parent_item(hir_id);
- (
- // Parent item could be a `mod`, so we check the HIR before calling:
- if let Some(Node::Item(Item {
- kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
- ..
- })) = hir.find_by_def_id(parent_id)
- {
- Some(self.tcx.generics_of(parent_id))
- } else {
- None
- },
- self.tcx.generics_of(owner.to_def_id()),
- hir.span(hir_id),
- )
- });
+ let generics = owner.map(|owner| {
+ let hir_id = hir.local_def_id_to_hir_id(owner);
+ let parent_id = hir.get_parent_item(hir_id);
+ (
+ // Parent item could be a `mod`, so we check the HIR before calling:
+ if let Some(Node::Item(Item {
+ kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
+ ..
+ })) = hir.find_by_def_id(parent_id)
+ {
+ Some(self.tcx.generics_of(parent_id))
+ } else {
+ None
+ },
+ self.tcx.generics_of(owner.to_def_id()),
+ hir.span(hir_id),
+ )
+ });
let span = match generics {
// This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
None,
);
if let Some(infer::RelateParamBound(_, t, _)) = origin {
- let return_impl_trait = self
- .in_progress_typeck_results
- .map(|typeck_results| typeck_results.borrow().hir_owner)
- .and_then(|owner| self.tcx.return_type_impl_trait(owner))
- .is_some();
+ let return_impl_trait =
+ owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
let t = self.resolve_vars_if_possible(t);
match t.kind() {
// We've got:
}
}
-enum FailureCode {
+pub enum FailureCode {
Error0038(DefId),
Error0317(&'static str),
Error0580(&'static str),
Error0644(&'static str),
}
-trait ObligationCauseExt<'tcx> {
+pub trait ObligationCauseExt<'tcx> {
fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode;
fn as_requirement_str(&self) -> &'static str;
}
/// See the `error_reporting` module for more details.
#[derive(Clone, Debug)]
pub struct TypeTrace<'tcx> {
- cause: ObligationCause<'tcx>,
- values: ValuePairs<'tcx>,
+ pub cause: ObligationCause<'tcx>,
+ pub values: ValuePairs<'tcx>,
}
/// The origin of a `r1 <= r2` constraint.
self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
}
- /// If `typ` is a type variable of some kind, resolve it one level
- /// (but do not resolve types found in the result). If `typ` is
- /// not a type variable, just return it unmodified.
- // FIXME(eddyb) inline into `ShallowResolver::visit_ty`.
- fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
- match *typ.kind() {
- ty::Infer(ty::TyVar(v)) => {
- // Not entirely obvious: if `typ` is a type variable,
- // it can be resolved to an int/float variable, which
- // can then be recursively resolved, hence the
- // recursion. Note though that we prevent type
- // variables from unifying to other type variables
- // directly (though they may be embedded
- // structurally), and we prevent cycles in any case,
- // so this recursion should always be of very limited
- // depth.
- //
- // Note: if these two lines are combined into one we get
- // dynamic borrow errors on `self.inner`.
- let known = self.inner.borrow_mut().type_variables().probe(v).known();
- known.map_or(typ, |t| self.shallow_resolve_ty(t))
- }
-
- ty::Infer(ty::IntVar(v)) => self
- .inner
- .borrow_mut()
- .int_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(self.tcx))
- .unwrap_or(typ),
-
- ty::Infer(ty::FloatVar(v)) => self
- .inner
- .borrow_mut()
- .float_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(self.tcx))
- .unwrap_or(typ),
-
- _ => typ,
- }
- }
-
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
/// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
/// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)
self.infcx.tcx
}
+ /// If `ty` is a type variable of some kind, resolve it one level
+ /// (but do not resolve types found in the result). If `typ` is
+ /// not a type variable, just return it unmodified.
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.infcx.shallow_resolve_ty(ty)
+ match *ty.kind() {
+ ty::Infer(ty::TyVar(v)) => {
+ // Not entirely obvious: if `typ` is a type variable,
+ // it can be resolved to an int/float variable, which
+ // can then be recursively resolved, hence the
+ // recursion. Note though that we prevent type
+ // variables from unifying to other type variables
+ // directly (though they may be embedded
+ // structurally), and we prevent cycles in any case,
+ // so this recursion should always be of very limited
+ // depth.
+ //
+ // Note: if these two lines are combined into one we get
+ // dynamic borrow errors on `self.inner`.
+ let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
+ known.map_or(ty, |t| self.fold_ty(t))
+ }
+
+ ty::Infer(ty::IntVar(v)) => self
+ .infcx
+ .inner
+ .borrow_mut()
+ .int_unification_table()
+ .probe_value(v)
+ .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+
+ ty::Infer(ty::FloatVar(v)) => self
+ .infcx
+ .inner
+ .borrow_mut()
+ .float_unification_table()
+ .probe_value(v)
+ .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+
+ _ => ty,
+ }
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
});
files.extend(extra_tracked_files);
- if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
- files.push(backend.to_string());
- }
-
if sess.binary_dep_depinfo() {
+ if let Some(ref backend) = sess.opts.debugging_opts.codegen_backend {
+ if backend.contains('.') {
+ // If the backend name contain a `.`, it is the path to an external dynamic
+ // library. If not, it is not a path.
+ files.push(backend.to_string());
+ }
+ }
+
boxed_resolver.borrow_mut().access(|resolver| {
for cnum in resolver.cstore().crates_untracked() {
let source = resolver.cstore().crate_source_untracked(cnum);
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
let mut finder = Finder { tcx, decls: None };
- tcx.hir().visit_all_item_likes(&mut finder);
- finder.decls.map(|id| tcx.hir().local_def_id(id))
-}
-
-struct Finder<'tcx> {
- tcx: TyCtxt<'tcx>,
- decls: Option<hir::HirId>,
-}
-
-impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- let attrs = self.tcx.hir().attrs(item.hir_id());
- if self.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
- self.decls = Some(item.hir_id());
+ for id in tcx.hir().items() {
+ let attrs = finder.tcx.hir().attrs(id.hir_id());
+ if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
+ finder.decls = Some(id.def_id);
}
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
+ finder.decls
+}
- fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+struct Finder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ decls: Option<hir::def_id::LocalDefId>,
}
pub(crate) fn provide(providers: &mut Providers) {
location: ExternLocation::ExactPaths(locations),
is_private_dep: false,
add_prelude: true,
+ nounused_dep: false,
}
}
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true);
+ tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, Some(true));
rustc_feature = { path = "../rustc_feature" }
rustc_index = { path = "../rustc_index" }
rustc_session = { path = "../rustc_session" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_parse_format = { path = "../rustc_parse_format" }
rustc_infer = { path = "../rustc_infer" }
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
-use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind};
-use rustc_hir::{HirId, Node};
+use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind};
use rustc_index::vec::Idx;
use rustc_middle::lint::LintDiagnosticBuilder;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
_,
ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. },
_,
+ _,
body,
) = fk
{
pub struct MissingDoc {
/// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes.
doc_hidden_stack: Vec<bool>,
-
- /// Private traits or trait items that leaked through. Don't check their methods.
- private_traits: FxHashSet<hir::HirId>,
}
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
impl MissingDoc {
pub fn new() -> MissingDoc {
- MissingDoc { doc_hidden_stack: vec![false], private_traits: FxHashSet::default() }
+ MissingDoc { doc_hidden_stack: vec![false] }
}
fn doc_hidden(&self) -> bool {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
match it.kind {
- hir::ItemKind::Trait(.., trait_item_refs) => {
+ hir::ItemKind::Trait(..) => {
// Issue #11592: traits are always considered exported, even when private.
- if let hir::VisibilityKind::Inherited = it.vis.node {
- self.private_traits.insert(it.hir_id());
- for trait_item_ref in trait_item_refs {
- self.private_traits.insert(trait_item_ref.id.hir_id());
- }
+ if cx.tcx.visibility(it.def_id)
+ == ty::Visibility::Restricted(
+ cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(),
+ )
+ {
return;
}
}
- hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), items, .. }) => {
- // If the trait is private, add the impl items to `private_traits` so they don't get
- // reported for missing docs.
- let real_trait = trait_ref.path.res.def_id();
- let Some(def_id) = real_trait.as_local() else { return };
- let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(def_id) else { return };
- if let hir::VisibilityKind::Inherited = item.vis.node {
- for impl_item_ref in items {
- self.private_traits.insert(impl_item_ref.id.hir_id());
- }
- }
- return;
- }
-
hir::ItemKind::TyAlias(..)
| hir::ItemKind::Fn(..)
| hir::ItemKind::Macro(..)
}
fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
- if self.private_traits.contains(&trait_item.hir_id()) {
- return;
- }
-
let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
self.check_missing_docs_attrs(cx, trait_item.def_id, trait_item.span, article, desc);
cx: &LateContext<'_>,
what: &str,
def_id: LocalDefId,
- vis: &hir::Visibility<'_>,
span: Span,
+ vis_span: Span,
exportable: bool,
) {
let mut applicability = Applicability::MachineApplicable;
- match vis.node {
- hir::VisibilityKind::Public if !cx.access_levels.is_reachable(def_id) => {
- if span.from_expansion() {
- applicability = Applicability::MaybeIncorrect;
+ if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) {
+ if vis_span.from_expansion() {
+ applicability = Applicability::MaybeIncorrect;
+ }
+ let def_span = cx.tcx.sess.source_map().guess_head_span(span);
+ cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
+ let mut err = lint.build(&format!("unreachable `pub` {}", what));
+ let replacement = if cx.tcx.features().crate_visibility_modifier {
+ "crate"
+ } else {
+ "pub(crate)"
}
- let def_span = cx.tcx.sess.source_map().guess_head_span(span);
- cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
- let mut err = lint.build(&format!("unreachable `pub` {}", what));
- let replacement = if cx.tcx.features().crate_visibility_modifier {
- "crate"
- } else {
- "pub(crate)"
- }
- .to_owned();
+ .to_owned();
- err.span_suggestion(
- vis.span,
- "consider restricting its visibility",
- replacement,
- applicability,
- );
- if exportable {
- err.help("or consider exporting it for use by other crates");
- }
- err.emit();
- });
- }
- _ => {}
+ err.span_suggestion(
+ vis_span,
+ "consider restricting its visibility",
+ replacement,
+ applicability,
+ );
+ if exportable {
+ err.help("or consider exporting it for use by other crates");
+ }
+ err.emit();
+ });
}
}
}
impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- self.perform_lint(cx, "item", item.def_id, &item.vis, item.span, true);
+ // Do not warn for fake `use` statements.
+ if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
+ return;
+ }
+ self.perform_lint(cx, "item", item.def_id, item.span, item.vis_span, true);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
cx,
"item",
foreign_item.def_id,
- &foreign_item.vis,
foreign_item.span,
+ foreign_item.vis_span,
true,
);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
let def_id = cx.tcx.hir().local_def_id(field.hir_id);
- self.perform_lint(cx, "field", def_id, &field.vis, field.span, false);
+ self.perform_lint(cx, "field", def_id, field.span, field.vis_span, false);
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
- self.perform_lint(cx, "item", impl_item.def_id, &impl_item.vis, impl_item.span, false);
+ // Only lint inherent impl items.
+ if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
+ self.perform_lint(
+ cx,
+ "item",
+ impl_item.def_id,
+ impl_item.span,
+ impl_item.vis_span,
+ false,
+ );
+ }
}
}
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
-use rustc_errors::{struct_span_err, Applicability, MultiSpan, SuggestionStyle};
+use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
+use rustc_errors::{Applicability, MultiSpan, SuggestionStyle};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools, Ty, TyCtxt};
-use rustc_serialize::json::Json;
-use rustc_session::lint::{BuiltinLintDiagnostics, ExternDepSpec};
+use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name;
) => {
db.span_note(span_def, "the macro is defined here");
}
+ BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+ n,
+ path_span,
+ incl_angl_brckt,
+ insertion_span,
+ ) => {
+ add_elided_lifetime_in_path_suggestion(
+ sess.source_map(),
+ &mut db,
+ n,
+ path_span,
+ incl_angl_brckt,
+ insertion_span,
+ );
+ }
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect);
}
BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => {
db.span_label(span, "the attribute is introduced here");
}
- BuiltinLintDiagnostics::ExternDepSpec(krate, loc) => {
- let json = match loc {
- ExternDepSpec::Json(json) => {
- db.help(&format!("remove unnecessary dependency `{}`", krate));
- json
- }
- ExternDepSpec::Raw(raw) => {
- db.help(&format!("remove unnecessary dependency `{}` at `{}`", krate, raw));
- db.span_suggestion_with_style(
- DUMMY_SP,
- "raw extern location",
- raw.clone(),
- Applicability::Unspecified,
- SuggestionStyle::CompletelyHidden,
- );
- Json::String(raw)
- }
- };
- db.tool_only_suggestion_with_metadata(
- "json extern location",
- Applicability::Unspecified,
- json
- );
- }
BuiltinLintDiagnostics::ProcMacroBackCompat(note) => {
db.note(¬e);
}
// Explicitly check for lints associated with 'closure_id', since
// it does not have a corresponding AST node
- if let ast_visit::FnKind::Fn(_, _, sig, _, _) = fk {
+ if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
if let ast::Async::Yes { closure_id, .. } = sig.header.asyncness {
self.check_id(closure_id);
}
ast_visit::walk_path(self, p);
}
+ fn visit_path_segment(&mut self, path_span: Span, s: &'a ast::PathSegment) {
+ self.check_id(s.id);
+ ast_visit::walk_path_segment(self, path_span, s);
+ }
+
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
run_early_pass!(self, check_attribute, attr);
}
}
_ => (),
},
- FnKind::ItemFn(ident, _, header, _) => {
+ FnKind::ItemFn(ident, _, header) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
return;
/// ### Example
///
/// ```rust,compile_fail
- /// #![deny(unaligned_references)]
- ///
/// #[repr(packed)]
/// pub struct Foo {
/// field1: u64,
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
/// [issue #82523]: https://github.com/rust-lang/rust/issues/82523
pub UNALIGNED_REFERENCES,
- Warn,
+ Deny,
"detects unaligned references to fields of packed structs",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
+ reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
};
report_in_external_macro
}
use rustc_ast::{AttrId, Attribute};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
use rustc_error_messages::MultiSpan;
+use rustc_hir::HashStableContext;
use rustc_hir::HirId;
-use rustc_serialize::json::Json;
use rustc_span::edition::Edition;
use rustc_span::{sym, symbol::Ident, Span, Symbol};
use rustc_target::spec::abi::Abi;
/// Setting for how to handle a lint.
///
/// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)]
pub enum Level {
/// The `allow` level will not issue any message.
Allow,
Forbid,
}
-rustc_data_structures::impl_stable_hash_via_hash!(Level);
-
impl Level {
/// Converts a level to a lower-case string.
pub fn as_str(self) -> &'static str {
}
}
-// Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency
-#[derive(PartialEq, Debug)]
-pub enum ExternDepSpec {
- Json(Json),
- Raw(String),
-}
-
// This could be a closure, but then implementing derive trait
// becomes hacky (and it gets allocated).
#[derive(Debug)]
AbsPathWithModule(Span),
ProcMacroDeriveResolutionFallback(Span),
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
+ ElidedLifetimesInPaths(usize, Span, bool, Span),
UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>, Option<Span>),
RedundantImport(Vec<(Span, bool)>, Ident),
UnusedBuiltinAttribute { attr_name: Symbol, macro_name: String, invoc_span: Span },
PatternsInFnsWithoutBody(Span, Ident),
LegacyDeriveHelpers(Span),
- ExternDepSpec(String, ExternDepSpec),
ProcMacroBackCompat(String),
OrPatternsBackCompat(Span, String),
ReservedPrefix(Span),
unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
}
+
+extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
+ RawRustStringOstream OS(Str);
+ GlobalValue *GV = unwrap<GlobalValue>(V);
+ Mangler().getNameWithPrefix(OS, GV, true);
+}
/// # extern crate rust_middle;
/// # use rustc_middle::ty::Ty;
/// #[derive(SessionDiagnostic)]
-/// #[error(code = "E0505", slug = "move-out-of-borrow-error")]
+/// #[error(code = "E0505", slug = "borrowck-move-out-of-borrow")]
/// pub struct MoveOutOfBorrowError<'tcx> {
/// pub name: Ident,
/// pub ty: Ty<'tcx>,
/// #[primary_span]
-/// #[label = "cannot move out of borrow"]
+/// #[label]
/// pub span: Span,
-/// #[label = "`{ty}` first borrowed here"]
-/// pub other_span: Span,
-/// #[suggestion(message = "consider cloning here", code = "{name}.clone()")]
-/// pub opt_sugg: Option<(Span, Applicability)>
+/// #[label = "first-borrow-label"]
+/// pub first_borrow_span: Span,
+/// #[suggestion(code = "{name}.clone()")]
+/// pub clone_sugg: Option<(Span, Applicability)>
/// }
/// ```
///
+/// ```fluent
+/// move-out-of-borrow = cannot move out of {$name} because it is borrowed
+/// .label = cannot move out of borrow
+/// .first-borrow-label = `{$ty}` first borrowed here
+/// .suggestion = consider cloning here
+/// ```
+///
/// Then, later, to emit the error:
///
/// ```ignore (pseudo-rust)
/// expected,
/// actual,
/// span,
-/// other_span,
-/// opt_sugg: Some(suggestion, Applicability::MachineApplicable),
+/// first_borrow_span,
+/// clone_sugg: Some(suggestion, Applicability::MachineApplicable),
/// });
/// ```
+///
+/// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`:
+/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html>
pub fn session_diagnostic_derive(s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
// Names for the diagnostic we build and the session we build it from.
let diag = format_ident!("diag");
use rustc_hir::definitions::Definitions;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::TyCtxt;
-use rustc_serialize::json::ToJson;
use rustc_session::config::{self, CrateType, ExternLocation};
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
use rustc_session::cstore::{ExternCrateSource, MetadataLoaderDyn};
-use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
+use rustc_session::lint;
use rustc_session::output::validate_crate_name;
use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_target::spec::{PanicStrategy, TargetTriple};
use proc_macro::bridge::client::ProcMacro;
-use std::collections::BTreeMap;
use std::ops::Fn;
use std::path::Path;
use std::{cmp, env};
// Don't worry about pathless `--extern foo` sysroot references
continue;
}
+ if entry.nounused_dep {
+ // We're not worried about this one
+ continue;
+ }
let name_interned = Symbol::intern(name);
if self.used_extern_options.contains(&name_interned) {
continue;
continue;
}
- let diag = match self.sess.opts.extern_dep_specs.get(name) {
- Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
- None => {
- // If we don't have a specific location, provide a json encoding of the `--extern`
- // option.
- let meta: BTreeMap<String, String> =
- std::iter::once(("name".to_string(), name.to_string())).collect();
- BuiltinLintDiagnostics::ExternDepSpec(
- name.clone(),
- ExternDepSpec::Json(meta.to_json()),
- )
- }
- };
- self.sess.parse_sess.buffer_lint_with_diagnostic(
+ self.sess.parse_sess.buffer_lint(
lint::builtin::UNUSED_CRATE_DEPENDENCIES,
span,
ast::CRATE_NODE_ID,
name,
self.local_crate_name,
name),
- diag,
);
}
}
use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ForeignModule;
crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
- let mut collector = Collector { modules: Vec::new() };
- tcx.hir().visit_all_item_likes(&mut collector);
- collector.modules
-}
-
-struct Collector {
- modules: Vec<ForeignModule>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
- fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
- let hir::ItemKind::ForeignMod { items, .. } = it.kind else {
- return;
- };
-
- let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
- self.modules.push(ForeignModule { foreign_items, def_id: it.def_id.to_def_id() });
+ let mut modules = Vec::new();
+ for id in tcx.hir().items() {
+ if !matches!(tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+ continue;
+ }
+ let item = tcx.hir().item(id);
+ if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
+ let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
+ modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() });
+ }
}
-
- fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
- fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
- fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
+ modules
}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)]
#![feature(drain_filter)]
+#![feature(generators)]
#![feature(let_else)]
#![feature(nll)]
#![feature(once_cell)]
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib};
use rustc_session::parse::feature_err;
crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
let mut collector = Collector { tcx, libs: Vec::new() };
- tcx.hir().visit_all_item_likes(&mut collector);
+ for id in tcx.hir().items() {
+ collector.process_item(id);
+ }
collector.process_command_line();
collector.libs
}
libs: Vec<NativeLib>,
}
-impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
- fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
+impl<'tcx> Collector<'tcx> {
+ fn process_item(&mut self, id: rustc_hir::ItemId) {
+ if !matches!(self.tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+ return;
+ }
+
+ let it = self.tcx.hir().item(id);
let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else {
return;
};
}
}
- fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem<'tcx>) {}
- fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem<'tcx>) {}
- fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {}
-}
-
-impl Collector<'_> {
fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) {
match span {
use rustc_middle::thir;
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::fast_reject::SimplifiedType;
+use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
use rustc_serialize::{opaque, Decodable, Decoder};
use rustc_session::cstore::{
// Iterate over all children.
if let Some(children) = self.root.tables.children.get(self, id) {
for child_index in children.decode((self, sess)) {
- if let Some(ident) = self.opt_item_ident(child_index, sess) {
- let kind = self.def_kind(child_index);
- let def_id = self.local_def_id(child_index);
- let res = Res::Def(kind, def_id);
- let vis = self.get_visibility(child_index);
- let span = self.get_span(child_index, sess);
- let macro_rules = match kind {
- DefKind::Macro(..) => match self.kind(child_index) {
- EntryKind::MacroDef(_, macro_rules) => macro_rules,
- _ => unreachable!(),
- },
- _ => false,
- };
-
- callback(ModChild { ident, res, vis, span, macro_rules });
-
- // For non-re-export structs and variants add their constructors to children.
- // Re-export lists automatically contain constructors when necessary.
- match kind {
- DefKind::Struct => {
- if let Some((ctor_def_id, ctor_kind)) =
- self.get_ctor_def_id_and_kind(child_index)
- {
- let ctor_res =
- Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
- let vis = self.get_visibility(ctor_def_id.index);
- callback(ModChild {
- ident,
- res: ctor_res,
- vis,
- span,
- macro_rules: false,
- });
- }
- }
- DefKind::Variant => {
- // Braced variants, unlike structs, generate unusable names in
- // value namespace, they are reserved for possible future use.
- // It's ok to use the variant's id as a ctor id since an
- // error will be reported on any use of such resolution anyway.
- let (ctor_def_id, ctor_kind) = self
- .get_ctor_def_id_and_kind(child_index)
- .unwrap_or((def_id, CtorKind::Fictive));
+ let ident = self.item_ident(child_index, sess);
+ let kind = self.def_kind(child_index);
+ let def_id = self.local_def_id(child_index);
+ let res = Res::Def(kind, def_id);
+ let vis = self.get_visibility(child_index);
+ let span = self.get_span(child_index, sess);
+ let macro_rules = match kind {
+ DefKind::Macro(..) => match self.kind(child_index) {
+ EntryKind::MacroDef(_, macro_rules) => macro_rules,
+ _ => unreachable!(),
+ },
+ _ => false,
+ };
+
+ callback(ModChild { ident, res, vis, span, macro_rules });
+
+ // For non-re-export structs and variants add their constructors to children.
+ // Re-export lists automatically contain constructors when necessary.
+ match kind {
+ DefKind::Struct => {
+ if let Some((ctor_def_id, ctor_kind)) =
+ self.get_ctor_def_id_and_kind(child_index)
+ {
let ctor_res =
- Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
- let mut vis = self.get_visibility(ctor_def_id.index);
- if ctor_def_id == def_id && vis.is_public() {
- // For non-exhaustive variants lower the constructor visibility to
- // within the crate. We only need this for fictive constructors,
- // for other constructors correct visibilities
- // were already encoded in metadata.
- let mut attrs = self.get_item_attrs(def_id.index, sess);
- if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
- let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
- vis = ty::Visibility::Restricted(crate_def_id);
- }
- }
+ Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
+ let vis = self.get_visibility(ctor_def_id.index);
callback(ModChild {
ident,
res: ctor_res,
macro_rules: false,
});
}
- _ => {}
}
+ DefKind::Variant => {
+ // Braced variants, unlike structs, generate unusable names in
+ // value namespace, they are reserved for possible future use.
+ // It's ok to use the variant's id as a ctor id since an
+ // error will be reported on any use of such resolution anyway.
+ let (ctor_def_id, ctor_kind) = self
+ .get_ctor_def_id_and_kind(child_index)
+ .unwrap_or((def_id, CtorKind::Fictive));
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
+ let mut vis = self.get_visibility(ctor_def_id.index);
+ if ctor_def_id == def_id && vis.is_public() {
+ // For non-exhaustive variants lower the constructor visibility to
+ // within the crate. We only need this for fictive constructors,
+ // for other constructors correct visibilities
+ // were already encoded in metadata.
+ let mut attrs = self.get_item_attrs(def_id.index, sess);
+ if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
+ let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
+ vis = ty::Visibility::Restricted(crate_def_id);
+ }
+ }
+ callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
+ }
+ _ => {}
}
}
}
.collect()
})
}
+
+ fn get_generator_diagnostic_data(
+ self,
+ tcx: TyCtxt<'tcx>,
+ id: DefIndex,
+ ) -> Option<GeneratorDiagnosticData<'tcx>> {
+ self.root
+ .tables
+ .generator_diagnostic_data
+ .get(self, id)
+ .map(|param| param.decode((self, tcx)))
+ .map(|generator_data| GeneratorDiagnosticData {
+ generator_interior_types: generator_data.generator_interior_types,
+ hir_owner: generator_data.hir_owner,
+ nodes_types: generator_data.nodes_types,
+ adjustments: generator_data.adjustments,
+ })
+ }
+
+ fn get_may_have_doc_links(self, index: DefIndex) -> bool {
+ self.root.tables.may_have_doc_links.get(self, index).is_some()
+ }
}
impl CrateMetadata {
use rustc_ast as ast;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::exported_symbols::ExportedSymbol;
crate_extern_paths => { cdata.source().paths().cloned().collect() }
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
+ generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) }
}
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
continue;
}
- bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX });
+ bfs_queue.push_back(cnum.as_def_id());
}
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &ModChild, parent: DefId| {
) -> impl Iterator<Item = DefId> + '_ {
self.get_crate_data(cnum).get_all_incoherent_impls()
}
+
+ pub fn associated_item_def_ids_untracked<'a>(
+ &'a self,
+ def_id: DefId,
+ sess: &'a Session,
+ ) -> impl Iterator<Item = DefId> + 'a {
+ self.get_crate_data(def_id.krate).get_associated_item_def_ids(def_id.index, sess)
+ }
+
+ pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool {
+ self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index)
+ }
}
impl CrateStore for CStore {
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::iter_from_generator;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
use rustc_hir as hir;
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+ fn encode_attrs(&mut self, def_id: DefId) {
+ let attrs = self.tcx.get_attrs(def_id);
+ record!(self.tables.attributes[def_id] <- attrs);
+ if attrs.iter().any(|attr| attr.may_have_doc_links()) {
+ self.tables.may_have_doc_links.set(def_id.index, ());
+ }
+ }
+
fn encode_def_ids(&mut self) {
if self.is_proc_macro {
return;
let Some(def_kind) = def_kind else { continue };
self.tables.opt_def_kind.set(def_id.index, def_kind);
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
- record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
+ self.encode_attrs(def_id);
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
if should_encode_visibility(def_kind) {
record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
// Encode this here because we don't do it in encode_def_ids.
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
} else {
- let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index);
- // Foreign items are planted into their parent modules from name resolution point of view.
- let tcx = self.tcx;
- let foreign_item_children = md
- .item_ids
- .iter()
- .filter_map(|item_id| match tcx.hir().item(*item_id).kind {
- hir::ItemKind::ForeignMod { items, .. } => {
- Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index))
+ record!(self.tables.children[def_id] <- iter_from_generator(|| {
+ for item_id in md.item_ids {
+ match tcx.hir().item(*item_id).kind {
+ // Foreign items are planted into their parent modules
+ // from name resolution point of view.
+ hir::ItemKind::ForeignMod { items, .. } => {
+ for foreign_item in items {
+ yield foreign_item.id.def_id.local_def_index;
+ }
+ }
+ // Only encode named non-reexport children, reexports are encoded
+ // separately and unnamed items are not used by name resolution.
+ hir::ItemKind::ExternCrate(..) => continue,
+ _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => {
+ yield item_id.def_id.local_def_index;
+ }
+ _ => continue,
}
- _ => None,
- })
- .flatten();
-
- record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children));
+ }
+ }));
}
}
fn encode_info_for_closure(&mut self, hir_id: hir::HirId) {
let def_id = self.tcx.hir().local_def_id(hir_id);
debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
-
// NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
// including on the signature, which is inferred in `typeck.
- let ty = self.tcx.typeck(def_id).node_type(hir_id);
-
+ let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
+ let ty = typeck_result.node_type(hir_id);
match ty.kind() {
ty::Generator(..) => {
let data = self.tcx.generator_kind(def_id).unwrap();
+ let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Generator);
record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
+ record!(self.tables.generator_diagnostic_data[def_id.to_def_id()] <- generator_diagnostic_data);
}
ty::Closure(..) => {
let hir = tcx.hir();
let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
- let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX));
+ let stability = tcx.lookup_stability(CRATE_DEF_ID);
let macros =
self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
- record!(self.tables.attributes[LOCAL_CRATE.as_def_id()] <- tcx.get_attrs(LOCAL_CRATE.as_def_id()));
+ self.encode_attrs(LOCAL_CRATE.as_def_id());
record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id()));
if let Some(stability) = stability {
record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
let def_id = id.to_def_id();
self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
- record!(self.tables.attributes[def_id] <- attrs);
+ self.encode_attrs(def_id);
record!(self.tables.def_keys[def_id] <- def_key);
record!(self.tables.def_ident_span[def_id] <- span);
record!(self.tables.def_span[def_id] <- span);
debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self);
let tcx = self.tcx;
- let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() };
- tcx.hir().visit_all_item_likes(&mut visitor);
+ let mut fx_hash_map: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>> =
+ FxHashMap::default();
+
+ for id in tcx.hir().items() {
+ if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
+ let simplified_self_ty = fast_reject::simplify_type(
+ self.tcx,
+ trait_ref.self_ty(),
+ TreatParams::AsPlaceholders,
+ );
- let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
+ fx_hash_map
+ .entry(trait_ref.def_id)
+ .or_default()
+ .push((id.def_id.local_def_index, simplified_self_ty));
+ }
+ }
+ }
+
+ let mut all_impls: Vec<_> = fx_hash_map.into_iter().collect();
// Bring everything into deterministic order for hashing
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
}
}
-struct ImplsVisitor<'tcx> {
- tcx: TyCtxt<'tcx>,
- impls: FxHashMap<DefId, Vec<(DefIndex, Option<SimplifiedType>)>>,
-}
-
-impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- match item.kind {
- hir::ItemKind::Impl(..) => {
- if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) {
- let simplified_self_ty = fast_reject::simplify_type(
- self.tcx,
- trait_ref.self_ty(),
- TreatParams::AsPlaceholders,
- );
-
- self.impls
- .entry(trait_ref.def_id)
- .or_default()
- .push((item.def_id.local_def_index, simplified_self_ty));
- }
- }
- _ => {}
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem<'v>) {}
-
- fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem<'v>) {
- // handled in `visit_item` above
- }
-
- fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
-}
-
/// Used to prefetch queries which will be needed later by metadata encoding.
/// Only a subset of the queries are actually prefetched to keep this code smaller.
fn prefetch_mir(tcx: TyCtxt<'_>) {
use rustc_middle::thir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::GeneratorDiagnosticData;
use rustc_middle::ty::{self, ReprOptions, Ty};
use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion;
def_keys: Table<DefIndex, Lazy<DefKey>>,
def_path_hashes: Table<DefIndex, DefPathHash>,
proc_macro_quoted_spans: Table<usize, Lazy<Span>>,
+ generator_diagnostic_data: Table<DefIndex, Lazy<GeneratorDiagnosticData<'tcx>>>,
+ may_have_doc_links: Table<DefIndex, ()>,
}
#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
}
}
+impl FixedSizeEncoding for Option<()> {
+ type ByteArray = [u8; 1];
+
+ #[inline]
+ fn from_bytes(b: &[u8; 1]) -> Self {
+ (b[0] != 0).then(|| ())
+ }
+
+ #[inline]
+ fn write_to_bytes(self, b: &mut [u8; 1]) {
+ b[0] = self.is_some() as u8
+ }
+}
+
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
// generic `Lazy<T>` impl, but in the general case we might not need / want to
// fit every `usize` in `u32`.
use crate::ty::TyCtxt;
use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::definitions::DefPathHash;
use rustc_hir::HirId;
use rustc_query_system::dep_graph::FingerprintStyle;
#[inline(always)]
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
- let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
+ let def_id = self.as_def_id();
def_id.to_fingerprint(tcx)
}
use rustc_index::vec::Idx;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
-use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
-use std::collections::VecDeque;
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
match node {
}
}
- pub fn items(self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
- let krate = self.krate();
- krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() {
- OwnerNode::Item(item) => Some(item),
- _ => None,
- })
+ pub fn items(self) -> impl Iterator<Item = ItemId> + 'hir {
+ self.tcx.hir_crate_items(()).items.iter().copied()
+ }
+
+ pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
+ par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
}
pub fn def_key(self, def_id: LocalDefId) -> DefKey {
| Node::Param(_)
| Node::Arm(_)
| Node::Lifetime(_)
- | Node::Visibility(_)
| Node::Block(_) => return None,
};
Some(def_kind)
}
pub fn for_each_module(self, f: impl Fn(LocalDefId)) {
- let mut queue = VecDeque::new();
- queue.push_back(CRATE_DEF_ID);
-
- while let Some(id) = queue.pop_front() {
- f(id);
- let items = self.tcx.hir_module_items(id);
- queue.extend(items.submodules.iter().copied())
+ let crate_items = self.tcx.hir_crate_items(());
+ for module in crate_items.submodules.iter() {
+ f(*module)
}
}
},
Node::Lifetime(lifetime) => lifetime.span,
Node::GenericParam(param) => param.span,
- Node::Visibility(&Spanned {
- node: VisibilityKind::Restricted { ref path, .. },
- ..
- }) => path.span,
Node::Infer(i) => i.span,
- Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
Node::Local(local) => local.span,
Node::Crate(item) => item.spans.inner_span,
};
}
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+ // Hash visibility information since it does not appear in HIR.
+ let resolutions = tcx.resolutions(());
+ resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher);
+ resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher);
let crate_hash: Fingerprint = stable_hasher.finish();
Svh::new(crate_hash.to_smaller_hash())
Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str),
Some(Node::Lifetime(_)) => node_str("lifetime"),
Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
- Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
Some(Node::Crate(..)) => String::from("root_crate"),
None => format!("unknown node{}", id_str),
}
}
}
}
+
+pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
+ let mut collector = CrateCollector {
+ tcx,
+ submodules: Vec::default(),
+ items: Vec::default(),
+ trait_items: Vec::default(),
+ impl_items: Vec::default(),
+ foreign_items: Vec::default(),
+ };
+
+ tcx.hir().walk_toplevel_module(&mut collector);
+
+ let CrateCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
+ collector;
+
+ return ModuleItems {
+ submodules: submodules.into_boxed_slice(),
+ items: items.into_boxed_slice(),
+ trait_items: trait_items.into_boxed_slice(),
+ impl_items: impl_items.into_boxed_slice(),
+ foreign_items: foreign_items.into_boxed_slice(),
+ };
+
+ struct CrateCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ submodules: Vec<LocalDefId>,
+ items: Vec<ItemId>,
+ trait_items: Vec<TraitItemId>,
+ impl_items: Vec<ImplItemId>,
+ foreign_items: Vec<ForeignItemId>,
+ }
+
+ impl<'hir> Visitor<'hir> for CrateCollector<'hir> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.tcx.hir()
+ }
+
+ fn visit_item(&mut self, item: &'hir Item<'hir>) {
+ self.items.push(item.item_id());
+ intravisit::walk_item(self, item)
+ }
+
+ fn visit_mod(&mut self, m: &'hir Mod<'hir>, _s: Span, n: HirId) {
+ self.submodules.push(n.owner);
+ intravisit::walk_mod(self, m, n);
+ }
+
+ fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
+ self.foreign_items.push(item.foreign_item_id());
+ intravisit::walk_foreign_item(self, item)
+ }
+
+ fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
+ self.trait_items.push(item.trait_item_id());
+ intravisit::walk_trait_item(self, item)
+ }
+
+ fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
+ self.impl_items.push(item.impl_item_id());
+ intravisit::walk_impl_item(self, item)
+ }
+ }
+}
foreign_items: Box<[ForeignItemId]>,
}
+impl ModuleItems {
+ pub fn items(&self) -> impl Iterator<Item = ItemId> + '_ {
+ self.items.iter().copied()
+ }
+
+ pub fn trait_items(&self) -> impl Iterator<Item = TraitItemId> + '_ {
+ self.trait_items.iter().copied()
+ }
+
+ pub fn impl_items(&self) -> impl Iterator<Item = ImplItemId> + '_ {
+ self.impl_items.iter().copied()
+ }
+
+ pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ {
+ self.foreign_items.iter().copied()
+ }
+}
+
impl<'tcx> TyCtxt<'tcx> {
#[inline(always)]
pub fn hir(self) -> map::Map<'tcx> {
hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))
};
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
+ providers.hir_crate_items = map::hir_crate_items;
providers.crate_hash = map::crate_hash;
providers.hir_module_items = map::hir_module_items;
providers.hir_owner = |tcx, id| {
use rustc_feature::GateIssue;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self, HirId};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
};
}
- let is_staged_api =
- self.lookup_stability(DefId { index: CRATE_DEF_INDEX, ..def_id }).is_some();
+ let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
if !is_staged_api {
return EvalResult::Allow;
}
/// `get_bytes_with_uninit_and_ptr` instead,
///
/// This function also guarantees that the resulting pointer will remain stable
- /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies
+ /// even when new allocations are pushed to the `HashMap`. `mem_copy_repeatedly` relies
/// on that.
///
/// It is the caller's responsibility to check bounds and alignment beforehand.
let val = match val {
ScalarMaybeUninit::Scalar(scalar) => scalar,
ScalarMaybeUninit::Uninit => {
- self.mark_init(range, false);
- return Ok(());
+ return self.write_uninit(cx, range);
}
};
Ok(())
}
+
+ /// Write "uninit" to the given memory range.
+ pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
+ self.mark_init(range, false);
+ self.clear_relocations(cx, range)?;
+ return Ok(());
+ }
}
/// Relocations.
if Tag::ERR_ON_PARTIAL_PTR_OVERWRITE {
return Err(AllocError::PartialPointerOverwrite(first));
}
+ warn!(
+ "Partial pointer overwrite! De-initializing memory at offsets {first:?}..{start:?}."
+ );
self.init_mask.set_range(first, start, false);
}
if last > end {
last - cx.data_layout().pointer_size,
));
}
+ warn!(
+ "Partial pointer overwrite! De-initializing memory at offsets {end:?}..{last:?}."
+ );
self.init_mask.set_range(end, last, false);
}
// Forget all the relocations.
+ // Since relocations do not overlap, we know that removing until `last` (exclusive) is fine,
+ // i.e., this will not remove any other relocations just after the ones we care about.
self.relocations.0.remove_range(first..last);
Ok(())
}
/// A partial, owned list of relocations to transfer into another allocation.
+///
+/// Offsets are already adjusted to the destination allocation.
pub struct AllocationRelocations<Tag> {
- relative_relocations: Vec<(Size, Tag)>,
+ dest_relocations: Vec<(Size, Tag)>,
}
impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
) -> AllocationRelocations<Tag> {
let relocations = self.get_relocations(cx, src);
if relocations.is_empty() {
- return AllocationRelocations { relative_relocations: Vec::new() };
+ return AllocationRelocations { dest_relocations: Vec::new() };
}
let size = src.size;
let mut new_relocations = Vec::with_capacity(relocations.len() * (count as usize));
+ // If `count` is large, this is rather wasteful -- we are allocating a big array here, which
+ // is mostly filled with redundant information since it's just N copies of the same `Tag`s
+ // at slightly adjusted offsets. The reason we do this is so that in `mark_relocation_range`
+ // we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces
+ // the right sequence of relocations for all N copies.
for i in 0..count {
new_relocations.extend(relocations.iter().map(|&(offset, reloc)| {
// compute offset for current repetition
}));
}
- AllocationRelocations { relative_relocations: new_relocations }
+ AllocationRelocations { dest_relocations: new_relocations }
}
/// Applies a relocation copy.
/// The affected range, as defined in the parameters to `prepare_relocation_copy` is expected
/// to be clear of relocations.
+ ///
+ /// This is dangerous to use as it can violate internal `Allocation` invariants!
+ /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>) {
- self.relocations.0.insert_presorted(relocations.relative_relocations);
+ self.relocations.0.insert_presorted(relocations.dest_relocations);
}
}
})
}
- pub fn mark_init(&mut self, range: AllocRange, is_init: bool) {
+ fn mark_init(&mut self, range: AllocRange, is_init: bool) {
if range.size.bytes() == 0 {
return;
}
}
/// Applies multiple instances of the run-length encoding to the initialization mask.
+ ///
+ /// This is dangerous to use as it can violate internal `Allocation` invariants!
+ /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
pub fn mark_compressed_init_range(
&mut self,
defined: &InitMaskCompressed,
}
static_assert_size!(Pointer, 16);
+// `Option<Tag>` pointers are also passed around quite a bit
+// (but not stored in permanent machine state).
+static_assert_size!(Pointer<Option<AllocId>>, 16);
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
// all the Miri types.
}
impl<Tag> Pointer<Option<Tag>> {
+ /// Convert this pointer that *might* have a tag into a pointer that *definitely* has a tag, or
+ /// an absolute address.
+ ///
+ /// This is rarely what you want; call `ptr_try_get_alloc_id` instead.
pub fn into_pointer_or_addr(self) -> Result<Pointer<Tag>, Size> {
match self.provenance {
Some(tag) => Ok(Pointer::new(tag, self.offset)),
None => Err(self.offset),
}
}
+
+ /// Returns the absolute address the pointer points to.
+ /// Only works if Tag::OFFSET_IS_ADDR is true!
+ pub fn addr(self) -> Size
+ where
+ Tag: Provenance,
+ {
+ assert!(Tag::OFFSET_IS_ADDR);
+ self.offset
+ }
}
impl<Tag> Pointer<Option<Tag>> {
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{CtorKind, Namespace};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::{self, GeneratorKind};
use rustc_hir::{self as hir, HirId};
use rustc_session::Session;
/// * [`StatementKind::Retag`]
///
/// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop`
- /// terminator means that the auto-generated drop glue will be invoked.
+ /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands
+ /// are allowed for non-`Copy` types.
DropsLowered = 3,
/// Beginning with this phase, the following variant is disallowed:
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
let mut body = Body {
phase: MirPhase::Built,
- source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
+ source: MirSource::item(CRATE_DEF_ID.to_def_id()),
basic_blocks,
source_scopes: IndexVec::new(),
generator: None,
/// validator.
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum Operand<'tcx> {
- /// Creates a value by loading the given place. The type of the place must be `Copy`
+ /// Creates a value by loading the given place.
+ ///
+ /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there
+ /// is no such requirement.
Copy(Place<'tcx>),
/// Creates a value by performing loading the place, just like the `Copy` operand.
/// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
/// parameter may be a `usize` as well.
/// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
- /// raw pointers, or function pointers of matching types and return a `bool`.
+ /// raw pointers, or function pointers and return a `bool`. The types of the operands must be
+ /// matching, up to the usual caveat of the lifetimes in function pointers.
/// * Left and right shift operations accept signed or unsigned integers not necessarily of the
/// same type and return a value of the same type as their LHS. Like in Rust, the RHS is
/// truncated as needed.
}
if let Some(&tag) = alloc.relocations().get(&i) {
// Memory with a relocation must be defined
+ assert!(alloc.init_mask().is_range_initialized(i, i + ptr_size).is_ok());
let j = i.bytes_usize();
let offset = alloc
.inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize());
desc { "get the crate HIR" }
}
+ /// All items in the crate.
+ query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
+ storage(ArenaCacheSelector<'tcx>)
+ eval_always
+ desc { "get HIR crate items" }
+ }
+
/// The items in a module.
///
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
eval_always
desc { "computing the backend features for CLI flags" }
}
+
+ query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
+ storage(ArenaCacheSelector<'tcx>)
+ desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
+ separate_provide_extern
+ }
}
/// A container for a THIR body.
///
/// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
- #[derive(Debug, HashStable)]
+ #[derive(Debug, HashStable, Clone)]
pub struct Thir<'tcx> {
$(
pub $name: IndexVec<$id, $value>,
Explicit(hir::HirId),
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct Block {
/// Whether the block itself has a label. Used by `label: {}`
/// and `try` blocks.
pub safety_mode: BlockSafety,
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct Adt<'tcx> {
/// The ADT we're constructing.
pub adt_def: AdtDef<'tcx>,
ExplicitUnsafe(hir::HirId),
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct Stmt<'tcx> {
pub kind: StmtKind<'tcx>,
pub opt_destruction_scope: Option<region::Scope>,
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub enum StmtKind<'tcx> {
/// An expression with a trailing semicolon.
Expr {
rustc_data_structures::static_assert_size!(Expr<'_>, 104);
/// A THIR expression.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct Expr<'tcx> {
/// The type of this expression
pub ty: Ty<'tcx>,
pub kind: ExprKind<'tcx>,
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub enum ExprKind<'tcx> {
/// `Scope`s are used to explicitly mark destruction scopes,
/// and to track the `HirId` of the expressions within the scope.
/// Represents the association of a field identifier and an expression.
///
/// This is used in struct constructors.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct FieldExpr {
pub name: Field,
pub expr: ExprId,
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct FruInfo<'tcx> {
pub base: ExprId,
pub field_types: Box<[Ty<'tcx>]>,
}
/// A `match` arm.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub struct Arm<'tcx> {
pub pattern: Pat<'tcx>,
pub guard: Option<Guard<'tcx>>,
}
/// A `match` guard.
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub enum Guard<'tcx> {
If(ExprId),
IfLet(Pat<'tcx>, ExprId),
Or,
}
-#[derive(Debug, HashStable)]
+#[derive(Clone, Debug, HashStable)]
pub enum InlineAsmOperand<'tcx> {
In {
reg: InlineAsmRegOrRegClass,
span: Span,
},
SymFn {
- expr: ExprId,
+ value: mir::ConstantKind<'tcx>,
+ span: Span,
},
SymStatic {
def_id: DefId,
match op {
In { expr, reg: _ }
| Out { expr: Some(expr), reg: _, late: _ }
- | InOut { expr, reg: _, late: _ }
- | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
+ | InOut { expr, reg: _, late: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
visitor.visit_expr(&visitor.thir()[*in_expr]);
if let Some(out_expr) = out_expr {
}
Out { expr: None, reg: _, late: _ }
| Const { value: _, span: _ }
+ | SymFn { value: _, span: _ }
| SymStatic { def_id: _ } => {}
}
}
static_assert_size!(ConstS<'_>, 48);
impl<'tcx> Const<'tcx> {
+ #[inline]
pub fn ty(self) -> Ty<'tcx> {
self.0.ty
}
+ #[inline]
pub fn val(self) -> ConstKind<'tcx> {
self.0.val
}
use super::ScalarInt;
-use rustc_macros::HashStable;
+use rustc_macros::{HashStable, TyDecodable, TyEncodable};
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
#[derive(HashStable)]
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.
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)))
match st[i].abi() {
Abi::Scalar(_) => Abi::Scalar(niche_scalar),
Abi::ScalarPair(first, second) => {
- // We need to use scalar_unit to reset the
- // valid range to the maximal one for that
- // primitive, because only the niche is
- // guaranteed to be initialised, not the
- // other primitive.
+ // Only the niche is guaranteed to be initialised,
+ // so use union layout for the other primitive.
if offset.bytes() == 0 {
- Abi::ScalarPair(
- niche_scalar,
- scalar_unit(second.primitive()),
- )
+ Abi::ScalarPair(niche_scalar, second.to_union())
} else {
- Abi::ScalarPair(
- scalar_unit(first.primitive()),
- niche_scalar,
- )
+ Abi::ScalarPair(first.to_union(), niche_scalar)
}
}
_ => Abi::Aggregate { sized: true },
} else {
// Try to use a ScalarPair for all tagged enums.
let mut common_prim = None;
+ let mut common_prim_initialized_in_all_variants = true;
for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
bug!();
let mut fields =
iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
let (field, offset) = match (fields.next(), fields.next()) {
- (None, None) => continue,
+ (None, None) => {
+ common_prim_initialized_in_all_variants = false;
+ continue;
+ }
(Some(pair), None) => pair,
_ => {
common_prim = None;
}
};
let prim = match field.abi {
- Abi::Scalar(scalar) => scalar.primitive(),
+ Abi::Scalar(scalar) => {
+ common_prim_initialized_in_all_variants &=
+ matches!(scalar, Scalar::Initialized { .. });
+ scalar.primitive()
+ }
_ => {
common_prim = None;
break;
}
}
if let Some((prim, offset)) = common_prim {
- let pair = self.scalar_pair(tag, scalar_unit(prim));
+ let prim_scalar = if common_prim_initialized_in_all_variants {
+ scalar_unit(prim)
+ } else {
+ // Common prim might be uninit.
+ Scalar::Union { value: prim }
+ };
+ let pair = self.scalar_pair(tag, prim_scalar);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
};
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
- CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
- Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
+ CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
+ GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
+ UserTypeAnnotationIndex,
};
pub use self::instance::{Instance, InstanceDef};
pub use self::list::List;
pub definitions: rustc_hir::definitions::Definitions,
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,
pub access_levels: AccessLevels,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
}
impl Visibility {
- pub fn from_hir(visibility: &hir::Visibility<'_>, id: hir::HirId, tcx: TyCtxt<'_>) -> Self {
- match visibility.node {
- hir::VisibilityKind::Public => Visibility::Public,
- hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
- hir::VisibilityKind::Restricted { ref path, .. } => match path.res {
- // If there is no resolution, `resolve` will have already reported an error, so
- // assume that the visibility is public to avoid reporting more privacy errors.
- Res::Err => Visibility::Public,
- def => Visibility::Restricted(def.def_id()),
- },
- hir::VisibilityKind::Inherited => {
- Visibility::Restricted(tcx.parent_module(id).to_def_id())
- }
- }
- }
-
/// Returns `true` if an item with this visibility is accessible from the given block.
pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
let restriction = match self {
}
fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
- if def_id.index == CRATE_DEF_INDEX {
- Some(self.crate_name(def_id.krate))
+ if let Some(cnum) = def_id.as_crate_root() {
+ Some(self.crate_name(cnum))
} else {
let def_key = self.def_key(def_id);
match def_key.disambiguated_data.data {
use rustc_data_structures::sso::SsoHashSet;
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
-use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
-use rustc_hir::ItemKind;
use rustc_session::config::TrimmedDefPaths;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_span::symbol::{kw, Ident, Symbol};
// If `def_id` is a direct or injected extern crate, return the
// path to the crate followed by the path to the item within the crate.
- if def_id.index == CRATE_DEF_INDEX {
- let cnum = def_id.krate;
-
+ if let Some(cnum) = def_id.as_crate_root() {
if cnum == LOCAL_CRATE {
return Ok((self.path_crate(cnum)?, true));
}
ty::BrNamed(_, _) => br.kind,
ty::BrAnon(i) => {
let name = region_map[&(i + 1)];
- ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+ ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
}
ty::BrEnv => {
let name = region_map[&0];
- ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+ ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
}
};
self.tcx.mk_region(ty::ReLateBound(
}
};
do_continue(&mut self, name);
- ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
+ ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
}
};
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) {
// Iterate all local crate items no matter where they are defined.
let hir = tcx.hir();
- for item in hir.items() {
- if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) {
+ for id in hir.items() {
+ if matches!(hir.def_kind(id.def_id), DefKind::Use) {
+ continue;
+ }
+
+ let item = hir.item(id);
+ if item.ident.name == kw::Empty {
continue;
}
let mut seen_defs: DefIdSet = Default::default();
for &cnum in tcx.crates(()).iter() {
- let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+ let def_id = cnum.as_def_id();
// Ignore crates that are not direct dependencies.
match tcx.extern_crate(def_id) {
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::GeneratorDiagnosticData;
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
use rustc_session::utils::NativeLibKind;
use rustc_session::Limits;
-use rustc_target::abi;
-use rustc_target::spec::PanicStrategy;
-
-use rustc_ast as ast;
-use rustc_attr as attr;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi;
+use rustc_target::spec::PanicStrategy;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
let tcx = self.tcx();
let opt_variances = tcx.variances_of(item_def_id);
- relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst)
+ relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst)
}
/// Switch variance for the purpose of relating `a` and `b`.
}
}
+#[inline]
pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
- variances: Option<(DefId, &[ty::Variance])>,
+ a_subst: SubstsRef<'tcx>,
+ b_subst: SubstsRef<'tcx>,
+) -> RelateResult<'tcx, SubstsRef<'tcx>> {
+ relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| {
+ relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
+ }))
+}
+
+pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
+ relation: &mut R,
+ ty_def_id: DefId,
+ variances: &[ty::Variance],
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
let tcx = relation.tcx();
- let mut cached_ty = None;
+ let mut cached_ty = None;
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
- let (variance, variance_info) = match variances {
- Some((ty_def_id, variances)) => {
- let variance = variances[i];
- let variance_info = if variance == ty::Invariant {
- let ty = *cached_ty
- .get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
- ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
- } else {
- ty::VarianceDiagInfo::default()
- };
- (variance, variance_info)
- }
- None => (ty::Invariant, ty::VarianceDiagInfo::default()),
+ let variance = variances[i];
+ let variance_info = if variance == ty::Invariant {
+ let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
+ ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
+ } else {
+ ty::VarianceDiagInfo::default()
};
relation.relate_with_variance(variance, variance_info, a, b)
});
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
- let substs = relate_substs(relation, None, a.substs, b.substs)?;
+ let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::TraitRef { def_id: a.def_id, substs })
}
}
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
- let substs = relate_substs(relation, None, a.substs, b.substs)?;
+ let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
}
}
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
- let substs = relate_substs(relation, None, a_substs, b_substs)?;
+ let substs = relate_substs(relation, a_substs, b_substs)?;
Ok(tcx.mk_opaque(a_def_id, substs))
}
a: ty::ClosureSubsts<'tcx>,
b: ty::ClosureSubsts<'tcx>,
) -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> {
- let substs = relate_substs(relation, None, a.substs, b.substs)?;
+ let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::ClosureSubsts { substs })
}
}
a: ty::GeneratorSubsts<'tcx>,
b: ty::GeneratorSubsts<'tcx>,
) -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>> {
- let substs = relate_substs(relation, None, a.substs, b.substs)?;
+ let substs = relate_substs(relation, a.substs, b.substs)?;
Ok(ty::GeneratorSubsts { substs })
}
}
a: SubstsRef<'tcx>,
b: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
- relate_substs(relation, None, a, b)
+ relate_substs(relation, a, b)
}
}
use rustc_data_structures::functor::IdFunctor;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
-use rustc_hir::def_id::CRATE_DEF_INDEX;
use rustc_index::vec::{Idx, IndexVec};
use std::fmt;
match *self {
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
ty::BrNamed(did, name) => {
- if did.index == CRATE_DEF_INDEX {
+ if did.is_crate_root() {
write!(f, "BrNamed({})", name)
} else {
write!(f, "BrNamed({:?}, {})", did, name)
func: fun,
args,
cleanup: None,
- // FIXME(varkor): replace this with an uninhabitedness-based check.
- // This requires getting access to the current module to call
- // `tcx.is_ty_uninhabited_from`, which is currently tricky to do.
- destination: if expr.ty.is_never() {
+ // The presence or absence of a return edge affects control-flow sensitive
+ // MIR checks and ultimately whether code is accepted or not. We can only
+ // omit the return edge if a return type is visibly uninhabited to a module
+ // that makes the call.
+ destination: if this.tcx.is_ty_uninhabited_from(
+ this.parent_module,
+ expr.ty,
+ this.param_env,
+ ) {
None
} else {
Some((destination, success))
value: Box::new(Constant { span, user_ty: None, literal: value }),
}
}
- thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn {
- value: Box::new(this.as_constant(&this.thir[expr])),
- },
+ thir::InlineAsmOperand::SymFn { value, span } => {
+ mir::InlineAsmOperand::SymFn {
+ value: Box::new(Constant {
+ span,
+ user_ty: None,
+ literal: value.into(),
+ }),
+ }
+ }
thir::InlineAsmOperand::SymStatic { def_id } => {
mir::InlineAsmOperand::SymStatic { def_id }
}
def_id: DefId,
hir_id: hir::HirId,
+ parent_module: DefId,
check_overflow: bool,
fn_span: Span,
arg_count: usize,
);
let lint_level = LintLevel::Explicit(hir_id);
+ let param_env = tcx.param_env(def.did);
let mut builder = Builder {
thir,
tcx,
infcx,
typeck_results: tcx.typeck_opt_const_arg(def),
region_scope_tree: tcx.region_scope_tree(def.did),
- param_env: tcx.param_env(def.did),
+ param_env,
def_id: def.did.to_def_id(),
hir_id,
+ parent_module: tcx.parent_module(hir_id).to_def_id(),
check_overflow,
cfg: CFG { basic_blocks: IndexVec::new() },
fn_span: span,
operands: asm
.operands
.iter()
- .map(|(op, _op_sp)| {
- match *op {
- hir::InlineAsmOperand::In { reg, ref expr } => {
- InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
- }
- hir::InlineAsmOperand::Out { reg, late, ref expr } => {
- InlineAsmOperand::Out {
- reg,
- late,
- expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
- }
- }
- hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
- InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
- }
- hir::InlineAsmOperand::SplitInOut {
- reg,
- late,
- ref in_expr,
- ref out_expr,
- } => InlineAsmOperand::SplitInOut {
+ .map(|(op, _op_sp)| match *op {
+ hir::InlineAsmOperand::In { reg, ref expr } => {
+ InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
+ }
+ hir::InlineAsmOperand::Out { reg, late, ref expr } => {
+ InlineAsmOperand::Out {
reg,
late,
- in_expr: self.mirror_expr(in_expr),
- out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
- },
- hir::InlineAsmOperand::Const { ref anon_const } => {
- let anon_const_def_id =
- self.tcx.hir().local_def_id(anon_const.hir_id);
- let value = mir::ConstantKind::from_anon_const(
- self.tcx,
- anon_const_def_id,
- self.param_env,
- );
- let span = self.tcx.hir().span(anon_const.hir_id);
-
- InlineAsmOperand::Const { value, span }
- }
- hir::InlineAsmOperand::Sym { ref expr } => {
- let hir::ExprKind::Path(ref qpath) = expr.kind else {
- span_bug!(
- expr.span,
- "asm `sym` operand should be a path, found {:?}",
- expr.kind
- );
- };
- let temp_lifetime =
- self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
- let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
- let ty;
- match res {
- Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
- ty = self.typeck_results().node_type(expr.hir_id);
- let user_ty =
- self.user_substs_applied_to_res(expr.hir_id, res);
- InlineAsmOperand::SymFn {
- expr: self.thir.exprs.push(Expr {
- ty,
- temp_lifetime,
- span: expr.span,
- kind: ExprKind::zero_sized_literal(user_ty),
- }),
- }
- }
-
- Res::Def(DefKind::Static(_), def_id) => {
- InlineAsmOperand::SymStatic { def_id }
- }
-
- _ => {
- self.tcx.sess.span_err(
- expr.span,
- "asm `sym` operand must point to a fn or static",
- );
-
- // Not a real fn, but we're not reaching codegen anyways...
- ty = self.tcx.ty_error();
- InlineAsmOperand::SymFn {
- expr: self.thir.exprs.push(Expr {
- ty,
- temp_lifetime,
- span: expr.span,
- kind: ExprKind::zero_sized_literal(None),
- }),
- }
- }
- }
+ expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
}
}
+ hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
+ InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
+ }
+ hir::InlineAsmOperand::SplitInOut {
+ reg,
+ late,
+ ref in_expr,
+ ref out_expr,
+ } => InlineAsmOperand::SplitInOut {
+ reg,
+ late,
+ in_expr: self.mirror_expr(in_expr),
+ out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
+ },
+ hir::InlineAsmOperand::Const { ref anon_const } => {
+ let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+ let value = mir::ConstantKind::from_anon_const(
+ self.tcx,
+ anon_const_def_id,
+ self.param_env,
+ );
+ let span = self.tcx.hir().span(anon_const.hir_id);
+
+ InlineAsmOperand::Const { value, span }
+ }
+ hir::InlineAsmOperand::SymFn { ref anon_const } => {
+ let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+ let value = mir::ConstantKind::from_anon_const(
+ self.tcx,
+ anon_const_def_id,
+ self.param_env,
+ );
+ let span = self.tcx.hir().span(anon_const.hir_id);
+
+ InlineAsmOperand::SymFn { value, span }
+ }
+ hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+ InlineAsmOperand::SymStatic { def_id }
+ }
})
.collect(),
options: asm.options,
format!(
"{}{}{} => todo!()",
comma,
- snippet.strip_prefix(",").unwrap_or(&snippet),
+ snippet.strip_prefix(',').unwrap_or(&snippet),
pattern
),
));
ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
- // FIXME(eddyb) avoid cloning this field more than once,
- // by accessing it through `ecx` instead.
- local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+ local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>,
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
// the last known `SourceInfo` here and just keep revisiting it.
source_info: Option<SourceInfo>,
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
let param_env = tcx.param_env_reveal_all_normalized(def_id);
- let span = tcx.def_span(def_id);
- // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts
- // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in
- // `layout_of` query invocations.
let can_const_prop = CanConstProp::check(tcx, param_env, body);
let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
for (l, mode) in can_const_prop.iter_enumerated() {
}
let mut ecx = InterpCx::new(
tcx,
- span,
+ tcx.def_span(def_id),
param_env,
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
);
ecx,
tcx,
param_env,
- // FIXME(eddyb) avoid cloning this field more than once,
- // by accessing it through `ecx` instead.
- //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
- local_decls: body.local_decls.clone(),
+ local_decls: &dummy_body.local_decls,
source_info: None,
}
}
let r = r?;
// We need the type of the LHS. We cannot use `place_layout` as that is the type
// of the result, which for checked binops is not the same!
- let left_ty = left.ty(&self.local_decls, self.tcx);
+ let left_ty = left.ty(self.local_decls, self.tcx);
let left_size = self.ecx.layout_of(left_ty).ok()?.size;
let right_size = r.layout.size;
let r_bits = r.to_scalar().ok();
ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
- // FIXME(eddyb) avoid cloning these two fields more than once,
- // by accessing them through `ecx` instead.
- source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
- local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+ source_scopes: &'mir IndexVec<SourceScope, SourceScopeData<'tcx>>,
+ local_decls: &'mir IndexVec<Local, LocalDecl<'tcx>>,
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
// the last known `SourceInfo` here and just keep revisiting it.
source_info: Option<SourceInfo>,
let substs = &InternalSubsts::identity_for_item(tcx, def_id);
let param_env = tcx.param_env_reveal_all_normalized(def_id);
- let span = tcx.def_span(def_id);
- // FIXME: `CanConstProp::check` computes the layout of all locals, return those layouts
- // so we can write them to `ecx.frame_mut().locals.layout, reducing the duplication in
- // `layout_of` query invocations.
let can_const_prop = CanConstProp::check(tcx, param_env, body);
let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
for (l, mode) in can_const_prop.iter_enumerated() {
}
let mut ecx = InterpCx::new(
tcx,
- span,
+ tcx.def_span(def_id),
param_env,
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
);
ecx,
tcx,
param_env,
- // FIXME(eddyb) avoid cloning these two fields more than once,
- // by accessing them through `ecx` instead.
- source_scopes: body.source_scopes.clone(),
- //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
- local_decls: body.local_decls.clone(),
+ source_scopes: &dummy_body.source_scopes,
+ local_decls: &dummy_body.local_decls,
source_info: None,
}
}
}
fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
- source_info.scope.lint_root(&self.source_scopes)
+ source_info.scope.lint_root(self.source_scopes)
}
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
let r = r?;
// We need the type of the LHS. We cannot use `place_layout` as that is the type
// of the result, which for checked binops is not the same!
- let left_ty = left.ty(&self.local_decls, self.tcx);
+ let left_ty = left.ty(self.local_decls, self.tcx);
let left_size = self.ecx.layout_of(left_ty).ok()?.size;
let right_size = r.layout.size;
let r_bits = r.to_scalar().ok();
let mut cnt = 0;
let validate = tcx.sess.opts.debugging_opts.validate_mir;
+ let overridden_passes = &tcx.sess.opts.debugging_opts.mir_enable_passes;
+ trace!(?overridden_passes);
if validate {
validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase));
}
for pass in passes {
- if !pass.is_enabled(&tcx.sess) {
- continue;
- }
-
let name = pass.name();
+
+ if let Some((_, polarity)) = overridden_passes.iter().rev().find(|(s, _)| s == &*name) {
+ trace!(
+ pass = %name,
+ "{} as requested by flag",
+ if *polarity { "Running" } else { "Not running" },
+ );
+ if !polarity {
+ continue;
+ }
+ } else {
+ if !pass.is_enabled(&tcx.sess) {
+ continue;
+ }
+ }
let dump_enabled = pass.is_mir_dump_enabled();
if dump_enabled {
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::GrowableBitSet;
use rustc_middle::mir::interpret::{AllocId, ConstValue};
debug!("collect_roots: entry_fn = {:?}", entry_fn);
- let mut visitor = RootCollector { tcx, mode, entry_fn, output: &mut roots };
+ let mut collector = RootCollector { tcx, mode, entry_fn, output: &mut roots };
- tcx.hir().visit_all_item_likes(&mut visitor);
+ let crate_items = tcx.hir_crate_items(());
- visitor.push_extra_entry_roots();
+ for id in crate_items.items() {
+ collector.process_item(id);
+ }
+
+ for id in crate_items.impl_items() {
+ collector.process_impl_item(id);
+ }
+
+ collector.push_extra_entry_roots();
}
// We can only codegen items that are instantiable - items all of
// are supported. Therefore the value should not
// depend on any other items.
}
- _ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
+ hir::InlineAsmOperand::SymFn { anon_const } => {
+ let def_id = tcx.hir().body_owner_def_id(anon_const.body).to_def_id();
+ if let Ok(val) = tcx.const_eval_poly(def_id) {
+ rustc_data_structures::stack::ensure_sufficient_stack(|| {
+ collect_const_value(tcx, val, &mut neighbors);
+ });
+ }
+ }
+ hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
+ let instance = Instance::mono(tcx, *def_id);
+ if should_codegen_locally(tcx, &instance) {
+ trace!("collecting static {:?}", def_id);
+ neighbors.push(dummy_spanned(MonoItem::Static(*def_id)));
+ }
+ }
+ hir::InlineAsmOperand::In { .. }
+ | hir::InlineAsmOperand::Out { .. }
+ | hir::InlineAsmOperand::InOut { .. }
+ | hir::InlineAsmOperand::SplitInOut { .. } => {
+ span_bug!(*op_sp, "invalid operand type for global_asm!")
+ }
}
}
} else {
entry_fn: Option<(DefId, EntryFnType)>,
}
-impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
- fn visit_item(&mut self, item: &'v hir::Item<'v>) {
- match item.kind {
- hir::ItemKind::ExternCrate(..)
- | hir::ItemKind::Use(..)
- | hir::ItemKind::Macro(..)
- | hir::ItemKind::ForeignMod { .. }
- | hir::ItemKind::TyAlias(..)
- | hir::ItemKind::Trait(..)
- | hir::ItemKind::TraitAlias(..)
- | hir::ItemKind::OpaqueTy(..)
- | hir::ItemKind::Mod(..) => {
- // Nothing to do, just keep recursing.
- }
-
- hir::ItemKind::Impl { .. } => {
- if self.mode == MonoItemCollectionMode::Eager {
- create_mono_items_for_default_impls(self.tcx, item, self.output);
- }
- }
-
- hir::ItemKind::Enum(_, ref generics)
- | hir::ItemKind::Struct(_, ref generics)
- | hir::ItemKind::Union(_, ref generics) => {
- if generics.params.is_empty() {
- if self.mode == MonoItemCollectionMode::Eager {
- debug!(
- "RootCollector: ADT drop-glue for {}",
- self.tcx.def_path_str(item.def_id.to_def_id())
- );
-
- let ty = Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
- .ty(self.tcx, ty::ParamEnv::reveal_all());
- visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+impl<'v> RootCollector<'_, 'v> {
+ fn process_item(&mut self, id: hir::ItemId) {
+ match self.tcx.hir().def_kind(id.def_id) {
+ DefKind::Enum | DefKind::Struct | DefKind::Union => {
+ let item = self.tcx.hir().item(id);
+ match item.kind {
+ hir::ItemKind::Enum(_, ref generics)
+ | hir::ItemKind::Struct(_, ref generics)
+ | hir::ItemKind::Union(_, ref generics) => {
+ if generics.params.is_empty() {
+ if self.mode == MonoItemCollectionMode::Eager {
+ debug!(
+ "RootCollector: ADT drop-glue for {}",
+ self.tcx.def_path_str(item.def_id.to_def_id())
+ );
+
+ let ty =
+ Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
+ .ty(self.tcx, ty::ParamEnv::reveal_all());
+ visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
+ }
+ }
}
+ _ => bug!(),
}
}
- hir::ItemKind::GlobalAsm(..) => {
+ DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(id.def_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::GlobalAsm(item.item_id())));
+ self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
}
- hir::ItemKind::Static(..) => {
+ DefKind::Static(..) => {
debug!(
"RootCollector: ItemKind::Static({})",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(id.def_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::Static(item.def_id.to_def_id())));
+ self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id())));
}
- hir::ItemKind::Const(..) => {
+ DefKind::Const => {
// const items only generate mono items if they are
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- if let Ok(val) = self.tcx.const_eval_poly(item.def_id.to_def_id()) {
+ if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) {
collect_const_value(self.tcx, val, &mut self.output);
}
}
- hir::ItemKind::Fn(..) => {
- self.push_if_root(item.def_id);
+ DefKind::Impl => {
+ if self.mode == MonoItemCollectionMode::Eager {
+ let item = self.tcx.hir().item(id);
+ create_mono_items_for_default_impls(self.tcx, item, self.output);
+ }
+ }
+ DefKind::Fn => {
+ self.push_if_root(id.def_id);
}
+ _ => {}
}
}
- fn visit_trait_item(&mut self, _: &'v hir::TraitItem<'v>) {
- // Even if there's a default body with no explicit generics,
- // it's still generic over some `Self: Trait`, so not a root.
- }
-
- fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
- if let hir::ImplItemKind::Fn(hir::FnSig { .. }, _) = ii.kind {
- self.push_if_root(ii.def_id);
+ fn process_impl_item(&mut self, id: hir::ImplItemId) {
+ if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) {
+ self.push_if_root(id.def_id);
}
}
- fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {}
-}
-
-impl<'v> RootCollector<'_, 'v> {
fn is_root(&self, def_id: LocalDefId) -> bool {
!item_requires_monomorphization(self.tcx, def_id)
&& match self.mode {
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathDataName;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::SymbolExportLevel;
let mut cgu_def_id = None;
// Walk backwards from the item we want to find the module for.
loop {
- if current_def_id.index == CRATE_DEF_INDEX {
+ if current_def_id.is_crate_root() {
if cgu_def_id.is_none() {
// If we have not found a module yet, take the crate root.
- cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX });
+ cgu_def_id = Some(def_id.krate.as_def_id());
}
break;
} else if tcx.def_kind(current_def_id) == DefKind::Mod {
}
rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
if !terminated {
- let msg = match doc_style {
- Some(_) => "unterminated block doc-comment",
- None => "unterminated block comment",
- };
- let last_bpos = self.pos;
- self.sess.span_diagnostic.span_fatal_with_code(
- self.mk_sp(start, last_bpos),
- msg,
- error_code!(E0758),
- );
+ self.report_unterminated_block_comment(start, doc_style);
}
// Skip non-doc comments
err.emit()
}
+ fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option<DocStyle>) {
+ let msg = match doc_style {
+ Some(_) => "unterminated block doc-comment",
+ None => "unterminated block comment",
+ };
+ let last_bpos = self.pos;
+ let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code(
+ self.mk_sp(start, last_bpos),
+ msg,
+ error_code!(E0758),
+ );
+ let mut nested_block_comment_open_idxs = vec![];
+ let mut last_nested_block_comment_idxs = None;
+ let mut content_chars = self.str_from(start).char_indices().peekable();
+
+ while let Some((idx, current_char)) = content_chars.next() {
+ match content_chars.peek() {
+ Some((_, '*')) if current_char == '/' => {
+ nested_block_comment_open_idxs.push(idx);
+ }
+ Some((_, '/')) if current_char == '*' => {
+ last_nested_block_comment_idxs =
+ nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx));
+ }
+ _ => {}
+ };
+ }
+
+ if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs {
+ err.span_label(self.mk_sp(start, start + BytePos(2)), msg)
+ .span_label(
+ self.mk_sp(
+ start + BytePos(nested_open_idx as u32),
+ start + BytePos(nested_open_idx as u32 + 2),
+ ),
+ "...as last nested comment starts here, maybe you want to close this instead?",
+ )
+ .span_label(
+ self.mk_sp(
+ start + BytePos(nested_close_idx as u32),
+ start + BytePos(nested_close_idx as u32 + 2),
+ ),
+ "...and last nested comment terminates here.",
+ );
+ }
+
+ err.emit();
+ }
+
// RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
// using a (unknown) prefix is an error. In earlier editions, however, they
// only result in a (allowed by default) lint, and are treated as regular
impl CreateTokenStream for LazyTokenStreamImpl {
fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
- // The token produced by the final call to `{,inlined_}next` or
- // `{,inlined_}next_desugared` was not actually consumed by the
- // callback. The combination of chaining the initial token and using
- // `take` produces the desired result - we produce an empty
- // `TokenStream` if no calls were made, and omit the final token
- // otherwise.
+ // The token produced by the final call to `{,inlined_}next` was not
+ // actually consumed by the callback. The combination of chaining the
+ // initial token and using `take` produces the desired result - we
+ // produce an empty `TokenStream` if no calls were made, and omit the
+ // final token otherwise.
let mut cursor_snapshot = self.cursor_snapshot.clone();
let tokens =
std::iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1))
.chain((0..self.num_calls).map(|_| {
- let token = if cursor_snapshot.desugar_doc_comments {
- cursor_snapshot.next_desugared()
- } else {
- cursor_snapshot.next()
- };
+ let token = cursor_snapshot.next(cursor_snapshot.desugar_doc_comments);
(FlatToken::Token(token.0), token.1)
}))
.take(self.num_calls);
pub capture_cfg: bool,
restrictions: Restrictions,
expected_tokens: Vec<TokenType>,
- // Important: This must only be advanced from `next_tok`
- // to ensure that `token_cursor.num_next_calls` is updated properly
+ // Important: This must only be advanced from `bump` to ensure that
+ // `token_cursor.num_next_calls` is updated properly.
token_cursor: TokenCursor,
desugar_doc_comments: bool,
/// This field is used to keep track of how many left angle brackets we have seen. This is
pub current_closure: Option<ClosureSpans>,
}
+// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
+// it doesn't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Parser<'_>, 328);
+
/// Stores span information about a closure.
#[derive(Clone)]
pub struct ClosureSpans {
#[derive(Clone)]
struct TokenCursor {
+ // The current (innermost) frame. `frame` and `stack` could be combined,
+ // but it's faster to have them separately to access `frame` directly
+ // rather than via something like `stack.last().unwrap()` or
+ // `stack[stack.len() - 1]`.
frame: TokenCursorFrame,
+ // Additional frames that enclose `frame`.
stack: Vec<TokenCursorFrame>,
desugar_doc_comments: bool,
- // Counts the number of calls to `{,inlined_}next` or
- // `{,inlined_}next_desugared`, depending on whether
- // `desugar_doc_comments` is set.
+ // Counts the number of calls to `{,inlined_}next`.
num_next_calls: usize,
// During parsing, we may sometimes need to 'unglue' a
// glued token into two component tokens
struct TokenCursorFrame {
delim: token::DelimToken,
span: DelimSpan,
- open_delim: bool,
tree_cursor: tokenstream::Cursor,
- close_delim: bool,
}
impl TokenCursorFrame {
fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
- TokenCursorFrame {
- delim,
- span,
- open_delim: false,
- tree_cursor: tts.into_trees(),
- close_delim: false,
- }
+ TokenCursorFrame { delim, span, tree_cursor: tts.into_trees() }
}
}
impl TokenCursor {
- fn next(&mut self) -> (Token, Spacing) {
- self.inlined_next()
+ fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
+ self.inlined_next(desugar_doc_comments)
}
/// This always-inlined version should only be used on hot code paths.
#[inline(always)]
- fn inlined_next(&mut self) -> (Token, Spacing) {
+ fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
loop {
- let (tree, spacing) = if !self.frame.open_delim {
- self.frame.open_delim = true;
- TokenTree::open_tt(self.frame.span, self.frame.delim).into()
- } else if let Some(tree) = self.frame.tree_cursor.next_with_spacing() {
- tree
- } else if !self.frame.close_delim {
- self.frame.close_delim = true;
- TokenTree::close_tt(self.frame.span, self.frame.delim).into()
+ // FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will
+ // need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be
+ // removed, as well as the loop.
+ if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing_ref() {
+ match tree {
+ &TokenTree::Token(ref token) => match (desugar_doc_comments, token) {
+ (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
+ return self.desugar(attr_style, data, span);
+ }
+ _ => return (token.clone(), *spacing),
+ },
+ &TokenTree::Delimited(sp, delim, ref tts) => {
+ // Set `open_delim` to true here because we deal with it immediately.
+ let frame = TokenCursorFrame::new(sp, delim, tts.clone());
+ self.stack.push(mem::replace(&mut self.frame, frame));
+ if delim != DelimToken::NoDelim {
+ return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
+ }
+ // No open delimeter to return; continue on to the next iteration.
+ }
+ };
} else if let Some(frame) = self.stack.pop() {
+ let delim = self.frame.delim;
+ let span = self.frame.span;
self.frame = frame;
- continue;
- } else {
- (TokenTree::Token(Token::new(token::Eof, DUMMY_SP)), Spacing::Alone)
- };
-
- match tree {
- TokenTree::Token(token) => {
- return (token, spacing);
- }
- TokenTree::Delimited(sp, delim, tts) => {
- let frame = TokenCursorFrame::new(sp, delim, tts);
- self.stack.push(mem::replace(&mut self.frame, frame));
+ if delim != DelimToken::NoDelim {
+ return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
}
+ // No close delimiter to return; continue on to the next iteration.
+ } else {
+ return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
}
}
}
- fn next_desugared(&mut self) -> (Token, Spacing) {
- self.inlined_next_desugared()
- }
-
- /// This always-inlined version should only be used on hot code paths.
- #[inline(always)]
- fn inlined_next_desugared(&mut self) -> (Token, Spacing) {
- let (data, attr_style, sp) = match self.inlined_next() {
- (Token { kind: token::DocComment(_, attr_style, data), span }, _) => {
- (data, attr_style, span)
- }
- tok => return tok,
- };
-
+ fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
// required to wrap the text.
let mut num_of_hashes = 0;
num_of_hashes = cmp::max(num_of_hashes, count);
}
- let delim_span = DelimSpan::from_single(sp);
+ let delim_span = DelimSpan::from_single(span);
let body = TokenTree::Delimited(
delim_span,
token::Bracket,
[
- TokenTree::token(token::Ident(sym::doc, false), sp),
- TokenTree::token(token::Eq, sp),
- TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), sp),
+ TokenTree::token(token::Ident(sym::doc, false), span),
+ TokenTree::token(token::Eq, span),
+ TokenTree::token(TokenKind::lit(token::StrRaw(num_of_hashes), data, None), span),
]
.iter()
.cloned()
delim_span,
token::NoDelim,
if attr_style == AttrStyle::Inner {
- [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body]
+ [TokenTree::token(token::Pound, span), TokenTree::token(token::Not, span), body]
.iter()
.cloned()
.collect::<TokenStream>()
} else {
- [TokenTree::token(token::Pound, sp), body]
+ [TokenTree::token(token::Pound, span), body]
.iter()
.cloned()
.collect::<TokenStream>()
),
));
- self.next()
+ self.next(/* desugar_doc_comments */ false)
}
}
desugar_doc_comments: bool,
subparser_name: Option<&'static str>,
) -> Self {
- let mut start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
- start_frame.open_delim = true;
- start_frame.close_delim = true;
+ // Note: because of the way `TokenCursor::inlined_next` is structured, the `span` and
+ // `delim` arguments here are never used.
+ let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
let mut parser = Parser {
sess,
parser
}
- #[inline]
- fn next_tok(&mut self, fallback_span: Span) -> (Token, Spacing) {
- loop {
- let (mut next, spacing) = if self.desugar_doc_comments {
- self.token_cursor.inlined_next_desugared()
- } else {
- self.token_cursor.inlined_next()
- };
- self.token_cursor.num_next_calls += 1;
- // We've retrieved an token from the underlying
- // cursor, so we no longer need to worry about
- // an unglued token. See `break_and_eat` for more details
- self.token_cursor.break_last_token = false;
- if next.span.is_dummy() {
- // Tweak the location for better diagnostics, but keep syntactic context intact.
- next.span = fallback_span.with_ctxt(next.span.ctxt());
- }
- if matches!(
- next.kind,
- token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
- ) {
- continue;
- }
- return (next, spacing);
- }
- }
-
pub fn unexpected<T>(&mut self) -> PResult<'a, T> {
match self.expect_one_of(&[], &[]) {
Err(e) => Err(e),
//
// If we consume any additional tokens, then this token
// is not needed (we'll capture the entire 'glued' token),
- // and `next_tok` will set this field to `None`
+ // and `bump` will set this field to `None`
self.token_cursor.break_last_token = true;
// Use the spacing of the glued token as the spacing
// of the unglued second token.
/// This always-inlined version should only be used on hot code paths.
#[inline(always)]
fn inlined_bump_with(&mut self, (next_token, next_spacing): (Token, Spacing)) {
- // Bumping after EOF is a bad sign, usually an infinite loop.
- if self.prev_token.kind == TokenKind::Eof {
- let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
- self.span_bug(self.token.span, msg);
- }
-
// Update the current and previous tokens.
self.prev_token = mem::replace(&mut self.token, next_token);
self.token_spacing = next_spacing;
/// Advance the parser by one token.
pub fn bump(&mut self) {
- let next_token = self.next_tok(self.token.span);
- self.inlined_bump_with(next_token);
+ // Note: destructuring here would give nicer code, but it was found in #96210 to be slower
+ // than `.0`/`.1` access.
+ let mut next = self.token_cursor.inlined_next(self.desugar_doc_comments);
+ self.token_cursor.num_next_calls += 1;
+ // We've retrieved an token from the underlying
+ // cursor, so we no longer need to worry about
+ // an unglued token. See `break_and_eat` for more details
+ self.token_cursor.break_last_token = false;
+ if next.0.span.is_dummy() {
+ // Tweak the location for better diagnostics, but keep syntactic context intact.
+ let fallback_span = self.token.span;
+ next.0.span = fallback_span.with_ctxt(next.0.span.ctxt());
+ }
+ debug_assert!(!matches!(
+ next.0.kind,
+ token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
+ ));
+ self.inlined_bump_with(next)
}
/// Look-ahead `dist` tokens of `self.token` and get access to that token there.
let mut i = 0;
let mut token = Token::dummy();
while i < dist {
- token = cursor.next().0;
+ token = cursor.next(/* desugar_doc_comments */ false).0;
if matches!(
token.kind,
token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
self.sess.gated_spans.gate(sym::inline_const, span);
}
self.eat_keyword(kw::Const);
- let blk = self.parse_block()?;
+ let (attrs, blk) = self.parse_inner_attrs_and_block()?;
let anon_const = AnonConst {
id: DUMMY_NODE_ID,
value: self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()),
};
let blk_span = anon_const.value.span;
- Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::new()))
+ Ok(self.mk_expr(span.to(blk_span), ExprKind::ConstBlock(anon_const), AttrVec::from(attrs)))
}
/// Parses mutability (`mut` or nothing).
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
match self.token.kind {
token::OpenDelim(..) => {
- let depth = self.token_cursor.stack.len();
+ // Grab the tokens from this frame.
+ let frame = &self.token_cursor.frame;
+ let stream = frame.tree_cursor.stream.clone();
+ let span = frame.span;
+ let delim = frame.delim;
- // We keep advancing the token cursor until we hit
- // the matching `CloseDelim` token.
- while !(depth == self.token_cursor.stack.len()
- && matches!(self.token.kind, token::CloseDelim(_)))
- {
+ // Advance the token cursor through the entire delimited
+ // sequence. After getting the `OpenDelim` we are *within* the
+ // delimited sequence, i.e. at depth `d`. After getting the
+ // matching `CloseDelim` we are *after* the delimited sequence,
+ // i.e. at depth `d - 1`.
+ let target_depth = self.token_cursor.stack.len() - 1;
+ loop {
// Advance one token at a time, so `TokenCursor::next()`
// can capture these tokens if necessary.
self.bump();
+ if self.token_cursor.stack.len() == target_depth {
+ debug_assert!(matches!(self.token.kind, token::CloseDelim(_)));
+ break;
+ }
}
- // We are still inside the frame corresponding
- // to the delimited stream we captured, so grab
- // the tokens from this frame.
- let frame = &self.token_cursor.frame;
- let stream = frame.tree_cursor.stream.clone();
- let span = frame.span;
- let delim = frame.delim;
+
// Consume close delimiter
self.bump();
TokenTree::Delimited(span, delim, stream)
impl<'a> Parser<'a> {
/// Checks whether a non-terminal may begin with a particular token.
///
- /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
- /// token. Be conservative (return true) if not sure.
+ /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with
+ /// that token. Be conservative (return true) if not sure. Inlined because it has a single call
+ /// site.
+ #[inline]
pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
/// Checks whether the non-terminal may contain a single (non-keyword) identifier.
fn may_be_ident(nt: &token::Nonterminal) -> bool {
}
}
- /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
+ /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
+ /// site.
+ #[inline]
pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
// Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
// needs to have them force-captured here.
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
let whole_span = lo.to(self.prev_token.span);
if let ast::Const::Yes(span) = constness {
+ // If we ever start to allow `const fn()`, then update
+ // feature gating for `#![feature(const_extern_fn)]` to
+ // cover it.
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
}
if let ast::Async::Yes { span, .. } = asyncness {
self.check_rustc_must_implement_one_of(attr, span, target)
}
sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
+ sym::thread_local => self.check_thread_local(attr, span, target),
sym::track_caller => {
self.check_track_caller(hir_id, attr.span, attrs, span, target)
}
}
}
+ /// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid.
+ fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ match target {
+ Target::ForeignStatic | Target::Static => true,
+ _ => {
+ self.tcx
+ .sess
+ .struct_span_err(attr.span, "attribute should be applied to a static")
+ .span_label(span, "not a static")
+ .emit();
+ false
+ }
+ }
+ }
+
fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) {
self.tcx
.sess
live_symbols: FxHashSet<LocalDefId>,
repr_has_repr_c: bool,
in_pat: bool,
- inherited_pub_visibility: bool,
- pub_visibility: bool,
ignore_variant_stack: Vec<DefId>,
// maps from tuple struct constructors to tuple struct items
struct_constructors: FxHashMap<LocalDefId, LocalDefId>,
}
let had_repr_c = self.repr_has_repr_c;
- let had_inherited_pub_visibility = self.inherited_pub_visibility;
- let had_pub_visibility = self.pub_visibility;
self.repr_has_repr_c = false;
- self.inherited_pub_visibility = false;
- self.pub_visibility = false;
match node {
- Node::Item(item) => {
- self.pub_visibility = item.vis.node.is_pub();
+ Node::Item(item) => match item.kind {
+ hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
+ let def = self.tcx.adt_def(item.def_id);
+ self.repr_has_repr_c = def.repr().c();
- match item.kind {
- hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- let def = self.tcx.adt_def(item.def_id);
- self.repr_has_repr_c = def.repr().c();
-
- intravisit::walk_item(self, &item);
- }
- hir::ItemKind::Enum(..) => {
- self.inherited_pub_visibility = self.pub_visibility;
-
- intravisit::walk_item(self, &item);
- }
- hir::ItemKind::ForeignMod { .. } => {}
- _ => {
- intravisit::walk_item(self, &item);
- }
+ intravisit::walk_item(self, &item);
}
- }
+ hir::ItemKind::Enum(..) => {
+ intravisit::walk_item(self, &item);
+ }
+ hir::ItemKind::ForeignMod { .. } => {}
+ _ => {
+ intravisit::walk_item(self, &item);
+ }
+ },
Node::TraitItem(trait_item) => {
intravisit::walk_trait_item(self, trait_item);
}
}
_ => {}
}
- self.pub_visibility = had_pub_visibility;
- self.inherited_pub_visibility = had_inherited_pub_visibility;
self.repr_has_repr_c = had_repr_c;
}
_: hir::HirId,
_: rustc_span::Span,
) {
+ let tcx = self.tcx;
let has_repr_c = self.repr_has_repr_c;
- let inherited_pub_visibility = self.inherited_pub_visibility;
- let pub_visibility = self.pub_visibility;
- let live_fields = def.fields().iter().filter(|f| {
- has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub()))
+ let live_fields = def.fields().iter().filter_map(|f| {
+ let def_id = tcx.hir().local_def_id(f.hir_id);
+ if has_repr_c {
+ return Some(def_id);
+ }
+ if !tcx.visibility(f.hir_id.owner).is_public() {
+ return None;
+ }
+ if tcx.visibility(def_id).is_public() { Some(def_id) } else { None }
});
- let hir = self.tcx.hir();
- self.live_symbols.extend(live_fields.map(|f| hir.local_def_id(f.hir_id)));
+ self.live_symbols.extend(live_fields);
intravisit::walk_struct_def(self, def);
}
.insert(self.tcx.hir().local_def_id(ctor_hir_id), item.def_id);
}
}
+ hir::ItemKind::GlobalAsm(_) => {
+ // global_asm! is always live.
+ self.worklist.push(item.def_id);
+ }
_ => (),
}
}
live_symbols: Default::default(),
repr_has_repr_c: false,
in_pat: false,
- inherited_pub_visibility: false,
- pub_visibility: false,
ignore_variant_stack: vec![],
struct_constructors,
ignored_derived_traits: FxHashMap::default(),
use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err;
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{ForeignItem, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID};
-use rustc_middle::hir::map::Map;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::config::{CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
-struct EntryContext<'a, 'tcx> {
- session: &'a Session,
-
- map: Map<'tcx>,
+struct EntryContext<'tcx> {
+ tcx: TyCtxt<'tcx>,
/// The function that has attribute named `main`.
attr_main_fn: Option<(LocalDefId, Span)>,
non_main_fns: Vec<Span>,
}
-impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
+impl<'tcx> ItemLikeVisitor<'tcx> for EntryContext<'tcx> {
fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
- let def_key = self.map.def_key(item.def_id);
- let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
+ let at_root = self.tcx.local_parent(item.def_id) == Some(CRATE_DEF_ID);
find_item(item, self, at_root);
}
return None;
}
- let mut ctxt = EntryContext {
- session: tcx.sess,
- map: tcx.hir(),
- attr_main_fn: None,
- start_fn: None,
- non_main_fns: Vec::new(),
- };
+ let mut ctxt =
+ EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() };
tcx.hir().visit_all_item_likes(&mut ctxt);
// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
// (with `ast::Item`), so make sure to keep them in sync.
-fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) -> EntryPointType {
- let attrs = ctxt.map.attrs(item.hir_id());
- if ctxt.session.contains_name(attrs, sym::start) {
+fn entry_point_type(ctxt: &EntryContext<'_>, item: &Item<'_>, at_root: bool) -> EntryPointType {
+ let attrs = ctxt.tcx.hir().attrs(item.hir_id());
+ if ctxt.tcx.sess.contains_name(attrs, sym::start) {
EntryPointType::Start
- } else if ctxt.session.contains_name(attrs, sym::rustc_main) {
+ } else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) {
EntryPointType::MainAttr
} else if item.ident.name == sym::main {
if at_root {
.emit();
}
-fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
+fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_>, at_root: bool) {
match entry_point_type(ctxt, item, at_root) {
EntryPointType::None => (),
_ if !matches!(item.kind, ItemKind::Fn(..)) => {
- let attrs = ctxt.map.attrs(item.hir_id());
- if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) {
- throw_attr_err(&ctxt.session, attr.span, "start");
+ let attrs = ctxt.tcx.hir().attrs(item.hir_id());
+ if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::start) {
+ throw_attr_err(&ctxt.tcx.sess, attr.span, "start");
}
- if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) {
- throw_attr_err(&ctxt.session, attr.span, "rustc_main");
+ if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym::rustc_main) {
+ throw_attr_err(&ctxt.tcx.sess, attr.span, "rustc_main");
}
}
EntryPointType::MainNamed => (),
ctxt.attr_main_fn = Some((item.def_id, item.span));
} else {
struct_span_err!(
- ctxt.session,
+ ctxt.tcx.sess,
item.span,
E0137,
"multiple functions with a `#[main]` attribute"
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((item.def_id, item.span));
} else {
- struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
+ struct_span_err!(ctxt.tcx.sess, item.span, E0138, "multiple `start` functions")
.span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
.span_label(item.span, "multiple `start` functions")
.emit();
}
}
-fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(DefId, EntryFnType)> {
+fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
if let Some((def_id, _)) = visitor.start_fn {
Some((def_id.to_def_id(), EntryFnType::Start))
} else if let Some((def_id, _)) = visitor.attr_main_fn {
}
}
-fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
+fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
let sp = tcx.def_span(CRATE_DEF_ID);
if *tcx.sess.parse_sess.reached_eof.borrow() {
// There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lock;
use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{HirId, ItemLocalId};
self.owner = Some(owner);
walk(self);
- if owner.local_def_index == CRATE_DEF_INDEX {
+ if owner == CRATE_DEF_ID {
return;
}
+use hir::intravisit::walk_inline_asm;
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::struct_span_err;
);
}
}
- hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {}
+ // These are checked in ItemVisitor.
+ hir::InlineAsmOperand::Const { .. }
+ | hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
}
ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body);
self.visit_body(body);
}
+
+ fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
+ for (op, op_sp) in asm.operands.iter() {
+ match *op {
+ // These are checked in ExprVisitor.
+ hir::InlineAsmOperand::In { .. }
+ | hir::InlineAsmOperand::Out { .. }
+ | hir::InlineAsmOperand::InOut { .. }
+ | hir::InlineAsmOperand::SplitInOut { .. } => {}
+ // No special checking is needed for these:
+ // - Typeck has checked that Const operands are integers.
+ // - AST lowering guarantees that SymStatic points to a static.
+ hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {}
+ // Check that sym actually points to a function. Later passes
+ // depend on this.
+ hir::InlineAsmOperand::SymFn { anon_const } => {
+ let ty = self.tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+ match ty.kind() {
+ ty::Never | ty::Error(_) => {}
+ ty::FnDef(..) => {}
+ _ => {
+ let mut err =
+ self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
+ err.span_label(
+ self.tcx.hir().span(anon_const.body.hir_id),
+ &format!("is {} `{}`", ty.kind().article(), ty),
+ );
+ err.help("`sym` operands must refer to either a function or a static");
+ err.emit();
+ }
+ };
+ }
+ }
+ }
+ walk_inline_asm(self, asm, id);
+ }
}
impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> {
use rustc_errors::{pluralize, struct_span_err};
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
tcx: TyCtxt<'tcx>,
}
-impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- self.check_for_lang(Target::from_item(item), item.hir_id());
-
- if let hir::ItemKind::Enum(def, ..) = &item.kind {
- for variant in def.variants {
- self.check_for_lang(Target::Variant, variant.id);
- }
- }
- }
-
- fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
- self.check_for_lang(Target::from_trait_item(trait_item), trait_item.hir_id())
- }
-
- fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
- self.check_for_lang(target_from_impl_item(self.tcx, impl_item), impl_item.hir_id())
- }
-
- fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
-}
-
impl<'tcx> LanguageItemCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> {
LanguageItemCollector { tcx, items: LanguageItems::new() }
}
// Collect lang items in this crate.
- tcx.hir().visit_all_item_likes(&mut collector);
+ let crate_items = tcx.hir_crate_items(());
+
+ for id in crate_items.items() {
+ collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id());
+
+ if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) {
+ let item = tcx.hir().item(id);
+ if let hir::ItemKind::Enum(def, ..) = &item.kind {
+ for variant in def.variants {
+ collector.check_for_lang(Target::Variant, variant.id);
+ }
+ }
+ }
+ }
+
+ // FIXME: avoid calling trait_item() when possible
+ for id in crate_items.trait_items() {
+ let item = tcx.hir().trait_item(id);
+ collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
+ }
+
+ // FIXME: avoid calling impl_item() when possible
+ for id in crate_items.impl_items() {
+ let item = tcx.hir().impl_item(id);
+ collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
+ }
// Extract out the found lang items.
let LanguageItemCollector { mut items, .. } = collector;
match op {
hir::InlineAsmOperand::In { .. }
| hir::InlineAsmOperand::Const { .. }
- | hir::InlineAsmOperand::Sym { .. } => {}
+ | hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {}
hir::InlineAsmOperand::Out { expr, .. } => {
if let Some(expr) = expr {
succ = self.write_place(expr, succ, ACC_WRITE);
let mut succ = succ;
for (op, _op_sp) in asm.operands.iter().rev() {
match op {
- hir::InlineAsmOperand::In { expr, .. }
- | hir::InlineAsmOperand::Sym { expr, .. } => {
+ hir::InlineAsmOperand::In { expr, .. } => {
succ = self.propagate_through_expr(expr, succ)
}
hir::InlineAsmOperand::Out { expr, .. } => {
}
succ = self.propagate_through_expr(in_expr, succ);
}
- hir::InlineAsmOperand::Const { .. } => {}
+ hir::InlineAsmOperand::Const { .. }
+ | hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
succ
.operands
.iter()
.filter_map(|&(ref op, op_sp)| match op {
- InlineAsmOperand::Const { .. } | InlineAsmOperand::Sym { .. } => None,
+ InlineAsmOperand::Const { .. }
+ | InlineAsmOperand::SymFn { .. }
+ | InlineAsmOperand::SymStatic { .. } => None,
InlineAsmOperand::In { .. }
| InlineAsmOperand::Out { .. }
| InlineAsmOperand::InOut { .. }
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else {
return;
};
- let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+ let def_id = cnum.as_def_id();
self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None);
}
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
-use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
use rustc_middle::middle::lang_items::required;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-
-struct Context<'a, 'tcx> {
- tcx: TyCtxt<'tcx>,
- items: &'a mut lang_items::LanguageItems,
-}
/// Checks the crate for usage of weak lang items, returning a vector of all the
/// language items required by this crate, but not defined yet.
items.missing.push(LangItem::EhCatchTypeinfo);
}
- {
- let mut cx = Context { tcx, items };
- tcx.hir().visit_all_item_likes(&mut cx.as_deep_visitor());
+ let crate_items = tcx.hir_crate_items(());
+ for id in crate_items.foreign_items() {
+ let attrs = tcx.hir().attrs(id.hir_id());
+ if let Some((lang_item, _)) = lang_items::extract(attrs) {
+ if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
+ if items.require(item).is_err() {
+ items.missing.push(item);
+ }
+ } else {
+ let span = tcx.def_span(id.def_id);
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0264,
+ "unknown external lang item: `{}`",
+ lang_item
+ )
+ .emit();
+ }
+ }
}
+
verify(tcx, items);
}
}
}
}
-
-impl<'a, 'tcx> Context<'a, 'tcx> {
- fn register(&mut self, name: Symbol, span: Span) {
- if let Some(&item) = WEAK_ITEMS_REFS.get(&name) {
- if self.items.require(item).is_err() {
- self.items.missing.push(item);
- }
- } else {
- struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name)
- .emit();
- }
- }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
- fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
- let attrs = self.tcx.hir().attrs(i.hir_id());
- if let Some((lang_item, _)) = lang_items::extract(attrs) {
- self.register(lang_item, i.span);
- }
- intravisit::walk_foreign_item(self, i)
- }
-}
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
}
-////////////////////////////////////////////////////////////////////////////////
-/// Visitor used to determine if pub(restricted) is used anywhere in the crate.
-///
-/// This is done so that `private_in_public` warnings can be turned into hard errors
-/// in crates that have been updated to use pub(restricted).
-////////////////////////////////////////////////////////////////////////////////
-struct PubRestrictedVisitor<'tcx> {
- tcx: TyCtxt<'tcx>,
- has_pub_restricted: bool,
-}
-
-impl<'tcx> Visitor<'tcx> for PubRestrictedVisitor<'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
- fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) {
- self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted();
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
/// Visitor used to determine impl visibility and reachability.
////////////////////////////////////////////////////////////////////////////////
self.update_with_hir_id(ctor_hir_id, item_level);
}
for field in def.fields() {
- if field.vis.node.is_pub() {
+ let def_id = self.tcx.hir().local_def_id(field.hir_id);
+ let vis = self.tcx.visibility(def_id);
+ if vis.is_public() {
self.update_with_hir_id(field.hir_id, item_level);
}
}
// .. and it corresponds to a private type in the AST (this returns
// `None` for type parameters).
match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) {
- Some(Node::Item(item)) => !item.vis.node.is_pub(),
+ Some(Node::Item(_)) => !self.tcx.visibility(did).is_public(),
Some(_) | None => false,
}
} else {
}
}
- fn item_is_public(&self, def_id: LocalDefId, vis: &hir::Visibility<'_>) -> bool {
- self.access_levels.is_reachable(def_id) || vis.node.is_pub()
+ fn item_is_public(&self, def_id: LocalDefId) -> bool {
+ self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
}
}
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item.kind {
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
- if self
- .item_is_public(impl_item.def_id, &impl_item.vis) =>
+ if self.item_is_public(impl_item.def_id) =>
{
intravisit::walk_impl_item(self, impl_item)
}
hir::ItemKind::TyAlias(..) => return,
// Not at all public, so we don't care.
- _ if !self.item_is_public(item.def_id, &item.vis) => {
+ _ if !self.item_is_public(item.def_id) => {
return;
}
}
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
- if s.vis.node.is_pub() || self.in_variant {
+ let def_id = self.tcx.hir().local_def_id(s.hir_id);
+ let vis = self.tcx.visibility(def_id);
+ if vis.is_public() || self.in_variant {
intravisit::walk_field_def(self, s);
}
}
item_def_id: LocalDefId,
/// The visitor checks that each component type is at least this visible.
required_visibility: ty::Visibility,
- has_pub_restricted: bool,
has_old_errors: bool,
in_assoc_ty: bool,
}
};
let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
let span = self.tcx.def_span(self.item_def_id.to_def_id());
- if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
+ if self.has_old_errors
+ || self.in_assoc_ty
+ || self.tcx.resolutions(()).has_pub_restricted
+ {
let mut err = if kind == "trait" {
struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
} else {
struct PrivateItemsInPublicInterfacesVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
- has_pub_restricted: bool,
old_error_set_ancestry: LocalDefIdSet,
}
tcx: self.tcx,
item_def_id: def_id,
required_visibility,
- has_pub_restricted: self.has_pub_restricted,
has_old_errors: self.old_error_set_ancestry.contains(&def_id),
in_assoc_ty: false,
}
match tcx.hir().get(hir_id) {
// Unique types created for closures participate in type privacy checking.
// They have visibilities inherited from the module they are defined in.
- Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
- ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id())
- }
- // - AST lowering may clone `use` items and the clones don't
+ Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. })
+ // - AST lowering creates dummy `use` items which don't
// get their entries in the resolver's visibility table.
// - AST lowering also creates opaque type items with inherited visibilities.
// Visibility on them should have no effect, but to avoid the visibility
// query failing on some items, we provide it for opaque types as well.
- Node::Item(hir::Item {
- vis,
- kind: hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..),
+ | Node::Item(hir::Item {
+ kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..),
..
- }) => ty::Visibility::from_hir(vis, hir_id, tcx),
+ }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_def_id()),
// Visibilities of trait impl items are inherited from their traits
// and are not filled in resolve.
Node::ImplItem(impl_item) => {
};
tcx.hir().walk_toplevel_module(&mut visitor);
- let has_pub_restricted = {
- let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false };
- tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor);
- pub_restricted_visitor.has_pub_restricted
- };
-
let mut old_error_set_ancestry = HirIdSet::default();
for mut id in visitor.old_error_set.iter().copied() {
loop {
// Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx,
- has_pub_restricted,
// Only definition IDs are ever searched in `old_error_set_ancestry`,
// so we can filter away all non-definition IDs at this point.
old_error_set_ancestry: old_error_set_ancestry
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_middle::ty::{TyCtxt, WithOptConstParam};
use rustc_query_system::query::QueryCache;
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId {
- builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
+ builder.def_id_to_string_id(self.as_def_id())
}
}
use rustc_expand::base::SyntaxExtension;
use rustc_expand::expand::AstFragment;
use rustc_hir::def::{self, *};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_metadata::creader::LoadedMacro;
use rustc_middle::bug;
use rustc_middle::metadata::ModChild;
let parent = def_key.parent.map(|index| {
self.get_nearest_non_block_module(DefId { index, krate: def_id.krate })
});
- let name = if def_id.index == CRATE_DEF_INDEX {
- self.cstore().crate_name(def_id.krate)
+ let name = if let Some(cnum) = def_id.as_crate_root() {
+ self.cstore().crate_name(cnum)
} else {
def_key.disambiguated_data.data.get_opt_name().expect("module without name")
};
match vis.kind {
ast::VisibilityKind::Public => Ok(ty::Visibility::Public),
ast::VisibilityKind::Crate(..) => {
- Ok(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)))
+ Ok(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()))
}
ast::VisibilityKind::Inherited => {
Ok(match self.parent_scope.module.kind {
})
}
ast::VisibilityKind::Restricted { ref path, id, .. } => {
+ // Make `PRIVATE_IN_PUBLIC` lint a hard error.
+ self.r.has_pub_restricted = true;
// For visibilities we are not ready to provide correct implementation of "uniform
// paths" right now, so on 2018 edition we only allow module-relative paths for now.
// On 2015 edition visibilities are resolved as crate-relative by default,
let mut source = module_path.pop().unwrap();
let mut type_ns_only = false;
+ self.r.visibilities.insert(self.r.local_def_id(id), vis);
+ if id1 != ast::DUMMY_NODE_ID {
+ self.r.visibilities.insert(self.r.local_def_id(id1), vis);
+ }
+ if id2 != ast::DUMMY_NODE_ID {
+ self.r.visibilities.insert(self.r.local_def_id(id2), vis);
+ }
+
if nested {
// Correctly handle `self`
if source.ident.name == kw::SelfLower {
// while the current crate doesn't have a valid `crate_name`.
if crate_name != kw::Empty {
// `crate_name` should not be interpreted as relative.
- module_path.push(Segment {
- ident: Ident { name: kw::PathRoot, span: source.ident.span },
- id: Some(self.r.next_node_id()),
- has_generic_args: false,
- });
+ module_path.push(Segment::from_ident_and_id(
+ Ident { name: kw::PathRoot, span: source.ident.span },
+ self.r.next_node_id(),
+ ));
source.ident.name = crate_name;
}
if rename.is_none() {
is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import),
max_vis: Cell::new(ty::Visibility::Invisible),
};
+ self.r.visibilities.insert(self.r.local_def_id(id), vis);
self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
}
ast::UseTreeKind::Nested(ref items) => {
let mut ctor_vis = if vis == ty::Visibility::Public
&& self.r.session.contains_name(&item.attrs, sym::non_exhaustive)
{
- ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+ ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
} else {
vis
};
root_span: span,
span,
module_path: Vec::new(),
- vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
+ vis: Cell::new(ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())),
used: Cell::new(false),
})
};
let vis = if is_macro_export {
ty::Visibility::Public
} else {
- ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+ ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
};
let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
self.r.set_binding_parent_module(binding, parent_scope.module);
let ctor_vis = if vis == ty::Visibility::Public
&& self.r.session.contains_name(&variant.attrs, sym::non_exhaustive)
{
- ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+ ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id())
} else {
vis
};
}
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
- if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
+ if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
+ self.visit_generics(generics);
+
let return_impl_trait_id =
self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::PrimTy;
use rustc_middle::bug;
use rustc_middle::ty::DefIdTree;
err.span_label(trait_item_span, "item in trait");
err
}
+ ResolutionError::InvalidAsmSym => {
+ let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
+ err.span_label(span, "is a local variable");
+ err.help("`sym` operands must refer to either a function or a static");
+ err
+ }
}
}
}
Scope::ExternPrelude => {
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
- let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
+ let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
filter_fn(res).then_some(TypoSuggestion::typo_from_res(ident.name, res))
}));
}
}
return Res::Err;
}
+ InlineAsmSymRibKind => {
+ if let Some(span) = finalize {
+ self.report_error(span, InvalidAsmSym);
+ }
+ return Res::Err;
+ }
}
}
if let Some((span, res_err)) = res_err {
}
return Res::Err;
}
+ InlineAsmSymRibKind => {
+ let features = self.session.features_untracked();
+ if !features.generic_const_exprs {
+ if let Some(span) = finalize {
+ self.report_error(
+ span,
+ ResolutionError::ParamInNonTrivialAnonConst {
+ name: rib_ident.name,
+ is_type: true,
+ },
+ );
+ }
+ return Res::Err;
+ }
+ continue;
+ }
};
if let Some(span) = finalize {
}
return Res::Err;
}
+ InlineAsmSymRibKind => {
+ let features = self.session.features_untracked();
+ if !features.generic_const_exprs {
+ if let Some(span) = finalize {
+ self.report_error(
+ span,
+ ResolutionError::ParamInNonTrivialAnonConst {
+ name: rib_ident.name,
+ is_type: false,
+ },
+ );
+ }
+ return Res::Err;
+ }
+ continue;
+ }
};
// This was an attempt to use a const parameter outside its scope.
let mut allow_super = true;
let mut second_binding = None;
- for (i, &Segment { ident, id, has_generic_args: _ }) in path.iter().enumerate() {
+ for (i, &Segment { ident, id, .. }) in path.iter().enumerate() {
debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
let record_segment_res = |this: &mut Self, res| {
if finalize.is_some() {
t
}
- // Define a "dummy" resolution containing a Res::Err as a placeholder for a
- // failed resolution
+ // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
+ // also mark such failed imports as used to avoid duplicate diagnostics.
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
- if let ImportKind::Single { target, .. } = import.kind {
+ if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
+ if target_bindings.iter().any(|binding| binding.get().is_some()) {
+ return; // Has resolution, do not create the dummy binding
+ }
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, import);
self.per_ns(|this, ns| {
let key = this.new_key(target, ns);
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
});
- // Consider erroneous imports used to avoid duplicate diagnostics.
self.record_use(target, dummy_binding, false);
+ } else if import.imported_module.get().is_none() {
+ import.used.set(true);
+ self.used_imports.insert(import.id);
}
}
}
.map(|i| (false, i))
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
{
- if let Some(err) = self.finalize_import(import) {
+ let unresolved_import_error = self.finalize_import(import);
+
+ // If this import is unresolved then create a dummy import
+ // resolution for it so that later resolve stages won't complain.
+ self.r.import_dummy_binding(import);
+
+ if let Some(err) = unresolved_import_error {
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
if source.name == kw::SelfLower {
// Silence `unresolved import` error if E0429 is already emitted
}
}
- // If the error is a single failed import then create a "fake" import
- // resolution for it so that later resolve stages won't complain.
- self.r.import_dummy_binding(import);
if prev_root_id.as_u32() != 0
&& prev_root_id.as_u32() != import.root_id.as_u32()
&& !errors.is_empty()
prev_root_id = import.root_id;
}
} else if is_indeterminate {
- // Consider erroneous imports used to avoid duplicate diagnostics.
- self.r.used_imports.insert(import.id);
let path = import_path_to_string(
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
&import.kind,
Err(Undetermined) => indeterminate = true,
// Don't update the resolution, because it was never added.
Err(Determined) if target.name == kw::Underscore => {}
- Err(Determined) => {
+ Ok(binding) if binding.is_importable() => {
+ let imported_binding = this.import(binding, import);
+ target_bindings[ns].set(Some(imported_binding));
+ this.define(parent, target, ns, imported_binding);
+ }
+ source_binding @ (Ok(..) | Err(Determined)) => {
+ if source_binding.is_ok() {
+ let msg = format!("`{}` is not directly importable", target);
+ struct_span_err!(this.session, import.span, E0253, "{}", &msg)
+ .span_label(import.span, "cannot be imported directly")
+ .emit();
+ }
let key = this.new_key(target, ns);
this.update_resolution(parent, key, |_, resolution| {
resolution.single_imports.remove(&Interned::new_unchecked(import));
});
}
- Ok(binding) if !binding.is_importable() => {
- let msg = format!("`{}` is not directly importable", target);
- struct_span_err!(this.session, import.span, E0253, "{}", &msg)
- .span_label(import.span, "cannot be imported directly")
- .emit();
- // Do not import this illegal binding. Import a dummy binding and pretend
- // everything is fine
- this.import_dummy_binding(import);
- }
- Ok(binding) => {
- let imported_binding = this.import(binding, import);
- target_bindings[ns].set(Some(imported_binding));
- this.define(parent, target, ns, imported_binding);
- }
}
}
});
);
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
import.vis.set(orig_vis);
- if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
- // Consider erroneous imports used to avoid duplicate diagnostics.
- self.r.used_imports.insert(import.id);
- }
let module = match path_res {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
})
} else {
// `resolve_ident_in_module` reported a privacy error.
- self.r.import_dummy_binding(import);
None
};
}
use rustc_errors::DiagnosticId;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::{PrimTy, TraitCandidate};
+use rustc_middle::ty::DefIdTree;
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
use smallvec::{smallvec, SmallVec};
use rustc_span::source_map::{respan, Spanned};
/// We are inside of the type of a const parameter. Can't refer to any
/// parameters.
ConstParamTyRibKind,
+
+ /// We are inside a `sym` inline assembly operand. Can only refer to
+ /// globals.
+ InlineAsmSymRibKind,
}
impl RibKind<'_> {
| ConstantItemRibKind(..)
| ModuleRibKind(_)
| MacroDefinition(_)
- | ConstParamTyRibKind => false,
+ | ConstParamTyRibKind
+ | InlineAsmSymRibKind => false,
AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true,
}
}
}
}
+#[derive(Copy, Clone, Debug)]
+enum LifetimeRibKind {
+ /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
+ Item,
+
+ /// This rib declares generic parameters.
+ Generics { span: Span, kind: LifetimeBinderKind },
+
+ /// For **Modern** cases, create a new anonymous region parameter
+ /// and reference that.
+ ///
+ /// For **Dyn Bound** cases, pass responsibility to
+ /// `resolve_lifetime` code.
+ ///
+ /// For **Deprecated** cases, report an error.
+ AnonymousCreateParameter,
+
+ /// Give a hard error when either `&` or `'_` is written. Used to
+ /// rule out things like `where T: Foo<'_>`. Does not imply an
+ /// error on default object bounds (e.g., `Box<dyn Foo>`).
+ AnonymousReportError,
+
+ /// Pass responsibility to `resolve_lifetime` code for all cases.
+ AnonymousPassThrough,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum LifetimeBinderKind {
+ BareFnType,
+ PolyTrait,
+ WhereBound,
+ Item,
+ Function,
+ ImplBlock,
+}
+
+impl LifetimeBinderKind {
+ fn descr(self) -> &'static str {
+ use LifetimeBinderKind::*;
+ match self {
+ BareFnType => "type",
+ PolyTrait => "bound",
+ WhereBound => "bound",
+ Item => "item",
+ ImplBlock => "impl block",
+ Function => "function",
+ }
+ }
+}
+
+#[derive(Debug)]
+struct LifetimeRib {
+ kind: LifetimeRibKind,
+ bindings: IdentMap<()>,
+}
+
+impl LifetimeRib {
+ fn new(kind: LifetimeRibKind) -> LifetimeRib {
+ LifetimeRib { bindings: Default::default(), kind }
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
crate enum AliasPossibility {
No,
/// The current set of local scopes, for labels.
label_ribs: Vec<Rib<'a, NodeId>>,
+ /// The current set of local scopes for lifetimes.
+ lifetime_ribs: Vec<LifetimeRib>,
+
/// The trait that the current context can refer to.
current_trait_ref: Option<(Module<'a>, TraitRef)>,
let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
// Always report errors in items we just entered.
let old_ignore = replace(&mut self.in_func_body, false);
- self.resolve_item(item);
+ self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
self.in_func_body = old_ignore;
self.diagnostic_metadata.current_item = prev;
}
let prev = self.diagnostic_metadata.current_trait_object;
let prev_ty = self.diagnostic_metadata.current_type_path;
match ty.kind {
+ TyKind::Rptr(None, _) => {
+ // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
+ // NodeId `ty.id`.
+ let span = self.r.session.source_map().next_point(ty.span.shrink_to_lo());
+ self.resolve_elided_lifetime(ty.id, span);
+ }
TyKind::Path(ref qself, ref path) => {
self.diagnostic_metadata.current_type_path = Some(ty);
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
TyKind::TraitObject(ref bounds, ..) => {
self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
}
+ TyKind::BareFn(ref bare_fn) => {
+ let span = if bare_fn.generic_params.is_empty() {
+ ty.span.shrink_to_lo()
+ } else {
+ ty.span
+ };
+ self.with_generic_param_rib(
+ &bare_fn.generic_params,
+ NormalRibKind,
+ LifetimeRibKind::Generics { kind: LifetimeBinderKind::BareFnType, span },
+ |this| {
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+ this.visit_generic_param_vec(&bare_fn.generic_params, false);
+ visit::walk_fn_decl(this, &bare_fn.decl);
+ });
+ },
+ );
+ self.diagnostic_metadata.current_trait_object = prev;
+ return;
+ }
_ => (),
}
visit::walk_ty(self, ty);
self.diagnostic_metadata.current_trait_object = prev;
self.diagnostic_metadata.current_type_path = prev_ty;
}
- fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
- self.smart_resolve_path(
- tref.trait_ref.ref_id,
- None,
- &tref.trait_ref.path,
- PathSource::Trait(AliasPossibility::Maybe),
+ fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef, _: &'ast TraitBoundModifier) {
+ let span =
+ if tref.bound_generic_params.is_empty() { tref.span.shrink_to_lo() } else { tref.span };
+ self.with_generic_param_rib(
+ &tref.bound_generic_params,
+ NormalRibKind,
+ LifetimeRibKind::Generics { kind: LifetimeBinderKind::PolyTrait, span },
+ |this| {
+ this.visit_generic_param_vec(&tref.bound_generic_params, false);
+ this.smart_resolve_path(
+ tref.trait_ref.ref_id,
+ None,
+ &tref.trait_ref.path,
+ PathSource::Trait(AliasPossibility::Maybe),
+ );
+ this.visit_trait_ref(&tref.trait_ref);
+ },
);
- visit::walk_poly_trait_ref(self, tref, m);
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
match foreign_item.kind {
- ForeignItemKind::Fn(box Fn { ref generics, .. })
- | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
- self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
- visit::walk_foreign_item(this, foreign_item);
+ ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
+ self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+ this.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ )
+ });
+ }
+ ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
+ self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+ this.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Function,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ )
});
}
ForeignItemKind::Static(..) => {
- self.with_item_rib(HasGenericParams::No, |this| {
+ self.with_item_rib(|this| {
visit::walk_foreign_item(this, foreign_item);
});
}
ForeignItemKind::MacCall(..) => {
- visit::walk_foreign_item(self, foreign_item);
+ panic!("unexpanded macro in resolve!")
}
}
}
let rib_kind = match fn_kind {
// Bail if the function is foreign, and thus cannot validly have
// a body, or if there's no body for some other reason.
- FnKind::Fn(FnCtxt::Foreign, _, sig, ..) | FnKind::Fn(_, _, sig, .., None) => {
- // We don't need to deal with patterns in parameters, because
- // they are not possible for foreign or bodiless functions.
- self.visit_fn_header(&sig.header);
- visit::walk_fn_decl(self, &sig.decl);
+ FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
+ | FnKind::Fn(_, _, sig, _, generics, None) => {
+ self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+ // We don't need to deal with patterns in parameters, because
+ // they are not possible for foreign or bodiless functions.
+ this.visit_fn_header(&sig.header);
+ this.visit_generics(generics);
+ visit::walk_fn_decl(this, &sig.decl);
+ });
return;
}
FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind,
self.with_rib(ValueNS, rib_kind, |this| {
// Create a label rib for the function.
this.with_label_rib(rib_kind, |this| {
- // Add each argument to the rib.
- this.resolve_params(&declaration.inputs);
+ let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id());
- visit::walk_fn_ret_ty(this, &declaration.output);
+ if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind {
+ this.visit_generics(generics);
+ }
+
+ if async_node_id.is_some() {
+ // In `async fn`, argument-position elided lifetimes
+ // must be transformed into fresh generic parameters so that
+ // they can be applied to the opaque `impl Trait` return type.
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
+ // Add each argument to the rib.
+ this.resolve_params(&declaration.inputs)
+ });
+
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+ visit::walk_fn_ret_ty(this, &declaration.output)
+ });
+ } else {
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+ // Add each argument to the rib.
+ this.resolve_params(&declaration.inputs);
+
+ visit::walk_fn_ret_ty(this, &declaration.output);
+ });
+ };
// 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);
// Resolve the function body, potentially inside the body of an async closure
- match fn_kind {
- FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
- FnKind::Closure(_, body) => this.visit_expr(body),
- };
+ this.with_lifetime_rib(
+ LifetimeRibKind::AnonymousPassThrough,
+ |this| match fn_kind {
+ FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
+ FnKind::Closure(_, body) => this.visit_expr(body),
+ },
+ );
debug!("(resolving function) leaving function");
this.in_func_body = previous_state;
});
self.diagnostic_metadata.current_function = previous_value;
}
+ fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
+ self.resolve_lifetime(lifetime)
+ }
fn visit_generics(&mut self, generics: &'ast Generics) {
- // For type parameter defaults, we have to ban access
- // to following type parameters, as the InternalSubsts can only
- // provide previous type parameters as they're built. We
- // put all the parameters on the ban list and then remove
- // them one by one as they are processed and become available.
- let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
- let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
- for param in generics.params.iter() {
- match param.kind {
- GenericParamKind::Type { .. } => {
- forward_ty_ban_rib
- .bindings
- .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
- }
- GenericParamKind::Const { .. } => {
- forward_const_ban_rib
- .bindings
- .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
- }
- GenericParamKind::Lifetime => {}
- }
- }
-
- // rust-lang/rust#61631: The type `Self` is essentially
- // another type parameter. For ADTs, we consider it
- // well-defined only after all of the ADT type parameters have
- // been provided. Therefore, we do not allow use of `Self`
- // anywhere in ADT type parameter defaults.
- //
- // (We however cannot ban `Self` for defaults on *all* generic
- // lists; e.g. trait generics can usefully refer to `Self`,
- // such as in the case of `trait Add<Rhs = Self>`.)
- if self.diagnostic_metadata.current_self_item.is_some() {
- // (`Some` if + only if we are in ADT's generics.)
- forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
- }
-
- for param in &generics.params {
- match param.kind {
- GenericParamKind::Lifetime => self.visit_generic_param(param),
- GenericParamKind::Type { ref default } => {
- for bound in ¶m.bounds {
- self.visit_param_bound(bound);
- }
-
- if let Some(ref ty) = default {
- self.ribs[TypeNS].push(forward_ty_ban_rib);
- self.ribs[ValueNS].push(forward_const_ban_rib);
- self.visit_ty(ty);
- forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
- forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
- }
-
- // Allow all following defaults to refer to this type parameter.
- forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
- }
- GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
- // Const parameters can't have param bounds.
- assert!(param.bounds.is_empty());
-
- self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
- self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
- self.visit_ty(ty);
- self.ribs[TypeNS].pop().unwrap();
- self.ribs[ValueNS].pop().unwrap();
-
- if let Some(ref expr) = default {
- self.ribs[TypeNS].push(forward_ty_ban_rib);
- self.ribs[ValueNS].push(forward_const_ban_rib);
- self.visit_anon_const(expr);
- forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
- forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
- }
-
- // Allow all following defaults to refer to this const parameter.
- forward_const_ban_rib
- .bindings
- .remove(&Ident::with_dummy_span(param.ident.name));
- }
- }
- }
+ self.visit_generic_param_vec(
+ &generics.params,
+ self.diagnostic_metadata.current_self_item.is_some(),
+ );
for p in &generics.where_clause.predicates {
self.visit_where_predicate(p);
}
self.diagnostic_metadata.currently_processing_generics = prev;
}
+ fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
+ if let Some(ref args) = path_segment.args {
+ match &**args {
+ GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
+ GenericArgs::Parenthesized(..) => self
+ .with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| {
+ visit::walk_generic_args(this, path_span, args)
+ }),
+ }
+ }
+ }
+
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
debug!("visit_where_predicate {:?}", p);
let previous_value =
replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p));
- visit::walk_where_predicate(self, p);
+ self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
+ if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+ ref bounded_ty,
+ ref bounds,
+ ref bound_generic_params,
+ span: predicate_span,
+ ..
+ }) = p
+ {
+ let span = if bound_generic_params.is_empty() {
+ predicate_span.shrink_to_lo()
+ } else {
+ *predicate_span
+ };
+ this.with_generic_param_rib(
+ &bound_generic_params,
+ NormalRibKind,
+ LifetimeRibKind::Generics { kind: LifetimeBinderKind::WhereBound, span },
+ |this| {
+ this.visit_generic_param_vec(&bound_generic_params, false);
+ this.visit_ty(bounded_ty);
+ for bound in bounds {
+ this.visit_param_bound(bound)
+ }
+ },
+ );
+ } else {
+ visit::walk_where_predicate(this, p);
+ }
+ });
self.diagnostic_metadata.current_where_predicate = previous_value;
}
+
+ fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
+ // This is similar to the code for AnonConst.
+ self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
+ this.with_rib(TypeNS, InlineAsmSymRibKind, |this| {
+ this.with_label_rib(InlineAsmSymRibKind, |this| {
+ this.smart_resolve_path(
+ sym.id,
+ sym.qself.as_ref(),
+ &sym.path,
+ PathSource::Expr(None),
+ );
+ visit::walk_inline_asm_sym(this, sym);
+ });
+ })
+ });
+ }
}
impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
macro_ns: vec![Rib::new(start_rib_kind)],
},
label_ribs: Vec::new(),
+ lifetime_ribs: Vec::new(),
current_trait_ref: None,
diagnostic_metadata: DiagnosticMetadata::default(),
// errors at module scope should always be reported
}
}
+ fn visit_generic_param_vec(&mut self, params: &'ast Vec<GenericParam>, add_self_upper: bool) {
+ // For type parameter defaults, we have to ban access
+ // to following type parameters, as the InternalSubsts can only
+ // provide previous type parameters as they're built. We
+ // put all the parameters on the ban list and then remove
+ // them one by one as they are processed and become available.
+ let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+ let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+ for param in params.iter() {
+ match param.kind {
+ GenericParamKind::Type { .. } => {
+ forward_ty_ban_rib
+ .bindings
+ .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+ }
+ GenericParamKind::Const { .. } => {
+ forward_const_ban_rib
+ .bindings
+ .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+ }
+ GenericParamKind::Lifetime => {}
+ }
+ }
+
+ // rust-lang/rust#61631: The type `Self` is essentially
+ // another type parameter. For ADTs, we consider it
+ // well-defined only after all of the ADT type parameters have
+ // been provided. Therefore, we do not allow use of `Self`
+ // anywhere in ADT type parameter defaults.
+ //
+ // (We however cannot ban `Self` for defaults on *all* generic
+ // lists; e.g. trait generics can usefully refer to `Self`,
+ // such as in the case of `trait Add<Rhs = Self>`.)
+ if add_self_upper {
+ // (`Some` if + only if we are in ADT's generics.)
+ forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
+ }
+
+ self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
+ for param in params {
+ match param.kind {
+ GenericParamKind::Lifetime => {
+ for bound in ¶m.bounds {
+ this.visit_param_bound(bound);
+ }
+ }
+ GenericParamKind::Type { ref default } => {
+ for bound in ¶m.bounds {
+ this.visit_param_bound(bound);
+ }
+
+ if let Some(ref ty) = default {
+ this.ribs[TypeNS].push(forward_ty_ban_rib);
+ this.ribs[ValueNS].push(forward_const_ban_rib);
+ this.visit_ty(ty);
+ forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
+ forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
+ }
+
+ // Allow all following defaults to refer to this type parameter.
+ forward_ty_ban_rib
+ .bindings
+ .remove(&Ident::with_dummy_span(param.ident.name));
+ }
+ GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
+ // Const parameters can't have param bounds.
+ assert!(param.bounds.is_empty());
+
+ this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
+ this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
+ this.visit_ty(ty);
+ this.ribs[TypeNS].pop().unwrap();
+ this.ribs[ValueNS].pop().unwrap();
+
+ if let Some(ref expr) = default {
+ this.ribs[TypeNS].push(forward_ty_ban_rib);
+ this.ribs[ValueNS].push(forward_const_ban_rib);
+ this.visit_anon_const(expr);
+ forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
+ forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
+ }
+
+ // Allow all following defaults to refer to this const parameter.
+ forward_const_ban_rib
+ .bindings
+ .remove(&Ident::with_dummy_span(param.ident.name));
+ }
+ }
+ }
+ })
+ }
+
+ #[tracing::instrument(level = "debug", skip(self, work))]
+ fn with_lifetime_rib<T>(
+ &mut self,
+ kind: LifetimeRibKind,
+ work: impl FnOnce(&mut Self) -> T,
+ ) -> T {
+ self.lifetime_ribs.push(LifetimeRib::new(kind));
+ let ret = work(self);
+ self.lifetime_ribs.pop();
+ ret
+ }
+
+ #[tracing::instrument(level = "debug", skip(self))]
+ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime) {
+ let ident = lifetime.ident;
+
+ if ident.name == kw::StaticLifetime {
+ return;
+ }
+
+ if ident.name == kw::UnderscoreLifetime {
+ return self.resolve_anonymous_lifetime(lifetime, false);
+ }
+
+ let mut indices = (0..self.lifetime_ribs.len()).rev();
+ for i in &mut indices {
+ let rib = &self.lifetime_ribs[i];
+ let normalized_ident = ident.normalize_to_macros_2_0();
+ if let Some(_) = rib.bindings.get_key_value(&normalized_ident) {
+ return;
+ }
+
+ if let LifetimeRibKind::Item = rib.kind {
+ break;
+ }
+ }
+
+ let mut outer_res = None;
+ for i in indices {
+ let rib = &self.lifetime_ribs[i];
+ let normalized_ident = ident.normalize_to_macros_2_0();
+ if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
+ outer_res = Some(outer);
+ break;
+ }
+ }
+
+ self.emit_undeclared_lifetime_error(lifetime, outer_res);
+ }
+
+ #[tracing::instrument(level = "debug", skip(self))]
+ fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
+ debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
+
+ for i in (0..self.lifetime_ribs.len()).rev() {
+ let rib = &mut self.lifetime_ribs[i];
+ match rib.kind {
+ LifetimeRibKind::AnonymousReportError => {
+ let (msg, note) = if elided {
+ (
+ "`&` without an explicit lifetime name cannot be used here",
+ "explicit lifetime name needed here",
+ )
+ } else {
+ ("`'_` cannot be used here", "`'_` is a reserved lifetime name")
+ };
+ rustc_errors::struct_span_err!(
+ self.r.session,
+ lifetime.ident.span,
+ E0637,
+ "{}",
+ msg,
+ )
+ .span_label(lifetime.ident.span, note)
+ .emit();
+
+ return;
+ }
+ LifetimeRibKind::AnonymousCreateParameter
+ | LifetimeRibKind::AnonymousPassThrough
+ | LifetimeRibKind::Item => return,
+ _ => {}
+ }
+ }
+ }
+
+ #[tracing::instrument(level = "debug", skip(self))]
+ fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
+ let id = self.r.next_node_id();
+ let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
+ self.resolve_anonymous_lifetime(<, true);
+ }
+
+ #[tracing::instrument(level = "debug", skip(self))]
+ fn resolve_elided_lifetimes_in_path(
+ &mut self,
+ path_id: NodeId,
+ partial_res: PartialRes,
+ path: &[Segment],
+ source: PathSource<'_>,
+ finalize: Finalize,
+ ) {
+ let Some(path_span) = finalize.path_span() else {
+ return;
+ };
+ let proj_start = path.len() - partial_res.unresolved_segments();
+ for (i, segment) in path.iter().enumerate() {
+ if segment.has_lifetime_args {
+ continue;
+ }
+ let Some(segment_id) = segment.id else {
+ continue;
+ };
+
+ // Figure out if this is a type/trait segment,
+ // which may need lifetime elision performed.
+ let type_def_id = match partial_res.base_res() {
+ Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
+ self.r.parent(def_id).unwrap()
+ }
+ Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
+ self.r.parent(def_id).unwrap()
+ }
+ Res::Def(DefKind::Struct, def_id)
+ | Res::Def(DefKind::Union, def_id)
+ | Res::Def(DefKind::Enum, def_id)
+ | Res::Def(DefKind::TyAlias, def_id)
+ | Res::Def(DefKind::Trait, def_id)
+ if i + 1 == proj_start =>
+ {
+ def_id
+ }
+ _ => continue,
+ };
+
+ let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id);
+ if expected_lifetimes == 0 {
+ continue;
+ }
+
+ let missing = match source {
+ PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => true,
+ PathSource::Expr(..)
+ | PathSource::Pat
+ | PathSource::Struct
+ | PathSource::TupleStruct(..) => false,
+ };
+ let mut error = false;
+ for rib in self.lifetime_ribs.iter().rev() {
+ match rib.kind {
+ // In create-parameter mode we error here because we don't want to support
+ // deprecated impl elision in new features like impl elision and `async fn`,
+ // both of which work using the `CreateParameter` mode:
+ //
+ // impl Foo for std::cell::Ref<u32> // note lack of '_
+ // async fn foo(_: std::cell::Ref<u32>) { ... }
+ LifetimeRibKind::AnonymousCreateParameter => {
+ error = true;
+ break;
+ }
+ // `PassThrough` is the normal case.
+ // `new_error_lifetime`, which would usually be used in the case of `ReportError`,
+ // is unsuitable here, as these can occur from missing lifetime parameters in a
+ // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
+ // lifetime. Instead, we simply create an implicit lifetime, which will be checked
+ // later, at which point a suitable error will be emitted.
+ LifetimeRibKind::AnonymousPassThrough
+ | LifetimeRibKind::AnonymousReportError
+ | LifetimeRibKind::Item => break,
+ _ => {}
+ }
+ }
+
+ if !missing {
+ continue;
+ }
+
+ let elided_lifetime_span = if segment.has_generic_args {
+ // If there are brackets, but not generic arguments, then use the opening bracket
+ segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
+ } else {
+ // If there are no brackets, use the identifier span.
+ // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
+ // originating from macros, since the segment's span might be from a macro arg.
+ segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
+ };
+ if error {
+ let sess = self.r.session;
+ let mut err = rustc_errors::struct_span_err!(
+ sess,
+ path_span,
+ E0726,
+ "implicit elided lifetime not allowed here"
+ );
+ rustc_errors::add_elided_lifetime_in_path_suggestion(
+ sess.source_map(),
+ &mut err,
+ expected_lifetimes,
+ path_span,
+ !segment.has_generic_args,
+ elided_lifetime_span,
+ );
+ err.note("assuming a `'static` lifetime...");
+ err.emit();
+ } else {
+ self.r.lint_buffer.buffer_lint_with_diagnostic(
+ lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
+ segment_id,
+ elided_lifetime_span,
+ "hidden lifetime parameters in types are deprecated",
+ lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+ expected_lifetimes,
+ path_span,
+ !segment.has_generic_args,
+ elided_lifetime_span,
+ ),
+ );
+ }
+ }
+ }
+
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
/// label and reports an error if the label is not found or is unreachable.
fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
| ConstantItemRibKind(..)
| ModuleRibKind(..)
| ForwardGenericParamBanRibKind
- | ConstParamTyRibKind => {
+ | ConstParamTyRibKind
+ | InlineAsmSymRibKind => {
return false;
}
}
fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
debug!("resolve_adt");
self.with_current_self_item(item, |this| {
- this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
- let item_def_id = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(
- Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
- |this| {
- visit::walk_item(this, item);
- },
- );
- });
+ this.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics { kind: LifetimeBinderKind::Item, span: generics.span },
+ |this| {
+ let item_def_id = this.r.local_def_id(item.id).to_def_id();
+ this.with_self_rib(
+ Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
+ |this| {
+ visit::walk_item(this, item);
+ },
+ );
+ },
+ );
});
}
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
match item.kind {
- ItemKind::TyAlias(box TyAlias { ref generics, .. })
- | ItemKind::Fn(box Fn { ref generics, .. }) => {
- self.compute_num_lifetime_params(item.id, generics);
- self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
- visit::walk_item(this, item)
- });
+ ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| visit::walk_item(this, item),
+ );
+ }
+
+ ItemKind::Fn(box Fn { ref generics, .. }) => {
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Function,
+ span: generics.span,
+ },
+ |this| visit::walk_item(this, item),
+ );
}
ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) => {
- self.compute_num_lifetime_params(item.id, generics);
self.resolve_adt(item, generics);
}
items: ref impl_items,
..
}) => {
- self.compute_num_lifetime_params(item.id, generics);
self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
}
ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
- self.compute_num_lifetime_params(item.id, generics);
// Create a new rib for the trait-wide type parameters.
- self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
- let def = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(Res::SelfTy { trait_: Some(def), alias_to: None }, |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds);
-
- let walk_assoc_item = |this: &mut Self, generics, item| {
- this.with_generic_param_rib(generics, AssocItemRibKind, |this| {
- visit::walk_assoc_item(this, item, AssocCtxt::Trait)
- });
- };
-
- this.with_trait_items(items, |this| {
- for item in items {
- match &item.kind {
- AssocItemKind::Const(_, ty, default) => {
- this.visit_ty(ty);
- // Only impose the restrictions of `ConstRibKind` for an
- // actual constant expression in a provided default.
- if let Some(expr) = default {
- // We allow arbitrary const expressions inside of associated consts,
- // even if they are potentially not const evaluatable.
- //
- // Type parameters can already be used and as associated consts are
- // not used as part of the type system, this is far less surprising.
- this.with_constant_rib(
- IsRepeatExpr::No,
- true,
- None,
- |this| this.visit_expr(expr),
- );
- }
- }
- AssocItemKind::Fn(box Fn { generics, .. }) => {
- walk_assoc_item(this, generics, item);
- }
- AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
- walk_assoc_item(this, generics, item);
- }
- AssocItemKind::MacCall(_) => {
- panic!("unexpanded macro in resolve!")
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| {
+ let local_def_id = this.r.local_def_id(item.id).to_def_id();
+ this.with_self_rib(
+ Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
+ |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds);
+
+ let walk_assoc_item =
+ |this: &mut Self,
+ generics: &Generics,
+ kind,
+ item: &'ast AssocItem| {
+ this.with_generic_param_rib(
+ &generics.params,
+ AssocItemRibKind,
+ LifetimeRibKind::Generics { span: generics.span, kind },
+ |this| {
+ visit::walk_assoc_item(this, item, AssocCtxt::Trait)
+ },
+ );
+ };
+
+ this.with_trait_items(items, |this| {
+ for item in items {
+ match &item.kind {
+ AssocItemKind::Const(_, ty, default) => {
+ this.visit_ty(ty);
+ // Only impose the restrictions of `ConstRibKind` for an
+ // actual constant expression in a provided default.
+ if let Some(expr) = default {
+ // We allow arbitrary const expressions inside of associated consts,
+ // even if they are potentially not const evaluatable.
+ //
+ // Type parameters can already be used and as associated consts are
+ // not used as part of the type system, this is far less surprising.
+ this.with_constant_rib(
+ IsRepeatExpr::No,
+ true,
+ None,
+ |this| this.visit_expr(expr),
+ );
+ }
+ }
+ AssocItemKind::Fn(box Fn { generics, .. }) => {
+ walk_assoc_item(
+ this,
+ generics,
+ LifetimeBinderKind::Function,
+ item,
+ );
+ }
+ AssocItemKind::TyAlias(box TyAlias {
+ generics,
+ ..
+ }) => {
+ walk_assoc_item(
+ this,
+ generics,
+ LifetimeBinderKind::Item,
+ item,
+ );
+ }
+ AssocItemKind::MacCall(_) => {
+ panic!("unexpanded macro in resolve!")
+ }
+ };
}
- };
- }
- });
- });
- });
+ });
+ },
+ );
+ },
+ );
}
ItemKind::TraitAlias(ref generics, ref bounds) => {
- self.compute_num_lifetime_params(item.id, generics);
// Create a new rib for the trait-wide type parameters.
- self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
- let def = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(Res::SelfTy { trait_: Some(def), alias_to: None }, |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds);
- });
- });
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes),
+ LifetimeRibKind::Generics {
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| {
+ let local_def_id = this.r.local_def_id(item.id).to_def_id();
+ this.with_self_rib(
+ Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
+ |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds);
+ },
+ );
+ },
+ );
}
ItemKind::Mod(..) | ItemKind::ForeignMod(_) => {
}
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
- self.with_item_rib(HasGenericParams::No, |this| {
+ self.with_item_rib(|this| {
this.visit_ty(ty);
if let Some(expr) = expr {
let constant_item_kind = match item.kind {
}
}
- fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F)
- where
+ fn with_generic_param_rib<'c, F>(
+ &'c mut self,
+ params: &'c Vec<GenericParam>,
+ kind: RibKind<'a>,
+ lifetime_kind: LifetimeRibKind,
+ f: F,
+ ) where
F: FnOnce(&mut Self),
{
debug!("with_generic_param_rib");
let mut function_type_rib = Rib::new(kind);
let mut function_value_rib = Rib::new(kind);
+ let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
let mut seen_bindings = FxHashMap::default();
// We also can't shadow bindings from the parent item
add_bindings_for_ns(TypeNS);
}
- for param in &generics.params {
- if let GenericParamKind::Lifetime = param.kind {
- continue;
- }
-
+ for param in params {
let ident = param.ident.normalize_to_macros_2_0();
debug!("with_generic_param_rib: {}", param.id);
Entry::Occupied(entry) => {
let span = *entry.get();
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
- self.report_error(param.ident.span, err);
+ if !matches!(param.kind, GenericParamKind::Lifetime) {
+ self.report_error(param.ident.span, err);
+ }
}
Entry::Vacant(entry) => {
entry.insert(param.ident.span);
}
}
+ if param.ident.name == kw::UnderscoreLifetime {
+ rustc_errors::struct_span_err!(
+ self.r.session,
+ param.ident.span,
+ E0637,
+ "`'_` cannot be used here"
+ )
+ .span_label(param.ident.span, "`'_` is a reserved lifetime name")
+ .emit();
+ continue;
+ }
+
+ if param.ident.name == kw::StaticLifetime {
+ rustc_errors::struct_span_err!(
+ self.r.session,
+ param.ident.span,
+ E0262,
+ "invalid lifetime parameter name: `{}`",
+ param.ident,
+ )
+ .span_label(param.ident.span, "'static is a reserved lifetime name")
+ .emit();
+ continue;
+ }
+
+ let def_id = self.r.local_def_id(param.id);
+
// Plain insert (no renaming).
let (rib, def_kind) = match param.kind {
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
- _ => unreachable!(),
+ GenericParamKind::Lifetime => {
+ function_lifetime_rib.bindings.insert(ident, ());
+ continue;
+ }
};
- let res = Res::Def(def_kind, self.r.local_def_id(param.id).to_def_id());
+ let res = Res::Def(def_kind, def_id.to_def_id());
self.r.record_partial_res(param.id, PartialRes::new(res));
rib.bindings.insert(ident, res);
}
+ self.lifetime_ribs.push(function_lifetime_rib);
self.ribs[ValueNS].push(function_value_rib);
self.ribs[TypeNS].push(function_type_rib);
self.ribs[TypeNS].pop();
self.ribs[ValueNS].pop();
+ self.lifetime_ribs.pop();
}
fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
self.label_ribs.pop();
}
- fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) {
- let kind = ItemRibKind(has_generic_params);
- self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
+ fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+ let kind = ItemRibKind(HasGenericParams::No);
+ self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
+ this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
+ })
}
// HACK(min_const_generics,const_evaluatable_unchecked): We
) {
debug!("resolve_implementation");
// If applicable, create a rib for the type parameters.
- self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
+ self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::ImplBlock }, |this| {
// Dummy self type for better errors if `Self` is used in the trait path.
this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
- // Resolve the trait reference, if necessary.
- this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
- let item_def_id = this.r.local_def_id(item_id);
-
- // Register the trait definitions from here.
- if let Some(trait_id) = trait_id {
- this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
- }
-
- let item_def_id = item_def_id.to_def_id();
- let res =
- Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
- this.with_self_rib(res, |this| {
- if let Some(trait_ref) = opt_trait_reference.as_ref() {
- // Resolve type arguments in the trait path.
- visit::walk_trait_ref(this, trait_ref);
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| {
+ // Resolve the trait reference, if necessary.
+ this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
+ let item_def_id = this.r.local_def_id(item_id);
+
+ // Register the trait definitions from here.
+ if let Some(trait_id) = trait_id {
+ this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
}
- // Resolve the self type.
- this.visit_ty(self_type);
- // Resolve the generic parameters.
- this.visit_generics(generics);
- // Resolve the items within the impl.
- this.with_current_self_type(self_type, |this| {
- this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
- debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
- for item in impl_items {
- use crate::ResolutionError::*;
- match &item.kind {
- AssocItemKind::Const(_default, _ty, _expr) => {
- debug!("resolve_implementation AssocItemKind::Const");
- // If this is a trait impl, ensure the const
- // exists in trait
- this.check_trait_item(
- item.id,
- item.ident,
- &item.kind,
- ValueNS,
- item.span,
- |i, s, c| ConstNotMemberOfTrait(i, s, c),
- );
-
- // We allow arbitrary const expressions inside of associated consts,
- // even if they are potentially not const evaluatable.
- //
- // Type parameters can already be used and as associated consts are
- // not used as part of the type system, this is far less surprising.
- this.with_constant_rib(
- IsRepeatExpr::No,
- true,
- None,
- |this| {
- visit::walk_assoc_item(
- this,
- item,
- AssocCtxt::Impl,
- )
- },
- );
- }
- AssocItemKind::Fn(box Fn { generics, .. }) => {
- debug!("resolve_implementation AssocItemKind::Fn");
- // We also need a new scope for the impl item type parameters.
- this.with_generic_param_rib(
- generics,
- AssocItemRibKind,
- |this| {
- // If this is a trait impl, ensure the method
- // exists in trait
- this.check_trait_item(
- item.id,
- item.ident,
- &item.kind,
- ValueNS,
- item.span,
- |i, s, c| MethodNotMemberOfTrait(i, s, c),
- );
- visit::walk_assoc_item(
- this,
- item,
- AssocCtxt::Impl,
- )
- },
- );
- }
- AssocItemKind::TyAlias(box TyAlias {
- generics, ..
- }) => {
- debug!("resolve_implementation AssocItemKind::TyAlias");
- // We also need a new scope for the impl item type parameters.
- this.with_generic_param_rib(
- generics,
- AssocItemRibKind,
- |this| {
- // If this is a trait impl, ensure the type
- // exists in trait
- this.check_trait_item(
- item.id,
- item.ident,
- &item.kind,
- TypeNS,
- item.span,
- |i, s, c| TypeNotMemberOfTrait(i, s, c),
- );
-
- visit::walk_assoc_item(
- this,
- item,
- AssocCtxt::Impl,
- )
- },
- );
- }
- AssocItemKind::MacCall(_) => {
- panic!("unexpanded macro in resolve!")
- }
- }
- }
- });
+ let item_def_id = item_def_id.to_def_id();
+ let res =
+ Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
+ this.with_self_rib(res, |this| {
+ if let Some(trait_ref) = opt_trait_reference.as_ref() {
+ // Resolve type arguments in the trait path.
+ visit::walk_trait_ref(this, trait_ref);
+ }
+ // Resolve the self type.
+ this.visit_ty(self_type);
+ // Resolve the generic parameters.
+ this.visit_generics(generics);
+
+ // Resolve the items within the impl.
+ this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough,
+ |this| {
+ this.with_current_self_type(self_type, |this| {
+ this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
+ debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
+ for item in impl_items {
+ use crate::ResolutionError::*;
+ match &item.kind {
+ AssocItemKind::Const(_default, _ty, _expr) => {
+ debug!("resolve_implementation AssocItemKind::Const");
+ // If this is a trait impl, ensure the const
+ // exists in trait
+ this.check_trait_item(
+ item.id,
+ item.ident,
+ &item.kind,
+ ValueNS,
+ item.span,
+ |i, s, c| ConstNotMemberOfTrait(i, s, c),
+ );
+
+ // We allow arbitrary const expressions inside of associated consts,
+ // even if they are potentially not const evaluatable.
+ //
+ // Type parameters can already be used and as associated consts are
+ // not used as part of the type system, this is far less surprising.
+ this.with_constant_rib(
+ IsRepeatExpr::No,
+ true,
+ None,
+ |this| {
+ visit::walk_assoc_item(
+ this,
+ item,
+ AssocCtxt::Impl,
+ )
+ },
+ );
+ }
+ AssocItemKind::Fn(box Fn { generics, .. }) => {
+ debug!("resolve_implementation AssocItemKind::Fn");
+ // We also need a new scope for the impl item type parameters.
+ this.with_generic_param_rib(
+ &generics.params,
+ AssocItemRibKind,
+ LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Function },
+ |this| {
+ // If this is a trait impl, ensure the method
+ // exists in trait
+ this.check_trait_item(
+ item.id,
+ item.ident,
+ &item.kind,
+ ValueNS,
+ item.span,
+ |i, s, c| MethodNotMemberOfTrait(i, s, c),
+ );
+
+ visit::walk_assoc_item(
+ this,
+ item,
+ AssocCtxt::Impl,
+ )
+ },
+ );
+ }
+ AssocItemKind::TyAlias(box TyAlias {
+ generics, ..
+ }) => {
+ debug!("resolve_implementation AssocItemKind::TyAlias");
+ // We also need a new scope for the impl item type parameters.
+ this.with_generic_param_rib(
+ &generics.params,
+ AssocItemRibKind,
+ LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Item },
+ |this| {
+ // If this is a trait impl, ensure the type
+ // exists in trait
+ this.check_trait_item(
+ item.id,
+ item.ident,
+ &item.kind,
+ TypeNS,
+ item.span,
+ |i, s, c| TypeNotMemberOfTrait(i, s, c),
+ );
+
+ visit::walk_assoc_item(
+ this,
+ item,
+ AssocCtxt::Impl,
+ )
+ },
+ );
+ }
+ AssocItemKind::MacCall(_) => {
+ panic!("unexpanded macro in resolve!")
+ }
+ }
+ }
+ });
+ });
+ },
+ );
});
});
});
self.r.record_partial_res(id, partial_res);
}
+ self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize);
partial_res
}
// trait to resolve. In that case, we leave the `B`
// segment to be resolved by type-check.
return Ok(Some(PartialRes::with_unresolved_segments(
- Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)),
+ Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()),
path.len(),
)));
}
Some((ident.name, ns)),
)
}
+}
+
+struct LifetimeCountVisitor<'a, 'b> {
+ r: &'b mut Resolver<'a>,
+}
- fn compute_num_lifetime_params(&mut self, id: NodeId, generics: &Generics) {
- let def_id = self.r.local_def_id(id);
- let count = generics
- .params
- .iter()
- .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
- .count();
- self.r.item_generics_num_lifetimes.insert(def_id, count);
+/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
+/// lifetime generic parameters.
+impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_> {
+ fn visit_item(&mut self, item: &'ast Item) {
+ match &item.kind {
+ ItemKind::TyAlias(box TyAlias { ref generics, .. })
+ | ItemKind::Fn(box Fn { ref generics, .. })
+ | ItemKind::Enum(_, ref generics)
+ | ItemKind::Struct(_, ref generics)
+ | ItemKind::Union(_, ref generics)
+ | ItemKind::Impl(box Impl { ref generics, .. })
+ | ItemKind::Trait(box Trait { ref generics, .. })
+ | ItemKind::TraitAlias(ref generics, _) => {
+ let def_id = self.r.local_def_id(item.id);
+ let count = generics
+ .params
+ .iter()
+ .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
+ .count();
+ self.r.item_generics_num_lifetimes.insert(def_id, count);
+ }
+
+ ItemKind::Mod(..)
+ | ItemKind::ForeignMod(..)
+ | ItemKind::Static(..)
+ | ItemKind::Const(..)
+ | ItemKind::Use(..)
+ | ItemKind::ExternCrate(..)
+ | ItemKind::MacroDef(..)
+ | ItemKind::GlobalAsm(..)
+ | ItemKind::MacCall(..) => {}
+ }
+ visit::walk_item(self, item)
}
}
impl<'a> Resolver<'a> {
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
+ visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext};
use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
+use crate::late::{LifetimeBinderKind, LifetimeRibKind};
use crate::path_names_to_string;
use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{PathResult, PathSource, Segment};
use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::PrimTy;
use rustc_session::parse::feature_err;
use rustc_span::edition::Edition;
}
})
.collect::<Vec<_>>();
- let crate_def_id = DefId::local(CRATE_DEF_INDEX);
+ let crate_def_id = CRATE_DEF_ID.to_def_id();
if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
let mut enum_candidates: Vec<_> = self
.r
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
self.r.crate_loader.maybe_process_path_extern(ident.name).and_then(
|crate_id| {
- let crate_mod = Res::Def(
- DefKind::Mod,
- DefId { krate: crate_id, index: CRATE_DEF_INDEX },
- );
+ let crate_mod =
+ Res::Def(DefKind::Mod, crate_id.as_def_id());
if filter_fn(crate_mod) {
Some(TypoSuggestion::typo_from_res(
(*ident, within_scope)
})
}
-}
-impl<'tcx> LifetimeContext<'_, 'tcx> {
- crate fn report_missing_lifetime_specifiers(
+ crate fn emit_undeclared_lifetime_error(
&self,
- spans: Vec<Span>,
- count: usize,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- struct_span_err!(
- self.tcx.sess,
- spans,
- E0106,
- "missing lifetime specifier{}",
- pluralize!(count)
- )
- }
+ lifetime_ref: &ast::Lifetime,
+ outer_lifetime_ref: Option<Ident>,
+ ) {
+ debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
+ let mut err = if let Some(outer) = outer_lifetime_ref {
+ let mut err = struct_span_err!(
+ self.r.session,
+ lifetime_ref.ident.span,
+ E0401,
+ "can't use generic parameters from outer item",
+ );
+ err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item");
+ err.span_label(outer.span, "lifetime parameter from outer item");
+ err
+ } else {
+ let mut err = struct_span_err!(
+ self.r.session,
+ lifetime_ref.ident.span,
+ E0261,
+ "use of undeclared lifetime name `{}`",
+ lifetime_ref.ident
+ );
+ err.span_label(lifetime_ref.ident.span, "undeclared lifetime");
+ err
+ };
+ let mut suggest_note = true;
- crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
- let mut err = struct_span_err!(
- self.tcx.sess,
- lifetime_ref.span,
- E0261,
- "use of undeclared lifetime name `{}`",
- lifetime_ref
- );
- err.span_label(lifetime_ref.span, "undeclared lifetime");
- let mut suggested_spans = vec![];
- for missing in &self.missing_named_lifetime_spots {
- match missing {
- MissingLifetimeSpot::Generics(generics) => {
- let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| {
- !matches!(
- p.kind,
- hir::GenericParamKind::Type { synthetic: true, .. }
- | hir::GenericParamKind::Lifetime {
- kind: hir::LifetimeParamKind::Elided,
- }
- )
- }) {
- (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
- } else {
- (generics.span, format!("<{}>", lifetime_ref))
- };
- if suggested_spans.contains(&span) {
+ for rib in self.lifetime_ribs.iter().rev() {
+ match rib.kind {
+ LifetimeRibKind::Generics { span, kind } => {
+ if !span.can_be_used_for_suggestions() && suggest_note {
+ suggest_note = false; // Avoid displaying the same help multiple times.
+ err.span_label(
+ span,
+ &format!(
+ "lifetime `{}` is missing in item created through this procedural macro",
+ lifetime_ref.ident,
+ ),
+ );
continue;
}
- suggested_spans.push(span);
- if span.can_be_used_for_suggestions() {
+
+ let higher_ranked = matches!(
+ kind,
+ LifetimeBinderKind::BareFnType
+ | LifetimeBinderKind::PolyTrait
+ | LifetimeBinderKind::WhereBound
+ );
+ let (span, sugg) = if span.is_empty() {
+ let sugg = format!(
+ "{}<{}>{}",
+ if higher_ranked { "for" } else { "" },
+ lifetime_ref.ident,
+ if higher_ranked { " " } else { "" },
+ );
+ (span, sugg)
+ } else {
+ let span =
+ self.r.session.source_map().span_through_char(span, '<').shrink_to_hi();
+ let sugg = format!("{}, ", lifetime_ref.ident);
+ (span, sugg)
+ };
+ if higher_ranked {
+ err.span_suggestion(
+ span,
+ &format!(
+ "consider making the {} lifetime-generic with a new `{}` lifetime",
+ kind.descr(),
+ lifetime_ref
+ ),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ err.note_once(
+ "for more information on higher-ranked polymorphism, visit \
+ https://doc.rust-lang.org/nomicon/hrtb.html",
+ );
+ } else {
err.span_suggestion(
span,
- &format!("consider introducing lifetime `{}` here", lifetime_ref),
+ &format!("consider introducing lifetime `{}` here", lifetime_ref.ident),
sugg,
Applicability::MaybeIncorrect,
);
}
}
- MissingLifetimeSpot::HigherRanked { span, span_type } => {
- err.span_suggestion(
- *span,
- &format!(
- "consider making the {} lifetime-generic with a new `{}` lifetime",
- span_type.descr(),
- lifetime_ref
- ),
- span_type.suggestion(&lifetime_ref.to_string()),
- Applicability::MaybeIncorrect,
- );
- err.note(
- "for more information on higher-ranked polymorphism, visit \
- https://doc.rust-lang.org/nomicon/hrtb.html",
- );
- }
+ LifetimeRibKind::Item => break,
_ => {}
}
}
+
err.emit();
}
+}
+
+impl<'tcx> LifetimeContext<'_, 'tcx> {
+ crate fn report_missing_lifetime_specifiers(
+ &self,
+ spans: Vec<Span>,
+ count: usize,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ struct_span_err!(
+ self.tcx.sess,
+ spans,
+ E0106,
+ "missing lifetime specifier{}",
+ pluralize!(count)
+ )
+ }
/// Returns whether to add `'static` lifetime to the suggested lifetime list.
crate fn report_elision_failure(
}
}
- crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) {
- let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| {
- lt.name == hir::LifetimeName::Implicit(true)
- }) else { return };
-
- let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
- spans.sort();
- let mut spans_dedup = spans.clone();
- spans_dedup.dedup();
- let spans_with_counts: Vec<_> = spans_dedup
- .into_iter()
- .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
- .collect();
-
- self.tcx.struct_span_lint_hir(
- rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
- missing_lifetime.hir_id,
- spans,
- |lint| {
- let mut db = lint.build("hidden lifetime parameters in types are deprecated");
- self.add_missing_lifetime_specifiers_label(
- &mut db,
- spans_with_counts,
- &FxHashSet::from_iter([kw::UnderscoreLifetime]),
- Vec::new(),
- &[],
- );
- db.emit();
- },
- );
- }
-
// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
// generics. We are disallowing this until we can decide on how we want to handle non-'static
// lifetimes in const generics. See issue #74052 for discussion.
);
let is_allowed_lifetime = matches!(
lifetime_ref.name,
- hir::LifetimeName::Implicit(_)
- | hir::LifetimeName::Static
- | hir::LifetimeName::Underscore
+ hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
);
if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
map: &'a mut NamedRegionMap,
scope: ScopeRef<'a>,
- /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
- is_in_fn_syntax: bool,
-
is_in_const_generic: bool,
/// Indicates that we only care about the definition of a trait. This should
tcx,
map: &mut named_region_map,
scope: ROOT_SCOPE,
- is_in_fn_syntax: false,
is_in_const_generic: false,
trait_definition_only,
labels_in_fn: vec![],
hir_id: hir::HirId,
) {
let name = match fk {
- intravisit::FnKind::ItemFn(id, _, _, _) => id.name,
- intravisit::FnKind::Method(id, _, _) => id.name,
+ intravisit::FnKind::ItemFn(id, _, _) => id.name,
+ intravisit::FnKind::Method(id, _) => id.name,
intravisit::FnKind::Closure => sym::closure,
};
let name = name.as_str();
match ty.kind {
hir::TyKind::BareFn(ref c) => {
let next_early_index = self.next_early_index();
- let was_in_fn_syntax = self.is_in_fn_syntax;
- self.is_in_fn_syntax = true;
let lifetime_span: Option<Span> =
c.generic_params.iter().rev().find_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(param.span),
intravisit::walk_ty(this, ty);
});
self.missing_named_lifetime_spots.pop();
- self.is_in_fn_syntax = was_in_fn_syntax;
}
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
debug!(?bounds, ?lifetime, "TraitObject");
}
});
match lifetime.name {
- LifetimeName::Implicit(_) => {
+ LifetimeName::Implicit => {
// For types like `dyn Foo`, we should
// generate a special form of elided.
span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
tcx: *tcx,
map,
scope: &wrap_scope,
- is_in_fn_syntax: self.is_in_fn_syntax,
is_in_const_generic: self.is_in_const_generic,
trait_definition_only: self.trait_definition_only,
labels_in_fn,
self.insert_lifetime(lifetime_ref, def);
} else {
- self.emit_undeclared_lifetime_error(lifetime_ref);
+ self.tcx.sess.delay_span_bug(
+ lifetime_ref.span,
+ &format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
+ );
}
}
);
if generic_args.parenthesized {
- let was_in_fn_syntax = self.is_in_fn_syntax;
- self.is_in_fn_syntax = true;
self.visit_fn_like_elision(generic_args.inputs(), Some(generic_args.bindings[0].ty()));
- self.is_in_fn_syntax = was_in_fn_syntax;
return;
}
let error = loop {
match *scope {
// Do not assign any resolution, it will be inferred.
- Scope::Body { .. } => break Ok(()),
+ Scope::Body { .. } => return,
- Scope::Root => break Err(None),
+ Scope::Root => break None,
Scope::Binder { s, ref lifetimes, scope_type, .. } => {
// collect named lifetimes for suggestions
self.insert_lifetime(lifetime_ref, lifetime);
}
- break Ok(());
+ return;
}
Scope::Elision { elide: Elide::Exact(l), .. } => {
for lifetime_ref in lifetime_refs {
self.insert_lifetime(lifetime_ref, lifetime);
}
- break Ok(());
+ return;
}
Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
_ => break,
}
}
- break Err(Some(&e[..]));
+ break Some(&e[..]);
}
- Scope::Elision { elide: Elide::Forbid, .. } => break Err(None),
+ Scope::Elision { elide: Elide::Forbid, .. } => break None,
Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
}
};
- let error = match error {
- Ok(()) => {
- self.report_elided_lifetime_in_ty(lifetime_refs);
- return;
- }
- Err(error) => error,
- };
-
// If we specifically need the `scope_for_path` map, then we're in the
// diagnostic pass and we don't want to emit more errors.
if self.map.scope_for_path.is_some() {
if let hir::ParamName::Plain(_) = lifetime_i_name {
let name = lifetime_i_name.ident().name;
if name == kw::UnderscoreLifetime || name == kw::StaticLifetime {
- let mut err = struct_span_err!(
- self.tcx.sess,
- lifetime_i.span,
- E0262,
- "invalid lifetime parameter name: `{}`",
- lifetime_i.name.ident(),
- );
- err.span_label(
+ self.tcx.sess.delay_span_bug(
lifetime_i.span,
- format!("{} is a reserved lifetime name", name),
+ &format!("invalid lifetime parameter name: `{}`", lifetime_i.name.ident()),
);
- err.emit();
}
}
))
.emit();
}
- hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => {
+ hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
self.resolve_lifetime_ref(lt);
}
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
#![feature(drain_filter)]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
+#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(never_type)]
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
-use rustc_ast::{Crate, Expr, ExprKind, LitKind, Path};
+use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
use rustc_ast_lowering::ResolverAstLowering;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::intern::Interned;
use rustc_hir::def::Namespace::*;
use rustc_hir::def::{self, CtorOf, DefKind, PartialRes};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId};
-use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::TraitCandidate;
use rustc_index::vec::IndexVec;
trait_item_span: Span,
code: rustc_errors::DiagnosticId,
},
+ /// Inline asm `sym` operand must refer to a `fn` or `static`.
+ InvalidAsmSym,
}
enum VisResolutionError<'a> {
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
/// nonsensical suggestions.
has_generic_args: bool,
+ /// Signals whether this `PathSegment` has lifetime arguments.
+ has_lifetime_args: bool,
+ args_span: Span,
}
impl Segment {
}
fn from_ident(ident: Ident) -> Segment {
- Segment { ident, id: None, has_generic_args: false }
+ Segment {
+ ident,
+ id: None,
+ has_generic_args: false,
+ has_lifetime_args: false,
+ args_span: DUMMY_SP,
+ }
+ }
+
+ fn from_ident_and_id(ident: Ident, id: NodeId) -> Segment {
+ Segment {
+ ident,
+ id: Some(id),
+ has_generic_args: false,
+ has_lifetime_args: false,
+ args_span: DUMMY_SP,
+ }
}
fn names_to_string(segments: &[Segment]) -> String {
impl<'a> From<&'a ast::PathSegment> for Segment {
fn from(seg: &'a ast::PathSegment) -> Segment {
- Segment { ident: seg.ident, id: Some(seg.id), has_generic_args: seg.args.is_some() }
+ let has_generic_args = seg.args.is_some();
+ let (args_span, has_lifetime_args) = if let Some(args) = seg.args.as_deref() {
+ match args {
+ GenericArgs::AngleBracketed(args) => {
+ let found_lifetimes = args
+ .args
+ .iter()
+ .any(|arg| matches!(arg, AngleBracketedArg::Arg(GenericArg::Lifetime(_))));
+ (args.span, found_lifetimes)
+ }
+ GenericArgs::Parenthesized(args) => (args.span, true),
+ }
+ } else {
+ (DUMMY_SP, false)
+ };
+ Segment {
+ ident: seg.ident,
+ id: Some(seg.id),
+ has_generic_args,
+ has_lifetime_args,
+ args_span,
+ }
}
}
NameBindingKind::Module(&ModuleData {
kind: ModuleKind::Def(DefKind::Mod, def_id, _),
..
- }) => def_id.index == CRATE_DEF_INDEX,
+ }) => def_id.is_crate_root(),
_ => false,
}
}
glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
/// Visibilities in "lowered" form, for all entities that have them.
visibilities: FxHashMap<LocalDefId, ty::Visibility>,
+ has_pub_restricted: bool,
used_imports: FxHashSet<NodeId>,
maybe_unused_trait_imports: FxHashSet<LocalDefId>,
maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
);
let definitions = Definitions::new(session.local_stable_crate_id(), krate.spans.inner_span);
- let root = definitions.get_root_def();
let mut visibilities = FxHashMap::default();
visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public);
let mut def_id_to_node_id = IndexVec::default();
- assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
+ assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID);
let mut node_id_to_def_id = FxHashMap::default();
- node_id_to_def_id.insert(CRATE_NODE_ID, root);
+ node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID);
let mut invocation_parents = FxHashMap::default();
- invocation_parents.insert(LocalExpnId::ROOT, (root, ImplTraitContext::Existential));
+ invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
.opts
glob_map: Default::default(),
visibilities,
+ has_pub_restricted: false,
used_imports: FxHashSet::default(),
maybe_unused_trait_imports: Default::default(),
maybe_unused_extern_crates: Vec::new(),
}
pub fn next_node_id(&mut self) -> NodeId {
- let next =
- self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
- mem::replace(&mut self.next_node_id, ast::NodeId::from_u32(next))
+ let start = self.next_node_id;
+ let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
+ self.next_node_id = ast::NodeId::from_u32(next);
+ start
+ }
+
+ pub fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
+ let start = self.next_node_id;
+ let end = start.as_usize().checked_add(count).expect("input too large; ran out of NodeIds");
+ self.next_node_id = ast::NodeId::from_usize(end);
+ start..self.next_node_id
}
pub fn lint_buffer(&mut self) -> &mut LintBuffer {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
let definitions = self.definitions;
let visibilities = self.visibilities;
+ let has_pub_restricted = self.has_pub_restricted;
let extern_crate_map = self.extern_crate_map;
let reexport_map = self.reexport_map;
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
definitions,
cstore: Box::new(self.crate_loader.into_cstore()),
visibilities,
+ has_pub_restricted,
access_levels,
extern_crate_map,
reexport_map,
access_levels: self.access_levels.clone(),
cstore: Box::new(self.cstore().clone()),
visibilities: self.visibilities.clone(),
+ has_pub_restricted: self.has_pub_restricted,
extern_crate_map: self.extern_crate_map.clone(),
reexport_map: self.reexport_map.clone(),
glob_map: self.glob_map.clone(),
use rustc_middle::span_bug;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::Input;
-use rustc_span::source_map::respan;
use rustc_span::symbol::Ident;
use rustc_span::*;
}
macro_rules! access_from {
- ($save_ctxt:expr, $item:expr, $id:expr) => {
+ ($save_ctxt:expr, $id:expr) => {
Access {
- public: $item.vis.node.is_pub(),
+ public: $save_ctxt.tcx.visibility($id).is_public(),
reachable: $save_ctxt.access_levels.is_reachable($id),
}
};
}
-macro_rules! access_from_vis {
- ($save_ctxt:expr, $vis:expr, $id:expr) => {
- Access { public: $vis.node.is_pub(), reachable: $save_ctxt.access_levels.is_reachable($id) }
- };
-}
-
pub struct DumpVisitor<'tcx> {
pub save_ctxt: SaveContext<'tcx>,
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
ident: Ident,
generics: &'tcx hir::Generics<'tcx>,
- vis: &hir::Visibility<'tcx>,
span: Span,
) {
debug!("process_method: {:?}:{}", def_id, ident);
v.process_generic_params(&generics, &method_data.qualname, hir_id);
method_data.value =
- fn_to_string(sig.decl, sig.header, Some(ident.name), generics, vis, &[], None);
+ fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None);
method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
- v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, def_id), method_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, def_id), method_data);
}
// walk arg and return types
let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(field_data) = field_data {
self.dumper.dump_def(
- &access_from!(self.save_ctxt, field, self.tcx.hir().local_def_id(field.hir_id)),
+ &access_from!(self.save_ctxt, self.tcx.hir().local_def_id(field.hir_id)),
field_data,
);
}
v.process_formals(body.params, &fn_data.qualname);
v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id());
- v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), fn_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), fn_data);
}
for arg in decl.inputs {
self.nest_typeck_results(item.def_id, |v| {
if let Some(var_data) = v.save_ctxt.get_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
- v.dumper.dump_def(&access_from!(v.save_ctxt, item, item.def_id), var_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), var_data);
}
v.visit_ty(&typ);
v.visit_expr(expr);
typ: &'tcx hir::Ty<'tcx>,
expr: Option<&'tcx hir::Expr<'tcx>>,
parent_id: DefId,
- vis: &hir::Visibility<'tcx>,
attrs: &'tcx [ast::Attribute],
) {
let qualname = format!("::{}", self.tcx.def_path_str(def_id.to_def_id()));
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
- &access_from_vis!(self.save_ctxt, vis, def_id),
+ &access_from!(self.save_ctxt, def_id),
Def {
kind: DefKind::Const,
id: id_from_hir_id(hir_id, &self.save_ctxt),
let fields_str = fields
.iter()
.filter_map(|f| {
- if include_priv_fields || f.vis.node.is_pub() {
+ if include_priv_fields {
+ return Some(f.ident.to_string());
+ }
+ let def_id = self.save_ctxt.tcx.hir().local_def_id(f.hir_id);
+ if self.save_ctxt.tcx.visibility(def_id).is_public() {
Some(f.ident.to_string())
} else {
None
let span = self.span_from_span(item.ident.span);
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def(
- &access_from!(self.save_ctxt, item, item.def_id),
+ &access_from!(self.save_ctxt, item.def_id),
Def {
kind,
id: id_from_def_id(item.def_id.to_def_id()),
};
down_cast_data!(enum_data, DefData, item.span);
- let access = access_from!(self.save_ctxt, item, item.def_id);
+ let access = access_from!(self.save_ctxt, item.def_id);
for variant in enum_definition.variants {
let name = variant.ident.name.to_string();
methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect();
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def(
- &access_from!(self.save_ctxt, item, item.def_id),
+ &access_from!(self.save_ctxt, item.def_id),
Def {
kind: DefKind::Trait,
id,
fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
down_cast_data!(mod_data, DefData, item.span);
- self.dumper.dump_def(&access_from!(self.save_ctxt, item, item.def_id), mod_data);
+ self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id), mod_data);
}
}
fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) {
self.process_macro_use(trait_item.span);
- let vis_span = trait_item.span.shrink_to_lo();
match trait_item.kind {
hir::TraitItemKind::Const(ref ty, body) => {
let body = body.map(|b| &self.tcx.hir().body(b).value);
- let respan = respan(vis_span, hir::VisibilityKind::Public);
let attrs = self.tcx.hir().attrs(trait_item.hir_id());
self.process_assoc_const(
trait_item.def_id,
&ty,
body,
trait_id,
- &respan,
attrs,
);
}
hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
let body =
if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None };
- let respan = respan(vis_span, hir::VisibilityKind::Public);
self.process_method(
sig,
body,
trait_item.def_id,
trait_item.ident,
&trait_item.generics,
- &respan,
trait_item.span,
);
}
&ty,
Some(&body.value),
impl_id,
- &impl_item.vis,
attrs,
);
}
impl_item.def_id,
impl_item.ident,
&impl_item.generics,
- &impl_item.vis,
impl_item.span,
);
}
hir::ItemKind::Use(path, hir::UseKind::Single) => {
let sub_span = path.segments.last().unwrap().ident.span;
if !self.span.filter_generated(sub_span) {
- let access = access_from!(self.save_ctxt, item, item.def_id);
+ let access = access_from!(self.save_ctxt, item.def_id);
let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id);
let span = self.span_from_span(sub_span);
let parent =
// we don't want to track anyway, since it's probably macro-internal `use`
if let Some(sub_span) = self.span.sub_span_of_star(item.span) {
if !self.span.filter_generated(item.span) {
- let access = access_from!(self.save_ctxt, item, item.def_id);
+ let access = access_from!(self.save_ctxt, item.def_id);
let span = self.span_from_span(sub_span);
let parent =
self.save_ctxt.tcx.parent(item.def_id.to_def_id()).map(id_from_def_id);
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def(
- &access_from!(self.save_ctxt, item, item.def_id),
+ &access_from!(self.save_ctxt, item.def_id),
Def {
kind: DefKind::Type,
id,
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- let access = access_from!(self.save_ctxt, item, item.def_id);
+ let access = access_from!(self.save_ctxt, item.def_id);
match item.kind {
hir::ForeignItemKind::Fn(decl, _, ref generics) => {
use rustc_session::config::{CrateType, Input, OutputType};
use rustc_session::cstore::ExternCrate;
use rustc_session::output::{filename_for_metadata, out_filename};
-use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
use rustc_span::*;
},
Some(item.ident.name),
generics,
- &item.vis,
arg_names,
None,
),
sig.header,
Some(item.ident.name),
generics,
- &item.vis,
&[],
None,
),
let qualname = format!("::{}", self.tcx.def_path_str(def_id));
filter!(self.span_utils, item.ident.span);
let value =
- enum_def_to_string(def, generics, item.ident.name, item.span, &item.vis);
+ enum_def_to_string(def, generics, item.ident.name, item.span);
Some(Data::DefData(Def {
kind: DefKind::Enum,
id: id_from_def_id(def_id),
Node::TraitRef(tr) => tr.path.res,
Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => path.res,
- Node::Visibility(&Spanned {
- node: hir::VisibilityKind::Restricted { ref path, .. },
- ..
- }) => path.res,
-
Node::PathSegment(seg) => match seg.res {
Some(res) if res != Res::Err => res,
_ => {
pub use crate::options::*;
-use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
use crate::{early_error, early_warn, Session};
+use crate::{lint, HashStableContext};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::impl_stable_hash_via_hash;
+use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_target::abi::{Align, TargetDataLayout};
use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
-use rustc_serialize::json;
-
use crate::parse::{CrateCheckConfig, CrateConfig};
use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
Full,
}
-#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)]
pub enum OptLevel {
No, // -O0
Less, // -O1
SizeMin, // -Oz
}
-impl_stable_hash_via_hash!(OptLevel);
-
/// This is what the `LtoCli` values get mapped to after resolving defaults and
/// and taking other command line options into account.
///
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic)]
#[derive(Encodable, Decodable)]
pub enum SymbolManglingVersion {
Legacy,
V0,
}
-impl_stable_hash_via_hash!(SymbolManglingVersion);
-
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub enum DebugInfo {
None,
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
#[derive(Encodable, Decodable)]
pub enum OutputType {
Bitcode,
DepInfo,
}
-impl_stable_hash_via_hash!(OutputType);
+impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
+ type KeyType = Self;
+
+ fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
+ *self
+ }
+}
impl OutputType {
fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
/// dependency tracking for command-line arguments. Also only hash keys, since tracking
/// should only depend on the output types, not the paths they're written to.
-#[derive(Clone, Debug, Hash)]
+#[derive(Clone, Debug, Hash, HashStable_Generic)]
pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
impl OutputTypes {
#[derive(Clone)]
pub struct Externs(BTreeMap<String, ExternEntry>);
-#[derive(Clone)]
-pub struct ExternDepSpecs(BTreeMap<String, ExternDepSpec>);
-
#[derive(Clone, Debug)]
pub struct ExternEntry {
pub location: ExternLocation,
/// This can be disabled with the `noprelude` option like
/// `--extern noprelude:name`.
pub add_prelude: bool,
+ /// The extern entry shouldn't be considered for unused dependency warnings.
+ ///
+ /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
+ /// suppress `unused-crate-dependencies` warnings.
+ pub nounused_dep: bool,
}
#[derive(Clone, Debug)]
ExactPaths(BTreeSet<CanonicalizedPath>),
}
-/// Supplied source location of a dependency - for example in a build specification
-/// file like Cargo.toml. We support several syntaxes: if it makes sense to reference
-/// a file and line, then the build system can specify that. On the other hand, it may
-/// make more sense to have an arbitrary raw string.
-#[derive(Clone, PartialEq)]
-pub enum ExternDepSpec {
- /// Raw string
- Raw(String),
- /// Raw data in json format
- Json(json::Json),
-}
-
-impl<'a> From<&'a ExternDepSpec> for rustc_lint_defs::ExternDepSpec {
- fn from(from: &'a ExternDepSpec) -> Self {
- match from {
- ExternDepSpec::Raw(s) => rustc_lint_defs::ExternDepSpec::Raw(s.clone()),
- ExternDepSpec::Json(json) => rustc_lint_defs::ExternDepSpec::Json(json.clone()),
- }
- }
-}
-
impl Externs {
/// Used for testing.
pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
impl ExternEntry {
fn new(location: ExternLocation) -> ExternEntry {
- ExternEntry { location, is_private_dep: false, add_prelude: false }
+ ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
}
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
}
}
-impl ExternDepSpecs {
- pub fn new(data: BTreeMap<String, ExternDepSpec>) -> ExternDepSpecs {
- ExternDepSpecs(data)
- }
-
- pub fn get(&self, key: &str) -> Option<&ExternDepSpec> {
- self.0.get(key)
- }
-}
-
-impl fmt::Display for ExternDepSpec {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- ExternDepSpec::Raw(raw) => fmt.write_str(raw),
- ExternDepSpec::Json(json) => json::as_json(json).fmt(fmt),
- }
- }
-}
-
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PrintRequest {
FileNames,
}
}
-#[derive(Clone, Hash, Debug)]
+#[derive(Clone, Hash, Debug, HashStable_Generic)]
pub struct OutputFilenames {
pub out_directory: PathBuf,
filestem: String,
pub outputs: OutputTypes,
}
-impl_stable_hash_via_hash!(OutputFilenames);
-
pub const RLINK_EXT: &str = "rlink";
pub const RUST_CGU_EXT: &str = "rcgu";
pub const DWARF_OBJECT_EXT: &str = "dwo";
cg: Default::default(),
error_format: ErrorOutputType::default(),
externs: Externs(BTreeMap::new()),
- extern_dep_specs: ExternDepSpecs(BTreeMap::new()),
crate_name: None,
libs: Vec::new(),
unstable_features: UnstableFeatures::Disallow,
}
// The type of entry function, so users can have their own entry functions
-#[derive(Copy, Clone, PartialEq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)]
pub enum EntryFnType {
Main,
Start,
}
-impl_stable_hash_via_hash!(EntryFnType);
-
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
pub enum CrateType {
Executable,
Dylib,
ProcMacro,
}
-impl_stable_hash_via_hash!(CrateType);
-
impl CrateType {
/// When generated, is this crate type an archive?
pub fn is_archive(&self) -> bool {
"Specify where an external rust library is located",
"NAME[=PATH]",
),
- opt::multi_s(
- "",
- "extern-location",
- "Location where an external crate dependency is specified",
- "NAME=LOCATION",
- ),
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
opt::multi("Z", "", "Set internal debugging options", "FLAG"),
opt::opt_s(
let mut is_private_dep = false;
let mut add_prelude = true;
+ let mut nounused_dep = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
);
}
}
+ "nounused" => nounused_dep = true,
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
}
}
// Crates start out being not private, and go to being private `priv`
// is specified.
entry.is_private_dep |= is_private_dep;
+ // likewise `nounused`
+ entry.nounused_dep |= nounused_dep;
// If any flag is missing `noprelude`, then add to the prelude.
entry.add_prelude |= add_prelude;
}
Externs(externs)
}
-fn parse_extern_dep_specs(
- matches: &getopts::Matches,
- debugging_opts: &DebuggingOptions,
- error_format: ErrorOutputType,
-) -> ExternDepSpecs {
- let is_unstable_enabled = debugging_opts.unstable_options;
- let mut map = BTreeMap::new();
-
- for arg in matches.opt_strs("extern-location") {
- if !is_unstable_enabled {
- early_error(
- error_format,
- "`--extern-location` option is unstable: set `-Z unstable-options`",
- );
- }
-
- let mut parts = arg.splitn(2, '=');
- let name = parts.next().unwrap_or_else(|| {
- early_error(error_format, "`--extern-location` value must not be empty")
- });
- let loc = parts.next().unwrap_or_else(|| {
- early_error(
- error_format,
- &format!("`--extern-location`: specify location for extern crate `{name}`"),
- )
- });
-
- let locparts: Vec<_> = loc.split(':').collect();
- let spec = match &locparts[..] {
- ["raw", ..] => {
- // Don't want `:` split string
- let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| {
- early_error(error_format, "`--extern-location`: missing `raw` location")
- });
- ExternDepSpec::Raw(raw.to_string())
- }
- ["json", ..] => {
- // Don't want `:` split string
- let raw = loc.splitn(2, ':').nth(1).unwrap_or_else(|| {
- early_error(error_format, "`--extern-location`: missing `json` location")
- });
- let json = json::from_str(raw).unwrap_or_else(|_| {
- early_error(
- error_format,
- &format!("`--extern-location`: malformed json location `{raw}`"),
- )
- });
- ExternDepSpec::Json(json)
- }
- [bad, ..] => early_error(
- error_format,
- &format!("unknown location type `{bad}`: use `raw` or `json`"),
- ),
- [] => early_error(error_format, "missing location specification"),
- };
-
- map.insert(name.to_string(), spec);
- }
-
- ExternDepSpecs::new(map)
-}
-
fn parse_remap_path_prefix(
matches: &getopts::Matches,
debugging_opts: &DebuggingOptions,
}
let externs = parse_externs(matches, &debugging_opts, error_format);
- let extern_dep_specs = parse_extern_dep_specs(matches, &debugging_opts, error_format);
let crate_name = matches.opt_str("crate-name");
error_format,
externs,
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
- extern_dep_specs,
crate_name,
libs,
debug_assertions,
borrowck_mode: BorrowckMode [UNTRACKED],
cg: CodegenOptions [SUBSTRUCT],
externs: Externs [UNTRACKED],
- extern_dep_specs: ExternDepSpecs [UNTRACKED],
crate_name: Option<String> [TRACKED],
/// Indicates how the compiler should treat unstable features.
unstable_features: UnstableFeatures [TRACKED],
pub const parse_opt_langid: &str = "a language identifier";
pub const parse_opt_pathbuf: &str = "a path";
pub const parse_list: &str = "a space-separated list of strings";
+ pub const parse_list_with_polarity: &str =
+ "a comma-separated list of strings, with elements beginning with + or -";
pub const parse_opt_comma_list: &str = "a comma-separated list of strings";
pub const parse_number: &str = "a number";
pub const parse_opt_number: &str = parse_number;
}
}
+ crate fn parse_list_with_polarity(slot: &mut Vec<(String, bool)>, v: Option<&str>) -> bool {
+ match v {
+ Some(s) => {
+ for s in s.split(",") {
+ let Some(pass_name) = s.strip_prefix(&['+', '-'][..]) else { return false };
+ slot.push((pass_name.to_string(), &s[..1] == "+"));
+ }
+ true
+ }
+ None => false,
+ }
+ }
+
crate fn parse_location_detail(ld: &mut LocationDetail, v: Option<&str>) -> bool {
if let Some(v) = v {
ld.line = false;
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
(default: no)"),
+ mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED],
+ "use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be \
+ enabled, overriding all other checks. Passes that are not specified are enabled or \
+ disabled by other flags as usual."),
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
pub file_name_str: String,
}
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable, HashStable_Generic)]
pub enum PathKind {
Native,
Crate,
All,
}
-rustc_data_structures::impl_stable_hash_via_hash!(PathKind);
-
impl PathKind {
pub fn matches(&self, kind: PathKind) -> bool {
match (self, kind) {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
pub enum NativeLibKind {
/// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
Static {
}
}
-rustc_data_structures::impl_stable_hash_via_hash!(NativeLibKind);
-
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
pub struct NativeLib {
pub name: String,
pub new_name: Option<String>,
}
}
-rustc_data_structures::impl_stable_hash_via_hash!(NativeLib);
-
/// A path that has been canonicalized along with its original, non-canonicalized form
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CanonicalizedPath {
self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self))
}
+ #[inline]
+ pub fn is_crate_root(self) -> bool {
+ self.index == CRATE_DEF_INDEX
+ }
+
+ #[inline]
+ pub fn as_crate_root(self) -> Option<CrateNum> {
+ if self.is_crate_root() { Some(self.krate) } else { None }
+ }
+
+ #[inline]
pub fn is_top_level_module(self) -> bool {
- self.is_local() && self.index == CRATE_DEF_INDEX
+ self.is_local() && self.is_crate_root()
}
}
#[inline]
pub fn is_top_level_module(self) -> bool {
- self.local_def_index == CRATE_DEF_INDEX
+ self == CRATE_DEF_ID
}
}
/// of `HashingControls` settings.
fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) {
match ctx.hashing_controls() {
- // Ideally, we would also check that `node_id_hashing_mode` was always
- // `NodeIdHashingMode::HashDefPath`. However, we currently end up hashing
- // `Span`s in this mode, and there's not an easy way to change that.
- // All of the span-related data that we hash is pretty self-contained
- // (in particular, we don't hash any `HirId`s), so this shouldn't result
- // in any caching problems.
- // FIXME: Enforce that we don't end up transitively hashing any `HirId`s,
- // or ensure that this method is always invoked with the same
- // `NodeIdHashingMode`
- //
// Note that we require that `hash_spans` be set according to the global
// `-Z incremental-ignore-spans` option. Normally, this option is disabled,
// which will cause us to require that this method always be called with `Span` hashing
mod analyze_source_file;
pub mod fatal_error;
+pub mod profiling;
+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc};
pub struct OffsetOverflowError;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
pub enum SourceFileHashAlgorithm {
Md5,
Sha1,
}
}
-rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm);
-
/// The hash of the on-disk source file used for debug info.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(HashStable_Generic, Encodable, Decodable)]
--- /dev/null
+use std::borrow::Borrow;
+
+use rustc_data_structures::profiling::EventArgRecorder;
+
+/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's
+/// event arguments.
+pub trait SpannedEventArgRecorder {
+ /// Records the following event arguments within the current generic activity being profiled:
+ /// - the provided `event_arg`
+ /// - a string representation of the provided `span`
+ ///
+ /// Note: when self-profiling with costly event arguments, at least one argument
+ /// needs to be recorded. A panic will be triggered if that doesn't happen.
+ fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+ where
+ A: Borrow<str> + Into<String>;
+}
+
+impl SpannedEventArgRecorder for EventArgRecorder<'_> {
+ fn record_arg_with_span<A>(&mut self, event_arg: A, span: crate::Span)
+ where
+ A: Borrow<str> + Into<String>,
+ {
+ self.record_arg(event_arg);
+
+ let span_arg = crate::with_session_globals(|session_globals| {
+ if let Some(source_map) = &*session_globals.source_map.borrow() {
+ source_map.span_to_embeddable_string(span)
+ } else {
+ format!("{:?}", span)
+ }
+ });
+ self.record_arg(span_arg);
+ }
+}
keyword,
kind,
kreg,
+ kreg0,
label,
label_break_value,
lang,
simd,
simd_add,
simd_and,
+ simd_arith_offset,
simd_as,
simd_bitmask,
simd_cast,
//! def-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
-use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
}
tcx.dep_graph.with_ignore(|| {
- let mut visitor = SymbolNamesTest { tcx };
- tcx.hir().visit_all_item_likes(&mut visitor);
+ let mut symbol_names = SymbolNamesTest { tcx };
+ let crate_items = tcx.hir_crate_items(());
+
+ for id in crate_items.items() {
+ symbol_names.process_attrs(id.def_id);
+ }
+
+ for id in crate_items.trait_items() {
+ symbol_names.process_attrs(id.def_id);
+ }
+
+ for id in crate_items.impl_items() {
+ symbol_names.process_attrs(id.def_id);
+ }
+
+ for id in crate_items.foreign_items() {
+ symbol_names.process_attrs(id.def_id);
+ }
})
}
}
}
}
-
-impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> {
- fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.process_attrs(item.def_id);
- }
-
- fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
- self.process_attrs(trait_item.def_id);
- }
-
- fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
- self.process_attrs(impl_item.def_id);
- }
-
- fn visit_foreign_item(&mut self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
- self.process_attrs(foreign_item.def_id);
- }
-}
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
- k1, k2, k3, k4, k5, k6, k7,
+ k0, k1, k2, k3, k4, k5, k6, k7,
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
st0, st1, st2, st3, st4, st5, st6, st7,
zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
- k1, k2, k3, k4, k5, k6, k7,
+ k0, k1, k2, k3, k4, k5, k6, k7,
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
st0, st1, st2, st3, st4, st5, st6, st7,
zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23,
zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31,
- k1, k2, k3, k4, k5, k6, k7,
+ k0, k1, k2, k3, k4, k5, k6, k7,
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7,
st0, st1, st2, st3, st4, st5, st6, st7,
ymm_reg,
zmm_reg,
kreg,
+ kreg0,
mmx_reg,
x87_reg,
}
}
Self::reg_byte => &[],
Self::xmm_reg | Self::ymm_reg | Self::zmm_reg => &['x', 'y', 'z'],
- Self::kreg => &[],
+ Self::kreg | Self::kreg0 => &[],
Self::mmx_reg | Self::x87_reg => &[],
}
}
256 => Some(('y', "ymm0")),
_ => Some(('x', "xmm0")),
},
- Self::kreg => None,
+ Self::kreg | Self::kreg0 => None,
Self::mmx_reg | Self::x87_reg => None,
}
}
Self::xmm_reg => Some(('x', "xmm0")),
Self::ymm_reg => Some(('y', "ymm0")),
Self::zmm_reg => Some(('z', "zmm0")),
- Self::kreg => None,
+ Self::kreg | Self::kreg0 => None,
Self::mmx_reg | Self::x87_reg => None,
}
}
avx512f: I8, I16;
avx512bw: I32, I64;
},
+ Self::kreg0 => &[],
Self::mmx_reg | Self::x87_reg => &[],
}
}
zmm29: zmm_reg = ["zmm29", "xmm29", "ymm29"] % x86_64_only,
zmm30: zmm_reg = ["zmm30", "xmm30", "ymm30"] % x86_64_only,
zmm31: zmm_reg = ["zmm31", "xmm31", "ymm31"] % x86_64_only,
+ k0: kreg0 = ["k0"],
k1: kreg = ["k1"],
k2: kreg = ["k2"],
k3: kreg = ["k3"],
"the stack pointer cannot be used as an operand for inline asm",
#error = ["ip", "eip", "rip"] =>
"the instruction pointer cannot be used as an operand for inline asm",
- #error = ["k0"] =>
- "the k0 AVX mask register cannot be used as an operand for inline asm",
}
}
}),
_ => None,
};
- self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
+ self.note_type_err(
+ &mut diag,
+ &obligation.cause,
+ secondary_span,
+ values,
+ err,
+ true,
+ false,
+ );
self.note_obligation_cause(&mut diag, obligation);
diag.emit();
});
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_middle::hir::map;
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
- Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable,
+ GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, ToPredicate, Ty, TyCtxt,
+ TypeFoldable,
};
use rustc_middle::ty::{TypeAndMut, TypeckResults};
use rustc_session::Limit;
Upvar(Span),
}
+// This type provides a uniform interface to retrieve data on generators, whether it originated from
+// the local crate being compiled or from a foreign crate.
+#[derive(Debug)]
+pub enum GeneratorData<'tcx, 'a> {
+ Local(&'a TypeckResults<'tcx>),
+ Foreign(&'tcx GeneratorDiagnosticData<'tcx>),
+}
+
+impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
+ // Try to get information about variables captured by the generator that matches a type we are
+ // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
+ // meet an obligation
+ fn try_get_upvar_span<F>(
+ &self,
+ infer_context: &InferCtxt<'a, 'tcx>,
+ generator_did: DefId,
+ ty_matches: F,
+ ) -> Option<GeneratorInteriorOrUpvar>
+ where
+ F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
+ {
+ match self {
+ GeneratorData::Local(typeck_results) => {
+ infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
+ upvars.iter().find_map(|(upvar_id, upvar)| {
+ let upvar_ty = typeck_results.node_type(*upvar_id);
+ let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
+ if ty_matches(ty::Binder::dummy(upvar_ty)) {
+ Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
+ } else {
+ None
+ }
+ })
+ })
+ }
+ GeneratorData::Foreign(_) => None,
+ }
+ }
+
+ // Try to get the span of a type being awaited on that matches the type we are looking with the
+ // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
+ // obligation
+ fn get_from_await_ty<F>(
+ &self,
+ visitor: AwaitsVisitor,
+ hir: map::Map<'tcx>,
+ ty_matches: F,
+ ) -> Option<Span>
+ where
+ F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
+ {
+ match self {
+ GeneratorData::Local(typeck_results) => visitor
+ .awaits
+ .into_iter()
+ .map(|id| hir.expect_expr(id))
+ .find(|await_expr| {
+ ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
+ })
+ .map(|expr| expr.span),
+ GeneratorData::Foreign(generator_diagnostic_data) => visitor
+ .awaits
+ .into_iter()
+ .map(|id| hir.expect_expr(id))
+ .find(|await_expr| {
+ ty_matches(ty::Binder::dummy(
+ generator_diagnostic_data
+ .adjustments
+ .get(&await_expr.hir_id.local_id)
+ .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..])
+ .last()
+ .map_or_else::<Ty<'tcx>, _, _>(
+ || {
+ generator_diagnostic_data
+ .nodes_types
+ .get(&await_expr.hir_id.local_id)
+ .cloned()
+ .unwrap_or_else(|| {
+ bug!(
+ "node_type: no type for node `{}`",
+ ty::tls::with(|tcx| tcx
+ .hir()
+ .node_to_string(await_expr.hir_id))
+ )
+ })
+ },
+ |adj| adj.target,
+ ),
+ ))
+ })
+ .map(|expr| expr.span),
+ }
+ }
+
+ /// Get the type, expression, span and optional scope span of all types
+ /// that are live across the yield of this generator
+ fn get_generator_interior_types(
+ &self,
+ ) -> ty::Binder<'tcx, &Vec<GeneratorInteriorTypeCause<'tcx>>> {
+ match self {
+ GeneratorData::Local(typeck_result) => typeck_result.generator_interior_types.as_ref(),
+ GeneratorData::Foreign(generator_diagnostic_data) => {
+ generator_diagnostic_data.generator_interior_types.as_ref()
+ }
+ }
+ }
+
+ // Used to get the source of the data, note we don't have as much information for generators
+ // originated from foreign crates
+ fn is_foreign(&self) -> bool {
+ match self {
+ GeneratorData::Local(_) => false,
+ GeneratorData::Foreign(_) => true,
+ }
+ }
+}
+
// This trait is public to expose the diagnostics methods to clippy.
pub trait InferCtxtExt<'tcx> {
fn suggest_restricting_param_bound(
err: &mut Diagnostic,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
- inner_generator_body: Option<&hir::Body<'tcx>>,
+ is_async: bool,
outer_generator: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>,
.map(|def_id| hir.local_def_id_to_hir_id(def_id))
.and_then(|hir_id| hir.maybe_body_owned_by(hir_id))
.map(|body_id| hir.body(body_id));
+ let is_async = match generator_did.as_local() {
+ Some(_) => generator_body
+ .and_then(|body| body.generator_kind())
+ .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
+ .unwrap_or(false),
+ None => self
+ .tcx
+ .generator_kind(generator_did)
+ .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
+ .unwrap_or(false),
+ };
let mut visitor = AwaitsVisitor::default();
if let Some(body) = generator_body {
visitor.visit_body(body);
// type-checking; otherwise, get them by performing a query. This is needed to avoid
// cycles. If we can't use resolved types because the generator comes from another crate,
// we still provide a targeted error but without all the relevant spans.
- let query_typeck_results;
- let typeck_results: Option<&TypeckResults<'tcx>> = match &in_progress_typeck_results {
- Some(t) if t.hir_owner.to_def_id() == generator_did_root => Some(&t),
+ let generator_data: Option<GeneratorData<'tcx, '_>> = match &in_progress_typeck_results {
+ Some(t) if t.hir_owner.to_def_id() == generator_did_root => {
+ Some(GeneratorData::Local(&t))
+ }
_ if generator_did.is_local() => {
- query_typeck_results = self.tcx.typeck(generator_did.expect_local());
- Some(&query_typeck_results)
+ Some(GeneratorData::Local(self.tcx.typeck(generator_did.expect_local())))
}
- _ => None, // Do not ICE on closure typeck (#66868).
+ _ => self
+ .tcx
+ .generator_diagnostic_data(generator_did)
+ .as_ref()
+ .map(|generator_diag_data| GeneratorData::Foreign(generator_diag_data)),
};
- if let Some(typeck_results) = typeck_results {
- if let Some(upvars) = self.tcx.upvars_mentioned(generator_did) {
- interior_or_upvar_span = upvars.iter().find_map(|(upvar_id, upvar)| {
- let upvar_ty = typeck_results.node_type(*upvar_id);
- let upvar_ty = self.resolve_vars_if_possible(upvar_ty);
- if ty_matches(ty::Binder::dummy(upvar_ty)) {
- Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
- } else {
- None
- }
- });
- };
+
+ if let Some(generator_data) = generator_data.as_ref() {
+ interior_or_upvar_span =
+ generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
// The generator interior types share the same binders
if let Some(cause) =
- typeck_results.generator_interior_types.as_ref().skip_binder().iter().find(
+ generator_data.get_generator_interior_types().skip_binder().iter().find(
|ty::GeneratorInteriorTypeCause { ty, .. }| {
- ty_matches(typeck_results.generator_interior_types.rebind(*ty))
+ ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
},
)
{
- // Check to see if any awaited expressions have the target type.
- let from_awaited_ty = visitor
- .awaits
- .into_iter()
- .map(|id| hir.expect_expr(id))
- .find(|await_expr| {
- ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
- })
- .map(|expr| expr.span);
+ let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } =
cause;
interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span));
interior_extra_info = Some((*scope_span, *yield_span, *expr, from_awaited_ty));
- };
- } else {
- interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
+ }
+
+ if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
+ interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span));
+ }
}
if let Some(interior_or_upvar_span) = interior_or_upvar_span {
+ let typeck_results = generator_data.and_then(|generator_data| match generator_data {
+ GeneratorData::Local(typeck_results) => Some(typeck_results),
+ GeneratorData::Foreign(_) => None,
+ });
self.note_obligation_cause_for_async_await(
err,
interior_or_upvar_span,
interior_extra_info,
- generator_body,
+ is_async,
outer_generator,
trait_ref,
target_ty,
err: &mut Diagnostic,
interior_or_upvar_span: GeneratorInteriorOrUpvar,
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
- inner_generator_body: Option<&hir::Body<'tcx>>,
+ is_async: bool,
outer_generator: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>,
) {
let source_map = self.tcx.sess.source_map();
- let is_async = inner_generator_body
- .and_then(|body| body.generator_kind())
- .map(|generator_kind| matches!(generator_kind, hir::GeneratorKind::Async(..)))
- .unwrap_or(false);
let (await_or_yield, an_await_or_yield) =
if is_async { ("await", "an await") } else { ("yield", "a yield") };
let future_or_generator = if is_async { "future" } else { "generator" };
&format!(
"consider annotating `{}` with `#[derive({})]`",
trait_pred.skip_binder().self_ty(),
- diagnostic_name.to_string(),
+ diagnostic_name,
),
- format!("#[derive({})]\n", diagnostic_name.to_string()),
+ format!("#[derive({})]\n", diagnostic_name),
Applicability::MaybeIncorrect,
);
}
use rustc_span::{Span, DUMMY_SP};
use std::collections::BTreeSet;
-use std::iter;
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
let mut suggestions = vec![];
let mut types_count = 0;
let mut where_constraints = vec![];
+ let mut already_has_generics_args_suggestion = false;
for (span, assoc_items) in &associated_types {
let mut names: FxHashMap<_, usize> = FxHashMap::default();
for item in assoc_items {
}
}
if potential_assoc_types.len() == assoc_items.len() {
- // Only suggest when the amount of missing associated types equals the number of
- // extra type arguments present, as that gives us a relatively high confidence
- // that the user forgot to give the associated type's name. The canonical
- // example would be trying to use `Iterator<isize>` instead of
- // `Iterator<Item = isize>`.
- for (potential, item) in iter::zip(&potential_assoc_types, assoc_items) {
- if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*potential) {
- suggestions.push((*potential, format!("{} = {}", item.name, snippet)));
- }
- }
+ // When the amount of missing associated types equals the number of
+ // extra type arguments present. A suggesting to replace the generic args with
+ // associated types is already emitted.
+ already_has_generics_args_suggestion = true;
} else if let (Ok(snippet), false) =
(tcx.sess.source_map().span_to_snippet(*span), dupes)
{
// the same associated type name.
err.help(where_msg);
}
- if suggestions.len() != 1 {
+ if suggestions.len() != 1 || already_has_generics_args_suggestion {
// We don't need this label if there's an inline suggestion, show otherwise.
for (span, assoc_items) in &associated_types {
let mut names: FxHashMap<_, usize> = FxHashMap::default();
// We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = HirPlaceholderCollector::default();
- for ty in decl.inputs {
- visitor.visit_ty(ty);
- }
+ let mut infer_replacements = vec![];
+
walk_generics(&mut visitor, generics);
- let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
+ let input_tys: Vec<_> = decl
+ .inputs
+ .iter()
+ .enumerate()
+ .map(|(i, a)| {
+ if let hir::TyKind::Infer = a.kind && !self.allow_ty_infer() {
+ if let Some(suggested_ty) =
+ self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
+ {
+ infer_replacements.push((a.span, suggested_ty.to_string()));
+ return suggested_ty;
+ }
+ }
+
+ // Only visit the type looking for `_` if we didn't fix the type above
+ visitor.visit_ty(a);
+ self.ty_of_arg(a, None)
+ })
+ .collect();
+
let output_ty = match decl.output {
hir::FnRetTy::Return(output) => {
- visitor.visit_ty(output);
- self.ast_ty_to_ty(output)
+ if let hir::TyKind::Infer = output.kind
+ && !self.allow_ty_infer()
+ && let Some(suggested_ty) =
+ self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
+ {
+ infer_replacements.push((output.span, suggested_ty.to_string()));
+ suggested_ty
+ } else {
+ visitor.visit_ty(output);
+ self.ast_ty_to_ty(output)
+ }
}
hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
};
debug!("ty_of_fn: output_ty={:?}", output_ty);
- let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi);
+ let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
- if !self.allow_ty_infer() {
+ if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
// We always collect the spans for placeholder types when evaluating `fn`s, but we
// only want to emit an error complaining about them if infer types (`_`) are not
// allowed. `allow_ty_infer` gates this behavior. We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
- crate::collect::placeholder_type_error(
+ let mut diag = crate::collect::placeholder_type_error_diag(
tcx,
ident_span.map(|sp| sp.shrink_to_hi()),
generics.params,
visitor.0,
+ infer_replacements.iter().map(|(s, _)| *s).collect(),
true,
hir_ty,
"function",
);
+
+ if !infer_replacements.is_empty() {
+ diag.multipart_suggestion(&format!(
+ "try replacing `_` with the type{} in the corresponding trait method signature",
+ rustc_errors::pluralize!(infer_replacements.len()),
+ ), infer_replacements, Applicability::MachineApplicable);
+ }
+
+ diag.emit();
}
// Find any late-bound regions declared in return type that do
bare_fn_ty
}
+ /// Given a fn_hir_id for a impl function, suggest the type that is found on the
+ /// corresponding function in the trait that the impl implements, if it exists.
+ /// If arg_idx is Some, then it corresponds to an input type index, otherwise it
+ /// corresponds to the return type.
+ fn suggest_trait_fn_ty_for_impl_fn_infer(
+ &self,
+ fn_hir_id: hir::HirId,
+ arg_idx: Option<usize>,
+ ) -> Option<Ty<'tcx>> {
+ let tcx = self.tcx();
+ let hir = tcx.hir();
+
+ let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
+ hir.get(fn_hir_id) else { return None };
+ let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
+ hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
+
+ let trait_ref =
+ self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
+
+ let x: &ty::AssocItem = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
+ tcx,
+ *ident,
+ ty::AssocKind::Fn,
+ trait_ref.def_id,
+ )?;
+
+ let fn_sig = tcx.fn_sig(x.def_id).subst(
+ tcx,
+ trait_ref.substs.extend_to(tcx, x.def_id, |param, _| tcx.mk_param_from_def(param)),
+ );
+
+ let ty = if let Some(arg_idx) = arg_idx { fn_sig.input(arg_idx) } else { fn_sig.output() };
+
+ Some(tcx.erase_late_bound_regions(ty))
+ }
+
fn validate_late_bound_regions(
&self,
constrained_regions: FxHashSet<ty::BoundRegionKind>,
));
let msg = "use `.addr()` to obtain the address of a pointer";
- if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
- let scalar_cast = match t_c {
- ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
- _ => format!(" as {}", self.cast_ty),
- };
+
+ let expr_prec = self.expr.precedence().order();
+ let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
+
+ let scalar_cast = match t_c {
+ ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
+ _ => format!(" as {}", self.cast_ty),
+ };
+
+ let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
+
+ if needs_parens {
+ let suggestions = vec![
+ (self.expr_span.shrink_to_lo(), String::from("(")),
+ (cast_span, format!(").addr(){scalar_cast}")),
+ ];
+
+ err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
+ } else {
err.span_suggestion(
- self.span,
+ cast_span,
msg,
- format!("({snippet}).addr(){scalar_cast}"),
- Applicability::MaybeIncorrect
+ format!(".addr(){scalar_cast}"),
+ Applicability::MaybeIncorrect,
);
- } else {
- err.help(msg);
}
+
err.help(
"if you can't comply with strict provenance and need to expose the pointer \
provenance you can use `.expose_addr()` instead"
self.expr_ty, self.cast_ty
));
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
- if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
- err.span_suggestion(
- self.span,
- msg,
- format!("(...).with_addr({snippet})"),
- Applicability::HasPlaceholders,
- );
- } else {
- err.help(msg);
- }
+ let suggestions = vec![
+ (self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
+ (self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
+ ];
+
+ err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
err.help(
"if you can't comply with strict provenance and don't have a pointer with \
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
found,
expected,
None,
- coercion_error,
+ Some(coercion_error),
);
}
})),
&terr,
false,
+ false,
);
return Err(diag.emit());
})),
&terr,
false,
+ false,
);
diag.emit();
}
expr_ty: Ty<'tcx>,
expected: Ty<'tcx>,
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
- error: TypeError<'tcx>,
+ error: Option<TypeError<'tcx>>,
) {
self.annotate_expected_due_to_let_ty(err, expr, error);
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
- self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, e);
+ self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
(expected, Some(err))
}
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
- error: TypeError<'_>,
+ error: Option<TypeError<'_>>,
) {
let parent = self.tcx.hir().get_parent_node(expr.hir_id);
match (self.tcx.hir().find(parent), error) {
Some(hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Assign(lhs, rhs, _), ..
})),
- TypeError::Sorts(ExpectedFound { expected, .. }),
+ Some(TypeError::Sorts(ExpectedFound { expected, .. })),
) if rhs.hir_id == expr.hir_id && !expected.is_closure() => {
// We ignore closures explicitly because we already point at them elsewhere.
// Point at the assigned-to binding.
}
#[instrument(skip(self, expr), level = "debug")]
- fn check_expr_kind(
+ pub(super) fn check_expr_kind(
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
) {
let tcx = self.tcx;
- let adt_ty_hint = self
- .expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
- .get(0)
- .cloned()
- .unwrap_or(adt_ty);
+ let expected_inputs =
+ self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]);
+ let adt_ty_hint = if let Some(expected_inputs) = expected_inputs {
+ expected_inputs.get(0).cloned().unwrap_or(adt_ty)
+ } else {
+ adt_ty
+ };
// re-link the regions that EIfEO can erase.
self.demand_eqtype(span, adt_ty_hint, adt_ty);
self.check_expr_asm_operand(out_expr, false);
}
}
- hir::InlineAsmOperand::Const { anon_const } => {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => {
self.to_const(anon_const);
}
- hir::InlineAsmOperand::Sym { expr } => {
- self.check_expr(expr);
- }
+ hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
expected_ret: Expectation<'tcx>,
formal_ret: Ty<'tcx>,
formal_args: &[Ty<'tcx>],
- ) -> Vec<Ty<'tcx>> {
+ ) -> Option<Vec<Ty<'tcx>>> {
let formal_ret = self.resolve_vars_with_obligations(formal_ret);
- let Some(ret_ty) = expected_ret.only_has_type(self) else { return Vec::new() };
+ let Some(ret_ty) = expected_ret.only_has_type(self) else { return None };
// HACK(oli-obk): This is a hack to keep RPIT and TAIT in sync wrt their behaviour.
// Without it, the inference
if let ty::subst::GenericArgKind::Type(ty) = ty.unpack() {
if let ty::Opaque(def_id, _) = *ty.kind() {
if self.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() {
- return Vec::new();
+ return None;
}
}
}
// Record all the argument types, with the substitutions
// produced from the above subtyping unification.
- Ok(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect())
+ Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()))
})
.unwrap_or_default();
debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret);
--- /dev/null
+use std::cmp;
+
+use rustc_middle::ty::error::TypeError;
+
+// An issue that might be found in the compatibility matrix
+enum Issue {
+ /// The given argument is the invalid type for the input
+ Invalid(usize),
+ /// There is a missing input
+ Missing(usize),
+ /// There's a superfluous argument
+ Extra(usize),
+ /// Two arguments should be swapped
+ Swap(usize, usize),
+ /// Several arguments should be reordered
+ Permutation(Vec<Option<usize>>),
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum Compatibility<'tcx> {
+ Compatible,
+ Incompatible(Option<TypeError<'tcx>>),
+}
+
+/// Similar to `Issue`, but contains some extra information
+pub(crate) enum Error<'tcx> {
+ /// The given argument is the invalid type for the input
+ Invalid(usize, Compatibility<'tcx>),
+ /// There is a missing input
+ Missing(usize),
+ /// There's a superfluous argument
+ Extra(usize),
+ /// Two arguments should be swapped
+ Swap(usize, usize, usize, usize),
+ /// Several arguments should be reordered
+ Permutation(Vec<(usize, usize)>), // dest_arg, dest_input
+}
+
+pub(crate) struct ArgMatrix<'tcx> {
+ input_indexes: Vec<usize>,
+ arg_indexes: Vec<usize>,
+ compatibility_matrix: Vec<Vec<Compatibility<'tcx>>>,
+}
+
+impl<'tcx> ArgMatrix<'tcx> {
+ pub(crate) fn new<F: FnMut(usize, usize) -> Compatibility<'tcx>>(
+ minimum_input_count: usize,
+ provided_arg_count: usize,
+ mut is_compatible: F,
+ ) -> Self {
+ let compatibility_matrix = (0..provided_arg_count)
+ .map(|i| (0..minimum_input_count).map(|j| is_compatible(i, j)).collect())
+ .collect();
+ ArgMatrix {
+ input_indexes: (0..minimum_input_count).collect(),
+ arg_indexes: (0..provided_arg_count).collect(),
+ compatibility_matrix,
+ }
+ }
+
+ /// Remove a given input from consideration
+ fn eliminate_input(&mut self, idx: usize) {
+ self.input_indexes.remove(idx);
+ for row in &mut self.compatibility_matrix {
+ row.remove(idx);
+ }
+ }
+
+ /// Remove a given argument from consideration
+ fn eliminate_arg(&mut self, idx: usize) {
+ self.arg_indexes.remove(idx);
+ self.compatibility_matrix.remove(idx);
+ }
+
+ /// "satisfy" an input with a given arg, removing both from consideration
+ fn satisfy_input(&mut self, input_idx: usize, arg_idx: usize) {
+ self.eliminate_input(input_idx);
+ self.eliminate_arg(arg_idx);
+ }
+
+ fn eliminate_satisfied(&mut self) -> Vec<(usize, usize)> {
+ let mut i = cmp::min(self.input_indexes.len(), self.arg_indexes.len());
+ let mut eliminated = vec![];
+ while i > 0 {
+ let idx = i - 1;
+ if matches!(self.compatibility_matrix[idx][idx], Compatibility::Compatible) {
+ eliminated.push((self.arg_indexes[idx], self.input_indexes[idx]));
+ self.satisfy_input(idx, idx);
+ }
+ i -= 1;
+ }
+ return eliminated;
+ }
+
+ // Check for the above mismatch cases
+ fn find_issue(&self) -> Option<Issue> {
+ let mat = &self.compatibility_matrix;
+ let ai = &self.arg_indexes;
+ let ii = &self.input_indexes;
+
+ for i in 0..cmp::max(ai.len(), ii.len()) {
+ // If we eliminate the last row, any left-over inputs are considered missing
+ if i >= mat.len() {
+ return Some(Issue::Missing(i));
+ }
+ // If we eliminate the last column, any left-over arguments are extra
+ if mat[i].len() == 0 {
+ return Some(Issue::Extra(i));
+ }
+
+ // Make sure we don't pass the bounds of our matrix
+ let is_arg = i < ai.len();
+ let is_input = i < ii.len();
+ if is_arg && is_input && matches!(mat[i][i], Compatibility::Compatible) {
+ // This is a satisfied input, so move along
+ continue;
+ }
+
+ let mut useless = true;
+ let mut unsatisfiable = true;
+ if is_arg {
+ for j in 0..ii.len() {
+ // If we find at least one input this argument could satisfy
+ // this argument isn't completely useless
+ if matches!(mat[i][j], Compatibility::Compatible) {
+ useless = false;
+ break;
+ }
+ }
+ }
+ if is_input {
+ for j in 0..ai.len() {
+ // If we find at least one argument that could satisfy this input
+ // this argument isn't unsatisfiable
+ if matches!(mat[j][i], Compatibility::Compatible) {
+ unsatisfiable = false;
+ break;
+ }
+ }
+ }
+
+ match (is_arg, is_input, useless, unsatisfiable) {
+ // If an input is unsatisfied, and the argument in its position is useless
+ // then the most likely explanation is that we just got the types wrong
+ (true, true, true, true) => return Some(Issue::Invalid(i)),
+ // Otherwise, if an input is useless, then indicate that this is an extra argument
+ (true, _, true, _) => return Some(Issue::Extra(i)),
+ // Otherwise, if an argument is unsatisfiable, indicate that it's missing
+ (_, true, _, true) => return Some(Issue::Missing(i)),
+ (true, true, _, _) => {
+ // The argument isn't useless, and the input isn't unsatisfied,
+ // so look for a parameter we might swap it with
+ // We look for swaps explicitly, instead of just falling back on permutations
+ // so that cases like (A,B,C,D) given (B,A,D,C) show up as two swaps,
+ // instead of a large permutation of 4 elements.
+ for j in 0..cmp::min(ai.len(), ii.len()) {
+ if i == j || matches!(mat[j][j], Compatibility::Compatible) {
+ continue;
+ }
+ if matches!(mat[i][j], Compatibility::Compatible)
+ && matches!(mat[j][i], Compatibility::Compatible)
+ {
+ return Some(Issue::Swap(i, j));
+ }
+ }
+ }
+ _ => {
+ continue;
+ }
+ };
+ }
+
+ // We didn't find any of the individual issues above, but
+ // there might be a larger permutation of parameters, so we now check for that
+ // by checking for cycles
+ // We use a double option at position i in this vec to represent:
+ // - None: We haven't computed anything about this argument yet
+ // - Some(None): This argument definitely doesn't participate in a cycle
+ // - Some(Some(x)): the i-th argument could permute to the x-th position
+ let mut permutation: Vec<Option<Option<usize>>> = vec![None; mat.len()];
+ let mut permutation_found = false;
+ for i in 0..mat.len() {
+ if permutation[i].is_some() {
+ // We've already decided whether this argument is or is not in a loop
+ continue;
+ }
+
+ let mut stack = vec![];
+ let mut j = i;
+ let mut last = i;
+ let mut is_cycle = true;
+ loop {
+ stack.push(j);
+ // Look for params this one could slot into
+ let compat: Vec<_> =
+ mat[j]
+ .iter()
+ .enumerate()
+ .filter_map(|(i, c)| {
+ if matches!(c, Compatibility::Compatible) { Some(i) } else { None }
+ })
+ .collect();
+ if compat.len() != 1 {
+ // this could go into multiple slots, don't bother exploring both
+ is_cycle = false;
+ break;
+ }
+ j = compat[0];
+ if stack.contains(&j) {
+ last = j;
+ break;
+ }
+ }
+ if stack.len() <= 2 {
+ // If we encounter a cycle of 1 or 2 elements, we'll let the
+ // "satisfy" and "swap" code above handle those
+ is_cycle = false;
+ }
+ // We've built up some chain, some of which might be a cycle
+ // ex: [1,2,3,4]; last = 2; j = 2;
+ // So, we want to mark 4, 3, and 2 as part of a permutation
+ permutation_found = is_cycle;
+ while let Some(x) = stack.pop() {
+ if is_cycle {
+ permutation[x] = Some(Some(j));
+ j = x;
+ if j == last {
+ // From here on out, we're a tail leading into a cycle,
+ // not the cycle itself
+ is_cycle = false;
+ }
+ } else {
+ // Some(None) ensures we save time by skipping this argument again
+ permutation[x] = Some(None);
+ }
+ }
+ }
+
+ if permutation_found {
+ // Map unwrap to remove the first layer of Some
+ let final_permutation: Vec<Option<usize>> =
+ permutation.into_iter().map(|x| x.unwrap()).collect();
+ return Some(Issue::Permutation(final_permutation));
+ }
+ return None;
+ }
+
+ // Obviously, detecting exact user intention is impossible, so the goal here is to
+ // come up with as likely of a story as we can to be helpful.
+ //
+ // We'll iteratively removed "satisfied" input/argument pairs,
+ // then check for the cases above, until we've eliminated the entire grid
+ //
+ // We'll want to know which arguments and inputs these rows and columns correspond to
+ // even after we delete them.
+ pub(crate) fn find_errors(mut self) -> (Vec<Error<'tcx>>, Vec<Option<usize>>) {
+ let provided_arg_count = self.arg_indexes.len();
+
+ let mut errors: Vec<Error<'tcx>> = vec![];
+ // For each expected argument, the matched *actual* input
+ let mut matched_inputs: Vec<Option<usize>> = vec![None; self.input_indexes.len()];
+
+ // Before we start looking for issues, eliminate any arguments that are already satisfied,
+ // so that an argument which is already spoken for by the input it's in doesn't
+ // spill over into another similarly typed input
+ // ex:
+ // fn some_func(_a: i32, _b: i32) {}
+ // some_func(1, "");
+ // Without this elimination, the first argument causes the second argument
+ // to show up as both a missing input and extra argument, rather than
+ // just an invalid type.
+ for (arg, inp) in self.eliminate_satisfied() {
+ matched_inputs[inp] = Some(arg);
+ }
+
+ while self.input_indexes.len() > 0 || self.arg_indexes.len() > 0 {
+ // Check for the first relevant issue
+ match self.find_issue() {
+ Some(Issue::Invalid(idx)) => {
+ let compatibility = self.compatibility_matrix[idx][idx].clone();
+ let input_idx = self.input_indexes[idx];
+ self.satisfy_input(idx, idx);
+ errors.push(Error::Invalid(input_idx, compatibility));
+ }
+ Some(Issue::Extra(idx)) => {
+ let arg_idx = self.arg_indexes[idx];
+ self.eliminate_arg(idx);
+ errors.push(Error::Extra(arg_idx));
+ }
+ Some(Issue::Missing(idx)) => {
+ let input_idx = self.input_indexes[idx];
+ self.eliminate_input(idx);
+ errors.push(Error::Missing(input_idx));
+ }
+ Some(Issue::Swap(idx, other)) => {
+ let input_idx = self.input_indexes[idx];
+ let other_input_idx = self.input_indexes[other];
+ let arg_idx = self.arg_indexes[idx];
+ let other_arg_idx = self.arg_indexes[other];
+ let (min, max) = (cmp::min(idx, other), cmp::max(idx, other));
+ self.satisfy_input(min, max);
+ // Subtract 1 because we already removed the "min" row
+ self.satisfy_input(max - 1, min);
+ errors.push(Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx));
+ matched_inputs[input_idx] = Some(other_arg_idx);
+ matched_inputs[other_input_idx] = Some(arg_idx);
+ }
+ Some(Issue::Permutation(args)) => {
+ // FIXME: If satisfy_input ever did anything non-trivial (emit obligations to help type checking, for example)
+ // we'd want to call this function with the correct arg/input pairs, but for now, we just throw them in a bucket.
+ // This works because they force a cycle, so each row is guaranteed to also be a column
+ let mut idxs: Vec<usize> = args.iter().filter_map(|&a| a).collect();
+
+ let mut real_idxs = vec![None; provided_arg_count];
+ for (src, dst) in
+ args.iter().enumerate().filter_map(|(src, dst)| dst.map(|dst| (src, dst)))
+ {
+ let src_arg = self.arg_indexes[src];
+ let dst_arg = self.arg_indexes[dst];
+ let dest_input = self.input_indexes[dst];
+ real_idxs[src_arg] = Some((dst_arg, dest_input));
+ matched_inputs[dest_input] = Some(src_arg);
+ }
+ idxs.sort();
+ idxs.reverse();
+ for i in idxs {
+ self.satisfy_input(i, i);
+ }
+ errors.push(Error::Permutation(real_idxs.into_iter().flatten().collect()));
+ }
+ None => {
+ // We didn't find any issues, so we need to push the algorithm forward
+ // First, eliminate any arguments that currently satisfy their inputs
+ for (arg, inp) in self.eliminate_satisfied() {
+ matched_inputs[inp] = Some(arg);
+ }
+ }
+ };
+ }
+
+ return (errors, matched_inputs);
+ }
+}
use crate::astconv::AstConv;
use crate::check::coercion::CoerceMany;
+use crate::check::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error};
use crate::check::gather_locals::Declaration;
use crate::check::method::MethodCallee;
use crate::check::Expectation::*;
potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
LocalTy, Needs, TupleArgumentsFlag,
};
+use crate::structured_errors::StructuredDiagnostic;
use rustc_ast as ast;
use rustc_data_structures::sync::Lrc;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{ExprKind, Node, QPath};
+use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
+use rustc_infer::infer::InferOk;
+use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
+use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty};
use rustc_session::Session;
use rustc_span::{self, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
-use crate::structured_errors::StructuredDiagnostic;
use std::iter;
use std::slice;
-struct FnArgsAsTuple<'hir> {
- first: &'hir hir::Expr<'hir>,
- last: &'hir hir::Expr<'hir>,
+enum TupleMatchFound {
+ None,
+ Single,
+ /// Beginning and end Span
+ Multiple(Span, Span),
}
-
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&self) {
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
sp,
expr,
&err_inputs,
- vec![],
+ None,
args_no_rcvr,
false,
tuple_arguments,
// Types (as defined in the *signature* of the target function)
formal_input_tys: &[Ty<'tcx>],
// More specific expected types, after unifying with caller output types
- expected_input_tys: Vec<Ty<'tcx>>,
+ expected_input_tys: Option<Vec<Ty<'tcx>>>,
// The expressions for each provided argument
provided_args: &'tcx [hir::Expr<'tcx>],
// Whether the function is variadic, for example when imported from C
fn_def_id: Option<DefId>,
) {
let tcx = self.tcx;
- // Grab the argument types, supplying fresh type variables
- // if the wrong number of arguments were supplied
- let supplied_arg_count =
- if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 };
+
+ // Conceptually, we've got some number of expected inputs, and some number of provided aguments
+ // and we can form a grid of whether each argument could satisfy a given input:
+ // in1 | in2 | in3 | ...
+ // arg1 ? | | |
+ // arg2 | ? | |
+ // arg3 | | ? |
+ // ...
+ // Initially, we just check the diagonal, because in the case of correct code
+ // these are the only checks that matter
+ // However, in the unhappy path, we'll fill in this whole grid to attempt to provide
+ // better error messages about invalid method calls.
// All the input types from the fn signature must outlive the call
// so as to validate implied bounds.
self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
}
- let expected_arg_count = formal_input_tys.len();
-
- // expected_count, arg_count, error_code, sugg_unit, sugg_tuple_wrap_args
- let mut arg_count_error: Option<(usize, usize, &str, bool, Option<FnArgsAsTuple<'_>>)> =
- None;
+ let mut err_code = "E0061";
// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
ty::Tuple(arg_types) => {
// Argument length differs
if arg_types.len() != provided_args.len() {
- arg_count_error =
- Some((arg_types.len(), provided_args.len(), "E0057", false, None));
+ err_code = "E0057";
}
- let expected_input_tys = match expected_input_tys.get(0) {
- Some(&ty) => match ty.kind() {
- ty::Tuple(tys) => tys.iter().collect(),
- _ => vec![],
+ let expected_input_tys = match expected_input_tys {
+ Some(expected_input_tys) => match expected_input_tys.get(0) {
+ Some(ty) => match ty.kind() {
+ ty::Tuple(tys) => Some(tys.iter().collect()),
+ _ => None,
+ },
+ None => None,
},
- None => vec![],
+ None => None,
};
(arg_types.iter().collect(), expected_input_tys)
}
for the function trait is neither a tuple nor unit"
)
.emit();
- (self.err_args(provided_args.len()), vec![])
+ (self.err_args(provided_args.len()), None)
}
}
- } else if expected_arg_count == supplied_arg_count {
- (formal_input_tys.to_vec(), expected_input_tys)
- } else if c_variadic {
- if supplied_arg_count >= expected_arg_count {
- (formal_input_tys.to_vec(), expected_input_tys)
- } else {
- arg_count_error =
- Some((expected_arg_count, supplied_arg_count, "E0060", false, None));
- (self.err_args(supplied_arg_count), vec![])
- }
} else {
- // is the missing argument of type `()`?
- let sugg_unit = if expected_input_tys.len() == 1 && supplied_arg_count == 0 {
- self.resolve_vars_if_possible(expected_input_tys[0]).is_unit()
- } else if formal_input_tys.len() == 1 && supplied_arg_count == 0 {
- self.resolve_vars_if_possible(formal_input_tys[0]).is_unit()
- } else {
- false
- };
-
- // are we passing elements of a tuple without the tuple parentheses?
- let expected_input_tys = if expected_input_tys.is_empty() {
- // In most cases we can use expected_input_tys, but some callers won't have the type
- // information, in which case we fall back to the types from the input expressions.
- formal_input_tys
- } else {
- &*expected_input_tys
- };
-
- let sugg_tuple_wrap_args = self.suggested_tuple_wrap(expected_input_tys, provided_args);
-
- arg_count_error = Some((
- expected_arg_count,
- supplied_arg_count,
- "E0061",
- sugg_unit,
- sugg_tuple_wrap_args,
- ));
- (self.err_args(supplied_arg_count), vec![])
+ (formal_input_tys.to_vec(), expected_input_tys)
};
- debug!(
- "check_argument_types: formal_input_tys={:?}",
- formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>()
- );
-
- // If there is no expectation, expect formal_input_tys.
- let expected_input_tys = if !expected_input_tys.is_empty() {
+ // If there are no external expectations at the call site, just use the types from the function defn
+ let expected_input_tys = if let Some(expected_input_tys) = expected_input_tys {
+ assert_eq!(expected_input_tys.len(), formal_input_tys.len());
expected_input_tys
} else {
formal_input_tys.clone()
};
- assert_eq!(expected_input_tys.len(), formal_input_tys.len());
-
- let provided_arg_count: usize = provided_args.len();
+ let minimum_input_count = expected_input_tys.len();
+ let provided_arg_count = provided_args.len();
- // Keep track of the fully coerced argument types
+ // We'll also want to keep track of the fully coerced argument types, for an awkward hack near the end
let mut final_arg_types: Vec<Option<(Ty<'_>, Ty<'_>)>> = vec![None; provided_arg_count];
// We introduce a helper function to demand that a given argument satisfy a given input
debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty);
- // The special-cased logic below has three functions:
- // 1. Provide as good of an expected type as possible.
+ // We're on the happy path here, so we'll do a more involved check and write back types
+ // To check compatibility, we'll do 3 things:
+ // 1. Unify the provided argument with the expected type
let expectation = Expectation::rvalue_hint(self, expected_input_ty);
let checked_ty = self.check_expr_with_expectation(provided_arg, expectation);
final_arg_types[idx] = Some((checked_ty, coerced_ty));
// Cause selection errors caused by resolving a single argument to point at the
- // argument and not the call. This is otherwise redundant with the `demand_coerce`
- // call immediately after, but it lets us customize the span pointed to in the
+ // argument and not the call. This lets us customize the span pointed to in the
// fulfillment error to be more accurate.
let coerced_ty =
self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
);
});
+ // Make sure we store the resolved type
final_arg_types[idx] = Some((checked_ty, coerced_ty));
- // We're processing function arguments so we definitely want to use
- // two-phase borrows.
- self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes);
+ let coerce_error = self
+ .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
+ .err();
+
+ if coerce_error.is_some() {
+ return Compatibility::Incompatible(coerce_error);
+ }
+
+ // 3. Check if the formal type is a supertype of the checked one
+ // and register any such obligations for future type checks
+ let supertype_error = self
+ .at(&self.misc(provided_arg.span), self.param_env)
+ .sup(formal_input_ty, coerced_ty);
+ let subtyping_error = match supertype_error {
+ Ok(InferOk { obligations, value: () }) => {
+ self.register_predicates(obligations);
+ None
+ }
+ Err(err) => Some(err),
+ };
- // 3. Relate the expected type and the formal one,
- // if the expected type was used for the coercion.
- self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty);
+ // If neither check failed, the types are compatible
+ match subtyping_error {
+ None => Compatibility::Compatible,
+ Some(_) => Compatibility::Incompatible(subtyping_error),
+ }
};
- let minimum_input_count = formal_input_tys.len();
+ // A "softer" version of the helper above, which checks types without persisting them,
+ // and treats error types differently
+ // This will allow us to "probe" for other argument orders that would likely have been correct
+ let check_compatible = |arg_idx, input_idx| {
+ let formal_input_ty: Ty<'tcx> = formal_input_tys[input_idx];
+ let expected_input_ty: Ty<'tcx> = expected_input_tys[input_idx];
+
+ // If either is an error type, we defy the usual convention and consider them to *not* be
+ // coercible. This prevents our error message heuristic from trying to pass errors into
+ // every argument.
+ if formal_input_ty.references_error() || expected_input_ty.references_error() {
+ return Compatibility::Incompatible(None);
+ }
+
+ let provided_arg: &hir::Expr<'tcx> = &provided_args[arg_idx];
+ let expectation = Expectation::rvalue_hint(self, expected_input_ty);
+ // FIXME: check that this is safe; I don't believe this commits any of the obligations, but I can't be sure.
+ //
+ // I had another method of "soft" type checking before,
+ // but it was failing to find the type of some expressions (like "")
+ // so I prodded this method and made it pub(super) so I could call it, and it seems to work well.
+ let checked_ty = self.check_expr_kind(provided_arg, expectation);
+
+ let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
+ let can_coerce = self.can_coerce(checked_ty, coerced_ty);
+
+ if !can_coerce {
+ return Compatibility::Incompatible(None);
+ }
+
+ let subtyping_result = self
+ .at(&self.misc(provided_arg.span), self.param_env)
+ .sup(formal_input_ty, coerced_ty);
+
+ // Same as above: if either the coerce type or the checked type is an error type,
+ // consider them *not* compatible.
+ let coercible =
+ !coerced_ty.references_error() && !checked_ty.references_error() && can_coerce;
+
+ match (coercible, &subtyping_result) {
+ (true, Ok(_)) => Compatibility::Compatible,
+ _ => Compatibility::Incompatible(subtyping_result.err()),
+ }
+ };
+
+ // To start, we only care "along the diagonal", where we expect every
+ // provided arg to be in the right spot
+ let mut compatibility = vec![Compatibility::Incompatible(None); provided_args.len()];
+
+ // Keep track of whether we *could possibly* be satisfied, i.e. whether we're on the happy path
+ // if the wrong number of arguments were supplied, we CAN'T be satisfied,
+ // and if we're c_variadic, the supplied arguments must be >= the minimum count from the function
+ // otherwise, they need to be identical, because rust doesn't currently support variadic functions
+ let mut call_appears_satisfied = if c_variadic {
+ provided_arg_count >= minimum_input_count
+ } else {
+ provided_arg_count == minimum_input_count
+ };
// Check the arguments.
// We do this in a pretty awful way: first we type-check any arguments
})
}
+ // Check each argument, to satisfy the input it was provided for
+ // Visually, we're traveling down the diagonal of the compatibility matrix
for (idx, arg) in provided_args.iter().enumerate() {
// Warn only for the first loop (the "no closures" one).
// Closure arguments themselves can't be diverging, but
continue;
}
- demand_compatible(idx, &mut final_arg_types);
+ let compatible = demand_compatible(idx, &mut final_arg_types);
+ let is_compatible = matches!(compatible, Compatibility::Compatible);
+ compatibility[idx] = compatible;
+
+ if !is_compatible {
+ call_appears_satisfied = false;
+ }
}
}
- // If there was an error in parameter count, emit that here
- if let Some((expected_count, arg_count, err_code, sugg_unit, sugg_tuple_wrap_args)) =
- arg_count_error
- {
- let (span, start_span, args, ctor_of) = match &call_expr.kind {
+ // Logic here is a bit hairy
+ 'errors: {
+ // If something above didn't typecheck, we've fallen off the happy path
+ // and we should make some effort to provide better error messages
+ if call_appears_satisfied {
+ break 'errors;
+ }
+
+ // The algorithm here is inspired by levenshtein distance and longest common subsequence.
+ // We'll try to detect 4 different types of mistakes:
+ // - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
+ // - An input is missing, which isn't satisfied by *any* of the other arguments
+ // - Some number of arguments have been provided in the wrong order
+ // - A type is straight up invalid
+
+ // First, let's find the errors
+ let mut compatibility: Vec<_> = compatibility.into_iter().map(Some).collect();
+ let (mut errors, matched_inputs) =
+ ArgMatrix::new(minimum_input_count, provided_arg_count, |i, j| {
+ if i == j { compatibility[i].take().unwrap() } else { check_compatible(i, j) }
+ })
+ .find_errors();
+
+ // Okay, so here's where it gets complicated in regards to what errors
+ // we emit and how.
+ // There are 3 different "types" of errors we might encounter.
+ // 1) Missing/extra/swapped arguments
+ // 2) Valid but incorrect arguments
+ // 3) Invalid arguments
+ // - Currently I think this only comes up with `CyclicTy`
+ //
+ // We first need to go through, remove those from (3) and emit those
+ // as their own error, particularly since they're error code and
+ // message is special. From what I can tell, we *must* emit these
+ // here (vs somewhere prior to this function) since the arguments
+ // become invalid *because* of how they get used in the function.
+ // It is what it is.
+
+ let found_errors = !errors.is_empty();
+
+ errors.drain_filter(|error| {
+ let Error::Invalid(input_idx, Compatibility::Incompatible(error)) = error else { return false };
+ let expected_ty = expected_input_tys[*input_idx];
+ let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
+ let cause = &self.misc(provided_args[*input_idx].span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ if let Some(e) = error {
+ if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
+ self.report_and_explain_type_error(trace, e).emit();
+ return true;
+ }
+ }
+ false
+ });
+
+ // We're done if we found errors, but we already emitted them.
+ // I don't think we *should* be able to enter this bit of code
+ // (`!call_appears_satisfied`) without *also* finding errors, but we
+ // don't want to accidentally not emit an error if there is some
+ // logic bug in the `ArgMatrix` code.
+ if found_errors && errors.is_empty() {
+ break 'errors;
+ }
+
+ // Next, let's construct the error
+ let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
hir::ExprKind::Call(
hir::Expr {
span,
)),
..
},
- args,
- ) => (*span, *span, &args[..], Some(of)),
- hir::ExprKind::Call(hir::Expr { span, .. }, args) => {
- (*span, *span, &args[..], None)
+ _,
+ ) => (call_span, *span, Some(of)),
+ hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
+ hir::ExprKind::MethodCall(path_segment, _, span) => {
+ let ident_span = path_segment.ident.span;
+ let ident_span = if let Some(args) = path_segment.args {
+ ident_span.with_hi(args.span_ext.hi())
+ } else {
+ ident_span
+ };
+ (
+ *span, ident_span, None, // methods are never ctors
+ )
}
- hir::ExprKind::MethodCall(path_segment, args, _) => (
- path_segment.ident.span,
- // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
- path_segment
- .args
- .and_then(|args| args.args.iter().last())
- // Account for `foo.bar::<T>()`.
- .map(|arg| {
- // Skip the closing `>`.
- tcx.sess
- .source_map()
- .next_point(tcx.sess.source_map().next_point(arg.span()))
- })
- .unwrap_or(path_segment.ident.span),
- &args[1..], // Skip the receiver.
- None, // methods are never ctors
- ),
k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
};
- let arg_spans = if provided_args.is_empty() {
- // foo()
- // ^^^-- supplied 0 arguments
- // |
- // expected 2 arguments
- vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())]
- } else {
- // foo(1, 2, 3)
- // ^^^ - - - supplied 3 arguments
- // |
- // expected 2 arguments
- args.iter().map(|arg| arg.span).collect::<Vec<Span>>()
- };
+ let args_span = error_span.trim_start(full_call_span).unwrap_or(error_span);
let call_name = match ctor_of {
Some(CtorOf::Struct) => "struct",
Some(CtorOf::Variant) => "enum variant",
None => "function",
};
- let mut err = tcx.sess.struct_span_err_with_code(
- span,
- &format!(
- "this {} takes {}{} but {} {} supplied",
+ if c_variadic && provided_arg_count < minimum_input_count {
+ err_code = "E0060";
+ }
+
+ // Next special case: The case where we expect a single tuple and
+ // wrapping all the args in parentheses (or adding a comma to
+ // already existing parentheses) will result in a tuple that
+ // satisfies the call.
+ // This isn't super ideal code, because we copy code from elsewhere
+ // and somewhat duplicate this. We also delegate to the general type
+ // mismatch suggestions for the single arg case.
+ let sugg_tuple_wrap_args =
+ self.suggested_tuple_wrap(&expected_input_tys, provided_args);
+ match sugg_tuple_wrap_args {
+ TupleMatchFound::None => {}
+ TupleMatchFound::Single => {
+ let expected_ty = expected_input_tys[0];
+ let provided_ty = final_arg_types[0].map(|ty| ty.0).unwrap();
+ let cause = &self.misc(provided_args[0].span);
+ let compatibility = demand_compatible(0, &mut final_arg_types);
+ let type_error = match compatibility {
+ Compatibility::Incompatible(Some(error)) => error,
+ _ => TypeError::Mismatch,
+ };
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ let mut err = self.report_and_explain_type_error(trace, &type_error);
+ self.emit_coerce_suggestions(
+ &mut err,
+ &provided_args[0],
+ final_arg_types[0].map(|ty| ty.0).unwrap(),
+ final_arg_types[0].map(|ty| ty.1).unwrap(),
+ None,
+ None,
+ );
+ err.span_label(
+ full_call_span,
+ format!("arguments to this {} are incorrect", call_name),
+ );
+ // Call out where the function is defined
+ if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+ let mut spans: MultiSpan = def_span.into();
+
+ let params = tcx
+ .hir()
+ .get_if_local(def_id)
+ .and_then(|node| node.body_id())
+ .into_iter()
+ .map(|id| tcx.hir().body(id).params)
+ .flatten();
+
+ for param in params {
+ spans.push_span_label(param.span, String::new());
+ }
+
+ let def_kind = tcx.def_kind(def_id);
+ err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+ }
+ err.emit();
+ break 'errors;
+ }
+ TupleMatchFound::Multiple(start, end) => {
+ let mut err = tcx.sess.struct_span_err_with_code(
+ full_call_span,
+ &format!(
+ "this {} takes {}{} but {} {} supplied",
+ call_name,
+ if c_variadic { "at least " } else { "" },
+ potentially_plural_count(minimum_input_count, "argument"),
+ potentially_plural_count(provided_arg_count, "argument"),
+ if provided_arg_count == 1 { "was" } else { "were" }
+ ),
+ DiagnosticId::Error(err_code.to_owned()),
+ );
+ // Call out where the function is defined
+ if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+ let mut spans: MultiSpan = def_span.into();
+
+ let params = tcx
+ .hir()
+ .get_if_local(def_id)
+ .and_then(|node| node.body_id())
+ .into_iter()
+ .map(|id| tcx.hir().body(id).params)
+ .flatten();
+
+ for param in params {
+ spans.push_span_label(param.span, String::new());
+ }
+
+ let def_kind = tcx.def_kind(def_id);
+ err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+ }
+ err.multipart_suggestion(
+ "use parentheses to construct a tuple",
+ vec![(start, '('.to_string()), (end, ')'.to_string())],
+ Applicability::MachineApplicable,
+ );
+ err.emit();
+ break 'errors;
+ }
+ }
+
+ // Okay, now that we've emitted the special errors separately, we
+ // are only left missing/extra/swapped and mismatched arguments, both
+ // can be collated pretty easily if needed.
+
+ // Next special case: if there is only one "Incompatible" error, just emit that
+ if errors.len() == 1 {
+ if let Some(Error::Invalid(input_idx, Compatibility::Incompatible(Some(error)))) =
+ errors.iter().next()
+ {
+ let expected_ty = expected_input_tys[*input_idx];
+ let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap();
+ let cause = &self.misc(provided_args[*input_idx].span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ let mut err = self.report_and_explain_type_error(trace, error);
+ self.emit_coerce_suggestions(
+ &mut err,
+ &provided_args[*input_idx],
+ final_arg_types[*input_idx].map(|ty| ty.0).unwrap(),
+ final_arg_types[*input_idx].map(|ty| ty.1).unwrap(),
+ None,
+ None,
+ );
+ err.span_label(
+ full_call_span,
+ format!("arguments to this {} are incorrect", call_name),
+ );
+ // Call out where the function is defined
+ if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
+ let mut spans: MultiSpan = def_span.into();
+
+ let params = tcx
+ .hir()
+ .get_if_local(def_id)
+ .and_then(|node| node.body_id())
+ .into_iter()
+ .map(|id| tcx.hir().body(id).params)
+ .flatten();
+
+ for param in params {
+ spans.push_span_label(param.span, String::new());
+ }
+
+ let def_kind = tcx.def_kind(def_id);
+ err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+ }
+ err.emit();
+ break 'errors;
+ }
+ }
+
+ let mut err = if minimum_input_count == provided_arg_count {
+ struct_span_err!(
+ tcx.sess,
+ full_call_span,
+ E0308,
+ "arguments to this {} are incorrect",
call_name,
- if c_variadic { "at least " } else { "" },
- potentially_plural_count(expected_count, "argument"),
- potentially_plural_count(arg_count, "argument"),
- if arg_count == 1 { "was" } else { "were" }
- ),
- DiagnosticId::Error(err_code.to_owned()),
- );
- let label = format!("supplied {}", potentially_plural_count(arg_count, "argument"));
- for (i, span) in arg_spans.into_iter().enumerate() {
- err.span_label(
- span,
- if arg_count == 0 || i + 1 == arg_count { &label } else { "" },
- );
+ )
+ } else {
+ tcx.sess.struct_span_err_with_code(
+ full_call_span,
+ &format!(
+ "this {} takes {}{} but {} {} supplied",
+ call_name,
+ if c_variadic { "at least " } else { "" },
+ potentially_plural_count(minimum_input_count, "argument"),
+ potentially_plural_count(provided_arg_count, "argument"),
+ if provided_arg_count == 1 { "was" } else { "were" }
+ ),
+ DiagnosticId::Error(err_code.to_owned()),
+ )
+ };
+
+ // As we encounter issues, keep track of what we want to provide for the suggestion
+ let mut labels = vec![];
+ // If there is a single error, we give a specific suggestion; otherwise, we change to
+ // "did you mean" with the suggested function call
+ enum SuggestionText {
+ None,
+ Provide(bool),
+ Remove(bool),
+ Swap,
+ Reorder,
+ DidYouMean,
}
+ let mut suggestion_text = SuggestionText::None;
+
+ let mut errors = errors.into_iter().peekable();
+ while let Some(error) = errors.next() {
+ match error {
+ Error::Invalid(input_idx, compatibility) => {
+ let expected_ty = expected_input_tys[input_idx];
+ if let Compatibility::Incompatible(error) = &compatibility {
+ let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap();
+ let cause = &self.misc(provided_args[input_idx].span);
+ let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
+ if let Some(e) = error {
+ self.note_type_err(
+ &mut err,
+ &trace.cause,
+ None,
+ Some(trace.values),
+ e,
+ false,
+ true,
+ );
+ }
+ }
+
+ self.emit_coerce_suggestions(
+ &mut err,
+ &provided_args[input_idx],
+ final_arg_types[input_idx].map(|ty| ty.0).unwrap(),
+ final_arg_types[input_idx].map(|ty| ty.1).unwrap(),
+ None,
+ None,
+ );
+ }
+ Error::Extra(arg_idx) => {
+ let arg_type = if let Some((_, ty)) = final_arg_types[arg_idx] {
+ if ty.references_error() || ty.has_infer_types() {
+ "".into()
+ } else {
+ format!(" of type `{}`", ty)
+ }
+ } else {
+ "".into()
+ };
+ labels.push((
+ provided_args[arg_idx].span,
+ format!("argument{} unexpected", arg_type),
+ ));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Remove(false),
+ SuggestionText::Remove(_) => SuggestionText::Remove(true),
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ Error::Missing(input_idx) => {
+ // If there are multiple missing arguments adjacent to each other,
+ // then we can provide a single error.
+
+ let mut missing_idxs = vec![input_idx];
+ while let Some(e) = errors.next_if(|e| matches!(e, Error::Missing(input_idx) if *input_idx == (missing_idxs.last().unwrap() + 1))) {
+ match e {
+ Error::Missing(input_idx) => missing_idxs.push(input_idx),
+ _ => unreachable!(),
+ }
+ }
+
+ // NOTE: Because we might be re-arranging arguments, might have extra
+ // arguments, etc. it's hard to *really* know where we should provide
+ // this error label, so as a heuristic, we point to the provided arg, or
+ // to the call if the missing inputs pass the provided args.
+ match &missing_idxs[..] {
+ &[input_idx] => {
+ let expected_ty = expected_input_tys[input_idx];
+ let input_ty = self.resolve_vars_if_possible(expected_ty);
+ let span = if input_idx < provided_arg_count {
+ let arg_span = provided_args[input_idx].span;
+ Span::new(arg_span.lo(), arg_span.hi(), arg_span.ctxt(), None)
+ } else {
+ args_span
+ };
+ let arg_type =
+ if input_ty.references_error() || input_ty.has_infer_types() {
+ "".into()
+ } else {
+ format!(" of type `{}`", input_ty)
+ };
+ labels.push((span, format!("an argument{} is missing", arg_type)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Provide(false),
+ SuggestionText::Provide(_) => SuggestionText::Provide(true),
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ &[first_idx, second_idx] => {
+ let first_input_ty =
+ self.resolve_vars_if_possible(expected_input_tys[first_idx]);
+ let second_input_ty =
+ self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+
+ let span = if second_idx < provided_arg_count {
+ let first_arg_span = provided_args[first_idx].span;
+ let second_arg_span = provided_args[second_idx].span;
+ Span::new(
+ first_arg_span.lo(),
+ second_arg_span.hi(),
+ first_arg_span.ctxt(),
+ None,
+ )
+ } else {
+ args_span
+ };
+ let any_unnameable = false
+ || first_input_ty.references_error()
+ || first_input_ty.has_infer_types()
+ || second_input_ty.references_error()
+ || second_input_ty.has_infer_types();
+ let arg_type = if any_unnameable {
+ "".into()
+ } else {
+ format!(
+ " of type `{}` and `{}`",
+ first_input_ty, second_input_ty
+ )
+ };
+ labels
+ .push((span, format!("two arguments{} are missing", arg_type)));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ &[first_idx, second_idx, third_idx] => {
+ let first_input_ty =
+ self.resolve_vars_if_possible(expected_input_tys[first_idx]);
+ let second_input_ty =
+ self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+ let third_input_ty =
+ self.resolve_vars_if_possible(expected_input_tys[second_idx]);
+ let span = if third_idx < provided_arg_count {
+ let first_arg_span = provided_args[first_idx].span;
+ let third_arg_span = provided_args[third_idx].span;
+ Span::new(
+ first_arg_span.lo(),
+ third_arg_span.hi(),
+ first_arg_span.ctxt(),
+ None,
+ )
+ } else {
+ args_span
+ };
+ let any_unnameable = false
+ || first_input_ty.references_error()
+ || first_input_ty.has_infer_types()
+ || second_input_ty.references_error()
+ || second_input_ty.has_infer_types()
+ || third_input_ty.references_error()
+ || third_input_ty.has_infer_types();
+ let arg_type = if any_unnameable {
+ "".into()
+ } else {
+ format!(
+ " of type `{}`, `{}`, and `{}`",
+ first_input_ty, second_input_ty, third_input_ty
+ )
+ };
+ labels.push((
+ span,
+ format!("three arguments{} are missing", arg_type),
+ ));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ missing_idxs => {
+ let first_idx = *missing_idxs.first().unwrap();
+ let second_idx = *missing_idxs.last().unwrap();
+ // NOTE: Because we might be re-arranging arguments, might have extra arguments, etc.
+ // It's hard to *really* know where we should provide this error label, so this is a
+ // decent heuristic
+ let span = if first_idx < provided_arg_count {
+ let first_arg_span = provided_args[first_idx].span;
+ let second_arg_span = provided_args[second_idx].span;
+ Span::new(
+ first_arg_span.lo(),
+ second_arg_span.hi(),
+ first_arg_span.ctxt(),
+ None,
+ )
+ } else {
+ // Otherwise just label the whole function
+ args_span
+ };
+ labels.push((span, format!("multiple arguments are missing")));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None | SuggestionText::Provide(_) => {
+ SuggestionText::Provide(true)
+ }
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ }
+ }
+ Error::Swap(input_idx, other_input_idx, arg_idx, other_arg_idx) => {
+ let first_span = provided_args[arg_idx].span;
+ let second_span = provided_args[other_arg_idx].span;
+
+ let first_expected_ty =
+ self.resolve_vars_if_possible(expected_input_tys[input_idx]);
+ let first_provided_ty = if let Some((ty, _)) = final_arg_types[arg_idx] {
+ format!(",found `{}`", ty)
+ } else {
+ "".into()
+ };
+ labels.push((
+ first_span,
+ format!("expected `{}`{}", first_expected_ty, first_provided_ty),
+ ));
+ let other_expected_ty =
+ self.resolve_vars_if_possible(expected_input_tys[other_input_idx]);
+ let other_provided_ty =
+ if let Some((ty, _)) = final_arg_types[other_arg_idx] {
+ format!(",found `{}`", ty)
+ } else {
+ "".into()
+ };
+ labels.push((
+ second_span,
+ format!("expected `{}`{}", other_expected_ty, other_provided_ty),
+ ));
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Swap,
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ Error::Permutation(args) => {
+ for (dst_arg, dest_input) in args {
+ let expected_ty =
+ self.resolve_vars_if_possible(expected_input_tys[dest_input]);
+ let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] {
+ format!(",found `{}`", ty)
+ } else {
+ "".into()
+ };
+ labels.push((
+ provided_args[dst_arg].span,
+ format!("expected `{}`{}", expected_ty, provided_ty),
+ ));
+ }
+
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Reorder,
+ _ => SuggestionText::DidYouMean,
+ };
+ }
+ }
+ }
+
+ // If we have less than 5 things to say, it would be useful to call out exactly what's wrong
+ if labels.len() <= 5 {
+ for (span, label) in labels {
+ err.span_label(span, label);
+ }
+ }
+
+ // Call out where the function is defined
if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) {
let mut spans: MultiSpan = def_span.into();
let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
- if sugg_unit {
- let sugg_span = tcx.sess.source_map().end_point(call_expr.span);
- // remove closing `)` from the span
- let sugg_span = sugg_span.shrink_to_lo();
- err.span_suggestion(
- sugg_span,
- "expected the unit value `()`; create it with empty parentheses",
- String::from("()"),
- Applicability::MachineApplicable,
- );
- } else if let Some(FnArgsAsTuple { first, last }) = sugg_tuple_wrap_args {
- err.multipart_suggestion(
- "use parentheses to construct a tuple",
- vec![
- (first.span.shrink_to_lo(), '('.to_string()),
- (last.span.shrink_to_hi(), ')'.to_string()),
- ],
- Applicability::MachineApplicable,
+
+ // And add a suggestion block for all of the parameters
+ let suggestion_text = match suggestion_text {
+ SuggestionText::None => None,
+ SuggestionText::Provide(plural) => {
+ Some(format!("provide the argument{}", if plural { "s" } else { "" }))
+ }
+ SuggestionText::Remove(plural) => {
+ Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+ }
+ SuggestionText::Swap => Some("swap these arguments".to_string()),
+ SuggestionText::Reorder => Some("reorder these arguments".to_string()),
+ SuggestionText::DidYouMean => Some("did you mean".to_string()),
+ };
+ if let Some(suggestion_text) = suggestion_text {
+ let source_map = self.sess().source_map();
+ let mut suggestion = format!(
+ "{}(",
+ source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| String::new())
);
- } else {
- err.span_label(
- span,
- format!(
- "expected {}{}",
- if c_variadic { "at least " } else { "" },
- potentially_plural_count(expected_count, "argument")
- ),
+ for (idx, arg) in matched_inputs.iter().enumerate() {
+ let suggestion_text = if let Some(arg) = arg {
+ let arg_span = provided_args[*arg].span;
+ let arg_text = source_map.span_to_snippet(arg_span).unwrap();
+ arg_text
+ } else {
+ // Propose a placeholder of the correct type
+ let expected_ty = expected_input_tys[idx];
+ let input_ty = self.resolve_vars_if_possible(expected_ty);
+ if input_ty.is_unit() {
+ "()".to_string()
+ } else {
+ format!("{{{}}}", input_ty)
+ }
+ };
+ suggestion += &suggestion_text;
+ if idx < minimum_input_count - 1 {
+ suggestion += ", ";
+ }
+ }
+ suggestion += ")";
+ err.span_suggestion_verbose(
+ error_span,
+ &suggestion_text,
+ suggestion,
+ Applicability::HasPlaceholders,
);
}
err.emit();
for arg in provided_args.iter().skip(minimum_input_count) {
let arg_ty = self.check_expr(&arg);
+ // If the function is c-style variadic, we skipped a bunch of arguments
+ // so we need to check those, and write out the types
+ // Ideally this would be folded into the above, for uniform style
+ // but c-variadic is already a corner case
if c_variadic {
- // We also need to make sure we at least write the ty of the other
- // arguments which we skipped above, either because they were additional
- // c_variadic args, or because we had an argument count mismatch.
fn variadic_error<'tcx>(sess: &Session, span: Span, ty: Ty<'tcx>, cast_ty: &str) {
use crate::structured_errors::MissingCastForVariadicArg;
&self,
expected_input_tys: &[Ty<'tcx>],
provided_args: &'tcx [hir::Expr<'tcx>],
- ) -> Option<FnArgsAsTuple<'_>> {
- let [expected_arg_type] = expected_input_tys[..] else { return None };
-
+ ) -> TupleMatchFound {
+ // Only handle the case where we expect only one tuple arg
+ let [expected_arg_type] = expected_input_tys[..] else { return TupleMatchFound::None };
let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind()
- else { return None };
+ else { return TupleMatchFound::None };
+
+ // First check that there are the same number of types.
+ if expected_types.len() != provided_args.len() {
+ return TupleMatchFound::None;
+ }
let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect();
let all_match = iter::zip(expected_types, supplied_types)
.all(|(expected, supplied)| self.can_eq(self.param_env, expected, supplied).is_ok());
- if all_match {
- match provided_args {
- [] => None,
- [_] => unreachable!(
- "shouldn't reach here - need count mismatch between 1-tuple and 1-argument"
- ),
- [first, .., last] => Some(FnArgsAsTuple { first, last }),
+ if !all_match {
+ return TupleMatchFound::None;
+ }
+ match provided_args {
+ [] => TupleMatchFound::None,
+ [_] => TupleMatchFound::Single,
+ [first, .., last] => {
+ TupleMatchFound::Multiple(first.span.shrink_to_lo(), last.span.shrink_to_hi())
}
- } else {
- None
}
}
mod _impl;
+mod arg_matrix;
mod checks;
mod suggestions;
pub use _impl::*;
-pub use checks::*;
pub use suggestions::*;
use crate::astconv::AstConv;
| hir::Node::Ctor(..)
| hir::Node::Lifetime(..)
| hir::Node::GenericParam(..)
- | hir::Node::Visibility(..)
| hir::Node::Crate(..)
| hir::Node::Infer(..) => bug!("Unsupported branch target: {:?}", node),
}
| sym::simd_fpow
| sym::simd_saturating_add
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
+ sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
sym::simd_neg
| sym::simd_fsqrt
| sym::simd_fsin
span,
}),
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
- | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. })
- if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const } => {
- anon_const.hir_id == id
- }
- _ => false,
- }) =>
- {
- // Inline assembly constants must be integers.
- fcx.next_int_var()
+ | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
+ let operand_ty = asm
+ .operands
+ .iter()
+ .filter_map(|(op, _op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const }
+ if anon_const.hir_id == id =>
+ {
+ // Inline assembly constants must be integers.
+ Some(fcx.next_int_var())
+ }
+ hir::InlineAsmOperand::SymFn { anon_const }
+ if anon_const.hir_id == id =>
+ {
+ Some(fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span,
+ }))
+ }
+ _ => None,
+ })
+ .next();
+ operand_ty.unwrap_or_else(fallback)
}
_ => fallback(),
},
self.tcx.sess,
span,
E0529,
- "expected an array or slice, found `{}`",
- expected_ty
+ "expected an array or slice, found `{expected_ty}`"
);
- if let ty::Ref(_, ty, _) = expected_ty.kind() {
- if let ty::Array(..) | ty::Slice(..) = ty.kind() {
- err.help("the semantics of slice patterns changed recently; see issue #62254");
- }
+ if let ty::Ref(_, ty, _) = expected_ty.kind()
+ && let ty::Array(..) | ty::Slice(..) = ty.kind()
+ {
+ err.help("the semantics of slice patterns changed recently; see issue #62254");
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
+ && let (Some(span), true) = (ti.span, ti.origin_expr)
+ && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
- if let (Some(span), true) = (ti.span, ti.origin_expr) {
- if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
- let applicability = Autoderef::new(
- &self.infcx,
- self.param_env,
- self.body_id,
- span,
- self.resolve_vars_if_possible(ti.expected),
+ let ty = self.resolve_vars_if_possible(ti.expected);
+ let is_slice_or_array_or_vector = self.is_slice_or_array_or_vector(&mut err, snippet.clone(), ty);
+ match is_slice_or_array_or_vector.1.kind() {
+ ty::Adt(adt_def, _)
+ if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
+ || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
+ {
+ // Slicing won't work here, but `.as_deref()` might (issue #91328).
+ err.span_suggestion(
span,
- )
- .find_map(|(ty, _)| {
- match ty.kind() {
- ty::Adt(adt_def, _)
- if self.tcx.is_diagnostic_item(sym::Option, adt_def.did())
- || self.tcx.is_diagnostic_item(sym::Result, adt_def.did()) =>
- {
- // Slicing won't work here, but `.as_deref()` might (issue #91328).
- err.span_suggestion(
- span,
- "consider using `as_deref` here",
- format!("{}.as_deref()", snippet),
- Applicability::MaybeIncorrect,
- );
- Some(None)
- }
-
- ty::Slice(..) | ty::Array(..) => {
- Some(Some(Applicability::MachineApplicable))
- }
-
- _ => None,
- }
- })
- .unwrap_or(Some(Applicability::MaybeIncorrect));
-
- if let Some(applicability) = applicability {
- err.span_suggestion(
- span,
- "consider slicing here",
- format!("{}[..]", snippet),
- applicability,
- );
- }
+ "consider using `as_deref` here",
+ format!("{snippet}.as_deref()"),
+ Applicability::MaybeIncorrect,
+ );
}
+ _ => ()
+ }
+ if is_slice_or_array_or_vector.0 {
+ err.span_suggestion(
+ span,
+ "consider slicing here",
+ format!("{snippet}[..]"),
+ Applicability::MachineApplicable,
+ );
}
}
- err.span_label(span, format!("pattern cannot match with input type `{}`", expected_ty));
+ err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
err.emit();
}
+
+ fn is_slice_or_array_or_vector(
+ &self,
+ err: &mut Diagnostic,
+ snippet: String,
+ ty: Ty<'tcx>,
+ ) -> (bool, Ty<'tcx>) {
+ match ty.kind() {
+ ty::Adt(adt_def, _) if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did()) => {
+ (true, ty)
+ }
+ ty::Ref(_, ty, _) => self.is_slice_or_array_or_vector(err, snippet, *ty),
+ ty::Slice(..) | ty::Array(..) => (true, ty),
+ _ => (false, ty),
+ }
+ }
}
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
use rustc_span::{Span, Symbol};
pub fn check_crate(tcx: TyCtxt<'_>) {
- let mut used_trait_imports = FxHashSet::default();
+ let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default();
+
for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
used_trait_imports.extend(imports.iter());
}
- let mut visitor = CheckVisitor { tcx, used_trait_imports };
- tcx.hir().visit_all_item_likes(&mut visitor);
-
- unused_crates_lint(tcx);
-}
-
-impl<'tcx> ItemLikeVisitor<'_> for CheckVisitor<'tcx> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- if item.vis.node.is_pub() || item.span.is_dummy() {
- return;
- }
- if let hir::ItemKind::Use(path, _) = item.kind {
- self.check_import(item.item_id(), path.span);
+ for id in tcx.hir().items() {
+ if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) {
+ if tcx.visibility(id.def_id).is_public() {
+ continue;
+ }
+ let item = tcx.hir().item(id);
+ if item.span.is_dummy() {
+ continue;
+ }
+ if let hir::ItemKind::Use(path, _) = item.kind {
+ check_import(tcx, &mut used_trait_imports, item.item_id(), path.span);
+ }
}
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
- fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
+ unused_crates_lint(tcx);
}
-struct CheckVisitor<'tcx> {
+fn check_import<'tcx>(
tcx: TyCtxt<'tcx>,
- used_trait_imports: FxHashSet<LocalDefId>,
-}
-
-impl<'tcx> CheckVisitor<'tcx> {
- fn check_import(&self, item_id: hir::ItemId, span: Span) {
- if !self.tcx.maybe_unused_trait_import(item_id.def_id) {
- return;
- }
-
- if self.used_trait_imports.contains(&item_id.def_id) {
- return;
- }
+ used_trait_imports: &mut FxHashSet<LocalDefId>,
+ item_id: hir::ItemId,
+ span: Span,
+) {
+ if !tcx.maybe_unused_trait_import(item_id.def_id) {
+ return;
+ }
- self.tcx.struct_span_lint_hir(
- lint::builtin::UNUSED_IMPORTS,
- item_id.hir_id(),
- span,
- |lint| {
- let msg = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
- format!("unused import: `{}`", snippet)
- } else {
- "unused import".to_owned()
- };
- lint.build(&msg).emit();
- },
- );
+ if used_trait_imports.contains(&item_id.def_id) {
+ return;
}
+
+ tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item_id.hir_id(), span, |lint| {
+ let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
+ format!("unused import: `{}`", snippet)
+ } else {
+ "unused import".to_owned()
+ };
+ lint.build(&msg).emit();
+ });
}
fn unused_crates_lint(tcx: TyCtxt<'_>) {
// Collect all the extern crates (in a reliable order).
let mut crates_to_lint = vec![];
- tcx.hir().visit_all_item_likes(&mut CollectExternCrateVisitor {
- crates_to_lint: &mut crates_to_lint,
- });
+
+ for id in tcx.hir().items() {
+ if matches!(tcx.hir().def_kind(id.def_id), DefKind::ExternCrate) {
+ let item = tcx.hir().item(id);
+ if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
+ crates_to_lint.push(ExternCrateToLint {
+ def_id: item.def_id.to_def_id(),
+ span: item.span,
+ orig_name,
+ warn_if_unused: !item.ident.as_str().starts_with('_'),
+ });
+ }
+ }
+ }
let extern_prelude = &tcx.resolutions(()).extern_prelude;
Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
None => format!("use {};", item.ident.name),
};
- let vis = tcx.sess.source_map().span_to_snippet(item.vis.span).unwrap_or_default();
+ let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
lint.build("`extern crate` is not idiomatic in the new edition")
.span_suggestion_short(
}
}
-struct CollectExternCrateVisitor<'a> {
- crates_to_lint: &'a mut Vec<ExternCrateToLint>,
-}
-
struct ExternCrateToLint {
/// `DefId` of the extern crate
def_id: DefId,
/// about it going unused (but we should still emit idiom lints).
warn_if_unused: bool,
}
-
-impl<'a, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
- self.crates_to_lint.push(ExternCrateToLint {
- def_id: item.def_id.to_def_id(),
- span: item.span,
- orig_name,
- warn_if_unused: !item.ident.as_str().starts_with('_'),
- });
- }
- }
-
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
- fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
-}
tcx,
sp,
tr.path.span,
+ trait_ref.self_ty(),
impl_.self_ty.span,
&impl_.generics,
err,
tcx: TyCtxt<'tcx>,
sp: Span,
trait_span: Span,
+ self_ty: Ty<'tcx>,
self_ty_span: Span,
generics: &hir::Generics<'tcx>,
err: traits::OrphanCheckErr<'tcx>,
) -> Result<!, ErrorGuaranteed> {
Err(match err {
traits::OrphanCheckErr::NonLocalInputType(tys) => {
+ let msg = match self_ty.kind() {
+ ty::Adt(..) => "can be implemented for types defined outside of the crate",
+ _ if self_ty.is_primitive() => "can be implemented for primitive types",
+ _ => "can be implemented for arbitrary types",
+ };
let mut err = struct_span_err!(
tcx.sess,
sp,
E0117,
- "only traits defined in the current crate can be implemented for \
- arbitrary types"
+ "only traits defined in the current crate {msg}"
);
err.span_label(sp, "impl doesn't use only types from inside the current crate");
for (ty, is_target_ty) in &tys {
return;
}
+ placeholder_type_error_diag(
+ tcx,
+ span,
+ generics,
+ placeholder_types,
+ vec![],
+ suggest,
+ hir_ty,
+ kind,
+ )
+ .emit();
+}
+
+crate fn placeholder_type_error_diag<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ span: Option<Span>,
+ generics: &[hir::GenericParam<'_>],
+ placeholder_types: Vec<Span>,
+ additional_spans: Vec<Span>,
+ suggest: bool,
+ hir_ty: Option<&hir::Ty<'_>>,
+ kind: &'static str,
+) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ if placeholder_types.is_empty() {
+ return bad_placeholder(tcx, additional_spans, kind);
+ }
+
let type_name = generics.next_type_param_name(None);
let mut sugg: Vec<_> =
placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
sugg.push((span, format!(", {}", type_name)));
}
- let mut err = bad_placeholder(tcx, placeholder_types, kind);
+ let mut err =
+ bad_placeholder(tcx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
// Suggest, but only if it is not a function in const or static
if suggest {
);
}
}
- err.emit();
+
+ err
}
fn reject_placeholder_type_signatures_in_item<'tcx>(
generics,
..
})
- | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. })
| Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => {
- match get_infer_ret_ty(&sig.decl.output) {
- Some(ty) => {
- let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
- // Typeck doesn't expect erased regions to be returned from `type_of`.
- let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
- ty::ReErased => tcx.lifetimes.re_static,
- _ => r,
- });
- let fn_sig = ty::Binder::dummy(fn_sig);
-
- let mut visitor = HirPlaceholderCollector::default();
- visitor.visit_ty(ty);
- let mut diag = bad_placeholder(tcx, visitor.0, "return type");
- let ret_ty = fn_sig.skip_binder().output();
- if !ret_ty.references_error() {
- if !ret_ty.is_closure() {
- let ret_ty_str = match ret_ty.kind() {
- // Suggest a function pointer return type instead of a unique function definition
- // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
- // syntax)
- ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
- _ => ret_ty.to_string(),
- };
- diag.span_suggestion(
- ty.span,
- "replace with the correct return type",
- ret_ty_str,
- Applicability::MaybeIncorrect,
- );
- } else {
- // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
- // to prevent the user from getting a papercut while trying to use the unique closure
- // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
- diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
- diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
- }
- }
- diag.emit();
+ infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
+ }
- fn_sig
- }
- None => <dyn AstConv<'_>>::ty_of_fn(
+ ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) => {
+ // Do not try to inference the return type for a impl method coming from a trait
+ if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
+ tcx.hir().get(tcx.hir().get_parent_node(hir_id))
+ && i.of_trait.is_some()
+ {
+ <dyn AstConv<'_>>::ty_of_fn(
&icx,
hir_id,
sig.header.unsafety,
generics,
Some(ident.span),
None,
- ),
+ )
+ } else {
+ infer_return_ty_for_fn_sig(tcx, sig, *ident, generics, def_id, &icx)
}
}
}
}
+fn infer_return_ty_for_fn_sig<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ sig: &hir::FnSig<'_>,
+ ident: Ident,
+ generics: &hir::Generics<'_>,
+ def_id: LocalDefId,
+ icx: &ItemCtxt<'tcx>,
+) -> ty::PolyFnSig<'tcx> {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+
+ match get_infer_ret_ty(&sig.decl.output) {
+ Some(ty) => {
+ let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
+ // Typeck doesn't expect erased regions to be returned from `type_of`.
+ let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
+ ty::ReErased => tcx.lifetimes.re_static,
+ _ => r,
+ });
+ let fn_sig = ty::Binder::dummy(fn_sig);
+
+ let mut visitor = HirPlaceholderCollector::default();
+ visitor.visit_ty(ty);
+ let mut diag = bad_placeholder(tcx, visitor.0, "return type");
+ let ret_ty = fn_sig.skip_binder().output();
+ if !ret_ty.references_error() {
+ if !ret_ty.is_closure() {
+ let ret_ty_str = match ret_ty.kind() {
+ // Suggest a function pointer return type instead of a unique function definition
+ // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
+ // syntax)
+ ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
+ _ => ret_ty.to_string(),
+ };
+ diag.span_suggestion(
+ ty.span,
+ "replace with the correct return type",
+ ret_ty_str,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
+ // to prevent the user from getting a papercut while trying to use the unique closure
+ // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
+ diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
+ diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
+ }
+ }
+ diag.emit();
+
+ fn_sig
+ }
+ None => <dyn AstConv<'_>>::ty_of_fn(
+ icx,
+ hir_id,
+ sig.header.unsafety,
+ sig.header.abi,
+ sig.decl,
+ generics,
+ Some(ident.span),
+ None,
+ ),
+ }
+}
+
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
match tcx.hir().expect_item(def_id.expect_local()).kind {
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
_ => false,
}) =>
{
#[primary_span]
#[label]
pub span: Span,
- #[suggestion_verbose(message = "suggestion", code = "{ty}")]
+ #[suggestion_verbose(code = "{ty}")]
pub opt_sugg: Option<(Span, Applicability)>,
}
hir::ExprKind::InlineAsm(asm) => {
for (op, _op_sp) in asm.operands {
match op {
- hir::InlineAsmOperand::In { expr, .. }
- | hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr),
+ hir::InlineAsmOperand::In { expr, .. } => self.consume_expr(expr),
hir::InlineAsmOperand::Out { expr: Some(expr), .. }
| hir::InlineAsmOperand::InOut { expr, .. } => {
self.mutate_expr(expr);
}
}
hir::InlineAsmOperand::Out { expr: None, .. }
- | hir::InlineAsmOperand::Const { .. } => {}
+ | hir::InlineAsmOperand::Const { .. }
+ | hir::InlineAsmOperand::SymFn { .. }
+ | hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
}
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)]
+#![feature(drain_filter)]
#![feature(hash_drain_filter)]
#![feature(if_let_guard)]
#![feature(is_sorted)]
+#![feature(label_break_value)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(min_specialization)]
use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
while predicates_added {
predicates_added = false;
- let mut visitor = InferVisitor {
- tcx,
- global_inferred_outlives: &mut global_inferred_outlives,
- predicates_added: &mut predicates_added,
- explicit_map,
- };
-
// Visit all the crates and infer predicates
- tcx.hir().visit_all_item_likes(&mut visitor);
- }
+ for id in tcx.hir().items() {
+ let item_did = id.def_id;
- global_inferred_outlives
-}
+ debug!("InferVisitor::visit_item(item={:?})", item_did);
-pub struct InferVisitor<'cx, 'tcx> {
- tcx: TyCtxt<'tcx>,
- global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
- predicates_added: &'cx mut bool,
- explicit_map: &'cx mut ExplicitPredicatesMap<'tcx>,
-}
-
-impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- let item_did = item.def_id;
-
- debug!("InferVisitor::visit_item(item={:?})", item_did);
+ let mut item_required_predicates = RequiredPredicates::default();
+ match tcx.hir().def_kind(item_did) {
+ DefKind::Union | DefKind::Enum | DefKind::Struct => {
+ let adt_def = tcx.adt_def(item_did.to_def_id());
- let mut item_required_predicates = RequiredPredicates::default();
- match item.kind {
- hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) => {
- let adt_def = self.tcx.adt_def(item_did.to_def_id());
-
- // Iterate over all fields in item_did
- for field_def in adt_def.all_fields() {
- // Calculating the predicate requirements necessary
- // for item_did.
- //
- // For field of type &'a T (reference) or Adt
- // (struct/enum/union) there will be outlive
- // requirements for adt_def.
- let field_ty = self.tcx.type_of(field_def.did);
- let field_span = self.tcx.def_span(field_def.did);
- insert_required_predicates_to_be_wf(
- self.tcx,
- field_ty,
- field_span,
- self.global_inferred_outlives,
- &mut item_required_predicates,
- &mut self.explicit_map,
- );
+ // Iterate over all fields in item_did
+ for field_def in adt_def.all_fields() {
+ // Calculating the predicate requirements necessary
+ // for item_did.
+ //
+ // For field of type &'a T (reference) or Adt
+ // (struct/enum/union) there will be outlive
+ // requirements for adt_def.
+ let field_ty = tcx.type_of(field_def.did);
+ let field_span = tcx.def_span(field_def.did);
+ insert_required_predicates_to_be_wf(
+ tcx,
+ field_ty,
+ field_span,
+ &mut global_inferred_outlives,
+ &mut item_required_predicates,
+ explicit_map,
+ );
+ }
}
- }
- _ => {}
- };
+ _ => {}
+ };
- // If new predicates were added (`local_predicate_map` has more
- // predicates than the `global_inferred_outlives`), the new predicates
- // might result in implied predicates for their parent types.
- // Therefore mark `predicates_added` as true and which will ensure
- // we walk the crates again and re-calculate predicates for all
- // items.
- let item_predicates_len: usize =
- self.global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
- if item_required_predicates.len() > item_predicates_len {
- *self.predicates_added = true;
- self.global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
+ // If new predicates were added (`local_predicate_map` has more
+ // predicates than the `global_inferred_outlives`), the new predicates
+ // might result in implied predicates for their parent types.
+ // Therefore mark `predicates_added` as true and which will ensure
+ // we walk the crates again and re-calculate predicates for all
+ // items.
+ let item_predicates_len: usize =
+ global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
+ if item_required_predicates.len() > item_predicates_len {
+ predicates_added = true;
+ global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
+ }
}
}
- fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
-
- fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
-
- fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
+ global_inferred_outlives
}
fn insert_required_predicates_to_be_wf<'tcx>(
use rustc_hir as hir;
use rustc_middle::hir::map::fn_sig;
use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath;
-use rustc_middle::ty::{self as ty, TyCtxt};
+use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
use rustc_session::Session;
use rustc_span::def_id::DefId;
+use std::iter;
use GenericArgsInfo::*;
.join(", ")
}
+ fn get_unbound_associated_types(&self) -> Vec<String> {
+ if self.tcx.is_trait(self.def_id) {
+ let items: &AssocItems<'_> = self.tcx.associated_items(self.def_id);
+ items
+ .in_definition_order()
+ .filter(|item| item.kind == AssocKind::Type)
+ .filter(|item| {
+ !self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name)
+ })
+ .map(|item| item.name.to_ident_string())
+ .collect()
+ } else {
+ Vec::default()
+ }
+ }
+
fn create_error_message(&self) -> String {
let def_path = self.tcx.def_path_str(self.def_id);
let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
fn suggest_removing_args_or_generics(&self, err: &mut Diagnostic) {
let num_provided_lt_args = self.num_provided_lifetime_args();
let num_provided_type_const_args = self.num_provided_type_or_const_args();
+ let unbound_types = self.get_unbound_associated_types();
let num_provided_args = num_provided_lt_args + num_provided_type_const_args;
assert!(num_provided_args > 0);
let redundant_type_or_const_args = num_redundant_type_or_const_args > 0;
let remove_entire_generics = num_redundant_args >= self.gen_args.args.len();
+ let provided_args_matches_unbound_traits =
+ unbound_types.len() == num_redundant_type_or_const_args;
let remove_lifetime_args = |err: &mut Diagnostic| {
let mut lt_arg_spans = Vec::new();
);
};
- if remove_entire_generics {
+ // If there is a single unbound associated type and a single excess generic param
+ // suggest replacing the generic param with the associated type bound
+ if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
+ let mut suggestions = vec![];
+ let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
+ for (potential, name) in iter::zip(unused_generics, &unbound_types) {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(potential.span()) {
+ suggestions.push((potential.span(), format!("{} = {}", name, snippet)));
+ }
+ }
+
+ if !suggestions.is_empty() {
+ err.multipart_suggestion(
+ &format!(
+ "replace the generic bound{s} with the associated type{s}",
+ s = pluralize!(unbound_types.len())
+ ),
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ } else if remove_entire_generics {
let span = self
.path_segment
.args
# FIXME(#61117): Some tests fail when this option is enabled.
#debuginfo-level-tests = 0
-# Whether to run `dsymutil` on Apple platforms to gather debug info into .dSYM
-# bundles. `dsymutil` adds time to builds for no clear benefit, and also makes
-# it more difficult for debuggers to find debug info. The compiler currently
-# defaults to running `dsymutil` to preserve its historical default, but when
-# compiling the compiler itself, we skip it by default since we know it's safe
-# to do so in that case.
-#run-dsymutil = false
+# Should rustc be build with split debuginfo? Default is platform dependent.
+# Valid values are the same as those accepted by `-C split-debuginfo`
+# (`off`/`unpacked`/`packed`).
+#
+# On Linux, split debuginfo is disabled by default.
+#
+# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
+# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
+# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
+# no clear benefit, and also makes it more difficult for debuggers to find
+# debug info. The compiler currently defaults to running `dsymutil` to preserve
+# its historical default, but when compiling the compiler itself, we skip it by
+# default since we know it's safe to do so in that case.
+#
+# On Windows platforms, packed debuginfo is the only supported option,
+# producing a `.pdb` file.
+#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
#backtrace = true
a.check();
}
+#[test]
+fn test_pop_first_last() {
+ let mut map = BTreeMap::new();
+ assert_eq!(map.pop_first(), None);
+ assert_eq!(map.pop_last(), None);
+
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.insert(3, 30);
+ map.insert(4, 40);
+
+ assert_eq!(map.len(), 4);
+
+ let (key, val) = map.pop_first().unwrap();
+ assert_eq!(key, 1);
+ assert_eq!(val, 10);
+ assert_eq!(map.len(), 3);
+
+ let (key, val) = map.pop_first().unwrap();
+ assert_eq!(key, 2);
+ assert_eq!(val, 20);
+ assert_eq!(map.len(), 2);
+ let (key, val) = map.pop_last().unwrap();
+ assert_eq!(key, 4);
+ assert_eq!(val, 40);
+ assert_eq!(map.len(), 1);
+
+ map.insert(5, 50);
+ map.insert(6, 60);
+ assert_eq!(map.len(), 3);
+
+ let (key, val) = map.pop_first().unwrap();
+ assert_eq!(key, 3);
+ assert_eq!(val, 30);
+ assert_eq!(map.len(), 2);
+
+ let (key, val) = map.pop_last().unwrap();
+ assert_eq!(key, 6);
+ assert_eq!(val, 60);
+ assert_eq!(map.len(), 1);
+
+ let (key, val) = map.pop_last().unwrap();
+ assert_eq!(key, 5);
+ assert_eq!(val, 50);
+ assert_eq!(map.len(), 0);
+
+ assert_eq!(map.pop_first(), None);
+ assert_eq!(map.pop_last(), None);
+
+ map.insert(7, 70);
+ map.insert(8, 80);
+
+ let (key, val) = map.pop_last().unwrap();
+ assert_eq!(key, 8);
+ assert_eq!(val, 80);
+ assert_eq!(map.len(), 1);
+
+ let (key, val) = map.pop_last().unwrap();
+ assert_eq!(key, 7);
+ assert_eq!(val, 70);
+ assert_eq!(map.len(), 0);
+
+ assert_eq!(map.pop_first(), None);
+ assert_eq!(map.pop_last(), None);
+}
+
+#[test]
+fn test_get_key_value() {
+ let mut map = BTreeMap::new();
+
+ assert!(map.is_empty());
+ assert_eq!(map.get_key_value(&1), None);
+ assert_eq!(map.get_key_value(&2), None);
+
+ map.insert(1, 10);
+ map.insert(2, 20);
+ map.insert(3, 30);
+
+ assert_eq!(map.len(), 3);
+ assert_eq!(map.get_key_value(&1), Some((&1, &10)));
+ assert_eq!(map.get_key_value(&3), Some((&3, &30)));
+ assert_eq!(map.get_key_value(&4), None);
+
+ map.remove(&3);
+
+ assert_eq!(map.len(), 2);
+ assert_eq!(map.get_key_value(&3), None);
+ assert_eq!(map.get_key_value(&2), Some((&2, &20)));
+}
+
#[test]
fn test_insert_into_full_height_0() {
let size = node::CAPACITY;
}
}
+#[test]
+fn test_try_insert() {
+ let mut map = BTreeMap::new();
+
+ assert!(map.is_empty());
+
+ assert_eq!(map.try_insert(1, 10).unwrap(), &10);
+ assert_eq!(map.try_insert(2, 20).unwrap(), &20);
+
+ let err = map.try_insert(2, 200).unwrap_err();
+ assert_eq!(err.entry.key(), &2);
+ assert_eq!(err.entry.get(), &20);
+ assert_eq!(err.value, 200);
+}
+
macro_rules! create_append_test {
($name:ident, $len:expr) => {
#[test]
/// be mindful of side effects.
///
/// [`Vec`]: crate::vec::Vec
-#[cfg(not(test))]
+#[cfg(all(not(no_global_oom_handling), not(test)))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "vec_macro"]
// required for this macro definition, is not available. Instead use the
// `slice::into_vec` function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
-#[cfg(test)]
+#[cfg(all(not(no_global_oom_handling), test))]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
fn inc_strong(&self) {
let strong = self.strong();
+ // We insert an `assume` here to hint LLVM at an otherwise
+ // missed optimization.
+ // SAFETY: The reference count will never be zero when this is
+ // called.
+ unsafe {
+ core::intrinsics::assume(strong != 0);
+ }
+
+ let strong = strong.wrapping_add(1);
+ self.strong_ref().set(strong);
+
// We want to abort on overflow instead of dropping the value.
- // The reference count will never be zero when this is called;
- // nevertheless, we insert an abort here to hint LLVM at
- // an otherwise missed optimization.
- if strong == 0 || strong == usize::MAX {
+ // Checking for overflow after the store instead of before
+ // allows for slightly better code generation.
+ if core::intrinsics::unlikely(strong == 0) {
abort();
}
- self.strong_ref().set(strong + 1);
}
#[inline]
fn inc_weak(&self) {
let weak = self.weak();
+ // We insert an `assume` here to hint LLVM at an otherwise
+ // missed optimization.
+ // SAFETY: The reference count will never be zero when this is
+ // called.
+ unsafe {
+ core::intrinsics::assume(weak != 0);
+ }
+
+ let weak = weak.wrapping_add(1);
+ self.weak_ref().set(weak);
+
// We want to abort on overflow instead of dropping the value.
- // The reference count will never be zero when this is called;
- // nevertheless, we insert an abort here to hint LLVM at
- // an otherwise missed optimization.
- if weak == 0 || weak == usize::MAX {
+ // Checking for overflow after the store instead of before
+ // allows for slightly better code generation.
+ if core::intrinsics::unlikely(weak == 0) {
abort();
}
- self.weak_ref().set(weak + 1);
}
#[inline]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn clear(&mut self) {
- self.truncate(0)
+ let elems: *mut [T] = self.as_mut_slice();
+
+ // SAFETY:
+ // - `elems` comes directly from `as_mut_slice` and is therefore valid.
+ // - Setting `self.len` before calling `drop_in_place` means that,
+ // if an element's `Drop` impl panics, the vector's `Drop` impl will
+ // do nothing (leaking the rest of the elements) instead of dropping
+ // some twice.
+ unsafe {
+ self.len = 0;
+ ptr::drop_in_place(elems);
+ }
}
/// Returns the number of elements in the vector, also referred to
#[inline]
fn contains_nonascii(v: usize) -> bool {
- const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+ const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; core::mem::size_of::<usize>()]);
(NONASCII_MASK & v) != 0
}
without modifying the original"]
#[inline]
pub const fn to_digit(self, radix: u32) -> Option<u32> {
- assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
// If not a digit, a number greater than radix will be created.
let mut digit = (self as u32).wrapping_sub('0' as u32);
if radix > 10 {
+ assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
if digit < 10 {
return Some(digit);
}
//! Compiler intrinsics.
//!
-//! The corresponding definitions are in `compiler/rustc_codegen_llvm/src/intrinsic.rs`.
-//! The corresponding const implementations are in `compiler/rustc_mir/src/interpret/intrinsics.rs`
+//! The corresponding definitions are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_codegen_llvm/src/intrinsic.rs>.
+//! The corresponding const implementations are in <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>.
//!
//! # Const intrinsics
//!
//!
//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs> to
-//! `compiler/rustc_mir/src/interpret/intrinsics.rs` and add a
-//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
+//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> and add a
+//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
//!
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
fn into_iter(self) -> Self::IntoIter;
}
+#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: Iterator> IntoIterator for I {
+impl<I: ~const Iterator> const IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
/// it will first try to advance the first iterator at most one time and if it still yielded an item
/// try to advance the second iterator at most one time.
///
+ /// To 'undo' the result of zipping up two iterators, see [`unzip`].
+ ///
+ /// [`unzip`]: Iterator::unzip
+ ///
/// # Examples
///
/// Basic usage:
#![feature(const_intrinsic_copy)]
#![feature(const_intrinsic_forget)]
#![feature(const_likely)]
+#![feature(const_maybe_uninit_uninit_array)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_maybe_uninit_assume_init)]
+#![feature(const_nonnull_new)]
#![feature(const_num_from_num)]
#![feature(const_ops)]
#![feature(const_option)]
#![feature(const_option_ext)]
#![feature(const_pin)]
#![feature(const_replace)]
+#![feature(const_ptr_as_ref)]
#![feature(const_ptr_is_null)]
#![feature(const_ptr_offset_from)]
#![feature(const_ptr_read)]
/// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
/// let data = read(&mut buf);
/// ```
- #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
- #[rustc_const_unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
+ #[unstable(feature = "maybe_uninit_uninit_array", issue = "96097")]
+ #[rustc_const_unstable(feature = "const_maybe_uninit_uninit_array", issue = "96097")]
#[must_use]
#[inline(always)]
- pub const fn uninit_array<const LEN: usize>() -> [Self; LEN] {
+ pub const fn uninit_array<const N: usize>() -> [Self; N] {
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
- unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
+ unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
}
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
///
/// assert_eq!(array, [0, 1, 2]);
/// ```
- #[unstable(feature = "maybe_uninit_array_assume_init", issue = "80908")]
+ #[unstable(feature = "maybe_uninit_array_assume_init", issue = "96097")]
+ #[rustc_const_unstable(feature = "const_maybe_uninit_array_assume_init", issue = "96097")]
#[inline(always)]
#[track_caller]
- pub unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
+ pub const unsafe fn array_assume_init<const N: usize>(array: [Self; N]) -> [T; N] {
// SAFETY:
// * The caller guarantees that all elements of the array are initialized
// * `MaybeUninit<T>` and T are guaranteed to have the same layout
// * `MaybeUninit` does not drop, so there are no double-frees
// And thus the conversion is safe
- unsafe {
+ let ret = unsafe {
intrinsics::assert_inhabited::<[T; N]>();
(&array as *const _ as *const [T; N]).read()
- }
+ };
+
+ // FIXME: required to avoid `~const Destruct` bound
+ super::forget(array);
+ ret
}
/// Assuming all the elements are initialized, get a slice to them.
#[inline]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub(crate) const fn abs_private(self) -> f32 {
- f32::from_bits(self.to_bits() & 0x7fff_ffff)
+ // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
+ unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & 0x7fff_ffff) }
}
/// Returns `true` if this value is positive infinity or negative infinity, and
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
#[inline]
pub const fn is_infinite(self) -> bool {
- self.abs_private() == Self::INFINITY
+ // Getting clever with transmutation can result in incorrect answers on some FPUs
+ // FIXME: alter the Rust <-> Rust calling convention to prevent this problem.
+ // See https://github.com/rust-lang/rust/issues/72327
+ (self == f32::INFINITY) | (self == f32::NEG_INFINITY)
}
/// Returns `true` if this number is neither infinite nor `NaN`.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn classify(self) -> FpCategory {
+ // A previous implementation tried to only use bitmask-based checks,
+ // using f32::to_bits to transmute the float to its bit repr and match on that.
+ // Unfortunately, floating point numbers can be much worse than that.
+ // This also needs to not result in recursive evaluations of f64::to_bits.
+ //
+ // On some processors, in some cases, LLVM will "helpfully" lower floating point ops,
+ // in spite of a request for them using f32 and f64, to things like x87 operations.
+ // These have an f64's mantissa, but can have a larger than normal exponent.
+ // FIXME(jubilee): Using x87 operations is never necessary in order to function
+ // on x86 processors for Rust-to-Rust calls, so this issue should not happen.
+ // Code generation should be adjusted to use non-C calling conventions, avoiding this.
+ //
+ if self.is_infinite() {
+ // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask.
+ FpCategory::Infinite
+ } else if self.is_nan() {
+ // And it may not be NaN, as it can simply be an "overextended" finite value.
+ FpCategory::Nan
+ } else {
+ // However, std can't simply compare to zero to check for zero, either,
+ // as correctness requires avoiding equality tests that may be Subnormal == -0.0
+ // because it may be wrong under "denormals are zero" and "flush to zero" modes.
+ // Most of std's targets don't use those, but they are used for thumbv7neon.
+ // So, this does use bitpattern matching for the rest.
+
+ // SAFETY: f32 to u32 is fine. Usually.
+ // If classify has gotten this far, the value is definitely in one of these categories.
+ unsafe { f32::partial_classify(self) }
+ }
+ }
+
+ // This doesn't actually return a right answer for NaN on purpose,
+ // seeing as how it cannot correctly discern between a floating point NaN,
+ // and some normal floating point numbers truncated from an x87 FPU.
+ // FIXME(jubilee): This probably could at least answer things correctly for Infinity,
+ // like the f64 version does, but I need to run more checks on how things go on x86.
+ // I fear losing mantissa data that would have answered that differently.
+ //
+ // # Safety
+ // This requires making sure you call this function for values it answers correctly on,
+ // otherwise it returns a wrong answer. This is not important for memory safety per se,
+ // but getting floats correct is important for not accidentally leaking const eval
+ // runtime-deviating logic which may or may not be acceptable.
+ #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+ const unsafe fn partial_classify(self) -> FpCategory {
const EXP_MASK: u32 = 0x7f800000;
const MAN_MASK: u32 = 0x007fffff;
- let bits = self.to_bits();
- match (bits & MAN_MASK, bits & EXP_MASK) {
+ // SAFETY: The caller is not asking questions for which this will tell lies.
+ let b = unsafe { mem::transmute::<f32, u32>(self) };
+ match (b & MAN_MASK, b & EXP_MASK) {
(0, 0) => FpCategory::Zero,
(_, 0) => FpCategory::Subnormal,
+ _ => FpCategory::Normal,
+ }
+ }
+
+ // This operates on bits, and only bits, so it can ignore concerns about weird FPUs.
+ // FIXME(jubilee): In a just world, this would be the entire impl for classify,
+ // plus a transmute. We do not live in a just world, but we can make it more so.
+ #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+ const fn classify_bits(b: u32) -> FpCategory {
+ const EXP_MASK: u32 = 0x7f800000;
+ const MAN_MASK: u32 = 0x007fffff;
+
+ match (b & MAN_MASK, b & EXP_MASK) {
(0, EXP_MASK) => FpCategory::Infinite,
(_, EXP_MASK) => FpCategory::Nan,
+ (0, 0) => FpCategory::Zero,
+ (_, 0) => FpCategory::Subnormal,
_ => FpCategory::Normal,
}
}
pub const fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
- self.to_bits() & 0x8000_0000 != 0
+ // SAFETY: This is just transmuting to get the sign bit, it's fine.
+ unsafe { mem::transmute::<f32, u32>(self) & 0x8000_0000 != 0 }
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
#[inline]
pub const fn to_bits(self) -> u32 {
- // SAFETY: `u32` is a plain old datatype so we can always transmute to it
- unsafe { mem::transmute(self) }
+ // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
+ // ...sorta.
+ //
+ // It turns out that at runtime, it is possible for a floating point number
+ // to be subject to a floating point mode that alters nonzero subnormal numbers
+ // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+ // This is not a problem per se, but at least one tier2 platform for Rust
+ // actually exhibits this behavior by default.
+ //
+ // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+ // i.e. not soft-float, the way Rust does parameter passing can actually alter
+ // a number that is "not infinity" to have the same exponent as infinity,
+ // in a slightly unpredictable manner.
+ //
+ // And, of course evaluating to a NaN value is fairly nondeterministic.
+ // More precisely: when NaN should be returned is knowable, but which NaN?
+ // So far that's defined by a combination of LLVM and the CPU, not Rust.
+ // This function, however, allows observing the bitstring of a NaN,
+ // thus introspection on CTFE.
+ //
+ // In order to preserve, at least for the moment, const-to-runtime equivalence,
+ // we reject any of these possible situations from happening.
+ #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ const fn ct_f32_to_u32(ct: f32) -> u32 {
+ match ct.classify() {
+ FpCategory::Nan => {
+ panic!("const-eval error: cannot use f32::to_bits on a NaN")
+ }
+ FpCategory::Subnormal => {
+ panic!("const-eval error: cannot use f32::to_bits on a subnormal number")
+ }
+ FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+ // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy.
+ unsafe { mem::transmute::<f32, u32>(ct) }
+ }
+ }
+ }
+ // SAFETY: `u32` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ let rt_f32_to_u32 = |rt| unsafe { mem::transmute::<f32, u32>(rt) };
+ // SAFETY: We use internal implementations that either always work or fail at compile time.
+ unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
}
/// Raw transmutation from `u32`.
#[must_use]
#[inline]
pub const fn from_bits(v: u32) -> Self {
- // SAFETY: `u32` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
- unsafe { mem::transmute(v) }
+ // SAFETY: `u32` is a plain old datatype so we can always transmute from it
+ // ...sorta.
+ //
+ // It turns out that at runtime, it is possible for a floating point number
+ // to be subject to floating point modes that alter nonzero subnormal numbers
+ // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+ // This is not a problem usually, but at least one tier2 platform for Rust
+ // actually exhibits this behavior by default: thumbv7neon
+ // aka "the Neon FPU in AArch32 state"
+ //
+ // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+ // i.e. not soft-float, the way Rust does parameter passing can actually alter
+ // a number that is "not infinity" to have the same exponent as infinity,
+ // in a slightly unpredictable manner.
+ //
+ // And, of course evaluating to a NaN value is fairly nondeterministic.
+ // More precisely: when NaN should be returned is knowable, but which NaN?
+ // So far that's defined by a combination of LLVM and the CPU, not Rust.
+ // This function, however, allows observing the bitstring of a NaN,
+ // thus introspection on CTFE.
+ //
+ // In order to preserve, at least for the moment, const-to-runtime equivalence,
+ // reject any of these possible situations from happening.
+ #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ const fn ct_u32_to_f32(ct: u32) -> f32 {
+ match f32::classify_bits(ct) {
+ FpCategory::Subnormal => {
+ panic!("const-eval error: cannot use f32::from_bits on a subnormal number")
+ }
+ FpCategory::Nan => {
+ panic!("const-eval error: cannot use f32::from_bits on NaN")
+ }
+ FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+ // SAFETY: It's not a frumious number
+ unsafe { mem::transmute::<u32, f32>(ct) }
+ }
+ }
+ }
+ // SAFETY: `u32` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ let rt_u32_to_f32 = |rt| unsafe { mem::transmute::<u32, f32>(rt) };
+ // SAFETY: We use internal implementations that either always work or fail at compile time.
+ unsafe { intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32) }
}
/// Return the memory representation of this floating point number as a byte array in
#[inline]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub(crate) const fn abs_private(self) -> f64 {
- f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
+ // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
+ unsafe {
+ mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & 0x7fff_ffff_ffff_ffff)
+ }
}
/// Returns `true` if this value is positive infinity or negative infinity, and
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
#[inline]
pub const fn is_infinite(self) -> bool {
- self.abs_private() == Self::INFINITY
+ // Getting clever with transmutation can result in incorrect answers on some FPUs
+ // FIXME: alter the Rust <-> Rust calling convention to prevent this problem.
+ // See https://github.com/rust-lang/rust/issues/72327
+ (self == f64::INFINITY) | (self == f64::NEG_INFINITY)
}
/// Returns `true` if this number is neither infinite nor `NaN`.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn classify(self) -> FpCategory {
+ // A previous implementation tried to only use bitmask-based checks,
+ // using f64::to_bits to transmute the float to its bit repr and match on that.
+ // Unfortunately, floating point numbers can be much worse than that.
+ // This also needs to not result in recursive evaluations of f64::to_bits.
+ //
+ // On some processors, in some cases, LLVM will "helpfully" lower floating point ops,
+ // in spite of a request for them using f32 and f64, to things like x87 operations.
+ // These have an f64's mantissa, but can have a larger than normal exponent.
+ // FIXME(jubilee): Using x87 operations is never necessary in order to function
+ // on x86 processors for Rust-to-Rust calls, so this issue should not happen.
+ // Code generation should be adjusted to use non-C calling conventions, avoiding this.
+ //
+ // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask.
+ // And it may not be NaN, as it can simply be an "overextended" finite value.
+ if self.is_nan() {
+ FpCategory::Nan
+ } else {
+ // However, std can't simply compare to zero to check for zero, either,
+ // as correctness requires avoiding equality tests that may be Subnormal == -0.0
+ // because it may be wrong under "denormals are zero" and "flush to zero" modes.
+ // Most of std's targets don't use those, but they are used for thumbv7neon.
+ // So, this does use bitpattern matching for the rest.
+
+ // SAFETY: f64 to u64 is fine. Usually.
+ // If control flow has gotten this far, the value is definitely in one of the categories
+ // that f64::partial_classify can correctly analyze.
+ unsafe { f64::partial_classify(self) }
+ }
+ }
+
+ // This doesn't actually return a right answer for NaN on purpose,
+ // seeing as how it cannot correctly discern between a floating point NaN,
+ // and some normal floating point numbers truncated from an x87 FPU.
+ #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+ const unsafe fn partial_classify(self) -> FpCategory {
const EXP_MASK: u64 = 0x7ff0000000000000;
const MAN_MASK: u64 = 0x000fffffffffffff;
- let bits = self.to_bits();
- match (bits & MAN_MASK, bits & EXP_MASK) {
+ // SAFETY: The caller is not asking questions for which this will tell lies.
+ let b = unsafe { mem::transmute::<f64, u64>(self) };
+ match (b & MAN_MASK, b & EXP_MASK) {
+ (0, EXP_MASK) => FpCategory::Infinite,
(0, 0) => FpCategory::Zero,
(_, 0) => FpCategory::Subnormal,
+ _ => FpCategory::Normal,
+ }
+ }
+
+ // This operates on bits, and only bits, so it can ignore concerns about weird FPUs.
+ // FIXME(jubilee): In a just world, this would be the entire impl for classify,
+ // plus a transmute. We do not live in a just world, but we can make it more so.
+ #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
+ const fn classify_bits(b: u64) -> FpCategory {
+ const EXP_MASK: u64 = 0x7ff0000000000000;
+ const MAN_MASK: u64 = 0x000fffffffffffff;
+
+ match (b & MAN_MASK, b & EXP_MASK) {
(0, EXP_MASK) => FpCategory::Infinite,
(_, EXP_MASK) => FpCategory::Nan,
+ (0, 0) => FpCategory::Zero,
+ (_, 0) => FpCategory::Subnormal,
_ => FpCategory::Normal,
}
}
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
#[inline]
pub const fn is_sign_negative(self) -> bool {
- self.to_bits() & 0x8000_0000_0000_0000 != 0
+ // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+ // applies to zeros and NaNs as well.
+ // SAFETY: This is just transmuting to get the sign bit, it's fine.
+ unsafe { mem::transmute::<f64, u64>(self) & 0x8000_0000_0000_0000 != 0 }
}
#[must_use]
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
#[inline]
pub const fn to_bits(self) -> u64 {
- // SAFETY: `u64` is a plain old datatype so we can always transmute to it
- unsafe { mem::transmute(self) }
+ // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
+ // ...sorta.
+ //
+ // See the SAFETY comment in f64::from_bits for more.
+ #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ const fn ct_f64_to_u64(ct: f64) -> u64 {
+ match ct.classify() {
+ FpCategory::Nan => {
+ panic!("const-eval error: cannot use f64::to_bits on a NaN")
+ }
+ FpCategory::Subnormal => {
+ panic!("const-eval error: cannot use f64::to_bits on a subnormal number")
+ }
+ FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+ // SAFETY: We have a normal floating point number. Now we transmute, i.e. do a bitcopy.
+ unsafe { mem::transmute::<f64, u64>(ct) }
+ }
+ }
+ }
+ // SAFETY: `u64` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ let rt_f64_to_u64 = |rt| unsafe { mem::transmute::<f64, u64>(rt) };
+ // SAFETY: We use internal implementations that either always work or fail at compile time.
+ unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
}
/// Raw transmutation from `u64`.
#[must_use]
#[inline]
pub const fn from_bits(v: u64) -> Self {
- // SAFETY: `u64` is a plain old datatype so we can always transmute from it
// It turns out the safety issues with sNaN were overblown! Hooray!
- unsafe { mem::transmute(v) }
+ // SAFETY: `u64` is a plain old datatype so we can always transmute from it
+ // ...sorta.
+ //
+ // It turns out that at runtime, it is possible for a floating point number
+ // to be subject to floating point modes that alter nonzero subnormal numbers
+ // to zero on reads and writes, aka "denormals are zero" and "flush to zero".
+ // This is not a problem usually, but at least one tier2 platform for Rust
+ // actually exhibits an FTZ behavior by default: thumbv7neon
+ // aka "the Neon FPU in AArch32 state"
+ //
+ // Even with this, not all instructions exhibit the FTZ behaviors on thumbv7neon,
+ // so this should load the same bits if LLVM emits the "correct" instructions,
+ // but LLVM sometimes makes interesting choices about float optimization,
+ // and other FPUs may do similar. Thus, it is wise to indulge luxuriously in caution.
+ //
+ // In addition, on x86 targets with SSE or SSE2 disabled and the x87 FPU enabled,
+ // i.e. not soft-float, the way Rust does parameter passing can actually alter
+ // a number that is "not infinity" to have the same exponent as infinity,
+ // in a slightly unpredictable manner.
+ //
+ // And, of course evaluating to a NaN value is fairly nondeterministic.
+ // More precisely: when NaN should be returned is knowable, but which NaN?
+ // So far that's defined by a combination of LLVM and the CPU, not Rust.
+ // This function, however, allows observing the bitstring of a NaN,
+ // thus introspection on CTFE.
+ //
+ // In order to preserve, at least for the moment, const-to-runtime equivalence,
+ // reject any of these possible situations from happening.
+ #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ const fn ct_u64_to_f64(ct: u64) -> f64 {
+ match f64::classify_bits(ct) {
+ FpCategory::Subnormal => {
+ panic!("const-eval error: cannot use f64::from_bits on a subnormal number")
+ }
+ FpCategory::Nan => {
+ panic!("const-eval error: cannot use f64::from_bits on NaN")
+ }
+ FpCategory::Infinite | FpCategory::Normal | FpCategory::Zero => {
+ // SAFETY: It's not a frumious number
+ unsafe { mem::transmute::<u64, f64>(ct) }
+ }
+ }
+ }
+ // SAFETY: `u64` is a plain old datatype so we can always... uh...
+ // ...look, just pretend you forgot what you just read.
+ // Stability concerns.
+ let rt_u64_to_f64 = |rt| unsafe { mem::transmute::<u64, f64>(rt) };
+ // SAFETY: We use internal implementations that either always work or fail at compile time.
+ unsafe { intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64) }
}
/// Return the memory representation of this floating point number as a byte array in
widening_impl! { usize, u128, 64, unsigned }
}
+impl usize {
+ /// Returns an `usize` where every byte is equal to `x`.
+ #[inline]
+ pub(crate) const fn repeat_u8(x: u8) -> usize {
+ usize::from_ne_bytes([x; mem::size_of::<usize>()])
+ }
+
+ /// Returns an `usize` where every byte pair is equal to `x`.
+ #[inline]
+ pub(crate) const fn repeat_u16(x: u16) -> usize {
+ let mut r = 0usize;
+ let mut i = 0;
+ while i < mem::size_of::<usize>() {
+ // Use `wrapping_shl` to make it work on targets with 16-bit `usize`
+ r = r.wrapping_shl(16) | (x as usize);
+ i += 2;
+ }
+ r
+ }
+}
+
/// A classification of floating point numbers.
///
/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
- /// In particular, for the duration of this lifetime, the memory the pointer points to must
+ /// In particular, while this reference exists, the memory the pointer points to must
/// not get accessed (read or written) through any other pointer.
///
/// This applies even if the result of this method is unused!
use crate::convert::From;
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
-use crate::mem;
use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::ptr::NonNull;
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
)]
#[doc(hidden)]
#[repr(transparent)]
-#[rustc_layout_scalar_valid_range_start(1)]
pub struct Unique<T: ?Sized> {
- pointer: *const T,
+ pointer: NonNull<T>,
// NOTE: this marker has no consequences for variance, but is necessary
// for dropck to understand that we logically own a `T`.
//
#[must_use]
#[inline]
pub const fn dangling() -> Self {
- // SAFETY: mem::align_of() returns a valid, non-null pointer. The
- // conditions to call new_unchecked() are thus respected.
- unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::<T>(mem::align_of::<T>())) }
+ Self::from(NonNull::dangling())
}
}
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
// SAFETY: the caller must guarantee that `ptr` is non-null.
- unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
+ unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
}
/// Creates a new `Unique` if `ptr` is non-null.
#[inline]
pub const fn new(ptr: *mut T) -> Option<Self> {
- if !ptr.is_null() {
- // SAFETY: The pointer has already been checked and is not null.
- Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
+ if let Some(pointer) = NonNull::new(ptr) {
+ Some(Unique { pointer, _marker: PhantomData })
} else {
None
}
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub const fn as_ptr(self) -> *mut T {
- self.pointer as *mut T
+ self.pointer.as_ptr()
}
/// Dereferences the content.
pub const unsafe fn as_ref(&self) -> &T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
- unsafe { &*self.as_ptr() }
+ unsafe { self.pointer.as_ref() }
}
/// Mutably dereferences the content.
pub const unsafe fn as_mut(&mut self) -> &mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
- unsafe { &mut *self.as_ptr() }
+ unsafe { self.pointer.as_mut() }
}
/// Casts to a pointer of another type.
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub const fn cast<U>(self) -> Unique<U> {
- // SAFETY: Unique::new_unchecked() creates a new unique and needs
- // the given pointer to not be null.
- // Since we are passing self as a pointer, it cannot be null.
- unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
+ Unique::from(self.pointer.cast())
}
}
/// This conversion is infallible since references cannot be null.
#[inline]
fn from(reference: &mut T) -> Self {
- // SAFETY: A mutable reference cannot be null
- unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
+ Self::from(NonNull::from(reference))
+ }
+}
+
+#[unstable(feature = "ptr_internals", issue = "none")]
+impl<T: ?Sized> const From<NonNull<T>> for Unique<T> {
+ /// Converts a `NonNull<T>` to a `Unique<T>`.
+ ///
+ /// This conversion is infallible since `NonNull` cannot be null.
+ #[inline]
+ fn from(pointer: NonNull<T>) -> Self {
+ Unique { pointer, _marker: PhantomData }
}
}
/// from `../str/mod.rs`, which does something similar for utf8 validation.
#[inline]
fn contains_nonascii(v: usize) -> bool {
- const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+ const NONASCII_MASK: usize = usize::repeat_u8(0x80);
(NONASCII_MASK & v) != 0
}
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
Self { v: slice, pred, finished: false }
}
+ /// Returns a slice which contains items not yet handled by split.
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(split_as_slice)]
+ /// let slice = [1,2,3,4,5];
+ /// let mut split = slice.split(|v| v % 2 == 0);
+ /// assert!(split.next().is_some());
+ /// assert_eq!(split.as_slice(), &[3,4,5]);
+ /// ```
+ #[unstable(feature = "split_as_slice", issue = "96137")]
+ pub fn as_slice(&self) -> &'a [T] {
+ if self.finished { &[] } else { &self.v }
+ }
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
use crate::cmp;
use crate::mem;
-const LO_U64: u64 = 0x0101010101010101;
-const HI_U64: u64 = 0x8080808080808080;
-
-// Use truncation.
-const LO_USIZE: usize = LO_U64 as usize;
-const HI_USIZE: usize = HI_U64 as usize;
+const LO_USIZE: usize = usize::repeat_u8(0x01);
+const HI_USIZE: usize = usize::repeat_u8(0x80);
const USIZE_BYTES: usize = mem::size_of::<usize>();
/// Returns `true` if `x` contains any zero byte.
// true)
#[inline]
fn contains_non_continuation_byte(w: usize) -> usize {
- const LSB: usize = 0x0101_0101_0101_0101u64 as usize;
+ const LSB: usize = usize::repeat_u8(0x01);
((!w >> 7) | (w >> 6)) & LSB
}
// more efficient.
#[inline]
fn sum_bytes_in_usize(values: usize) -> usize {
- const LSB_SHORTS: usize = 0x0001_0001_0001_0001_u64 as usize;
- const SKIP_BYTES: usize = 0x00ff_00ff_00ff_00ff_u64 as usize;
+ const LSB_SHORTS: usize = usize::repeat_u16(0x0001);
+ const SKIP_BYTES: usize = usize::repeat_u16(0x00ff);
let pair_sum: usize = (values & SKIP_BYTES) + ((values >> 8) & SKIP_BYTES);
pair_sum.wrapping_mul(LSB_SHORTS) >> ((USIZE_SIZE - 2) * 8)
Some(ch)
}
-// use truncation to fit u64 into usize
-const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
+const NONASCII_MASK: usize = usize::repeat_u8(0x80);
/// Returns `true` if any byte in the word `x` is nonascii (>= 128).
#[inline]
}
}
-macro_rules! u8to64_le {
- ($buf:expr, $i:expr) => {
- $buf[0 + $i] as u64
- | ($buf[1 + $i] as u64) << 8
- | ($buf[2 + $i] as u64) << 16
- | ($buf[3 + $i] as u64) << 24
- | ($buf[4 + $i] as u64) << 32
- | ($buf[5 + $i] as u64) << 40
- | ($buf[6 + $i] as u64) << 48
- | ($buf[7 + $i] as u64) << 56
- };
- ($buf:expr, $i:expr, $len:expr) => {{
- let mut t = 0;
- let mut out = 0;
- while t < $len {
- out |= ($buf[t + $i] as u64) << t * 8;
- t += 1;
- }
- out
- }};
-}
-
fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
x.hash(&mut st);
st.finish()
let mut state_inc = SipHasher13::new_with_keys(k0, k1);
while t < 64 {
- let vec = u8to64_le!(vecs[t], 0);
+ let vec = u64::from_le_bytes(vecs[t]);
let out = hash_with(SipHasher13::new_with_keys(k0, k1), &Bytes(&buf));
assert_eq!(vec, out);
let mut state_inc = SipHasher::new_with_keys(k0, k1);
while t < 64 {
- let vec = u8to64_le!(vecs[t], 0);
+ let vec = u64::from_le_bytes(vecs[t]);
let out = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
assert_eq!(vec, out);
#![feature(sort_internals)]
#![feature(slice_take)]
#![feature(slice_from_ptr_range)]
+#![feature(split_as_slice)]
#![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_write_slice)]
}
}
+#[test]
+fn split_as_slice() {
+ let arr = [1, 2, 3, 4, 5, 6];
+ let mut split = arr.split(|v| v % 2 == 0);
+ assert_eq!(split.as_slice(), &[1, 2, 3, 4, 5, 6]);
+ assert!(split.next().is_some());
+ assert_eq!(split.as_slice(), &[3, 4, 5, 6]);
+ assert!(split.next().is_some());
+ assert!(split.next().is_some());
+ assert_eq!(split.as_slice(), &[]);
+}
+
#[should_panic]
#[test]
fn slice_split_array_ref_out_of_bounds() {
/// xor
pub(crate) fn simd_xor<T>(x: T, y: T) -> T;
+ /// getelementptr (without inbounds)
+ #[cfg(not(bootstrap))]
+ pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
+
/// fptoui/fptosi/uitofp/sitofp
/// casting floats to integers is truncating, so it is safe to convert values like e.g. 1.5
/// but the truncated value must fit in the target type or the result is poison.
//! Private implementation details of public gather/scatter APIs.
+#[cfg(not(bootstrap))]
+use crate::simd::intrinsics;
use crate::simd::{LaneCount, Simd, SupportedLaneCount};
+#[cfg(bootstrap)]
use core::mem;
/// A vector of *const T.
#[inline]
#[must_use]
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+ #[cfg(bootstrap)]
// Safety: converting pointers to usize and vice-versa is safe
// (even if using that pointer is not)
unsafe {
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
}
+ #[cfg(not(bootstrap))]
+ // Safety: this intrinsic doesn't have a precondition
+ unsafe { intrinsics::simd_arith_offset(self, addend) }
}
}
#[inline]
#[must_use]
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
+ #[cfg(bootstrap)]
// Safety: converting pointers to usize and vice-versa is safe
// (even if using that pointer is not)
unsafe {
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
}
+ #[cfg(not(bootstrap))]
+ // Safety: this intrinsic doesn't have a precondition
+ unsafe { intrinsics::simd_arith_offset(self, addend) }
}
}
[dependencies]
std = { path = "../std" }
+# Workaround: when documenting this crate rustdoc will try to load crate named
+# `core` when resolving doc links. Without this line a different `core` will be
+# loaded from sysroot causing duplicate lang items and other similar errors.
+core = { path = "../core" }
#![feature(exhaustive_patterns)]
#![feature(intra_doc_pointers)]
#![feature(lang_items)]
+#![feature(let_chains)]
#![feature(linkage)]
#![feature(min_specialization)]
#![feature(must_not_suspend)]
/// Run a parser, but fail if the entire input wasn't consumed.
/// Doesn't run atomically.
- fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError>
+ fn parse_with<T, F>(&mut self, inner: F, kind: AddrKind) -> Result<T, AddrParseError>
where
F: FnOnce(&mut Parser<'_>) -> Option<T>,
{
let result = inner(self);
- if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(()))
+ if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind))
}
/// Peek the next character from the input
impl FromStr for IpAddr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
- Parser::new(s).parse_with(|p| p.read_ip_addr())
+ Parser::new(s).parse_with(|p| p.read_ip_addr(), AddrKind::Ip)
}
}
fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
// don't try to parse if too long
if s.len() > 15 {
- Err(AddrParseError(()))
+ Err(AddrParseError(AddrKind::Ipv4))
} else {
- Parser::new(s).parse_with(|p| p.read_ipv4_addr())
+ Parser::new(s).parse_with(|p| p.read_ipv4_addr(), AddrKind::Ipv4)
}
}
}
impl FromStr for Ipv6Addr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
- Parser::new(s).parse_with(|p| p.read_ipv6_addr())
+ Parser::new(s).parse_with(|p| p.read_ipv6_addr(), AddrKind::Ipv6)
}
}
impl FromStr for SocketAddrV4 {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
- Parser::new(s).parse_with(|p| p.read_socket_addr_v4())
+ Parser::new(s).parse_with(|p| p.read_socket_addr_v4(), AddrKind::SocketV4)
}
}
impl FromStr for SocketAddrV6 {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
- Parser::new(s).parse_with(|p| p.read_socket_addr_v6())
+ Parser::new(s).parse_with(|p| p.read_socket_addr_v6(), AddrKind::SocketV6)
}
}
impl FromStr for SocketAddr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
- Parser::new(s).parse_with(|p| p.read_socket_addr())
+ Parser::new(s).parse_with(|p| p.read_socket_addr(), AddrKind::Socket)
}
}
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum AddrKind {
+ Ip,
+ Ipv4,
+ Ipv6,
+ Socket,
+ SocketV4,
+ SocketV6,
+}
+
/// An error which can be returned when parsing an IP address or a socket address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct AddrParseError(());
+pub struct AddrParseError(AddrKind);
#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
impl fmt::Display for AddrParseError {
impl Error for AddrParseError {
#[allow(deprecated)]
fn description(&self) -> &str {
- "invalid IP address syntax"
+ match self.0 {
+ AddrKind::Ip => "invalid IP address syntax",
+ AddrKind::Ipv4 => "invalid IPv4 address syntax",
+ AddrKind::Ipv6 => "invalid IPv6 address syntax",
+ AddrKind::Socket => "invalid socket address syntax",
+ AddrKind::SocketV4 => "invalid IPv4 socket address syntax",
+ AddrKind::SocketV6 => "invalid IPv6 socket address syntax",
+ }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
fn uid(
&mut self,
- #[cfg(not(target_os = "vxworks"))] id: u32,
- #[cfg(target_os = "vxworks")] id: u16,
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
) -> &mut process::Command;
/// Similar to `uid`, but sets the group ID of the child process. This has
#[stable(feature = "rust1", since = "1.0.0")]
fn gid(
&mut self,
- #[cfg(not(target_os = "vxworks"))] id: u32,
- #[cfg(target_os = "vxworks")] id: u16,
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
) -> &mut process::Command;
/// Sets the supplementary group IDs for the calling process. Translates to
#[unstable(feature = "setgroups", issue = "90747")]
fn groups(
&mut self,
- #[cfg(not(target_os = "vxworks"))] groups: &[u32],
- #[cfg(target_os = "vxworks")] groups: &[u16],
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
) -> &mut process::Command;
/// Schedules a closure to be run just before the `exec` function is
impl CommandExt for process::Command {
fn uid(
&mut self,
- #[cfg(not(target_os = "vxworks"))] id: u32,
- #[cfg(target_os = "vxworks")] id: u16,
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
) -> &mut process::Command {
self.as_inner_mut().uid(id);
self
fn gid(
&mut self,
- #[cfg(not(target_os = "vxworks"))] id: u32,
- #[cfg(target_os = "vxworks")] id: u16,
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
) -> &mut process::Command {
self.as_inner_mut().gid(id);
self
fn groups(
&mut self,
- #[cfg(not(target_os = "vxworks"))] groups: &[u32],
- #[cfg(target_os = "vxworks")] groups: &[u16],
+ #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
) -> &mut process::Command {
self.as_inner_mut().groups(groups);
self
/// Device namespace prefix, e.g., `\\.\COM42`.
///
- /// Device namespace prefixes consist of `\\.\` immediately followed by the
- /// device name.
+ /// Device namespace prefixes consist of `\\.\` (possibly using `/`
+ /// instead of `\`), immediately followed by the device name.
#[stable(feature = "rust1", since = "1.0.0")]
DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
fn len(&self) -> usize {
use self::Prefix::*;
fn os_str_len(s: &OsStr) -> usize {
- os_str_as_u8_slice(s).len()
+ s.bytes().len()
}
match *self {
Verbatim(x) => 4 + os_str_len(x),
}
}
-// See note at the top of this module to understand why these are used:
-//
-// These casts are safe as OsStr is internally a wrapper around [u8] on all
-// platforms.
-//
-// Note that currently this relies on the special knowledge that libstd has;
-// these types are single-element structs but are not marked repr(transparent)
-// or repr(C) which would make these casts allowable outside std.
-fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
- unsafe { &*(s as *const OsStr as *const [u8]) }
-}
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
- // SAFETY: see the comment of `os_str_as_u8_slice`
+ // SAFETY: See note at the top of this module to understand why this and
+ // `OsStr::bytes` are used:
+ //
+ // This casts are safe as OsStr is internally a wrapper around [u8] on all
+ // platforms.
+ //
+ // Note that currently this relies on the special knowledge that libstd has;
+ // these types are single-element structs but are not marked
+ // repr(transparent) or repr(C) which would make these casts not allowable
+ // outside std.
unsafe { &*(s as *const [u8] as *const OsStr) }
}
// basic workhorse for splitting stem and extension
fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
- if os_str_as_u8_slice(file) == b".." {
+ if file.bytes() == b".." {
return (Some(file), None);
}
// and back. This is safe to do because (1) we only look at ASCII
// contents of the encoding and (2) new &OsStr values are produced
// only from ASCII-bounded slices of existing &OsStr values.
- let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
+ let mut iter = file.bytes().rsplitn(2, |b| *b == b'.');
let after = iter.next();
let before = iter.next();
if before == Some(b"") {
}
fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
- let slice = os_str_as_u8_slice(file);
+ let slice = file.bytes();
if slice == b".." {
return (file, None);
}
fn _set_extension(&mut self, extension: &OsStr) -> bool {
let file_stem = match self.file_stem() {
None => return false,
- Some(f) => os_str_as_u8_slice(f),
+ Some(f) => f.bytes(),
};
// truncate until right after the file stem
let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();
- let start = os_str_as_u8_slice(&self.inner).as_ptr().addr();
+ let start = self.inner.bytes().as_ptr().addr();
let v = self.as_mut_vec();
v.truncate(end_file_stem.wrapping_sub(start));
// add the new extension, if any
- let new = os_str_as_u8_slice(extension);
+ let new = extension.bytes();
if !new.is_empty() {
v.reserve_exact(new.len() + 1);
v.push(b'.');
}
// The following (private!) function reveals the byte encoding used for OsStr.
fn as_u8_slice(&self) -> &[u8] {
- os_str_as_u8_slice(&self.inner)
+ self.inner.bytes()
}
/// Directly wraps a string slice as a `Path` slice.
file_prefix: None
);
- t!("\\\\?\\C:/foo",
- iter: ["\\\\?\\C:/foo"],
+ t!("\\\\?\\C:/foo/bar",
+ iter: ["\\\\?\\C:", "\\", "foo/bar"],
has_root: true,
is_absolute: true,
- parent: None,
- file_name: None,
- file_stem: None,
+ parent: Some("\\\\?\\C:/"),
+ file_name: Some("foo/bar"),
+ file_stem: Some("foo/bar"),
extension: None,
- file_prefix: None
+ file_prefix: Some("foo/bar")
);
t!("\\\\.\\foo\\bar",
use crate::cell::UnsafeCell;
use crate::collections::VecDeque;
-use crate::ffi::c_void;
use crate::hint;
use crate::ops::{Deref, DerefMut, Drop};
use crate::ptr;
#[inline]
pub unsafe fn destroy(&self) {}
}
-
-pub struct ReentrantMutex {
- inner: *const c_void,
-}
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { inner: ptr::null() }
- }
-
- #[inline]
- pub unsafe fn init(&self) {
- let _ = abi::recmutex_init(&self.inner as *const *const c_void as *mut _);
- }
-
- #[inline]
- pub unsafe fn lock(&self) {
- let _ = abi::recmutex_lock(self.inner);
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- true
- }
-
- #[inline]
- pub unsafe fn unlock(&self) {
- let _ = abi::recmutex_unlock(self.inner);
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- let _ = abi::recmutex_destroy(self.inner);
- }
-}
error::{expect_success, expect_success_aborting, fail, ItronError},
spin::SpinIdOnceCell,
};
-use crate::cell::UnsafeCell;
pub struct Mutex {
/// The ID of the underlying mutex object
unsafe { self.0.unlock() };
}
}
-
-// All empty stubs because this platform does not yet support threads, so lock
-// acquisition always succeeds.
-pub struct ReentrantMutex {
- /// The ID of the underlying mutex object
- mtx: abi::ID,
- /// The lock count.
- count: UnsafeCell<usize>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { mtx: 0, count: UnsafeCell::new(0) }
- }
-
- pub unsafe fn init(&mut self) {
- self.mtx = expect_success(
- unsafe {
- abi::acre_mtx(&abi::T_CMTX {
- // Priority inheritance mutex
- mtxatr: abi::TA_INHERIT,
- // Unused
- ceilpri: 0,
- })
- },
- &"acre_mtx",
- );
- }
-
- pub unsafe fn lock(&self) {
- match unsafe { abi::loc_mtx(self.mtx) } {
- abi::E_OBJ => {
- // Recursive lock
- unsafe {
- let count = &mut *self.count.get();
- if let Some(new_count) = count.checked_add(1) {
- *count = new_count;
- } else {
- // counter overflow
- rtabort!("lock count overflow");
- }
- }
- }
- er => {
- expect_success(er, &"loc_mtx");
- }
- }
- }
-
- pub unsafe fn unlock(&self) {
- unsafe {
- let count = &mut *self.count.get();
- if *count > 0 {
- *count -= 1;
- return;
- }
- }
-
- expect_success_aborting(unsafe { abi::unl_mtx(self.mtx) }, &"unl_mtx");
- }
-
- pub unsafe fn try_lock(&self) -> bool {
- let er = unsafe { abi::ploc_mtx(self.mtx) };
- if er == abi::E_OBJ {
- // Recursive lock
- unsafe {
- let count = &mut *self.count.get();
- if let Some(new_count) = count.checked_add(1) {
- *count = new_count;
- } else {
- // counter overflow
- rtabort!("lock count overflow");
- }
- }
- true
- } else if er == abi::E_TMOUT {
- // Locked by another thread
- false
- } else {
- expect_success(er, &"ploc_mtx");
- // Top-level lock by the current thread
- true
- }
- }
-
- pub unsafe fn destroy(&self) {
- expect_success_aborting(unsafe { abi::del_mtx(self.mtx) }, &"del_mtx");
- }
-}
-use fortanix_sgx_abi::Tcs;
-
-use super::abi::thread;
-
-use super::waitqueue::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable};
+use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
pub struct Mutex {
inner: SpinMutex<WaitVariable<bool>>,
#[inline]
pub unsafe fn destroy(&self) {}
}
-
-struct ReentrantLock {
- owner: Option<Tcs>,
- count: usize,
-}
-
-pub struct ReentrantMutex {
- inner: SpinMutex<WaitVariable<ReentrantLock>>,
-}
-
-impl ReentrantMutex {
- pub const fn uninitialized() -> ReentrantMutex {
- ReentrantMutex {
- inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })),
- }
- }
-
- #[inline]
- pub unsafe fn init(&self) {}
-
- #[inline]
- pub unsafe fn lock(&self) {
- let mut guard = self.inner.lock();
- match guard.lock_var().owner {
- Some(tcs) if tcs != thread::current() => {
- // Another thread has the lock, wait
- WaitQueue::wait(guard, || {});
- // Another thread has passed the lock to us
- }
- _ => {
- // We are just now obtaining the lock
- guard.lock_var_mut().owner = Some(thread::current());
- guard.lock_var_mut().count += 1;
- }
- }
- }
-
- #[inline]
- pub unsafe fn unlock(&self) {
- let mut guard = self.inner.lock();
- if guard.lock_var().count > 1 {
- guard.lock_var_mut().count -= 1;
- } else {
- match WaitQueue::notify_one(guard) {
- Err(mut guard) => {
- // No other waiters, unlock
- guard.lock_var_mut().count = 0;
- guard.lock_var_mut().owner = None;
- }
- Ok(mut guard) => {
- // There was a thread waiting, just pass the lock
- if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
- guard.lock_var_mut().owner = Some(tcs)
- } else {
- unreachable!() // called notify_one
- }
- }
- }
- }
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- let mut guard = try_lock_or_false!(self.inner);
- match guard.lock_var().owner {
- Some(tcs) if tcs != thread::current() => {
- // Another thread has the lock
- false
- }
- _ => {
- // We are just now obtaining the lock
- guard.lock_var_mut().owner = Some(thread::current());
- guard.lock_var_mut().count += 1;
- true
- }
- }
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {}
-}
use libc::{c_int, c_void};
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re"
+))]
+use libc::off64_t;
+#[cfg(not(any(
+ target_os = "linux",
+ target_os = "emscripten",
+ target_os = "l4re",
+ target_os = "android"
+)))]
+use libc::off_t as off64_t;
+
#[derive(Debug)]
pub struct FileDesc(OwnedFd);
self.as_raw_fd(),
buf.as_mut_ptr() as *mut c_void,
cmp::min(buf.len(), READ_LIMIT),
- offset as i64,
+ offset as off64_t,
))
.map(|n| n as usize)
}
self.as_raw_fd(),
buf.as_ptr() as *const c_void,
cmp::min(buf.len(), READ_LIMIT),
- offset as i64,
+ offset as off64_t,
))
.map(|n| n as usize)
}
SeekFrom::End(off) => (libc::SEEK_END, off),
SeekFrom::Current(off) => (libc::SEEK_CUR, off),
};
- let n = cvt(unsafe { lseek64(self.as_raw_fd(), pos, whence) })?;
+ let n = cvt(unsafe { lseek64(self.as_raw_fd(), pos as off64_t, whence) })?;
Ok(n as u64)
}
fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> {
// try opening as directory
let fd = match openat_nofollow_dironly(parent_fd, &path) {
- Err(err) if err.raw_os_error() == Some(libc::ENOTDIR) => {
+ Err(err) if matches!(err.raw_os_error(), Some(libc::ENOTDIR | libc::ELOOP)) => {
// not a directory - don't traverse further
+ // (for symlinks, older Linux kernels may return ELOOP instead of ENOTDIR)
return match parent_fd {
// unlink...
Some(parent_fd) => {
}
}
-#[cfg(target_os = "emscripten")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
- extern "C" {
- fn emscripten_futex_wait(
- addr: *const AtomicU32,
- val: libc::c_uint,
- max_wait_ms: libc::c_double,
- ) -> libc::c_int;
- }
-
- unsafe {
- emscripten_futex_wait(
- futex,
- expected,
- timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0),
- );
- }
-}
-
/// Wake up one thread that's blocked on futex_wait on this futex.
///
/// Returns true if this actually woke up such a thread,
}
#[cfg(target_os = "emscripten")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
- extern "C" {
- fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
+extern "C" {
+ fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
+ fn emscripten_futex_wait(
+ addr: *const AtomicU32,
+ val: libc::c_uint,
+ max_wait_ms: libc::c_double,
+ ) -> libc::c_int;
+}
+
+#[cfg(target_os = "emscripten")]
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+ unsafe {
+ emscripten_futex_wait(
+ futex,
+ expected,
+ timeout.map_or(f64::INFINITY, |d| d.as_secs_f64() * 1000.0),
+ ) != -libc::ETIMEDOUT
}
+}
+#[cfg(target_os = "emscripten")]
+pub fn futex_wake(futex: &AtomicU32) -> bool {
unsafe { emscripten_futex_wake(futex, 1) > 0 }
}
+
+#[cfg(target_os = "emscripten")]
+pub fn futex_wake_all(futex: &AtomicU32) {
+ unsafe { emscripten_futex_wake(futex, i32::MAX) };
+}
-use crate::cell::UnsafeCell;
use crate::sync::atomic::{
- AtomicU32, AtomicUsize,
+ AtomicU32,
Ordering::{Acquire, Relaxed, Release},
};
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
r
}
}
-
-/// A reentrant mutex. Used by stdout().lock() and friends.
-///
-/// The 'owner' field tracks which thread has locked the mutex.
-///
-/// We use current_thread_unique_ptr() as the thread identifier,
-/// which is just the address of a thread local variable.
-///
-/// If `owner` is set to the identifier of the current thread,
-/// we assume the mutex is already locked and instead of locking it again,
-/// we increment `lock_count`.
-///
-/// When unlocking, we decrement `lock_count`, and only unlock the mutex when
-/// it reaches zero.
-///
-/// `lock_count` is protected by the mutex and only accessed by the thread that has
-/// locked the mutex, so needs no synchronization.
-///
-/// `owner` can be checked by other threads that want to see if they already
-/// hold the lock, so needs to be atomic. If it compares equal, we're on the
-/// same thread that holds the mutex and memory access can use relaxed ordering
-/// since we're not dealing with multiple threads. If it compares unequal,
-/// synchronization is left to the mutex, making relaxed memory ordering for
-/// the `owner` field fine in all cases.
-pub struct ReentrantMutex {
- mutex: Mutex,
- owner: AtomicUsize,
- lock_count: UnsafeCell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
- #[inline]
- pub const unsafe fn uninitialized() -> Self {
- Self { mutex: Mutex::new(), owner: AtomicUsize::new(0), lock_count: UnsafeCell::new(0) }
- }
-
- #[inline]
- pub unsafe fn init(&self) {}
-
- #[inline]
- pub unsafe fn destroy(&self) {}
-
- pub unsafe fn try_lock(&self) -> bool {
- let this_thread = current_thread_unique_ptr();
- if self.owner.load(Relaxed) == this_thread {
- self.increment_lock_count();
- true
- } else if self.mutex.try_lock() {
- self.owner.store(this_thread, Relaxed);
- debug_assert_eq!(*self.lock_count.get(), 0);
- *self.lock_count.get() = 1;
- true
- } else {
- false
- }
- }
-
- pub unsafe fn lock(&self) {
- let this_thread = current_thread_unique_ptr();
- if self.owner.load(Relaxed) == this_thread {
- self.increment_lock_count();
- } else {
- self.mutex.lock();
- self.owner.store(this_thread, Relaxed);
- debug_assert_eq!(*self.lock_count.get(), 0);
- *self.lock_count.get() = 1;
- }
- }
-
- unsafe fn increment_lock_count(&self) {
- *self.lock_count.get() = (*self.lock_count.get())
- .checked_add(1)
- .expect("lock count overflow in reentrant mutex");
- }
-
- pub unsafe fn unlock(&self) {
- *self.lock_count.get() -= 1;
- if *self.lock_count.get() == 0 {
- self.owner.store(0, Relaxed);
- self.mutex.unlock();
- }
- }
-}
-
-/// Get an address that is unique per running thread.
-///
-/// This can be used as a non-null usize-sized ID.
-pub fn current_thread_unique_ptr() -> usize {
- // Use a non-drop type to make sure it's still available during thread destruction.
- thread_local! { static X: u8 = const { 0 } }
- X.with(|x| <*const _>::addr(x))
-}
if #[cfg(any(
target_os = "linux",
target_os = "android",
+ all(target_os = "emscripten", target_feature = "atomics"),
))] {
mod futex;
mod futex_rwlock;
- pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar, ReentrantMutex};
+ pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
pub use futex_rwlock::{RwLock, MovableRwLock};
} else {
mod pthread_mutex;
- mod pthread_remutex;
mod pthread_rwlock;
mod pthread_condvar;
pub use pthread_mutex::{Mutex, MovableMutex};
- pub use pthread_remutex::ReentrantMutex;
pub use pthread_rwlock::{RwLock, MovableRwLock};
pub use pthread_condvar::{Condvar, MovableCondvar};
}
+++ /dev/null
-use super::pthread_mutex::PthreadMutexAttr;
-use crate::cell::UnsafeCell;
-use crate::mem::MaybeUninit;
-use crate::sys::cvt_nz;
-
-pub struct ReentrantMutex {
- inner: UnsafeCell<libc::pthread_mutex_t>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
- }
-
- pub unsafe fn init(&self) {
- let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
- cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
- let attr = PthreadMutexAttr(&mut attr);
- cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE))
- .unwrap();
- cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
- }
-
- pub unsafe fn lock(&self) {
- let result = libc::pthread_mutex_lock(self.inner.get());
- debug_assert_eq!(result, 0);
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- libc::pthread_mutex_trylock(self.inner.get()) == 0
- }
-
- pub unsafe fn unlock(&self) {
- let result = libc::pthread_mutex_unlock(self.inner.get());
- debug_assert_eq!(result, 0);
- }
-
- pub unsafe fn destroy(&self) {
- let result = libc::pthread_mutex_destroy(self.inner.get());
- debug_assert_eq!(result, 0);
- }
-}
crate::fs::read_to_string("sys:exe").map(PathBuf::from)
}
-#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
+#[cfg(target_os = "l4re")]
pub fn current_exe() -> io::Result<PathBuf> {
use crate::io::ErrorKind;
Err(io::const_io_error!(ErrorKind::Unsupported, "Not yet implemented!"))
super::unsupported::unsupported()
}
+#[cfg(target_os = "fuchsia")]
+pub fn current_exe() -> io::Result<PathBuf> {
+ use crate::io::ErrorKind;
+
+ #[cfg(test)]
+ use realstd::env;
+
+ #[cfg(not(test))]
+ use crate::env;
+
+ let exe_path = env::args().next().ok_or(io::const_io_error!(
+ ErrorKind::Uncategorized,
+ "an executable path was not found because no arguments were provided through argv"
+ ))?;
+ let path = PathBuf::from(exe_path);
+
+ // Prepend the current working directory to the path if it's not absolute.
+ if !path.is_absolute() { getcwd().map(|cwd| cwd.join(path)) } else { Ok(path) }
+}
+
pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
}
use crate::ffi::OsStr;
use crate::mem;
use crate::ptr;
-use crate::sys::cvt;
+use crate::sys::{cvt, cvt_nz};
macro_rules! t {
($e:expr) => {
let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
t!(cvt(sigemptyset(set.as_mut_ptr())));
t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
- t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
+ t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
cmd.stdin(Stdio::MakePipe);
cmd.stdout(Stdio::MakePipe);
let stdin_write = pipes.stdin.take().unwrap();
let stdout_read = pipes.stdout.take().unwrap();
- t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
+ t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
// We need to wait until SIGINT is definitely delivered. The
#[cfg(not(target_os = "emscripten"))]
{
use crate::mem::MaybeUninit;
+ use crate::sys::cvt_nz;
// Reset signal handling so the child process starts in a
// standardized state. libstd ignores SIGPIPE, and signal-handling
// libraries often set a mask. Child processes inherit ignored
// we're about to run.
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
cvt(sigemptyset(set.as_mut_ptr()))?;
- cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
+ cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
#[cfg(target_os = "android")] // see issue #88585
{
use crate::ffi::CStr;
use crate::marker::PhantomData;
use crate::mem;
-use crate::sync::atomic::{self, AtomicUsize, Ordering};
+use crate::ptr;
+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")))]
}
pub(crate) struct DlsymWeak<F> {
name: &'static str,
- addr: AtomicUsize,
+ func: AtomicPtr<libc::c_void>,
_marker: PhantomData<F>,
}
impl<F> DlsymWeak<F> {
pub(crate) const fn new(name: &'static str) -> Self {
- DlsymWeak { name, addr: AtomicUsize::new(1), _marker: PhantomData }
+ DlsymWeak { name, func: AtomicPtr::new(ptr::invalid_mut(1)), _marker: PhantomData }
}
#[inline]
unsafe {
// Relaxed is fine here because we fence before reading through the
// pointer (see the comment below).
- match self.addr.load(Ordering::Relaxed) {
- 1 => self.initialize(),
- 0 => None,
- addr => {
- let func = mem::transmute_copy::<usize, F>(&addr);
+ match self.func.load(Ordering::Relaxed) {
+ func if func.addr() == 1 => self.initialize(),
+ func if func.is_null() => None,
+ func => {
+ let func = mem::transmute_copy::<*mut libc::c_void, F>(&func);
// The caller is presumably going to read through this value
// (by calling the function we've dlsymed). This means we'd
// need to have loaded it with at least C11's consume
// Cold because it should only happen during first-time initialization.
#[cold]
unsafe fn initialize(&self) -> Option<F> {
- assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+ assert_eq!(mem::size_of::<F>(), mem::size_of::<*mut libc::c_void>());
let val = fetch(self.name);
// This synchronizes with the acquire fence in `get`.
- self.addr.store(val, Ordering::Release);
+ self.func.store(val, Ordering::Release);
- match val {
- 0 => None,
- addr => Some(mem::transmute_copy::<usize, F>(&addr)),
- }
+ if val.is_null() { None } else { Some(mem::transmute_copy::<*mut libc::c_void, F>(&val)) }
}
}
-unsafe fn fetch(name: &str) -> usize {
+unsafe fn fetch(name: &str) -> *mut libc::c_void {
let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
Ok(cstr) => cstr,
- Err(..) => return 0,
+ Err(..) => return ptr::null_mut(),
};
- libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
+ libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr())
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
mod mutex;
mod rwlock;
pub use condvar::{Condvar, MovableCondvar};
-pub use mutex::{MovableMutex, Mutex, ReentrantMutex};
+pub use mutex::{MovableMutex, Mutex};
pub use rwlock::{MovableRwLock, RwLock};
#[inline]
pub unsafe fn destroy(&self) {}
}
-
-// All empty stubs because this platform does not yet support threads, so lock
-// acquisition always succeeds.
-pub struct ReentrantMutex {}
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex {}
- }
-
- pub unsafe fn init(&self) {}
-
- pub unsafe fn lock(&self) {}
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- true
- }
-
- pub unsafe fn unlock(&self) {}
-
- pub unsafe fn destroy(&self) {}
-}
+++ /dev/null
-use crate::arch::wasm32;
-use crate::cmp;
-use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-use crate::sys::locks::Mutex;
-use crate::time::Duration;
-
-pub struct Condvar {
- cnt: AtomicUsize,
-}
-
-pub type MovableCondvar = Condvar;
-
-// Condition variables are implemented with a simple counter internally that is
-// likely to cause spurious wakeups. Blocking on a condition variable will first
-// read the value of the internal counter, unlock the given mutex, and then
-// block if and only if the counter's value is still the same. Notifying a
-// condition variable will modify the counter (add one for now) and then wake up
-// a thread waiting on the address of the counter.
-//
-// A thread waiting on the condition variable will as a result avoid going to
-// sleep if it's notified after the lock is unlocked but before it fully goes to
-// sleep. A sleeping thread is guaranteed to be woken up at some point as it can
-// only be woken up with a call to `wake`.
-//
-// Note that it's possible for 2 or more threads to be woken up by a call to
-// `notify_one` with this implementation. That can happen where the modification
-// of `cnt` causes any threads in the middle of `wait` to avoid going to sleep,
-// and the subsequent `wake` may wake up a thread that's actually blocking. We
-// consider this a spurious wakeup, though, which all users of condition
-// variables must already be prepared to handle. As a result, this source of
-// spurious wakeups is currently though to be ok, although it may be problematic
-// later on if it causes too many spurious wakeups.
-
-impl Condvar {
- pub const fn new() -> Condvar {
- Condvar { cnt: AtomicUsize::new(0) }
- }
-
- #[inline]
- pub unsafe fn init(&mut self) {
- // nothing to do
- }
-
- pub unsafe fn notify_one(&self) {
- self.cnt.fetch_add(1, SeqCst);
- // SAFETY: ptr() is always valid
- unsafe {
- wasm32::memory_atomic_notify(self.ptr(), 1);
- }
- }
-
- #[inline]
- pub unsafe fn notify_all(&self) {
- self.cnt.fetch_add(1, SeqCst);
- // SAFETY: ptr() is always valid
- unsafe {
- wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
- }
- }
-
- pub unsafe fn wait(&self, mutex: &Mutex) {
- // "atomically block and unlock" implemented by loading our current
- // counter's value, unlocking the mutex, and blocking if the counter
- // still has the same value.
- //
- // Notifications happen by incrementing the counter and then waking a
- // thread. Incrementing the counter after we unlock the mutex will
- // prevent us from sleeping and otherwise the call to `wake` will
- // wake us up once we're asleep.
- let ticket = self.cnt.load(SeqCst) as i32;
- mutex.unlock();
- let val = wasm32::memory_atomic_wait32(self.ptr(), ticket, -1);
- // 0 == woken, 1 == not equal to `ticket`, 2 == timeout (shouldn't happen)
- debug_assert!(val == 0 || val == 1);
- mutex.lock();
- }
-
- pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- let ticket = self.cnt.load(SeqCst) as i32;
- mutex.unlock();
- let nanos = dur.as_nanos();
- let nanos = cmp::min(i64::MAX as u128, nanos);
-
- // If the return value is 2 then a timeout happened, so we return
- // `false` as we weren't actually notified.
- let ret = wasm32::memory_atomic_wait32(self.ptr(), ticket, nanos as i64) != 2;
- mutex.lock();
- return ret;
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- // nothing to do
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
- self.cnt.as_mut_ptr() as *mut i32
- }
-}
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) {
+/// Wait for a futex_wake operation to wake us.
+///
+/// Returns directly if the futex doesn't hold the expected value.
+///
+/// Returns false on timeout, and true in all other cases.
+pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
unsafe {
wasm32::memory_atomic_wait32(
futex as *const AtomicU32 as *mut i32,
expected as i32,
timeout,
- );
+ ) < 2
}
}
-pub fn futex_wake(futex: &AtomicU32) {
+/// Wake up one thread that's blocked on futex_wait on this futex.
+///
+/// Returns true if this actually woke up such a thread,
+/// or false if no thread was waiting on this futex.
+pub fn futex_wake(futex: &AtomicU32) -> bool {
+ unsafe { wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1) > 0 }
+}
+
+/// Wake up all threads that are waiting on futex_wait on this futex.
+pub fn futex_wake_all(futex: &AtomicU32) {
unsafe {
- wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1);
+ wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, i32::MAX as u32);
}
}
+++ /dev/null
-use crate::arch::wasm32;
-use crate::cell::UnsafeCell;
-use crate::mem;
-use crate::sync::atomic::{AtomicU32, AtomicUsize, Ordering::SeqCst};
-use crate::sys::thread;
-
-pub struct Mutex {
- locked: AtomicUsize,
-}
-
-pub type MovableMutex = Mutex;
-
-// Mutexes have a pretty simple implementation where they contain an `i32`
-// internally that is 0 when unlocked and 1 when the mutex is locked.
-// Acquisition has a fast path where it attempts to cmpxchg the 0 to a 1, and
-// if it fails it then waits for a notification. Releasing a lock is then done
-// by swapping in 0 and then notifying any waiters, if present.
-
-impl Mutex {
- pub const fn new() -> Mutex {
- Mutex { locked: AtomicUsize::new(0) }
- }
-
- #[inline]
- pub unsafe fn init(&mut self) {
- // nothing to do
- }
-
- pub unsafe fn lock(&self) {
- while !self.try_lock() {
- // SAFETY: the caller must uphold the safety contract for `memory_atomic_wait32`.
- let val = unsafe {
- wasm32::memory_atomic_wait32(
- self.ptr(),
- 1, // we expect our mutex is locked
- -1, // wait infinitely
- )
- };
- // we should have either woke up (0) or got a not-equal due to a
- // race (1). We should never time out (2)
- debug_assert!(val == 0 || val == 1);
- }
- }
-
- pub unsafe fn unlock(&self) {
- let prev = self.locked.swap(0, SeqCst);
- debug_assert_eq!(prev, 1);
- wasm32::memory_atomic_notify(self.ptr(), 1); // wake up one waiter, if any
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- self.locked.compare_exchange(0, 1, SeqCst, SeqCst).is_ok()
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- // nothing to do
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
- self.locked.as_mut_ptr() as *mut i32
- }
-}
-
-pub struct ReentrantMutex {
- owner: AtomicU32,
- recursions: UnsafeCell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-// Reentrant mutexes are similarly implemented to mutexes above except that
-// instead of "1" meaning unlocked we use the id of a thread to represent
-// whether it has locked a mutex. That way we have an atomic counter which
-// always holds the id of the thread that currently holds the lock (or 0 if the
-// lock is unlocked).
-//
-// Once a thread acquires a lock recursively, which it detects by looking at
-// the value that's already there, it will update a local `recursions` counter
-// in a nonatomic fashion (as we hold the lock). The lock is then fully
-// released when this recursion counter reaches 0.
-
-impl ReentrantMutex {
- pub const unsafe fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { owner: AtomicU32::new(0), recursions: UnsafeCell::new(0) }
- }
-
- pub unsafe fn init(&self) {
- // nothing to do...
- }
-
- pub unsafe fn lock(&self) {
- let me = thread::my_id();
- while let Err(owner) = self._try_lock(me) {
- // SAFETY: the caller must guarantee that `self.ptr()` and `owner` are valid i32.
- let val = unsafe { wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1) };
- debug_assert!(val == 0 || val == 1);
- }
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- unsafe { self._try_lock(thread::my_id()).is_ok() }
- }
-
- #[inline]
- unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
- let id = id.checked_add(1).unwrap();
- match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
- // we transitioned from unlocked to locked
- Ok(_) => {
- debug_assert_eq!(*self.recursions.get(), 0);
- Ok(())
- }
-
- // we currently own this lock, so let's update our count and return
- // true.
- Err(n) if n == id => {
- *self.recursions.get() += 1;
- Ok(())
- }
-
- // Someone else owns the lock, let our caller take care of it
- Err(other) => Err(other),
- }
- }
-
- pub unsafe fn unlock(&self) {
- // If we didn't ever recursively lock the lock then we fully unlock the
- // mutex and wake up a waiter, if any. Otherwise we decrement our
- // recursive counter and let some one else take care of the zero.
- match *self.recursions.get() {
- 0 => {
- self.owner.swap(0, SeqCst);
- // SAFETY: the caller must guarantee that `self.ptr()` is valid i32.
- unsafe {
- wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1);
- } // wake up one waiter, if any
- }
- ref mut n => *n -= 1,
- }
- }
-
- pub unsafe fn destroy(&self) {
- // nothing to do...
- }
-
- #[inline]
- fn ptr(&self) -> *mut i32 {
- self.owner.as_mut_ptr() as *mut i32
- }
-}
+++ /dev/null
-use crate::cell::UnsafeCell;
-use crate::sys::locks::{Condvar, Mutex};
-
-pub struct RwLock {
- lock: Mutex,
- cond: Condvar,
- state: UnsafeCell<State>,
-}
-
-pub type MovableRwLock = RwLock;
-
-enum State {
- Unlocked,
- Reading(usize),
- Writing,
-}
-
-unsafe impl Send for RwLock {}
-unsafe impl Sync for RwLock {}
-
-// This rwlock implementation is a relatively simple implementation which has a
-// condition variable for readers/writers as well as a mutex protecting the
-// internal state of the lock. A current downside of the implementation is that
-// unlocking the lock will notify *all* waiters rather than just readers or just
-// writers. This can cause lots of "thundering stampede" problems. While
-// hopefully correct this implementation is very likely to want to be changed in
-// the future.
-
-impl RwLock {
- pub const fn new() -> RwLock {
- RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
- }
-
- #[inline]
- pub unsafe fn read(&self) {
- self.lock.lock();
- while !(*self.state.get()).inc_readers() {
- self.cond.wait(&self.lock);
- }
- self.lock.unlock();
- }
-
- #[inline]
- pub unsafe fn try_read(&self) -> bool {
- self.lock.lock();
- let ok = (*self.state.get()).inc_readers();
- self.lock.unlock();
- return ok;
- }
-
- #[inline]
- pub unsafe fn write(&self) {
- self.lock.lock();
- while !(*self.state.get()).inc_writers() {
- self.cond.wait(&self.lock);
- }
- self.lock.unlock();
- }
-
- #[inline]
- pub unsafe fn try_write(&self) -> bool {
- self.lock.lock();
- let ok = (*self.state.get()).inc_writers();
- self.lock.unlock();
- return ok;
- }
-
- #[inline]
- pub unsafe fn read_unlock(&self) {
- self.lock.lock();
- let notify = (*self.state.get()).dec_readers();
- self.lock.unlock();
- if notify {
- // FIXME: should only wake up one of these some of the time
- self.cond.notify_all();
- }
- }
-
- #[inline]
- pub unsafe fn write_unlock(&self) {
- self.lock.lock();
- (*self.state.get()).dec_writers();
- self.lock.unlock();
- // FIXME: should only wake up one of these some of the time
- self.cond.notify_all();
- }
-
- #[inline]
- pub unsafe fn destroy(&self) {
- self.lock.destroy();
- self.cond.destroy();
- }
-}
-
-impl State {
- fn inc_readers(&mut self) -> bool {
- match *self {
- State::Unlocked => {
- *self = State::Reading(1);
- true
- }
- State::Reading(ref mut cnt) => {
- *cnt += 1;
- true
- }
- State::Writing => false,
- }
- }
-
- fn inc_writers(&mut self) -> bool {
- match *self {
- State::Unlocked => {
- *self = State::Writing;
- true
- }
- State::Reading(_) | State::Writing => false,
- }
- }
-
- fn dec_readers(&mut self) -> bool {
- let zero = match *self {
- State::Reading(ref mut cnt) => {
- *cnt -= 1;
- *cnt == 0
- }
- State::Unlocked | State::Writing => invalid(),
- };
- if zero {
- *self = State::Unlocked;
- }
- zero
- }
-
- fn dec_writers(&mut self) {
- match *self {
- State::Writing => {}
- State::Unlocked | State::Reading(_) => invalid(),
- }
- *self = State::Unlocked;
- }
-}
-
-fn invalid() -> ! {
- panic!("inconsistent rwlock");
-}
None
}
}
-
-// We currently just use our own thread-local to store our
-// current thread's ID, and then we lazily initialize it to something allocated
-// from a global counter.
-pub fn my_id() -> u32 {
- use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
-
- static NEXT_ID: AtomicU32 = AtomicU32::new(0);
-
- #[thread_local]
- static mut MY_ID: u32 = 0;
-
- unsafe {
- // If our thread ID isn't set yet then we need to allocate one. Do so
- // with with a simple "atomically add to a global counter" strategy.
- // This strategy doesn't handled what happens when the counter
- // overflows, however, so just abort everything once the counter
- // overflows and eventually we could have some sort of recycling scheme
- // (or maybe this is all totally irrelevant by that point!). In any case
- // though we're using a CAS loop instead of a `fetch_add` to ensure that
- // the global counter never overflows.
- if MY_ID == 0 {
- let mut cur = NEXT_ID.load(SeqCst);
- MY_ID = loop {
- let next = cur.checked_add(1).unwrap_or_else(|| crate::process::abort());
- match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
- Ok(_) => break next,
- Err(i) => cur = i,
- }
- };
- }
- MY_ID
- }
-}
cfg_if::cfg_if! {
if #[cfg(target_feature = "atomics")] {
- #[path = "atomics/condvar.rs"]
- mod condvar;
- #[path = "atomics/mutex.rs"]
- mod mutex;
- #[path = "atomics/rwlock.rs"]
- mod rwlock;
+ #[path = "../unix/locks"]
pub mod locks {
- pub use super::condvar::*;
- pub use super::mutex::*;
- pub use super::rwlock::*;
+ #![allow(unsafe_op_in_unsafe_fn)]
+ mod futex;
+ mod futex_rwlock;
+ pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
+ pub use futex_rwlock::{RwLock, MovableRwLock};
}
#[path = "atomics/futex.rs"]
pub mod futex;
pub struct SRWLOCK {
pub ptr: LPVOID,
}
-#[repr(C)]
-pub struct CRITICAL_SECTION {
- CriticalSectionDebug: LPVOID,
- LockCount: LONG,
- RecursionCount: LONG,
- OwningThread: HANDLE,
- LockSemaphore: HANDLE,
- SpinCount: ULONG_PTR,
-}
#[repr(C)]
pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
#[link(name = "kernel32")]
extern "system" {
pub fn GetCurrentProcessId() -> DWORD;
- pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
- pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
- pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOL;
- pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
- pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
mod mutex;
mod rwlock;
pub use condvar::{Condvar, MovableCondvar};
-pub use mutex::{MovableMutex, Mutex, ReentrantMutex};
+pub use mutex::{MovableMutex, Mutex};
pub use rwlock::{MovableRwLock, RwLock};
//! is that there are no guarantees of fairness.
use crate::cell::UnsafeCell;
-use crate::mem::MaybeUninit;
use crate::sys::c;
pub struct Mutex {
// SRWLock does not need to be destroyed.
}
}
-
-pub struct ReentrantMutex {
- inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
- pub const fn uninitialized() -> ReentrantMutex {
- ReentrantMutex { inner: MaybeUninit::uninit() }
- }
-
- pub unsafe fn init(&self) {
- c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
- }
-
- pub unsafe fn lock(&self) {
- c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
- }
-
- #[inline]
- pub unsafe fn try_lock(&self) -> bool {
- c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
- }
-
- pub unsafe fn unlock(&self) {
- c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
- }
-
- pub unsafe fn destroy(&self) {
- c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
- }
-}
pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
- let mut maybe_result: Vec<u16> = s.encode_wide().collect();
+ // Most paths are ASCII, so reserve capacity for as much as there are bytes
+ // in the OsStr plus one for the null-terminating character. We are not
+ // wasting bytes here as paths created by this function are primarily used
+ // in an ephemeral fashion.
+ let mut maybe_result = Vec::with_capacity(s.len() + 1);
+ maybe_result.extend(s.encode_wide());
+
if unrolled_find_u16s(0, &maybe_result).is_some() {
return Err(crate::io::const_io_error!(
ErrorKind::InvalidInput,
{
// Start off with a stack buf but then spill over to the heap if we end up
// needing more space.
+ //
+ // This initial size also works around `GetFullPathNameW` returning
+ // incorrect size hints for some short paths:
+ // https://github.com/dylni/normpath/issues/5
let mut stack_buf = [0u16; 512];
let mut heap_buf = Vec::new();
unsafe {
path.into()
}
+struct PrefixParser<'a, const LEN: usize> {
+ path: &'a OsStr,
+ prefix: [u8; LEN],
+}
+
+impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
+ #[inline]
+ fn get_prefix(path: &OsStr) -> [u8; LEN] {
+ let mut prefix = [0; LEN];
+ // SAFETY: Only ASCII characters are modified.
+ for (i, &ch) in path.bytes().iter().take(LEN).enumerate() {
+ prefix[i] = if ch == b'/' { b'\\' } else { ch };
+ }
+ prefix
+ }
+
+ fn new(path: &'a OsStr) -> Self {
+ Self { path, prefix: Self::get_prefix(path) }
+ }
+
+ fn as_slice(&self) -> PrefixParserSlice<'a, '_> {
+ PrefixParserSlice {
+ path: self.path,
+ prefix: &self.prefix[..LEN.min(self.path.len())],
+ index: 0,
+ }
+ }
+}
+
+struct PrefixParserSlice<'a, 'b> {
+ path: &'a OsStr,
+ prefix: &'b [u8],
+ index: usize,
+}
+
+impl<'a> PrefixParserSlice<'a, '_> {
+ fn strip_prefix(&self, prefix: &str) -> Option<Self> {
+ self.prefix[self.index..]
+ .starts_with(prefix.as_bytes())
+ .then(|| Self { index: self.index + prefix.len(), ..*self })
+ }
+
+ fn prefix_bytes(&self) -> &'a [u8] {
+ &self.path.bytes()[..self.index]
+ }
+
+ fn finish(self) -> &'a OsStr {
+ // SAFETY: The unsafety here stems from converting between &OsStr and
+ // &[u8] and back. This is safe to do because (1) we only look at ASCII
+ // contents of the encoding and (2) new &OsStr values are produced only
+ // from ASCII-bounded slices of existing &OsStr values.
+ unsafe { bytes_as_os_str(&self.path.bytes()[self.index..]) }
+ }
+}
+
pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
use Prefix::{DeviceNS, Disk, Verbatim, VerbatimDisk, VerbatimUNC, UNC};
- if let Some(path) = strip_prefix(path, r"\\") {
+ let parser = PrefixParser::<8>::new(path);
+ let parser = parser.as_slice();
+ if let Some(parser) = parser.strip_prefix(r"\\") {
// \\
- if let Some(path) = strip_prefix(path, r"?\") {
+
+ // The meaning of verbatim paths can change when they use a different
+ // separator.
+ if let Some(parser) = parser.strip_prefix(r"?\") && !parser.prefix_bytes().iter().any(|&x| x == b'/') {
// \\?\
- if let Some(path) = strip_prefix(path, r"UNC\") {
+ if let Some(parser) = parser.strip_prefix(r"UNC\") {
// \\?\UNC\server\share
+ let path = parser.finish();
let (server, path) = parse_next_component(path, true);
let (share, _) = parse_next_component(path, true);
Some(VerbatimUNC(server, share))
} else {
- let (prefix, _) = parse_next_component(path, true);
+ let path = parser.finish();
// in verbatim paths only recognize an exact drive prefix
- if let Some(drive) = parse_drive_exact(prefix) {
+ if let Some(drive) = parse_drive_exact(path) {
// \\?\C:
Some(VerbatimDisk(drive))
} else {
// \\?\prefix
+ let (prefix, _) = parse_next_component(path, true);
Some(Verbatim(prefix))
}
}
- } else if let Some(path) = strip_prefix(path, r".\") {
+ } else if let Some(parser) = parser.strip_prefix(r".\") {
// \\.\COM42
+ let path = parser.finish();
let (prefix, _) = parse_next_component(path, false);
Some(DeviceNS(prefix))
} else {
+ let path = parser.finish();
let (server, path) = parse_next_component(path, false);
let (share, _) = parse_next_component(path, false);
}
// Parses a drive prefix, e.g. "C:" and "C:\whatever"
-fn parse_drive(prefix: &OsStr) -> Option<u8> {
+fn parse_drive(path: &OsStr) -> Option<u8> {
// In most DOS systems, it is not possible to have more than 26 drive letters.
// See <https://en.wikipedia.org/wiki/Drive_letter_assignment#Common_assignments>.
fn is_valid_drive_letter(drive: &u8) -> bool {
drive.is_ascii_alphabetic()
}
- match prefix.bytes() {
+ match path.bytes() {
[drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
_ => None,
}
}
// Parses a drive prefix exactly, e.g. "C:"
-fn parse_drive_exact(prefix: &OsStr) -> Option<u8> {
+fn parse_drive_exact(path: &OsStr) -> Option<u8> {
// only parse two bytes: the drive letter and the drive separator
- if prefix.len() == 2 { parse_drive(prefix) } else { None }
-}
-
-fn strip_prefix<'a>(path: &'a OsStr, prefix: &str) -> Option<&'a OsStr> {
- // `path` and `prefix` are valid wtf8 and utf8 encoded slices respectively, `path[prefix.len()]`
- // is thus a code point boundary and `path[prefix.len()..]` is a valid wtf8 encoded slice.
- match path.bytes().strip_prefix(prefix.as_bytes()) {
- Some(path) => unsafe { Some(bytes_as_os_str(path)) },
- None => None,
+ if path.bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
+ parse_drive(path)
+ } else {
+ None
}
}
// SAFETY: `fill_utf16_buf` ensures the `buffer` and `size` are valid.
// `lpfilename` is a pointer to a null terminated string that is not
// invalidated until after `GetFullPathNameW` returns successfully.
- |buffer, size| unsafe {
- // While the docs for `GetFullPathNameW` have the standard note
- // about needing a `\\?\` path for a long lpfilename, this does not
- // appear to be true in practice.
- // See:
- // https://stackoverflow.com/questions/38036943/getfullpathnamew-and-long-windows-file-paths
- // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
- c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut())
- },
+ |buffer, size| unsafe { c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()) },
|mut absolute| {
path.clear();
/// Make a Windows path absolute.
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
- if path.as_os_str().bytes().starts_with(br"\\?\") {
- return Ok(path.into());
+ let path = path.as_os_str();
+ let prefix = parse_prefix(path);
+ // Verbatim paths should not be modified.
+ if prefix.map(|x| x.is_verbatim()).unwrap_or(false) {
+ // NULs in verbatim paths are rejected for consistency.
+ if path.bytes().contains(&0) {
+ return Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "strings passed to WinAPI cannot contain NULs",
+ ));
+ }
+ return Ok(path.to_owned().into());
}
+
let path = to_u16s(path)?;
let lpfilename = path.as_ptr();
fill_utf16_buf(
// A path that contains null is not a valid path.
assert!(maybe_verbatim(Path::new("\0")).is_err());
}
+
+fn parse_prefix(path: &str) -> Option<Prefix<'_>> {
+ super::parse_prefix(OsStr::new(path))
+}
+
+#[test]
+fn test_parse_prefix_verbatim() {
+ let prefix = Some(Prefix::VerbatimDisk(b'C'));
+ assert_eq!(prefix, parse_prefix(r"\\?\C:/windows/system32/notepad.exe"));
+ assert_eq!(prefix, parse_prefix(r"\\?\C:\windows\system32\notepad.exe"));
+}
+
+#[test]
+fn test_parse_prefix_verbatim_device() {
+ let prefix = Some(Prefix::UNC(OsStr::new("?"), OsStr::new("C:")));
+ assert_eq!(prefix, parse_prefix(r"//?/C:/windows/system32/notepad.exe"));
+ assert_eq!(prefix, parse_prefix(r"//?/C:\windows\system32\notepad.exe"));
+ assert_eq!(prefix, parse_prefix(r"/\?\C:\windows\system32\notepad.exe"));
+ assert_eq!(prefix, parse_prefix(r"\\?/C:\windows\system32\notepad.exe"));
+}
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
+use crate::cell::UnsafeCell;
use crate::marker::PhantomPinned;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::pin::Pin;
+use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use crate::sys::locks as sys;
/// A re-entrant mutual exclusion
/// This mutex will block *other* threads waiting for the lock to become
/// available. The thread which has already locked the mutex can lock it
/// multiple times without blocking, preventing a common source of deadlocks.
+///
+/// This is used by stdout().lock() and friends.
+///
+/// ## Implementation details
+///
+/// The 'owner' field tracks which thread has locked the mutex.
+///
+/// We use current_thread_unique_ptr() as the thread identifier,
+/// which is just the address of a thread local variable.
+///
+/// If `owner` is set to the identifier of the current thread,
+/// we assume the mutex is already locked and instead of locking it again,
+/// we increment `lock_count`.
+///
+/// When unlocking, we decrement `lock_count`, and only unlock the mutex when
+/// it reaches zero.
+///
+/// `lock_count` is protected by the mutex and only accessed by the thread that has
+/// locked the mutex, so needs no synchronization.
+///
+/// `owner` can be checked by other threads that want to see if they already
+/// hold the lock, so needs to be atomic. If it compares equal, we're on the
+/// same thread that holds the mutex and memory access can use relaxed ordering
+/// since we're not dealing with multiple threads. If it compares unequal,
+/// synchronization is left to the mutex, making relaxed memory ordering for
+/// the `owner` field fine in all cases.
pub struct ReentrantMutex<T> {
- inner: sys::ReentrantMutex,
+ mutex: sys::Mutex,
+ owner: AtomicUsize,
+ lock_count: UnsafeCell<u32>,
data: T,
_pinned: PhantomPinned,
}
/// lock/unlock methods safe.
pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
ReentrantMutex {
- inner: sys::ReentrantMutex::uninitialized(),
+ mutex: sys::Mutex::new(),
+ owner: AtomicUsize::new(0),
+ lock_count: UnsafeCell::new(0),
data: t,
_pinned: PhantomPinned,
}
/// Unsafe to call more than once, and must be called after this will no
/// longer move in memory.
pub unsafe fn init(self: Pin<&mut Self>) {
- self.get_unchecked_mut().inner.init()
+ self.get_unchecked_mut().mutex.init()
}
/// Acquires a mutex, blocking the current thread until it is able to do so.
/// this call will return failure if the mutex would otherwise be
/// acquired.
pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
- unsafe { self.inner.lock() }
+ let this_thread = current_thread_unique_ptr();
+ // Safety: We only touch lock_count when we own the lock,
+ // and since self is pinned we can safely call the lock() on the mutex.
+ unsafe {
+ if self.owner.load(Relaxed) == this_thread {
+ self.increment_lock_count();
+ } else {
+ self.mutex.lock();
+ self.owner.store(this_thread, Relaxed);
+ debug_assert_eq!(*self.lock_count.get(), 0);
+ *self.lock_count.get() = 1;
+ }
+ }
ReentrantMutexGuard { lock: self }
}
/// this call will return failure if the mutex would otherwise be
/// acquired.
pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
- if unsafe { self.inner.try_lock() } {
- Some(ReentrantMutexGuard { lock: self })
- } else {
- None
+ let this_thread = current_thread_unique_ptr();
+ // Safety: We only touch lock_count when we own the lock,
+ // and since self is pinned we can safely call the try_lock on the mutex.
+ unsafe {
+ if self.owner.load(Relaxed) == this_thread {
+ self.increment_lock_count();
+ Some(ReentrantMutexGuard { lock: self })
+ } else if self.mutex.try_lock() {
+ self.owner.store(this_thread, Relaxed);
+ debug_assert_eq!(*self.lock_count.get(), 0);
+ *self.lock_count.get() = 1;
+ Some(ReentrantMutexGuard { lock: self })
+ } else {
+ None
+ }
}
}
+
+ unsafe fn increment_lock_count(&self) {
+ *self.lock_count.get() = (*self.lock_count.get())
+ .checked_add(1)
+ .expect("lock count overflow in reentrant mutex");
+ }
}
impl<T> Drop for ReentrantMutex<T> {
fn drop(&mut self) {
- // This is actually safe b/c we know that there is no further usage of
- // this mutex (it's up to the user to arrange for a mutex to get
- // dropped, that's not our job)
- unsafe { self.inner.destroy() }
+ // Safety: We're the unique owner of this mutex and not going to use it afterwards.
+ unsafe { self.mutex.destroy() }
}
}
impl<T> Drop for ReentrantMutexGuard<'_, T> {
#[inline]
fn drop(&mut self) {
+ // Safety: We own the lock, and the lock is pinned.
unsafe {
- self.lock.inner.unlock();
+ *self.lock.lock_count.get() -= 1;
+ if *self.lock.lock_count.get() == 0 {
+ self.lock.owner.store(0, Relaxed);
+ self.lock.mutex.unlock();
+ }
}
}
}
+
+/// Get an address that is unique per running thread.
+///
+/// This can be used as a non-null usize-sized ID.
+pub fn current_thread_unique_ptr() -> usize {
+ // Use a non-drop type to make sure it's still available during thread destruction.
+ thread_local! { static X: u8 = const { 0 } }
+ X.with(|x| <*const _>::addr(x))
+}
macro_rules! __thread_local_inner {
// used to generate the `LocalKey` value for const-initialized thread locals
(@key $t:ty, const $init:expr) => {{
- #[cfg_attr(not(windows), inline(always))] // see comments below
+ #[cfg_attr(not(windows), inline)] // see comments below
#[deny(unsafe_op_in_unsafe_fn)]
unsafe fn __getit(
_init: $crate::option::Option<&mut $crate::option::Option<$t>>,
// gets the pessimistic path for now where it's never inlined.
//
// The issue of "should enable on Windows sometimes" is #84933
- #[cfg_attr(not(windows), inline(always))]
+ #[cfg_attr(not(windows), inline)]
unsafe fn __getit(
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
let mut cmd = Command::new(rustdoc);
- if target.is_some() {
+ // I am not actually sure why it's necessary to pass the sysroot for `--test`,
+ // but `test --doc --stage 0` is broken without it :(
+ if target.is_some() || args.iter().any(|x| x == "--test") {
// The stage0 compiler has a special sysroot distinct from what we
// actually downloaded, so we just always pass the `--sysroot` option,
// unless one is already set.
return os.path.join(self.bin_root(True), '.rustfmt-stamp')
def llvm_stamp(self):
- """Return the path for .rustfmt-stamp
+ """Return the path for .llvm-stamp
>>> rb = RustBuild()
>>> rb.build_dir = "build"
use std::collections::BTreeSet;
use std::env;
use std::ffi::OsStr;
-use std::fmt::Debug;
+use std::fmt::{Debug, Write};
use std::fs;
use std::hash::Hash;
use std::ops::Deref;
use crate::cache::{Cache, Interned, INTERNER};
use crate::check;
use crate::compile;
-use crate::config::TargetSelection;
+use crate::config::{SplitDebuginfo, TargetSelection};
use crate::dist;
use crate::doc;
use crate::flags::{Color, Subcommand};
if found_kind.is_empty() {
panic!("empty kind in task path {}", path.display());
}
- kind = Some(Kind::parse(found_kind));
+ kind = Kind::parse(found_kind);
+ assert!(kind.is_some());
path = Path::new(found_prefix).join(components.as_path());
}
}
self
}
+ // single alias, which does not correspond to any on-disk path
+ pub fn alias(mut self, alias: &str) -> Self {
+ assert!(
+ !self.builder.src.join(alias).exists(),
+ "use `builder.path()` for real paths: {}",
+ alias
+ );
+ self.paths.insert(PathSet::Set(
+ std::iter::once(TaskPath { path: alias.into(), kind: Some(self.kind) }).collect(),
+ ));
+ self
+ }
+
// single, non-aliased path
pub fn path(self, path: &str) -> Self {
self.paths(&[path])
// multiple aliases for the same job
pub fn paths(mut self, paths: &[&str]) -> Self {
self.paths.insert(PathSet::Set(
- paths.iter().map(|p| TaskPath { path: p.into(), kind: Some(self.kind) }).collect(),
+ paths
+ .iter()
+ .map(|p| {
+ // FIXME(#96188): make sure this is actually a path.
+ // This currently breaks for paths within submodules.
+ //assert!(
+ // self.builder.src.join(p).exists(),
+ // "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {}",
+ // p
+ //);
+ TaskPath { path: p.into(), kind: Some(self.kind) }
+ })
+ .collect(),
));
self
}
Check,
Clippy,
Fix,
+ Format,
Test,
Bench,
- Dist,
Doc,
+ Clean,
+ Dist,
Install,
Run,
+ Setup,
}
impl Kind {
- fn parse(string: &str) -> Kind {
- match string {
- "build" => Kind::Build,
- "check" => Kind::Check,
+ pub fn parse(string: &str) -> Option<Kind> {
+ // these strings, including the one-letter aliases, must match the x.py help text
+ Some(match string {
+ "build" | "b" => Kind::Build,
+ "check" | "c" => Kind::Check,
"clippy" => Kind::Clippy,
"fix" => Kind::Fix,
- "test" => Kind::Test,
+ "fmt" => Kind::Format,
+ "test" | "t" => Kind::Test,
"bench" => Kind::Bench,
+ "doc" | "d" => Kind::Doc,
+ "clean" => Kind::Clean,
"dist" => Kind::Dist,
- "doc" => Kind::Doc,
"install" => Kind::Install,
- "run" => Kind::Run,
- other => panic!("unknown kind: {}", other),
- }
+ "run" | "r" => Kind::Run,
+ "setup" => Kind::Setup,
+ _ => return None,
+ })
}
- fn as_str(&self) -> &'static str {
+ pub fn as_str(&self) -> &'static str {
match self {
Kind::Build => "build",
Kind::Check => "check",
Kind::Clippy => "clippy",
Kind::Fix => "fix",
+ Kind::Format => "fmt",
Kind::Test => "test",
Kind::Bench => "bench",
- Kind::Dist => "dist",
Kind::Doc => "doc",
+ Kind::Clean => "clean",
+ Kind::Dist => "dist",
Kind::Install => "install",
Kind::Run => "run",
+ Kind::Setup => "setup",
}
}
}
native::Lld,
native::CrtBeginEnd
),
- Kind::Check | Kind::Clippy { .. } | Kind::Fix => describe!(
+ Kind::Check => describe!(
check::Std,
check::Rustc,
check::Rustdoc,
install::Rustc
),
Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0),
+ // These commands either don't use paths, or they're special-cased in Build::build()
+ Kind::Clean | Kind::Clippy | Kind::Fix | Kind::Format | Kind::Setup => vec![],
}
}
- pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
- let kind = match subcommand {
- "build" | "b" => Kind::Build,
- "doc" | "d" => Kind::Doc,
- "test" | "t" => Kind::Test,
- "bench" => Kind::Bench,
- "dist" => Kind::Dist,
- "install" => Kind::Install,
- _ => return None,
- };
+ pub fn get_help(build: &Build, kind: Kind) -> Option<String> {
+ let step_descriptions = Builder::get_step_descriptions(kind);
+ if step_descriptions.is_empty() {
+ return None;
+ }
let builder = Self::new_internal(build, kind, vec![]);
let builder = &builder;
// The "build" kind here is just a placeholder, it will be replaced with something else in
// the following statement.
let mut should_run = ShouldRun::new(builder, Kind::Build);
- for desc in Builder::get_step_descriptions(builder.kind) {
+ for desc in step_descriptions {
should_run.kind = desc.kind;
should_run = (desc.should_run)(should_run);
}
let mut help = String::from("Available paths:\n");
let mut add_path = |path: &Path| {
- help.push_str(&format!(" ./x.py {} {}\n", subcommand, path.display()));
+ t!(write!(help, " ./x.py {} {}\n", kind.as_str(), path.display()));
};
for pathset in should_run.paths {
match pathset {
},
);
- // `dsymutil` adds time to builds on Apple platforms for no clear benefit, and also makes
- // it more difficult for debuggers to find debug info. The compiler currently defaults to
- // running `dsymutil` to preserve its historical default, but when compiling the compiler
- // itself, we skip it by default since we know it's safe to do so in that case.
- // See https://github.com/rust-lang/rust/issues/79361 for more info on this flag.
- if target.contains("apple") {
- if self.config.rust_run_dsymutil {
- rustflags.arg("-Csplit-debuginfo=packed");
- } else {
- rustflags.arg("-Csplit-debuginfo=unpacked");
+ // FIXME(davidtwco): #[cfg(not(bootstrap))] - #95612 needs to be in the bootstrap compiler
+ // for this conditional to be removed.
+ if !target.contains("windows") || compiler.stage >= 1 {
+ if target.contains("linux") || target.contains("windows") {
+ rustflags.arg("-Zunstable-options");
}
+ match self.config.rust_split_debuginfo {
+ SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
+ SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
+ SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
+ };
}
if self.config.cmd.bless() {
// don't save toolstates
config.save_toolstates = None;
config.dry_run = true;
+ config.submodules = Some(false);
config.ninja_in_file = false;
// try to avoid spurious failures in dist where we create/delete each others file
// HACK: rather than pull in `tempdir`, use the one that cargo has conveniently created for us
v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
}
+fn run_build(paths: &[PathBuf], config: Config) -> Cache {
+ let kind = config.cmd.kind();
+ let build = Build::new(config);
+ let builder = Builder::new(&build);
+ builder.run_step_descriptions(&Builder::get_step_descriptions(kind), paths);
+ builder.cache
+}
+
+#[test]
+fn test_exclude() {
+ let mut config = configure("test", &["A"], &["A"]);
+ config.exclude = vec![TaskPath::parse("src/tools/tidy")];
+ let cache = run_build(&[], config);
+
+ // Ensure we have really excluded tidy
+ assert!(!cache.contains::<test::Tidy>());
+
+ // Ensure other tests are not affected.
+ assert!(cache.contains::<test::RustdocUi>());
+}
+
+#[test]
+fn test_exclude_kind() {
+ let path = PathBuf::from("src/tools/cargotest");
+ let exclude = TaskPath::parse("test::src/tools/cargotest");
+ assert_eq!(exclude, TaskPath { kind: Some(Kind::Test), path: path.clone() });
+
+ let mut config = configure("test", &["A"], &["A"]);
+ // Ensure our test is valid, and `test::Cargotest` would be run without the exclude.
+ assert!(run_build(&[path.clone()], config.clone()).contains::<test::Cargotest>());
+ // Ensure tests for cargotest are skipped.
+ config.exclude = vec![exclude.clone()];
+ assert!(!run_build(&[path.clone()], config).contains::<test::Cargotest>());
+
+ // Ensure builds for cargotest are not skipped.
+ let mut config = configure("build", &["A"], &["A"]);
+ config.exclude = vec![exclude];
+ assert!(run_build(&[path], config).contains::<tool::CargoTest>());
+}
+
mod defaults {
- use super::{configure, first};
+ use super::{configure, first, run_build};
use crate::builder::*;
use crate::Config;
use pretty_assertions::assert_eq;
#[test]
fn build_default() {
- let build = Build::new(configure("build", &["A"], &["A"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+ let mut cache = run_build(&[], configure("build", &["A"], &["A"]));
let a = TargetSelection::from_user("A");
assert_eq!(
- first(builder.cache.all::<compile::Std>()),
+ first(cache.all::<compile::Std>()),
&[
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
]
);
- assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+ assert!(!cache.all::<compile::Assemble>().is_empty());
// Make sure rustdoc is only built once.
assert_eq!(
- first(builder.cache.all::<tool::Rustdoc>()),
+ first(cache.all::<tool::Rustdoc>()),
// Recall that rustdoc stages are off-by-one
// - this is the compiler it's _linked_ to, not built with.
&[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
);
assert_eq!(
- first(builder.cache.all::<compile::Rustc>()),
+ first(cache.all::<compile::Rustc>()),
&[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },]
);
}
#[test]
fn build_stage_0() {
let config = Config { stage: 0, ..configure("build", &["A"], &["A"]) };
- let build = Build::new(config);
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+ let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
assert_eq!(
- first(builder.cache.all::<compile::Std>()),
+ first(cache.all::<compile::Std>()),
&[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },]
);
- assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+ assert!(!cache.all::<compile::Assemble>().is_empty());
assert_eq!(
- first(builder.cache.all::<tool::Rustdoc>()),
+ first(cache.all::<tool::Rustdoc>()),
// This is the beta rustdoc.
// Add an assert here to make sure this is the only rustdoc built.
&[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
);
- assert!(builder.cache.all::<compile::Rustc>().is_empty());
+ assert!(cache.all::<compile::Rustc>().is_empty());
}
#[test]
fn build_cross_compile() {
let config = Config { stage: 1, ..configure("build", &["A", "B"], &["A", "B"]) };
- let build = Build::new(config);
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+ let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
// (since we're producing stage 1 libraries/binaries). But currently
// rustbuild is just a bit buggy here; this should be fixed though.
assert_eq!(
- first(builder.cache.all::<compile::Std>()),
+ first(cache.all::<compile::Std>()),
&[
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
]
);
assert_eq!(
- first(builder.cache.all::<compile::Assemble>()),
+ first(cache.all::<compile::Assemble>()),
&[
compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
]
);
assert_eq!(
- first(builder.cache.all::<tool::Rustdoc>()),
+ first(cache.all::<tool::Rustdoc>()),
&[
tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
tool::Rustdoc { compiler: Compiler { host: b, stage: 1 } },
],
);
assert_eq!(
- first(builder.cache.all::<compile::Rustc>()),
+ first(cache.all::<compile::Rustc>()),
&[
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: b },
let mut config = configure("doc", &["A"], &["A"]);
config.compiler_docs = true;
config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
- let build = Build::new(config);
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+ let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
// error_index_generator uses stage 0 to share rustdoc artifacts with the
// rustdoc tool.
+ assert_eq!(first(cache.all::<doc::ErrorIndex>()), &[doc::ErrorIndex { target: a },]);
assert_eq!(
- first(builder.cache.all::<doc::ErrorIndex>()),
- &[doc::ErrorIndex { target: a },]
- );
- assert_eq!(
- first(builder.cache.all::<tool::ErrorIndex>()),
+ first(cache.all::<tool::ErrorIndex>()),
&[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
);
// docs should be built with the beta compiler, not with the stage0 artifacts.
// recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
// not the one it was built by.
assert_eq!(
- first(builder.cache.all::<tool::Rustdoc>()),
+ first(cache.all::<tool::Rustdoc>()),
&[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
);
}
}
mod dist {
- use super::{first, Config};
+ use super::{first, run_build, Config};
use crate::builder::*;
use pretty_assertions::assert_eq;
#[test]
fn dist_baseline() {
- let build = Build::new(configure(&["A"], &["A"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], configure(&["A"], &["A"]));
let a = TargetSelection::from_user("A");
- assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
- assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
+ assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
+ assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
);
- assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+ assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
// Make sure rustdoc is only built once.
assert_eq!(
- first(builder.cache.all::<tool::Rustdoc>()),
+ first(cache.all::<tool::Rustdoc>()),
&[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
);
}
#[test]
fn dist_with_targets() {
- let build = Build::new(configure(&["A"], &["A", "B"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], configure(&["A"], &["A", "B"]));
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
assert_eq!(
- first(builder.cache.all::<dist::Docs>()),
+ first(cache.all::<dist::Docs>()),
&[dist::Docs { host: a }, dist::Docs { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Mingw>()),
+ first(cache.all::<dist::Mingw>()),
&[dist::Mingw { host: a }, dist::Mingw { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
]
);
- assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+ assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_hosts() {
- let build = Build::new(configure(&["A", "B"], &["A", "B"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
assert_eq!(
- first(builder.cache.all::<dist::Docs>()),
+ first(cache.all::<dist::Docs>()),
&[dist::Docs { host: a }, dist::Docs { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Mingw>()),
+ first(cache.all::<dist::Mingw>()),
&[dist::Mingw { host: a }, dist::Mingw { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]
);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
]
);
assert_eq!(
- first(builder.cache.all::<compile::Std>()),
+ first(cache.all::<compile::Std>()),
&[
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
],
);
- assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+ assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_only_cross_host() {
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
- let mut build = Build::new(configure(&["A", "B"], &["A", "B"]));
- build.config.docs = false;
- build.config.extended = true;
- build.hosts = vec![b];
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut config = configure(&["A", "B"], &["A", "B"]);
+ config.docs = false;
+ config.extended = true;
+ config.hosts = vec![b];
+ let mut cache = run_build(&[], config);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
);
assert_eq!(
- first(builder.cache.all::<compile::Rustc>()),
+ first(cache.all::<compile::Rustc>()),
&[
compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
#[test]
fn dist_with_targets_and_hosts() {
- let build = Build::new(configure(&["A", "B"], &["A", "B", "C"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B", "C"]));
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
let c = TargetSelection::from_user("C");
assert_eq!(
- first(builder.cache.all::<dist::Docs>()),
+ first(cache.all::<dist::Docs>()),
&[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
);
assert_eq!(
- first(builder.cache.all::<dist::Mingw>()),
+ first(cache.all::<dist::Mingw>()),
&[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]
);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
]
);
- assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+ assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_empty_host() {
let config = configure(&[], &["C"]);
- let build = Build::new(config);
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
let c = TargetSelection::from_user("C");
- assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
- assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
+ assert_eq!(first(cache.all::<dist::Docs>()), &[dist::Docs { host: c },]);
+ assert_eq!(first(cache.all::<dist::Mingw>()), &[dist::Mingw { host: c },]);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },]
);
}
#[test]
fn dist_with_same_targets_and_hosts() {
- let build = Build::new(configure(&["A", "B"], &["A", "B"]));
- let mut builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+ let mut cache = run_build(&[], configure(&["A", "B"], &["A", "B"]));
let a = TargetSelection::from_user("A");
let b = TargetSelection::from_user("B");
assert_eq!(
- first(builder.cache.all::<dist::Docs>()),
+ first(cache.all::<dist::Docs>()),
&[dist::Docs { host: a }, dist::Docs { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Mingw>()),
+ first(cache.all::<dist::Mingw>()),
&[dist::Mingw { host: a }, dist::Mingw { host: b },]
);
assert_eq!(
- first(builder.cache.all::<dist::Rustc>()),
+ first(cache.all::<dist::Rustc>()),
&[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]
);
assert_eq!(
- first(builder.cache.all::<dist::Std>()),
+ first(cache.all::<dist::Std>()),
&[
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
]
);
- assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+ assert_eq!(first(cache.all::<dist::Src>()), &[dist::Src]);
assert_eq!(
- first(builder.cache.all::<compile::Std>()),
+ first(cache.all::<compile::Std>()),
&[
compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
]
);
assert_eq!(
- first(builder.cache.all::<compile::Assemble>()),
+ first(cache.all::<compile::Assemble>()),
&[
compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
);
}
- #[test]
- fn test_exclude() {
- let mut config = configure(&["A"], &["A"]);
- config.exclude = vec![TaskPath::parse("src/tools/tidy")];
- config.cmd = Subcommand::Test {
- paths: Vec::new(),
- test_args: Vec::new(),
- rustc_args: Vec::new(),
- fail_fast: true,
- doc_tests: DocTests::No,
- bless: false,
- force_rerun: false,
- compare_mode: None,
- rustfix_coverage: false,
- pass: None,
- run: None,
- };
-
- let build = Build::new(config);
- let builder = Builder::new(&build);
- builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-
- // Ensure we have really excluded tidy
- assert!(!builder.cache.contains::<test::Tidy>());
-
- // Ensure other tests are not affected.
- assert!(builder.cache.contains::<test::RustdocUi>());
- }
-
#[test]
fn doc_ci() {
let mut config = configure(&["A"], &["A"]);
build.verbose(&format!("AR_{} = {:?}", &target.triple, ar));
build.ar.insert(target, ar);
}
+
+ if let Some(ranlib) = config.and_then(|c| c.ranlib.clone()) {
+ build.ranlib.insert(target, ranlib);
+ }
}
}
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.all_krates("test")
+ run.all_krates("test").path("library")
}
fn make_run(run: RunConfig<'_>) {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.all_krates("rustc-main")
+ run.all_krates("rustc-main").path("compiler")
}
fn make_run(run: RunConfig<'_>) {
// When downloading stage1, the standard library has already been copied to the sysroot, so
// there's no need to rebuild it.
let download_rustc = run.builder.config.download_rustc;
- run.all_krates("test").default_condition(!download_rustc)
+ run.all_krates("test").path("library").default_condition(!download_rustc)
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("compiler/rustc")
+ run.path("compiler/rustc").path("compiler")
}
fn make_run(run: RunConfig<'_>) {
/// each field, see the corresponding fields in
/// `config.toml.example`.
#[derive(Default)]
+#[cfg_attr(test, derive(Clone))]
pub struct Config {
pub changelog_seen: Option<usize>,
pub ccache: Option<String>,
pub rust_debuginfo_level_std: u32,
pub rust_debuginfo_level_tools: u32,
pub rust_debuginfo_level_tests: u32,
- pub rust_run_dsymutil: bool,
+ pub rust_split_debuginfo: SplitDebuginfo,
pub rust_rpath: bool,
pub rustc_parallel: bool,
pub rustc_default_linker: Option<String>,
}
}
-#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum SplitDebuginfo {
+ Packed,
+ Unpacked,
+ Off,
+}
+
+impl Default for SplitDebuginfo {
+ fn default() -> Self {
+ SplitDebuginfo::Off
+ }
+}
+
+impl std::str::FromStr for SplitDebuginfo {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "packed" => Ok(SplitDebuginfo::Packed),
+ "unpacked" => Ok(SplitDebuginfo::Unpacked),
+ "off" => Ok(SplitDebuginfo::Off),
+ _ => Err(()),
+ }
+ }
+}
+
+impl SplitDebuginfo {
+ /// Returns the default `-Csplit-debuginfo` value for the current target. See the comment for
+ /// `rust.split-debuginfo` in `config.toml.example`.
+ fn default_for_platform(target: &str) -> Self {
+ if target.contains("apple") {
+ SplitDebuginfo::Unpacked
+ } else if target.contains("windows") {
+ SplitDebuginfo::Packed
+ } else {
+ SplitDebuginfo::Off
+ }
+ }
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TargetSelection {
pub triple: Interned<String>,
file: Option<Interned<String>>,
}
}
+impl fmt::Debug for TargetSelection {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self)
+ }
+}
+
impl PartialEq<&str> for TargetSelection {
fn eq(&self, other: &&str) -> bool {
self.triple == *other
/// Per-target configuration stored in the global configuration structure.
#[derive(Default)]
+#[cfg_attr(test, derive(Clone))]
pub struct Target {
/// Some(path to llvm-config) if using an external LLVM.
pub llvm_config: Option<PathBuf>,
debuginfo_level_std: Option<u32> = "debuginfo-level-std",
debuginfo_level_tools: Option<u32> = "debuginfo-level-tools",
debuginfo_level_tests: Option<u32> = "debuginfo-level-tests",
+ split_debuginfo: Option<String> = "split-debuginfo",
run_dsymutil: Option<bool> = "run-dsymutil",
backtrace: Option<bool> = "backtrace",
incremental: Option<bool> = "incremental",
debuginfo_level_std = rust.debuginfo_level_std;
debuginfo_level_tools = rust.debuginfo_level_tools;
debuginfo_level_tests = rust.debuginfo_level_tests;
- config.rust_run_dsymutil = rust.run_dsymutil.unwrap_or(false);
+ 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;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = run.builder.config.docs;
- run.path("rust-docs").default_condition(default)
+ run.alias("rust-docs").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("rustc-docs").default_condition(builder.config.compiler_docs)
+ run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
}
fn make_run(run: RunConfig<'_>) {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rust-mingw")
+ run.alias("rust-mingw")
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rustc")
+ run.alias("rustc")
}
fn make_run(run: RunConfig<'_>) {
type Output = ();
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/lldb_batchmode.py")
+ run.path("src/etc/lldb_batchmode.py")
}
fn make_run(run: RunConfig<'_>) {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rust-std")
+ run.alias("rust-std")
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rustc-dev")
+ run.alias("rustc-dev")
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "analysis");
- run.path("rust-analysis").default_condition(default)
+ run.alias("rust-analysis").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rust-src")
+ run.alias("rust-src")
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("rustc-src").default_condition(builder.config.rust_dist_src)
+ run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "cargo");
- run.path("cargo").default_condition(default)
+ run.alias("cargo").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "rls");
- run.path("rls").default_condition(default)
+ run.alias("rls").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "rust-analyzer");
- run.path("rust-analyzer").default_condition(default)
+ run.alias("rust-analyzer").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "clippy");
- run.path("clippy").default_condition(default)
+ run.alias("clippy").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "miri");
- run.path("miri").default_condition(default)
+ run.alias("miri").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "rustfmt");
- run.path("rustfmt").default_condition(default)
+ run.alias("rustfmt").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
// we run the step by default when only `extended = true`, and decide whether to actually
// run it or not later.
let default = run.builder.config.extended;
- run.path("rust-demangler").default_condition(default)
+ run.alias("rust-demangler").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("extended").default_condition(builder.config.extended)
+ run.alias("extended").default_condition(builder.config.extended)
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(&run.builder, "llvm-tools");
- run.path("llvm-tools").default_condition(default)
+ // FIXME: allow using the names of the tools themselves?
+ run.alias("llvm-tools").default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("rust-dev")
+ run.alias("rust-dev")
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("build-manifest")
+ run.alias("build-manifest")
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("reproducible-artifacts")
+ run.alias("reproducible-artifacts")
}
fn make_run(run: RunConfig<'_>) {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.all_krates("test").default_condition(builder.config.docs)
+ run.all_krates("test").path("library").default_condition(builder.config.docs)
}
fn make_run(run: RunConfig<'_>) {
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, builder.config.build);
- builder.ensure(compile::Std { compiler, target });
let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
.iter()
.map(components_simplified)
.filter_map(|path| {
- if path.get(0) == Some(&"library") {
+ if path.len() >= 2 && path.get(0) == Some(&"library") {
+ // single crate
Some(path[1].to_owned())
} else if !path.is_empty() {
+ // ??
Some(path[0].to_owned())
} else {
+ // all library crates
None
}
})
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
- builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
let paths = builder
.paths
let out = builder.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
- // Build rustc.
+ // Build the standard library, so that proc-macros can use it.
+ // (Normally, only the metadata would be necessary, but proc-macros are special since they run at compile-time.)
let compiler = builder.compiler(stage, builder.config.build);
- builder.ensure(compile::Rustc { compiler, target });
+ builder.ensure(compile::Std { compiler, target: builder.config.build });
+
+ builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
// This uses a shared directory so that librustdoc documentation gets
// correctly built and merged with the rustc documentation. This is
($tool: ident, $should_run: literal, $path: literal, [$($krate: literal),+ $(,)?] $(,)?) => {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $tool {
- stage: u32,
target: TargetSelection,
}
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure($tool { stage: run.builder.top_stage, target: run.target });
+ run.builder.ensure($tool { target: run.target });
}
/// Generates compiler documentation.
/// we do not merge it with the other documentation from std, test and
/// proc_macros. This is largely just a wrapper around `cargo doc`.
fn run(self, builder: &Builder<'_>) {
- let stage = self.stage;
+ let stage = builder.top_stage;
let target = self.target;
+
+ // This is the intended out directory for compiler documentation.
+ let out = builder.compiler_doc_out(target);
+ t!(fs::create_dir_all(&out));
+
+ // Build rustc docs so that we generate relative links.
+ builder.ensure(Rustc { stage, target });
+ // Rustdoc needs the rustc sysroot available to build.
+ // FIXME: is there a way to only ensure `check::Rustc` here? Last time I tried it failed
+ // with strange errors, but only on a full bors test ...
+ let compiler = builder.compiler(stage, builder.config.build);
+ builder.ensure(compile::Rustc { compiler, target });
+
builder.info(
&format!(
"Documenting stage{} {} ({})",
),
);
- // This is the intended out directory for compiler documentation.
- let out = builder.compiler_doc_out(target);
- t!(fs::create_dir_all(&out));
-
- let compiler = builder.compiler(stage, builder.config.build);
-
- // Build rustc docs so that we generate relative links.
- builder.ensure(Rustc { stage, target });
-
// Symlink compiler docs to the output directory of rustdoc documentation.
let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
t!(fs::create_dir_all(&out_dir));
use getopts::Options;
-use crate::builder::Builder;
+use crate::builder::{Builder, Kind};
use crate::config::{Config, TargetSelection};
use crate::setup::Profile;
use crate::util::t;
use crate::{Build, DocTests};
+#[derive(Copy, Clone)]
pub enum Color {
Always,
Never,
pub llvm_profile_generate: bool,
}
+#[cfg_attr(test, derive(Clone))]
pub enum Subcommand {
Build {
paths: Vec<PathBuf>,
// the subcommand. Therefore we must manually identify the subcommand first, so that we can
// complete the definition of the options. Then we can use the getopt::Matches object from
// there on out.
- let subcommand = args.iter().find(|&s| {
- (s == "build")
- || (s == "b")
- || (s == "check")
- || (s == "c")
- || (s == "clippy")
- || (s == "fix")
- || (s == "fmt")
- || (s == "test")
- || (s == "t")
- || (s == "bench")
- || (s == "doc")
- || (s == "d")
- || (s == "clean")
- || (s == "dist")
- || (s == "install")
- || (s == "run")
- || (s == "r")
- || (s == "setup")
- });
- let subcommand = match subcommand {
+ let subcommand = match args.iter().find_map(|s| Kind::parse(&s)) {
Some(s) => s,
None => {
// No or an invalid subcommand -- show the general usage and subcommand help
};
// Some subcommands get extra options
- match subcommand.as_str() {
- "test" | "t" => {
+ match subcommand {
+ Kind::Test => {
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
opts.optmulti(
"",
`/<build_base>/rustfix_missing_coverage.txt`",
);
}
- "check" | "c" => {
+ Kind::Check => {
opts.optflag("", "all-targets", "Check all targets");
}
- "bench" => {
+ Kind::Bench => {
opts.optmulti("", "test-args", "extra arguments", "ARGS");
}
- "clippy" => {
+ Kind::Clippy => {
opts.optflag("", "fix", "automatically apply lint suggestions");
}
- "doc" | "d" => {
+ Kind::Doc => {
opts.optflag("", "open", "open the docs in a browser");
}
- "clean" => {
+ Kind::Clean => {
opts.optflag("", "all", "clean all build artifacts");
}
- "fmt" => {
+ Kind::Format => {
opts.optflag("", "check", "check formatting instead of applying.");
}
_ => {}
// fn usage()
let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
- let mut extra_help = String::new();
-
- // All subcommands except `clean` can have an optional "Available paths" section
- if verbose {
- let config = Config::parse(&["build".to_string()]);
- let build = Build::new(config);
-
- let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
- extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
- } else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
- extra_help.push_str(
- format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand)
- .as_str(),
- );
- }
+ let config = Config::parse(&["build".to_string()]);
+ let build = Build::new(config);
+ let paths = Builder::get_help(&build, subcommand);
println!("{}", opts.usage(subcommand_help));
- if !extra_help.is_empty() {
- println!("{}", extra_help);
+ if let Some(s) = paths {
+ if verbose {
+ println!("{}", s);
+ } else {
+ println!(
+ "Run `./x.py {} -h -v` to see a list of available paths.",
+ subcommand.as_str()
+ );
+ }
+ } else if verbose {
+ panic!("No paths available for subcommand `{}`", subcommand.as_str());
}
process::exit(exit_code);
};
// ^-- option ^ ^- actual subcommand
// \_ arg to option could be mistaken as subcommand
let mut pass_sanity_check = true;
- match matches.free.get(0) {
+ match matches.free.get(0).and_then(|s| Kind::parse(&s)) {
Some(check_subcommand) => {
if check_subcommand != subcommand {
pass_sanity_check = false;
process::exit(1);
}
// Extra help text for some commands
- match subcommand.as_str() {
- "build" | "b" => {
+ match subcommand {
+ Kind::Build => {
subcommand_help.push_str(
"\n
Arguments:
./x.py build ",
);
}
- "check" | "c" => {
+ Kind::Check => {
subcommand_help.push_str(
"\n
Arguments:
If no arguments are passed then many artifacts are checked.",
);
}
- "clippy" => {
+ Kind::Clippy => {
subcommand_help.push_str(
"\n
Arguments:
./x.py clippy library/core library/proc_macro",
);
}
- "fix" => {
+ Kind::Fix => {
subcommand_help.push_str(
"\n
Arguments:
./x.py fix library/core library/proc_macro",
);
}
- "fmt" => {
+ Kind::Format => {
subcommand_help.push_str(
"\n
Arguments:
./x.py fmt --check",
);
}
- "test" | "t" => {
+ Kind::Test => {
subcommand_help.push_str(
"\n
Arguments:
./x.py test --stage 1",
);
}
- "doc" | "d" => {
+ Kind::Doc => {
subcommand_help.push_str(
"\n
Arguments:
./x.py doc --stage 1",
);
}
- "run" | "r" => {
+ Kind::Run => {
subcommand_help.push_str(
"\n
Arguments:
At least a tool needs to be called.",
);
}
- "setup" => {
+ Kind::Setup => {
subcommand_help.push_str(&format!(
"\n
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
Profile::all_for_help(" ").trim_end()
));
}
- _ => {}
+ Kind::Bench | Kind::Clean | Kind::Dist | Kind::Install => {}
};
// Get any optional paths which occur after the subcommand
let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
usage(0, &opts, verbose, &subcommand_help);
}
- let cmd = match subcommand.as_str() {
- "build" | "b" => Subcommand::Build { paths },
- "check" | "c" => {
+ let cmd = match subcommand {
+ Kind::Build => Subcommand::Build { paths },
+ Kind::Check => {
if matches.opt_present("all-targets") {
eprintln!(
"Warning: --all-targets is now on by default and does not need to be passed explicitly."
}
Subcommand::Check { paths }
}
- "clippy" => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
- "fix" => Subcommand::Fix { paths },
- "test" | "t" => Subcommand::Test {
+ Kind::Clippy => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
+ Kind::Fix => Subcommand::Fix { paths },
+ Kind::Test => Subcommand::Test {
paths,
bless: matches.opt_present("bless"),
force_rerun: matches.opt_present("force-rerun"),
DocTests::Yes
},
},
- "bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
- "doc" | "d" => Subcommand::Doc { paths, open: matches.opt_present("open") },
- "clean" => {
+ Kind::Bench => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
+ Kind::Doc => Subcommand::Doc { paths, open: matches.opt_present("open") },
+ Kind::Clean => {
if !paths.is_empty() {
println!("\nclean does not take a path argument\n");
usage(1, &opts, verbose, &subcommand_help);
Subcommand::Clean { all: matches.opt_present("all") }
}
- "fmt" => Subcommand::Format { check: matches.opt_present("check"), paths },
- "dist" => Subcommand::Dist { paths },
- "install" => Subcommand::Install { paths },
- "run" | "r" => {
+ Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths },
+ Kind::Dist => Subcommand::Dist { paths },
+ Kind::Install => Subcommand::Install { paths },
+ Kind::Run => {
if paths.is_empty() {
println!("\nrun requires at least a path!\n");
usage(1, &opts, verbose, &subcommand_help);
}
Subcommand::Run { paths }
}
- "setup" => {
+ Kind::Setup => {
let profile = if paths.len() > 1 {
println!("\nat most one profile can be passed to setup\n");
usage(1, &opts, verbose, &subcommand_help)
};
Subcommand::Setup { profile }
}
- _ => {
- usage(1, &opts, verbose, &subcommand_help);
- }
};
if let Subcommand::Check { .. } = &cmd {
}
impl Subcommand {
+ pub fn kind(&self) -> Kind {
+ match self {
+ Subcommand::Bench { .. } => Kind::Bench,
+ Subcommand::Build { .. } => Kind::Build,
+ Subcommand::Check { .. } => Kind::Check,
+ Subcommand::Clippy { .. } => Kind::Clippy,
+ Subcommand::Doc { .. } => Kind::Doc,
+ Subcommand::Fix { .. } => Kind::Fix,
+ Subcommand::Format { .. } => Kind::Format,
+ Subcommand::Test { .. } => Kind::Test,
+ Subcommand::Clean { .. } => Kind::Clean,
+ Subcommand::Dist { .. } => Kind::Dist,
+ Subcommand::Install { .. } => Kind::Install,
+ Subcommand::Run { .. } => Kind::Run,
+ Subcommand::Setup { .. } => Kind::Setup,
+ }
+ }
+
pub fn test_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
macro_rules! install {
(($sel:ident, $builder:ident, $_config:ident),
$($name:ident,
- $path:expr,
+ $condition_name: ident = $path_or_alias: literal,
$default_cond:expr,
only_hosts: $only_hosts:expr,
$run_item:block $(, $c:ident)*;)+) => {
#[allow(dead_code)]
fn should_build(config: &Config) -> bool {
config.extended && config.tools.as_ref()
- .map_or(true, |t| t.contains($path))
+ .map_or(true, |t| t.contains($path_or_alias))
}
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let $_config = &run.builder.config;
- run.path($path).default_condition($default_cond)
+ run.$condition_name($path_or_alias).default_condition($default_cond)
}
fn make_run(run: RunConfig<'_>) {
}
install!((self, builder, _config),
- Docs, "src/doc", _config.docs, only_hosts: false, {
+ Docs, path = "src/doc", _config.docs, only_hosts: false, {
let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
};
- Std, "library/std", true, only_hosts: false, {
+ Std, path = "library/std", true, only_hosts: false, {
for target in &builder.targets {
// `expect` should be safe, only None when host != build, but this
// only runs when host == build
install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
}
};
- Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
+ Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, {
let tarball = builder
.ensure(dist::Cargo { compiler: self.compiler, target: self.target })
.expect("missing cargo");
install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
};
- Rls, "rls", Self::should_build(_config), only_hosts: true, {
+ Rls, alias = "rls", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
} else {
);
}
};
- RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
+ RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) =
builder.ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
{
);
}
};
- Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
+ Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, {
let tarball = builder
.ensure(dist::Clippy { compiler: self.compiler, target: self.target })
.expect("missing clippy");
install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
};
- Miri, "miri", Self::should_build(_config), only_hosts: true, {
+ Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
} else {
);
}
};
- Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
+ Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
compiler: self.compiler,
target: self.target
);
}
};
- RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, {
+ RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, {
// Note: Even though `should_build` may return true for `extended` default tools,
// dist::RustDemangler may still return None, unless the target-dependent `profiler` config
// is also true, or the `tools` array explicitly includes "rust-demangler".
);
}
};
- Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
+ Analysis, alias = "analysis", Self::should_build(_config), only_hosts: false, {
// `expect` should be safe, only None with host != build, but this
// only uses the `build` compiler
let tarball = builder.ensure(dist::Analysis {
}).expect("missing analysis");
install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
};
- Rustc, "src/librustc", true, only_hosts: true, {
+ Rustc, path = "compiler/rustc", true, only_hosts: true, {
let tarball = builder.ensure(dist::Rustc {
compiler: builder.compiler(builder.top_stage, self.target),
});
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/llvm-project").path("src/llvm-project/llvm").path("src/llvm")
+ run.path("src/llvm-project").path("src/llvm-project/llvm")
}
fn make_run(run: RunConfig<'_>) {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/llvm-project/lld").path("src/tools/lld")
+ run.path("src/llvm-project/lld")
}
fn make_run(run: RunConfig<'_>) {
type Output = Vec<SanitizerRuntime>;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/llvm-project/compiler-rt").path("src/sanitizers")
+ run.alias("sanitizers")
}
fn make_run(run: RunConfig<'_>) {
t!(std::fs::rename(&self.image_dir, &dest));
self.run(|this, cmd| {
+ let distdir = crate::dist::distdir(this.builder);
+ t!(std::fs::create_dir_all(&distdir));
cmd.arg("tarball")
.arg("--input")
.arg(&dest)
.arg("--output")
- .arg(crate::dist::distdir(this.builder).join(this.package_name()));
+ .arg(distdir.join(this.package_name()));
})
}
targetflags.extend(builder.lld_flags(target));
cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
- cmd.arg("--docck-python").arg(builder.python());
-
- cmd.arg("--lldb-python").arg(builder.python());
+ cmd.arg("--python").arg(builder.python());
if let Some(ref gdb) = builder.config.gdb {
cmd.arg("--gdb").arg(gdb);
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let compiler = builder.compiler(builder.top_stage, run.build_triple());
+ let host = run.build_triple();
+ let compiler = builder.compiler_for(builder.top_stage, host, host);
let krate = builder.crate_paths[&run.path];
let test_kind = builder.kind.into();
fn make_run(run: RunConfig<'_>) {
let builder = run.builder;
- let compiler = builder.compiler(builder.top_stage, run.build_triple());
+ let host = run.build_triple();
+ let compiler = builder.compiler_for(builder.top_stage, host, host);
let test_kind = builder.kind.into();
let krate = builder.crate_paths[&run.path];
type Output = ();
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("distcheck")
+ run.alias("distcheck")
}
fn make_run(run: RunConfig<'_>) {
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("check-tools")
+ run.alias("check-tools")
}
fn make_run(run: RunConfig<'_>) {
run: git config --global core.autocrlf false
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'
steps:
- name: checkout the source code
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
fetch-depth: 2
-Subproject commit ea90bbaf53ba64ef4e2da9ac2352b298aec6bec8
+Subproject commit de0dbffc5812fd885700874e8d258dd334733ac4
-Subproject commit a6de8b6e3ea5d4f0de8b7b9a7e5c1405dc2c2ddb
+Subproject commit f7cefbb995eec8c6148f213235e9e2e03268e775
-Subproject commit 11f1165e8a2f5840467e748c8108dc53c948ee9a
+Subproject commit c7d8467ca9158da58ef295ae65dbf00a308752d9
-Subproject commit c97d14fa6fed0baa9255432b8a93cb70614f80e3
+Subproject commit b5f6c2362baf932db9440fbfcb509b309237ee85
-Subproject commit ec954f35eedf592cd173b21c05a7f80a65b61d8a
+Subproject commit 44a80e8d8bfc5881c9bd69a2cb3a570776ee4181
-Subproject commit 155126b1d2e2cb01ddb1d7ba9489b90d7cd173ad
+Subproject commit 043e60f4f191651e9f8bf52fa32df14defbb23d9
- [Platform Support](platform-support.md)
- [Template for target-specific documentation](platform-support/TEMPLATE.md)
- [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
+ - [aarch64-unknown-none-hermitkernel](platform-support/aarch64-unknown-none-hermitkernel.md)
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
+ - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
+ - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
- [*-unknown-openbsd](platform-support/openbsd.md)
- - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
+ - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [Target Tier Policy](target-tier-policy.md)
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
`i686-uwp-windows-gnu` | ? | |
`i686-uwp-windows-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
-`m68k-unknown-linux-gnu` | ? | | Motorola 680x0 Linux
+[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
-`mips64-openwrt-linux-musl` | ? | | MIPS64 for OpenWrt Linux MUSL
+[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat
+++ /dev/null
-# `extern-location`
-
-MCP for this feature: [#303]
-
-[#303]: https://github.com/rust-lang/compiler-team/issues/303
-
-------------------------
-
-The `unused-extern-crates` lint reports when a crate was specified on the rustc
-command-line with `--extern name=path` but no symbols were referenced in it.
-This is useful to know, but it's hard to map that back to a specific place a user
-or tool could fix (ie, to remove the unused dependency).
-
-The `--extern-location` flag allows the build system to associate a location with
-the `--extern` option, which is then emitted as part of the diagnostics. This location
-is abstract and just round-tripped through rustc; the compiler never attempts to
-interpret it in any way.
-
-There are two supported forms of location: a bare string, or a blob of json:
-- `--extern-location foo=raw:Makefile:123` would associate the raw string `Makefile:123`
-- `--extern-location 'bar=json:{"target":"//my_project:library","dep":"//common:serde"}` would
- associate the json structure with `--extern bar=<path>`, indicating which dependency of
- which rule introduced the unused extern crate.
-
-This primarily intended to be used with tooling - for example a linter which can automatically
-remove unused dependencies - rather than being directly presented to users.
-
-`raw` locations are presented as part of the normal rendered diagnostics and included in
-the json form. `json` locations are only included in the json form of diagnostics,
-as a `tool_metadata` field. For `raw` locations `tool_metadata` is simply a json string,
-whereas `json` allows the rustc invoker to fully control its form and content.
The `doc_cfg` feature allows an API be documented as only available in some specific platforms.
This attribute has two effects:
-1. In the annotated item's documentation, there will be a message saying "This is supported on
+1. In the annotated item's documentation, there will be a message saying "Available on
(platform) only".
2. The item's doc-tests will only run on the specific platform.
def unwrap_unique_or_non_null(unique_or_nonnull):
# BACKCOMPAT: rust 1.32
# https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+ # BACKCOMPAT: rust 1.60
+ # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
ptr = unique_or_nonnull["pointer"]
- return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD]
+ return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]]
class EnumProvider:
return ''.join(acc)
+def make_xml(text):
+ xml = ET.XML('<xml>%s</xml>' % text)
+ return xml
+
+
def normalize_xpath(path):
path = path.replace("{{channel}}", channel)
if path.startswith('//'):
return len(tree.findall(path))
-def check_snapshot(snapshot_name, tree, normalize_to_text):
+def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
assert rust_test_path.endswith('.rs')
snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
try:
raise FailedCheck('No saved snapshot value')
if not normalize_to_text:
- actual_str = ET.tostring(tree).decode('utf-8')
+ actual_str = ET.tostring(actual_tree).decode('utf-8')
else:
- actual_str = flatten(tree)
+ actual_str = flatten(actual_tree)
+
+ # Conditions:
+ # 1. Is --bless
+ # 2. Are actual and expected tree different
+ # 3. Are actual and expected text different
+ if not expected_str \
+ or (not normalize_to_text and \
+ not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
+ or (normalize_to_text and actual_str != expected_str):
- if expected_str != actual_str:
if bless:
with open(snapshot_path, 'w') as snapshot_file:
snapshot_file.write(actual_str)
print()
raise FailedCheck('Actual snapshot value is different than expected')
+
+# Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
+def compare_tree(x1, x2, reporter=None):
+ if x1.tag != x2.tag:
+ if reporter:
+ reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
+ return False
+ for name, value in x1.attrib.items():
+ if x2.attrib.get(name) != value:
+ if reporter:
+ reporter('Attributes do not match: %s=%r, %s=%r'
+ % (name, value, name, x2.attrib.get(name)))
+ return False
+ for name in x2.attrib:
+ if name not in x1.attrib:
+ if reporter:
+ reporter('x2 has an attribute x1 is missing: %s'
+ % name)
+ return False
+ if not text_compare(x1.text, x2.text):
+ if reporter:
+ reporter('text: %r != %r' % (x1.text, x2.text))
+ return False
+ if not text_compare(x1.tail, x2.tail):
+ if reporter:
+ reporter('tail: %r != %r' % (x1.tail, x2.tail))
+ return False
+ cl1 = list(x1)
+ cl2 = list(x2)
+ if len(cl1) != len(cl2):
+ if reporter:
+ reporter('children length differs, %i != %i'
+ % (len(cl1), len(cl2)))
+ return False
+ i = 0
+ for c1, c2 in zip(cl1, cl2):
+ i += 1
+ if not compare_tree(c1, c2, reporter=reporter):
+ if reporter:
+ reporter('children %i do not match: %s'
+ % (i, c1.tag))
+ return False
+ return True
+
+
+def text_compare(t1, t2):
+ if not t1 and not t2:
+ return True
+ if t1 == '*' or t2 == '*':
+ return True
+ return (t1 or '').strip() == (t2 or '').strip()
+
+
def stderr(*args):
if sys.version_info.major < 3:
file = codecs.getwriter('utf-8')(sys.stderr)
def unwrap_unique_or_non_null(unique_or_nonnull):
# BACKCOMPAT: rust 1.32
# https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+ # BACKCOMPAT: rust 1.60
+ # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
+ rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
struct NonZero<T>(T)
+ struct NonNull<T> { pointer: *const T }
"""
def __init__(self, valobj, dict):
<Item Name="[capacity]" ExcludeView="simple">buf.cap</Item>
<ArrayItems>
<Size>len</Size>
- <ValuePointer>buf.ptr.pointer</ValuePointer>
+ <ValuePointer>buf.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<If Condition="i == head">
<Break/>
</If>
- <Item>buf.ptr.pointer[i]</Item>
+ <Item>buf.ptr.pointer.pointer[i]</Item>
<Exec>i = (i + 1 == buf.cap ? 0 : i + 1)</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="alloc::string::String">
- <DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
- <StringView>(char*)vec.buf.ptr.pointer,[vec.len]s8</StringView>
+ <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
+ <StringView>(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8</StringView>
<Expand>
<Item Name="[len]" ExcludeView="simple">vec.len</Item>
<Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>
<Synthetic Name="[chars]">
- <DisplayString>{(char*)vec.buf.ptr.pointer,[vec.len]s8}</DisplayString>
+ <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
<Expand>
<ArrayItems>
<Size>vec.len</Size>
- <ValuePointer>(char*)vec.buf.ptr.pointer</ValuePointer>
+ <ValuePointer>(char*)vec.buf.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Synthetic>
</Type>
<Type Name="core::ptr::unique::Unique<*>">
- <DisplayString>Unique({(void*)pointer}: {pointer})</DisplayString>
+ <DisplayString>Unique({(void*)pointer.pointer}: {pointer.pointer})</DisplayString>
<Expand>
<ExpandedItem>pointer</ExpandedItem>
</Expand>
</Type>
<Type Name="std::ffi::os_str::OsString">
- <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+ <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
<Expand>
<Synthetic Name="[chars]">
- <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer,[inner.inner.bytes.len]}</DisplayString>
+ <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
<Expand>
<ArrayItems>
<Size>inner.inner.bytes.len</Size>
- <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer</ValuePointer>
+ <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Synthetic>
rustdoc-json-types = { path = "../rustdoc-json-types" }
tracing = "0.1"
tracing-tree = "0.2.0"
+once_cell = "1.10.0"
[dependencies.tracing-subscriber]
version = "0.3.3"
name: None,
attrs: Default::default(),
visibility: Inherited,
- def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
+ item_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
unsafety: hir::Unsafety::Normal,
generics: new_generics,
name: None,
attrs: Default::default(),
visibility: Inherited,
- def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
+ item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
unsafety: hir::Unsafety::Normal,
generics: clean_ty_generics(
pub(crate) fn render_long_html(&self) -> String {
let on = if self.should_use_with_in_description() { "with" } else { "on" };
- let mut msg = format!(
- "This is supported {} <strong>{}</strong>",
- on,
- Display(self, Format::LongHtml)
- );
+ let mut msg =
+ format!("Available {on} <strong>{}</strong>", Display(self, Format::LongHtml));
if self.should_append_only_to_description() {
msg.push_str(" only");
}
pub(crate) fn render_long_plain(&self) -> String {
let on = if self.should_use_with_in_description() { "with" } else { "on" };
- let mut msg = format!("This is supported {} {}", on, Display(self, Format::LongPlain));
+ let mut msg = format!("Available {on} {}", Display(self, Format::LongPlain));
if self.should_append_only_to_description() {
msg.push_str(" only");
}
#[test]
fn test_render_long_html() {
create_default_session_globals_then(|| {
- assert_eq!(
- word_cfg("unix").render_long_html(),
- "This is supported on <strong>Unix</strong> only."
- );
+ assert_eq!(word_cfg("unix").render_long_html(), "Available on <strong>Unix</strong> only.");
assert_eq!(
name_value_cfg("target_os", "macos").render_long_html(),
- "This is supported on <strong>macOS</strong> only."
+ "Available on <strong>macOS</strong> only."
);
assert_eq!(
name_value_cfg("target_os", "wasi").render_long_html(),
- "This is supported on <strong>WASI</strong> only."
+ "Available on <strong>WASI</strong> only."
);
assert_eq!(
name_value_cfg("target_pointer_width", "16").render_long_html(),
- "This is supported on <strong>16-bit</strong> only."
+ "Available on <strong>16-bit</strong> only."
);
assert_eq!(
name_value_cfg("target_endian", "little").render_long_html(),
- "This is supported on <strong>little-endian</strong> only."
+ "Available on <strong>little-endian</strong> only."
);
assert_eq!(
(!word_cfg("windows")).render_long_html(),
- "This is supported on <strong>non-Windows</strong> only."
+ "Available on <strong>non-Windows</strong> only."
);
assert_eq!(
(word_cfg("unix") & word_cfg("windows")).render_long_html(),
- "This is supported on <strong>Unix and Windows</strong> only."
+ "Available on <strong>Unix and Windows</strong> only."
);
assert_eq!(
(word_cfg("unix") | word_cfg("windows")).render_long_html(),
- "This is supported on <strong>Unix or Windows</strong> only."
+ "Available on <strong>Unix or Windows</strong> only."
);
assert_eq!(
(word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
.render_long_html(),
- "This is supported on <strong>Unix and Windows and debug-assertions enabled\
- </strong> only."
+ "Available on <strong>Unix and Windows and debug-assertions enabled</strong> only."
);
assert_eq!(
(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
.render_long_html(),
- "This is supported on <strong>Unix or Windows or debug-assertions enabled\
- </strong> only."
+ "Available on <strong>Unix or Windows or debug-assertions enabled</strong> only."
);
assert_eq!(
(!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
.render_long_html(),
- "This is supported on <strong>neither Unix nor Windows nor debug-assertions \
- enabled</strong>."
+ "Available on <strong>neither Unix nor Windows nor debug-assertions enabled</strong>."
);
assert_eq!(
((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
| (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
.render_long_html(),
- "This is supported on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
+ "Available on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
);
assert_eq!(
(!(word_cfg("unix") & word_cfg("windows"))).render_long_html(),
- "This is supported on <strong>not (Unix and Windows)</strong>."
+ "Available on <strong>not (Unix and Windows)</strong>."
);
assert_eq!(
((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
.render_long_html(),
- "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
- </strong> only."
+ "Available on <strong>(debug-assertions enabled or Windows) and Unix</strong> only."
);
assert_eq!(
name_value_cfg("target_feature", "sse2").render_long_html(),
- "This is supported with <strong>target feature <code>sse2</code></strong> only."
+ "Available with <strong>target feature <code>sse2</code></strong> only."
);
assert_eq!(
(name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
.render_long_html(),
- "This is supported on <strong>x86-64 and target feature \
- <code>sse2</code></strong> only."
+ "Available on <strong>x86-64 and target feature <code>sse2</code></strong> only."
);
})
}
items.push(clean::Item {
name: None,
attrs: box clean::Attributes::default(),
- def_id: ItemId::Primitive(prim_ty, did.krate),
+ item_id: ItemId::Primitive(prim_ty, did.krate),
visibility: clean::Public,
kind: box clean::ImportItem(clean::Import::new_simple(
item.ident.name,
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
// this is the ID of the `extern crate` statement
let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
// this is the ID of the crate itself
- let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+ let crate_def_id = cnum.as_def_id();
let attrs = cx.tcx.hir().attrs(krate.hir_id());
let ty_vis = cx.tcx.visibility(krate.def_id);
let please_inline = ty_vis.is_public()
vec![Item {
name: Some(name),
attrs: box attrs.clean(cx),
- def_id: crate_def_id.into(),
+ item_id: crate_def_id.into(),
visibility: ty_vis.clean(cx),
kind: box ExternCrateItem { src: orig_name },
cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
} else {
if inline_attr.is_none() {
if let Res::Def(DefKind::Mod, did) = path.res {
- if !did.is_local() && did.index == CRATE_DEF_INDEX {
+ if !did.is_local() && did.is_crate_root() {
// if we're `pub use`ing an extern crate root, don't inline it unless we
// were specifically asked for it
denied = true;
use std::cell::RefCell;
use std::default::Default;
-use std::fmt;
use std::hash::Hash;
-use std::iter;
use std::lazy::SyncOnceCell as OnceCell;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
-use std::vec;
+use std::{cmp, fmt, iter};
use arrayvec::ArrayVec;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{BodyId, Mutability};
use rustc_index::vec::IndexVec;
};
crate use self::Visibility::{Inherited, Public};
+#[cfg(test)]
+mod tests;
+
crate type ItemIdSet = FxHashSet<ItemId>;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
ItemId::Primitive(_, krate) => krate,
}
}
-
- #[inline]
- crate fn index(self) -> Option<DefIndex> {
- match self {
- ItemId::DefId(id) => Some(id.index),
- _ => None,
- }
- }
}
impl From<DefId> for ItemId {
#[inline]
crate fn def_id(&self) -> DefId {
- DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
+ self.crate_num.as_def_id()
}
crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
// Failing that, see if there's an attribute specifying where to find this
// external crate
- let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
+ let did = self.crate_num.as_def_id();
tcx.get_attrs(did)
.lists(sym::doc)
.filter(|a| a.has_name(sym::html_root_url))
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
crate kind: Box<ItemKind>,
- crate def_id: ItemId,
+ crate item_id: ItemId,
crate cfg: Option<Arc<Cfg>>,
}
let mut fmt = f.debug_struct("Item");
fmt.field("name", &self.name)
.field("visibility", &self.visibility)
- .field("def_id", &self.def_id);
+ .field("item_id", &self.item_id);
// allow printing the full item if someone really wants to
if alternate {
fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
impl Item {
crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
- self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
+ self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
}
crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
- self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
+ self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
}
crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
- self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
+ self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
}
crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
- self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
+ self.item_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
}
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
ItemKind::ModuleItem(Module { span, .. }) => *span,
ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
- if let ItemId::Blanket { impl_id, .. } = self.def_id {
+ if let ItemId::Blanket { impl_id, .. } = self.item_id {
rustc_span(impl_id, tcx)
} else {
panic!("blanket impl item has non-blanket ID")
}
}
_ => {
- self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+ self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
}
}
}
cx.tcx.visibility(def_id).clean(cx)
};
- Item { def_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
+ Item { item_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
}
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
cx.cache()
.intra_doc_links
- .get(&self.def_id)
+ .get(&self.item_id)
.map_or(&[][..], |v| v.as_slice())
.iter()
.filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
crate fn link_names(&self, cache: &Cache) -> Vec<RenderedLink> {
cache
.intra_doc_links
- .get(&self.def_id)
+ .get(&self.item_id)
.map_or(&[][..], |v| v.as_slice())
.iter()
.map(|ItemLink { link: s, link_text, .. }| RenderedLink {
}
crate fn is_crate(&self) -> bool {
- self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
+ self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.is_crate_root())
}
crate fn is_mod(&self) -> bool {
self.type_() == ItemType::Module
}
let header = match *self.kind {
ItemKind::ForeignFunctionItem(_) => {
- let abi = tcx.fn_sig(self.def_id.as_def_id().unwrap()).abi();
+ let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
hir::FnHeader {
unsafety: if abi == Abi::RustIntrinsic {
intrinsic_operation_unsafety(self.name.unwrap())
}
}
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) => {
- let def_id = self.def_id.as_def_id().unwrap();
+ let def_id = self.item_id.as_def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
}
ItemKind::TyMethodItem(_) => {
- build_fn_header(self.def_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
+ build_fn_header(self.item_id.as_def_id().unwrap(), tcx, hir::IsAsync::NotAsync)
}
_ => return None,
};
acc
}
+/// Removes excess indentation on comments in order for the Markdown
+/// to be parsed correctly. This is necessary because the convention for
+/// writing documentation is to provide a space between the /// or //! marker
+/// and the doc text, but Markdown is whitespace-sensitive. For example,
+/// a block of text with four-space indentation is parsed as a code block,
+/// so if we didn't unindent comments, these list items
+///
+/// /// A list:
+/// ///
+/// /// - Foo
+/// /// - Bar
+///
+/// would be parsed as if they were in a code block, which is likely not what the user intended.
+fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
+ // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
+ // fragments kind's lines are never starting with a whitespace unless they are using some
+ // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
+ // we need to take into account the fact that the minimum indent minus one (to take this
+ // whitespace into account).
+ //
+ // For example:
+ //
+ // /// hello!
+ // #[doc = "another"]
+ //
+ // In this case, you want "hello! another" and not "hello! another".
+ let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
+ && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
+ {
+ // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
+ // "decide" how much the minimum indent will be.
+ 1
+ } else {
+ 0
+ };
+
+ // `min_indent` is used to know how much whitespaces from the start of each lines must be
+ // removed. Example:
+ //
+ // /// hello!
+ // #[doc = "another"]
+ //
+ // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
+ // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
+ // (5 - 1) whitespaces.
+ let Some(min_indent) = docs
+ .iter()
+ .map(|fragment| {
+ fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
+ if line.chars().all(|c| c.is_whitespace()) {
+ min_indent
+ } else {
+ // Compare against either space or tab, ignoring whether they are
+ // mixed or not.
+ let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
+ cmp::min(min_indent, whitespace)
+ + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
+ }
+ })
+ })
+ .min()
+ else {
+ return;
+ };
+
+ for fragment in docs {
+ if fragment.doc == kw::Empty {
+ continue;
+ }
+
+ let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
+ min_indent - add
+ } else {
+ min_indent
+ };
+
+ fragment.indent = min_indent;
+ }
+}
+
/// A link that has not yet been rendered.
///
/// This link will be turned into a rendered link by [`Item::links`].
attrs: &[ast::Attribute],
additional_attrs: Option<(&[ast::Attribute], DefId)>,
) -> Attributes {
- let mut doc_strings: Vec<DocFragment> = vec![];
- let clean_attr = |(attr, parent_module): (&ast::Attribute, Option<DefId>)| {
- if let Some((value, kind)) = attr.doc_str_and_comment_kind() {
- trace!("got doc_str={:?}", value);
- let value = beautify_doc_string(value, kind);
+ // Additional documentation should be shown before the original documentation.
+ let attrs1 = additional_attrs
+ .into_iter()
+ .flat_map(|(attrs, def_id)| attrs.iter().map(move |attr| (attr, Some(def_id))));
+ let attrs2 = attrs.iter().map(|attr| (attr, None));
+ Attributes::from_ast_iter(attrs1.chain(attrs2), false)
+ }
+
+ crate fn from_ast_iter<'a>(
+ attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
+ doc_only: bool,
+ ) -> Attributes {
+ let mut doc_strings = Vec::new();
+ let mut other_attrs = Vec::new();
+ for (attr, parent_module) in attrs {
+ if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
+ trace!("got doc_str={doc_str:?}");
+ let doc = beautify_doc_string(doc_str, comment_kind);
let kind = if attr.is_doc_comment() {
DocFragmentKind::SugaredDoc
} else {
DocFragmentKind::RawDoc
};
-
- let frag =
- DocFragment { span: attr.span, doc: value, kind, parent_module, indent: 0 };
-
- doc_strings.push(frag);
-
- None
- } else {
- Some(attr.clone())
+ let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
+ doc_strings.push(fragment);
+ } else if !doc_only {
+ other_attrs.push(attr.clone());
}
- };
+ }
- // Additional documentation should be shown before the original documentation
- let other_attrs = additional_attrs
- .into_iter()
- .flat_map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
- .chain(attrs.iter().map(|attr| (attr, None)))
- .filter_map(clean_attr)
- .collect();
+ unindent_doc_fragments(&mut doc_strings);
Attributes { doc_strings, other_attrs }
}
}
/// Return the doc-comments on this item, grouped by the module they came from.
- ///
/// The module can be different if this is a re-export with added documentation.
- crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
- let mut ret = FxHashMap::default();
- if self.doc_strings.len() == 0 {
- return ret;
- }
- let last_index = self.doc_strings.len() - 1;
-
- for (i, new_frag) in self.doc_strings.iter().enumerate() {
- let out = ret.entry(new_frag.parent_module).or_default();
- add_doc_fragment(out, new_frag);
- if i == last_index {
- out.pop();
- }
+ ///
+ /// The last newline is not trimmed so the produced strings are reusable between
+ /// early and late doc link resolution regardless of their position.
+ crate fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
+ let mut res = FxHashMap::default();
+ for fragment in &self.doc_strings {
+ let out_str = res.entry(fragment.parent_module).or_default();
+ add_doc_fragment(out_str, fragment);
}
- ret
+ res
}
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
--- /dev/null
+use super::*;
+
+use crate::clean::collapse_doc_fragments;
+
+use rustc_span::create_default_session_globals_then;
+use rustc_span::source_map::DUMMY_SP;
+use rustc_span::symbol::Symbol;
+
+fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
+ vec![DocFragment {
+ span: DUMMY_SP,
+ parent_module: None,
+ doc: Symbol::intern(s),
+ kind: DocFragmentKind::SugaredDoc,
+ indent: 0,
+ }]
+}
+
+#[track_caller]
+fn run_test(input: &str, expected: &str) {
+ create_default_session_globals_then(|| {
+ let mut s = create_doc_fragment(input);
+ unindent_doc_fragments(&mut s);
+ assert_eq!(collapse_doc_fragments(&s), expected);
+ });
+}
+
+#[test]
+fn should_unindent() {
+ run_test(" line1\n line2", "line1\nline2");
+}
+
+#[test]
+fn should_unindent_multiple_paragraphs() {
+ run_test(" line1\n\n line2", "line1\n\nline2");
+}
+
+#[test]
+fn should_leave_multiple_indent_levels() {
+ // Line 2 is indented another level beyond the
+ // base indentation and should be preserved
+ run_test(" line1\n\n line2", "line1\n\n line2");
+}
+
+#[test]
+fn should_ignore_first_line_indent() {
+ run_test("line1\n line2", "line1\n line2");
+}
+
+#[test]
+fn should_not_ignore_first_line_indent_in_a_single_line_para() {
+ run_test("line1\n\n line2", "line1\n\n line2");
+}
+
+#[test]
+fn should_unindent_tabs() {
+ run_test("\tline1\n\tline2", "line1\nline2");
+}
+
+#[test]
+fn should_trim_mixed_indentation() {
+ run_test("\t line1\n\t line2", "line1\nline2");
+ run_test(" \tline1\n \tline2", "line1\nline2");
+}
+
+#[test]
+fn should_not_trim() {
+ run_test("\t line1 \n\t line2", "line1 \nline2");
+ run_test(" \tline1 \n \tline2", "line1 \nline2");
+}
// `#[doc(masked)]` to the injected `extern crate` because it's unstable.
if it.is_extern_crate()
&& (it.attrs.has_doc_flag(sym::masked)
- || cx.tcx.is_compiler_builtins(it.def_id.krate()))
+ || cx.tcx.is_compiler_builtins(it.item_id.krate()))
{
- cx.cache.masked_crates.insert(it.def_id.krate());
+ cx.cache.masked_crates.insert(it.item_id.krate());
}
}
}
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::json::JsonEmitter;
use rustc_feature::UnstableFeatures;
-use rustc_hir::def::Res;
+use rustc_hir::def::{Namespace, Res};
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path, TraitCandidate};
use crate::clean::{self, ItemId, TraitWithExtraInfo};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
+use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink;
use crate::passes::{self, Condition::*};
crate use rustc_session::config::{DebuggingOptions, Input, Options};
crate struct ResolverCaches {
+ crate markdown_links: Option<FxHashMap<String, Vec<PreprocessedMarkdownLink>>>,
+ crate doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<NodeId>>>,
/// Traits in scope for a given module.
/// See `collect_intra_doc_links::traits_implemented_by` for more details.
crate traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
/// (This avoids a slice-index-out-of-bounds panic.)
- crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
- match def_id {
+ crate fn as_local_hir_id(tcx: TyCtxt<'_>, item_id: ItemId) -> Option<HirId> {
+ match item_id {
ItemId::DefId(real_id) => {
real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
);
tcx.struct_lint_node(
crate::lint::MISSING_CRATE_LEVEL_DOCS,
- DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
+ DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
|lint| {
let mut diag =
lint.build("no documentation found for this crate's top-level module");
nested: F,
) {
let ast_attrs = self.tcx.hir().attrs(hir_id);
- let mut attrs = Attributes::from_ast(ast_attrs, None);
-
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) {
return;
self.collector.names.push(name);
}
- attrs.unindent_doc_comments();
// The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
// anything else, this will combine them for us.
+ let attrs = Attributes::from_ast(ast_attrs, None);
if let Some(doc) = attrs.collapsed_doc_value() {
// Use the outermost invocation, so that doctest names come from where the docs were written.
let span = ast_attrs
use std::mem;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::ty::TyCtxt;
use rustc_span::{sym, Symbol};
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
struct CacheBuilder<'a, 'tcx> {
cache: &'a mut Cache,
+ /// This field is used to prevent duplicated impl blocks.
+ impl_ids: FxHashMap<DefId, FxHashSet<DefId>>,
tcx: TyCtxt<'tcx>,
}
.insert(def_id, (vec![crate_name, prim.as_sym()], ItemType::Primitive));
}
- krate = CacheBuilder { tcx, cache: &mut cx.cache }.fold_crate(krate);
+ let (krate, mut impl_ids) = {
+ let mut cache_builder =
+ CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: FxHashMap::default() };
+ krate = cache_builder.fold_crate(krate);
+ (krate, cache_builder.impl_ids)
+ };
for (trait_did, dids, impl_) in cx.cache.orphan_trait_impls.drain(..) {
if cx.cache.traits.contains_key(&trait_did) {
for did in dids {
- cx.cache.impls.entry(did).or_default().push(impl_.clone());
+ if impl_ids.entry(did).or_default().insert(impl_.def_id()) {
+ cx.cache.impls.entry(did).or_default().push(impl_.clone());
+ }
}
}
}
impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
- if item.def_id.is_local() {
- debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
+ if item.item_id.is_local() {
+ debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.item_id);
}
// If this is a stripped module,
// If the impl is from a masked crate or references something from a
// masked crate then remove it completely.
if let clean::ImplItem(ref i) = *item.kind {
- if self.cache.masked_crates.contains(&item.def_id.krate())
+ if self.cache.masked_crates.contains(&item.item_id.krate())
|| i.trait_
.as_ref()
.map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate))
// Propagate a trait method's documentation to all implementors of the
// trait.
if let clean::TraitItem(ref t) = *item.kind {
- self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
+ self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
clean::TraitWithExtraInfo {
trait_: t.clone(),
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
// A crate has a module at its root, containing all items,
// which should not be indexed. The crate-item itself is
// inserted later on when serializing the search-index.
- if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
+ if item.item_id.as_def_id().map_or(false, |idx| !idx.is_crate_root()) {
let desc = item.doc_value().map_or_else(String::new, |x| {
short_markdown_summary(x.as_str(), &item.link_names(self.cache))
});
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
- if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
- || self.cache.access_levels.is_public(item.def_id.expect_def_id())
+ if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
+ || self.cache.access_levels.is_public(item.item_id.expect_def_id())
{
self.cache.paths.insert(
- item.def_id.expect_def_id(),
+ item.item_id.expect_def_id(),
(self.cache.stack.clone(), item.type_()),
);
}
clean::PrimitiveItem(..) => {
self.cache
.paths
- .insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
+ .insert(item.item_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
}
clean::ExternCrateItem { .. }
| clean::StructItem(..)
| clean::UnionItem(..)
| clean::VariantItem(..) => {
- self.cache.parent_stack.push(item.def_id.expect_def_id());
+ self.cache.parent_stack.push(item.item_id.expect_def_id());
self.cache.parent_is_trait_impl = false;
true
}
let impl_item = Impl { impl_item: item };
if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
for did in dids {
- self.cache.impls.entry(did).or_insert_with(Vec::new).push(impl_item.clone());
+ if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) {
+ self.cache
+ .impls
+ .entry(did)
+ .or_insert_with(Vec::new)
+ .push(impl_item.clone());
+ }
}
} else {
let trait_did = impl_item.trait_did().expect("no trait did");
crate use renderer::{run_format, FormatRenderer};
-use crate::clean;
+use crate::clean::{self, ItemId};
/// Specifies whether rendering directly implemented trait items or ones from a certain Deref
/// impl.
crate fn trait_did(&self) -> Option<DefId> {
self.inner_impl().trait_.as_ref().map(|t| t.def_id())
}
+
+ /// This function is used to extract a `DefId` to be used as a key for the `Cache::impls` field.
+ ///
+ /// It allows to prevent having duplicated implementations showing up (the biggest issue was
+ /// with blanket impls).
+ ///
+ /// It panics if `self` is a `ItemId::Primitive`.
+ crate fn def_id(&self) -> DefId {
+ match self.impl_item.item_id {
+ ItemId::Blanket { impl_id, .. } => impl_id,
+ ItemId::Auto { trait_, .. } => trait_,
+ ItemId::DefId(def_id) => def_id,
+ ItemId::Primitive(_, _) => {
+ panic!(
+ "Unexpected ItemId::Primitive in expect_def_id: {:?}",
+ self.impl_item.item_id
+ )
+ }
+ }
+ }
}
use rustc_middle::ty;
use rustc_middle::ty::DefIdTree;
use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::{sym, Symbol};
use rustc_target::spec::abi::Abi;
indent: usize,
end_newline: bool,
) -> impl fmt::Display + 'a + Captures<'tcx> {
+ use fmt::Write;
+
display_fn(move |f| {
let mut where_predicates = gens.where_predicates.iter().filter(|pred| {
!matches!(pred, clean::WherePredicate::BoundPredicate { bounds, .. } if bounds.is_empty())
match pred {
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
- let bounds = bounds;
- let for_prefix = if bound_params.is_empty() {
- String::new()
- } else if f.alternate() {
- format!(
- "for<{:#}> ",
- comma_sep(bound_params.iter().map(|lt| lt.print()), true)
- )
- } else {
- format!(
- "for<{}> ",
- comma_sep(bound_params.iter().map(|lt| lt.print()), true)
- )
- };
+ let ty_cx = ty.print(cx);
+ let generic_bounds = print_generic_bounds(bounds, cx);
- if f.alternate() {
- write!(
- f,
- "{}{:#}: {:#}",
- for_prefix,
- ty.print(cx),
- print_generic_bounds(bounds, cx)
- )
+ if bound_params.is_empty() {
+ if f.alternate() {
+ write!(f, "{ty_cx:#}: {generic_bounds:#}")
+ } else {
+ write!(f, "{ty_cx}: {generic_bounds}")
+ }
} else {
- write!(
- f,
- "{}{}: {}",
- for_prefix,
- ty.print(cx),
- print_generic_bounds(bounds, cx)
- )
+ if f.alternate() {
+ write!(
+ f,
+ "for<{:#}> {ty_cx:#}: {generic_bounds:#}",
+ comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+ )
+ } else {
+ write!(
+ f,
+ "for<{}> {ty_cx}: {generic_bounds}",
+ comma_sep(bound_params.iter().map(|lt| lt.print()), true)
+ )
+ }
}
}
clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
- write!(
- f,
- "{}: {}",
- lifetime.print(),
- bounds
- .iter()
- .map(|b| b.print(cx).to_string())
- .collect::<Vec<_>>()
- .join(" + ")
- )
+ let mut bounds_display = String::new();
+ for bound in bounds.iter().map(|b| b.print(cx)) {
+ write!(bounds_display, "{bound} + ")?;
+ }
+ bounds_display.truncate(bounds_display.len() - " + ".len());
+ write!(f, "{}: {bounds_display}", lifetime.print())
}
clean::WherePredicate::EqPredicate { lhs, rhs } => {
if f.alternate() {
- write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx),)
+ write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
} else {
- write!(f, "{} == {}", lhs.print(cx), rhs.print(cx),)
+ write!(f, "{} == {}", lhs.print(cx), rhs.print(cx))
}
}
}
return Ok(());
}
- let mut clause = String::new();
-
- if f.alternate() {
- clause.push_str(" where");
- } else {
+ let where_preds = comma_sep(where_predicates, false);
+ let clause = if f.alternate() {
if end_newline {
- clause.push_str(" <span class=\"where fmt-newline\">where");
+ // add a space so stripping <br> tags and breaking spaces still renders properly
+ format!(" where{where_preds}, ")
} else {
- clause.push_str(" <span class=\"where\">where");
+ format!(" where{where_preds}")
}
- }
-
- clause.push_str(&comma_sep(where_predicates, false).to_string());
-
- if end_newline {
- clause.push(',');
- // add a space so stripping <br> tags and breaking spaces still renders properly
- if f.alternate() {
- clause.push(' ');
- } else {
- clause.push_str(" ");
+ } else {
+ let mut br_with_padding = String::with_capacity(6 * indent + 28);
+ br_with_padding.push_str("<br>");
+ for _ in 0..indent + 4 {
+ br_with_padding.push_str(" ");
}
- }
+ let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
- if !f.alternate() {
- clause.push_str("</span>");
- let padding = " ".repeat(indent + 4);
- clause = clause.replace("<br>", &format!("<br>{}", padding));
- clause.insert_str(0, &" ".repeat(indent.saturating_sub(1)));
- if !end_newline {
- clause.insert_str(0, "<br>");
+ if end_newline {
+ let mut clause = " ".repeat(indent.saturating_sub(1));
+ // add a space so stripping <br> tags and breaking spaces still renders properly
+ write!(
+ clause,
+ " <span class=\"where fmt-newline\">where{where_preds}, </span>"
+ )?;
+ clause
+ } else {
+ // insert a <br> tag after a single space but before multiple spaces at the start
+ if indent == 0 {
+ format!(" <br><span class=\"where\">where{where_preds}</span>")
+ } else {
+ let mut clause = br_with_padding;
+ clause.truncate(clause.len() - 5 * " ".len());
+ write!(clause, " <span class=\"where\">where{where_preds}</span>")?;
+ clause
+ }
}
- }
- write!(f, "{}", clause)
+ };
+ write!(f, "{clause}")
})
}
// visibility, so it shouldn't matter.
let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
- if vis_did.index == CRATE_DEF_INDEX {
+ if vis_did.is_crate_root() {
"pub(crate) ".to_owned()
} else if parent_module == Some(vis_did) {
// `pub(in foo)` where `foo` is the parent module
// visibility, so it shouldn't matter.
let parent_module = find_nearest_parent_module(tcx, item_did);
- if vis_did.index == CRATE_DEF_INDEX {
+ if vis_did.is_crate_root() {
"pub(crate) ".to_owned()
} else if parent_module == Some(vis_did) {
// `pub(in foo)` where `foo` is the parent module
use rustc_span::edition::Edition;
use rustc_span::Span;
+use once_cell::sync::Lazy;
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::VecDeque;
pub range: Range<usize>,
}
-crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
+crate fn markdown_links<R>(md: &str, filter_map: impl Fn(MarkdownLink) -> Option<R>) -> Vec<R> {
if md.is_empty() {
return vec![];
}
let mut push = |link: BrokenLink<'_>| {
let span = span_for_link(&link.reference, link.span);
- links.borrow_mut().push(MarkdownLink {
+ filter_map(MarkdownLink {
kind: LinkType::ShortcutUnknown,
link: link.reference.to_string(),
range: span,
- });
+ })
+ .map(|link| links.borrow_mut().push(link));
None
};
let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push))
let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1));
for ev in iter {
- if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 {
+ if let Event::Start(Tag::Link(
+ // `<>` links cannot be intra-doc links so we skip them.
+ kind @ (LinkType::Inline
+ | LinkType::Reference
+ | LinkType::ReferenceUnknown
+ | LinkType::Collapsed
+ | LinkType::CollapsedUnknown
+ | LinkType::Shortcut
+ | LinkType::ShortcutUnknown),
+ dest,
+ _,
+ )) = ev.0
+ {
debug!("found link: {dest}");
let span = span_for_link(&dest, ev.1);
- links.borrow_mut().push(MarkdownLink { kind, link: dest.into_string(), range: span });
+ filter_map(MarkdownLink { kind, link: dest.into_string(), range: span })
+ .map(|link| links.borrow_mut().push(link));
}
}
#[derive(Clone, Default, Debug)]
pub struct IdMap {
- map: FxHashMap<String, usize>,
+ map: FxHashMap<Cow<'static, str>, usize>,
}
-fn init_id_map() -> FxHashMap<String, usize> {
+// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
+static DEFAULT_ID_MAP: Lazy<FxHashMap<Cow<'static, str>, usize>> = Lazy::new(|| init_id_map());
+
+fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
let mut map = FxHashMap::default();
// This is the list of IDs used in Javascript.
- map.insert("help".to_owned(), 1);
+ map.insert("help".into(), 1);
// This is the list of IDs used in HTML generated in Rust (including the ones
// used in tera template files).
- map.insert("mainThemeStyle".to_owned(), 1);
- map.insert("themeStyle".to_owned(), 1);
- map.insert("theme-picker".to_owned(), 1);
- map.insert("theme-choices".to_owned(), 1);
- map.insert("settings-menu".to_owned(), 1);
- map.insert("help-button".to_owned(), 1);
- map.insert("main-content".to_owned(), 1);
- map.insert("search".to_owned(), 1);
- map.insert("crate-search".to_owned(), 1);
- map.insert("render-detail".to_owned(), 1);
- map.insert("toggle-all-docs".to_owned(), 1);
- map.insert("all-types".to_owned(), 1);
- map.insert("default-settings".to_owned(), 1);
- map.insert("rustdoc-vars".to_owned(), 1);
- map.insert("sidebar-vars".to_owned(), 1);
- map.insert("copy-path".to_owned(), 1);
- map.insert("TOC".to_owned(), 1);
+ map.insert("mainThemeStyle".into(), 1);
+ map.insert("themeStyle".into(), 1);
+ map.insert("theme-picker".into(), 1);
+ map.insert("theme-choices".into(), 1);
+ map.insert("settings-menu".into(), 1);
+ map.insert("help-button".into(), 1);
+ map.insert("main-content".into(), 1);
+ map.insert("search".into(), 1);
+ map.insert("crate-search".into(), 1);
+ map.insert("render-detail".into(), 1);
+ map.insert("toggle-all-docs".into(), 1);
+ map.insert("all-types".into(), 1);
+ map.insert("default-settings".into(), 1);
+ map.insert("rustdoc-vars".into(), 1);
+ map.insert("sidebar-vars".into(), 1);
+ map.insert("copy-path".into(), 1);
+ map.insert("TOC".into(), 1);
// This is the list of IDs used by rustdoc sections (but still generated by
// rustdoc).
- map.insert("fields".to_owned(), 1);
- map.insert("variants".to_owned(), 1);
- map.insert("implementors-list".to_owned(), 1);
- map.insert("synthetic-implementors-list".to_owned(), 1);
- map.insert("foreign-impls".to_owned(), 1);
- map.insert("implementations".to_owned(), 1);
- map.insert("trait-implementations".to_owned(), 1);
- map.insert("synthetic-implementations".to_owned(), 1);
- map.insert("blanket-implementations".to_owned(), 1);
- map.insert("required-associated-types".to_owned(), 1);
- map.insert("provided-associated-types".to_owned(), 1);
- map.insert("provided-associated-consts".to_owned(), 1);
- map.insert("required-associated-consts".to_owned(), 1);
- map.insert("required-methods".to_owned(), 1);
- map.insert("provided-methods".to_owned(), 1);
- map.insert("implementors".to_owned(), 1);
- map.insert("synthetic-implementors".to_owned(), 1);
- map.insert("implementations-list".to_owned(), 1);
- map.insert("trait-implementations-list".to_owned(), 1);
- map.insert("synthetic-implementations-list".to_owned(), 1);
- map.insert("blanket-implementations-list".to_owned(), 1);
- map.insert("deref-methods".to_owned(), 1);
+ map.insert("fields".into(), 1);
+ map.insert("variants".into(), 1);
+ map.insert("implementors-list".into(), 1);
+ map.insert("synthetic-implementors-list".into(), 1);
+ map.insert("foreign-impls".into(), 1);
+ map.insert("implementations".into(), 1);
+ map.insert("trait-implementations".into(), 1);
+ map.insert("synthetic-implementations".into(), 1);
+ map.insert("blanket-implementations".into(), 1);
+ map.insert("required-associated-types".into(), 1);
+ map.insert("provided-associated-types".into(), 1);
+ map.insert("provided-associated-consts".into(), 1);
+ map.insert("required-associated-consts".into(), 1);
+ map.insert("required-methods".into(), 1);
+ map.insert("provided-methods".into(), 1);
+ map.insert("implementors".into(), 1);
+ map.insert("synthetic-implementors".into(), 1);
+ map.insert("implementations-list".into(), 1);
+ map.insert("trait-implementations-list".into(), 1);
+ map.insert("synthetic-implementations-list".into(), 1);
+ map.insert("blanket-implementations-list".into(), 1);
+ map.insert("deref-methods".into(), 1);
map
}
impl IdMap {
pub fn new() -> Self {
- IdMap { map: init_id_map() }
+ IdMap { map: DEFAULT_ID_MAP.clone() }
}
crate fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
}
};
- self.map.insert(id.clone(), 1);
+ self.map.insert(id.clone().into(), 1);
id
}
}
&self.shared.style_files,
)
} else {
- if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
+ if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
if self.current.len() + 1 != names.len()
|| self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
{
w,
"{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}",
extra = extra,
- vis = it.visibility.print_with_space(it.def_id, cx),
+ vis = it.visibility.print_with_space(it.item_id, cx),
href = assoc_href_attr(it, link, cx),
name = it.name.as_ref().unwrap(),
ty = ty.print(cx),
) {
let header = meth.fn_header(cx.tcx()).expect("Trying to get header from a non-function item");
let name = meth.name.as_ref().unwrap();
- let vis = meth.visibility.print_with_space(meth.def_id, cx).to_string();
+ let vis = meth.visibility.print_with_space(meth.item_id, cx).to_string();
// FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
// this condition.
let constness = match render_mode {
}
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
- let did = it.def_id.expect_def_id();
+ let did = it.item_id.expect_def_id();
let cache = cx.cache();
if let Some(v) = cache.impls.get(&did) {
);
let cache = cx.cache();
- if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
+ if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
let mut res = implementors
.iter()
.filter(|i| {
/// Generates the HTML for example call locations generated via the --scrape-examples flag.
fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
let tcx = cx.tcx();
- let def_id = item.def_id.expect_def_id();
+ let def_id = item.item_id.expect_def_id();
let key = tcx.def_path_hash(def_id);
let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
// (which is the position in the vector).
indices.dedup_by_key(|i| {
(
- items[*i].def_id,
+ items[*i].item_id,
if items[*i].name.is_some() { Some(full_path(cx, &items[*i])) } else { None },
items[*i].type_(),
if items[*i].is_import() { *i } else { 0 },
Some(src) => write!(
w,
"<div class=\"item-left\"><code>{}extern crate {} as {};",
- myitem.visibility.print_with_space(myitem.def_id, cx),
- anchor(myitem.def_id.expect_def_id(), src, cx),
+ myitem.visibility.print_with_space(myitem.item_id, cx),
+ anchor(myitem.item_id.expect_def_id(), src, cx),
myitem.name.unwrap(),
),
None => write!(
w,
"<div class=\"item-left\"><code>{}extern crate {};",
- myitem.visibility.print_with_space(myitem.def_id, cx),
- anchor(myitem.def_id.expect_def_id(), myitem.name.unwrap(), cx),
+ myitem.visibility.print_with_space(myitem.item_id, cx),
+ anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
),
}
w.write_str("</code></div>");
// Just need an item with the correct def_id and attrs
let import_item = clean::Item {
- def_id: import_def_id.into(),
+ item_id: import_def_id.into(),
attrs: import_attrs,
cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg),
..myitem.clone()
<div class=\"item-right docblock-short\">{stab_tags}</div>",
stab = stab.unwrap_or_default(),
add = add,
- vis = myitem.visibility.print_with_space(myitem.def_id, cx),
+ vis = myitem.visibility.print_with_space(myitem.item_id, cx),
imp = import.print(cx),
stab_tags = stab_tags.unwrap_or_default(),
);
let unsafety = header.unsafety.print_with_space();
let abi = print_abi_with_space(header.abi).to_string();
let asyncness = header.asyncness.print_with_space();
- let visibility = it.visibility.print_with_space(it.def_id, cx).to_string();
+ let visibility = it.visibility.print_with_space(it.item_id, cx).to_string();
let name = it.name.unwrap();
let generics_len = format!("{:#}", f.generics.print(cx)).len();
write!(
w,
"{}{}{}trait {}{}{}",
- it.visibility.print_with_space(it.def_id, cx),
+ it.visibility.print_with_space(it.item_id, cx),
t.unsafety.print_with_space(),
if t.is_auto { "auto " } else { "" },
it.name.unwrap(),
}
// If there are methods directly on this trait object, render them here.
- render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
+ render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
let cache = cx.cache();
- if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
+ if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
// The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
for implementor in foreign {
let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx());
let assoc_link =
- AssocItemLink::GotoSource(implementor.impl_item.def_id, &provided_methods);
+ AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
render_impl(
w,
cx,
.take(cx.current.len())
.chain(std::iter::once("implementors"))
.collect();
- if it.def_id.is_local() {
+ if it.item_id.is_local() {
js_src_path.extend(cx.current.iter().copied());
} else {
- let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
+ let (ref path, _) = cache.external_paths[&it.item_id.expect_def_id()];
js_src_path.extend(path[..path.len() - 1].iter().copied());
}
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
- render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
}
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
- render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
}
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
wrap_item(w, "typedef", |w| {
render_attributes_in_pre(w, it, "");
- write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
+ write!(w, "{}", it.visibility.print_with_space(it.item_id, cx));
write!(
w,
"type {}{}{where_clause} = {type_};",
document(w, cx, it, None, HeadingOffset::H2);
- let def_id = it.def_id.expect_def_id();
+ let def_id = it.item_id.expect_def_id();
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
document(w, cx, field, Some(it), HeadingOffset::H3);
}
}
- let def_id = it.def_id.expect_def_id();
+ let def_id = it.item_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
write!(
w,
"{}enum {}{}{}",
- it.visibility.print_with_space(it.def_id, cx),
+ it.visibility.print_with_space(it.item_id, cx),
it.name.unwrap(),
e.generics.print(cx),
print_where_clause(&e.generics, cx, 0, true),
document(w, cx, variant, Some(it), HeadingOffset::H4);
}
}
- let def_id = it.def_id.expect_def_id();
+ let def_id = it.item_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None, HeadingOffset::H2);
- render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
}
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
write!(
w,
"{vis}const {name}: {typ}",
- vis = it.visibility.print_with_space(it.def_id, cx),
+ vis = it.visibility.print_with_space(it.item_id, cx),
name = it.name.unwrap(),
typ = c.type_.print(cx),
);
}
}
}
- let def_id = it.def_id.expect_def_id();
+ let def_id = it.item_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
write!(
w,
"{vis}static {mutability}{name}: {typ}",
- vis = it.visibility.print_with_space(it.def_id, cx),
+ vis = it.visibility.print_with_space(it.item_id, cx),
mutability = s.mutability.print_with_space(),
name = it.name.unwrap(),
typ = s.type_.print(cx)
write!(
w,
" {}type {};\n}}",
- it.visibility.print_with_space(it.def_id, cx),
+ it.visibility.print_with_space(it.item_id, cx),
it.name.unwrap(),
);
});
document(w, cx, it, None, HeadingOffset::H2);
- render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
+ render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
}
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
tab: &str,
cx: &Context<'_>,
) {
- write!(w, "{}union {}", it.visibility.print_with_space(it.def_id, cx), it.name.unwrap());
+ write!(w, "{}union {}", it.visibility.print_with_space(it.item_id, cx), it.name.unwrap());
if let Some(g) = g {
write!(w, "{}", g.print(cx));
write!(w, "{}", print_where_clause(g, cx, 0, true));
write!(
w,
" {}{}: {},\n{}",
- field.visibility.print_with_space(field.def_id, cx),
+ field.visibility.print_with_space(field.item_id, cx),
field.name.unwrap(),
ty.print(cx),
tab
write!(
w,
"{}{}{}",
- it.visibility.print_with_space(it.def_id, cx),
+ it.visibility.print_with_space(it.item_id, cx),
if structhead { "struct " } else { "" },
it.name.unwrap()
);
w,
"\n{} {}{}: {},",
tab,
- field.visibility.print_with_space(field.def_id, cx),
+ field.visibility.print_with_space(field.item_id, cx),
field.name.unwrap(),
ty.print(cx),
);
write!(
w,
"{}{}",
- field.visibility.print_with_space(field.def_id, cx),
+ field.visibility.print_with_space(field.item_id, cx),
ty.print(cx),
)
}
//
// If the implementation is from another crate then that crate
// should add it.
- if imp.impl_item.def_id.krate() == did.krate || !imp.impl_item.def_id.is_local() {
+ if imp.impl_item.item_id.krate() == did.krate || !imp.impl_item.item_id.is_local() {
None
} else {
Some(Implementor {
/**
* @typedef {{
- * raw: string,
- * query: string,
- * type: string,
- * id: string,
+ * name: string,
+ * fullPath: Array<string>,
+ * pathWithoutLast: Array<string>,
+ * pathLast: string,
+ * generics: Array<QueryElement>,
+ * }}
+ */
+var QueryElement;
+
+/**
+ * @typedef {{
+ * pos: number,
+ * totalElems: number,
+ * typeFilter: (null|string),
+ * userQuery: string,
+ * }}
+ */
+var ParserState;
+
+/**
+ * @typedef {{
+ * original: string,
+ * userQuery: string,
+ * typeFilter: number,
+ * elems: Array<QueryElement>,
+ * args: Array<QueryElement>,
+ * returned: Array<QueryElement>,
+ * foundElems: number,
* }}
*/
var ParsedQuery;
* }}
*/
var Row;
+
+/**
+ * @typedef {{
+ * in_args: Array<Object>,
+ * returned: Array<Object>,
+ * others: Array<Object>,
+ * query: ParsedQuery,
+ * }}
+ */
+var ResultsTable;
+
+/**
+ * @typedef {{
+ * desc: string,
+ * displayPath: string,
+ * fullPath: string,
+ * href: string,
+ * id: number,
+ * lev: number,
+ * name: string,
+ * normalizedName: string,
+ * parent: (Object|undefined),
+ * path: string,
+ * ty: number,
+ * }}
+ */
+var Results;
});
}
-function removeEmptyStringsFromArray(x) {
- for (var i = 0, len = x.length; i < len; ++i) {
- if (x[i] === "") {
- x.splice(i, 1);
- i -= 1;
- }
- }
-}
-
/**
* A function to compute the Levenshtein distance between two strings
* Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
searchState.input.value = params.search || "";
}
+ function isWhitespace(c) {
+ return " \t\n\r".indexOf(c) !== -1;
+ }
+
+ function isSpecialStartCharacter(c) {
+ return "<\"".indexOf(c) !== -1;
+ }
+
+ function isEndCharacter(c) {
+ return ",>-".indexOf(c) !== -1;
+ }
+
+ function isStopCharacter(c) {
+ return isWhitespace(c) || isEndCharacter(c);
+ }
+
+ function isErrorCharacter(c) {
+ return "()".indexOf(c) !== -1;
+ }
+
+ function itemTypeFromName(typename) {
+ for (var i = 0, len = itemTypes.length; i < len; ++i) {
+ if (itemTypes[i] === typename) {
+ return i;
+ }
+ }
+
+ throw new Error("Unknown type filter `" + typename + "`");
+ }
+
+ /**
+ * If we encounter a `"`, then we try to extract the string from it until we find another `"`.
+ *
+ * This function will throw an error in the following cases:
+ * * There is already another string element.
+ * * We are parsing a generic argument.
+ * * There is more than one element.
+ * * There is no closing `"`.
+ *
+ * @param {ParsedQuery} query
+ * @param {ParserState} parserState
+ * @param {boolean} isInGenerics
+ */
+ function getStringElem(query, parserState, isInGenerics) {
+ if (isInGenerics) {
+ throw new Error("`\"` cannot be used in generics");
+ } else if (query.literalSearch) {
+ throw new Error("Cannot have more than one literal search element");
+ } else if (parserState.totalElems - parserState.genericsElems > 0) {
+ throw new Error("Cannot use literal search when there is more than one element");
+ }
+ parserState.pos += 1;
+ var start = parserState.pos;
+ var end = getIdentEndPosition(parserState);
+ if (parserState.pos >= parserState.length) {
+ throw new Error("Unclosed `\"`");
+ } else if (parserState.userQuery[end] !== "\"") {
+ throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
+ } else if (start === end) {
+ throw new Error("Cannot have empty string element");
+ }
+ // To skip the quote at the end.
+ parserState.pos += 1;
+ query.literalSearch = true;
+ }
+
+ /**
+ * Returns `true` if the current parser position is starting with "::".
+ *
+ * @param {ParserState} parserState
+ *
+ * @return {boolean}
+ */
+ function isPathStart(parserState) {
+ return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '::';
+ }
+
+ /**
+ * Returns `true` if the current parser position is starting with "->".
+ *
+ * @param {ParserState} parserState
+ *
+ * @return {boolean}
+ */
+ function isReturnArrow(parserState) {
+ return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '->';
+ }
+
+ /**
+ * Returns `true` if the given `c` character is valid for an ident.
+ *
+ * @param {string} c
+ *
+ * @return {boolean}
+ */
+ function isIdentCharacter(c) {
+ return (
+ c === '_' ||
+ (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z'));
+ }
+
+ /**
+ * Returns `true` if the given `c` character is a separator.
+ *
+ * @param {string} c
+ *
+ * @return {boolean}
+ */
+ function isSeparatorCharacter(c) {
+ return c === "," || isWhitespaceCharacter(c);
+ }
+
+ /**
+ * Returns `true` if the given `c` character is a whitespace.
+ *
+ * @param {string} c
+ *
+ * @return {boolean}
+ */
+ function isWhitespaceCharacter(c) {
+ return c === " " || c === "\t";
+ }
+
+ /**
+ * @param {ParsedQuery} query
+ * @param {ParserState} parserState
+ * @param {string} name - Name of the query element.
+ * @param {Array<QueryElement>} generics - List of generics of this query element.
+ *
+ * @return {QueryElement} - The newly created `QueryElement`.
+ */
+ function createQueryElement(query, parserState, name, generics, isInGenerics) {
+ if (name === '*' || (name.length === 0 && generics.length === 0)) {
+ return;
+ }
+ if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
+ throw new Error("You cannot have more than one element if you use quotes");
+ }
+ var pathSegments = name.split("::");
+ if (pathSegments.length > 1) {
+ for (var i = 0, len = pathSegments.length; i < len; ++i) {
+ var pathSegment = pathSegments[i];
+
+ if (pathSegment.length === 0) {
+ if (i === 0) {
+ throw new Error("Paths cannot start with `::`");
+ } else if (i + 1 === len) {
+ throw new Error("Paths cannot end with `::`");
+ }
+ throw new Error("Unexpected `::::`");
+ }
+ }
+ }
+ // In case we only have something like `<p>`, there is no name.
+ if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
+ throw new Error("Found generics without a path");
+ }
+ parserState.totalElems += 1;
+ if (isInGenerics) {
+ parserState.genericsElems += 1;
+ }
+ return {
+ name: name,
+ fullPath: pathSegments,
+ pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
+ pathLast: pathSegments[pathSegments.length - 1],
+ generics: generics,
+ };
+ }
+
+ /**
+ * This function goes through all characters until it reaches an invalid ident character or the
+ * end of the query. It returns the position of the last character of the ident.
+ *
+ * @param {ParserState} parserState
+ *
+ * @return {integer}
+ */
+ function getIdentEndPosition(parserState) {
+ var end = parserState.pos;
+ while (parserState.pos < parserState.length) {
+ var c = parserState.userQuery[parserState.pos];
+ if (!isIdentCharacter(c)) {
+ if (isErrorCharacter(c)) {
+ throw new Error(`Unexpected \`${c}\``);
+ } else if (
+ isStopCharacter(c) ||
+ isSpecialStartCharacter(c) ||
+ isSeparatorCharacter(c))
+ {
+ break;
+ }
+ // If we allow paths ("str::string" for example).
+ else if (c === ":") {
+ if (!isPathStart(parserState)) {
+ break;
+ }
+ // Skip current ":".
+ parserState.pos += 1;
+ } else {
+ throw new Error(`Unexpected \`${c}\``);
+ }
+ }
+ parserState.pos += 1;
+ end = parserState.pos;
+ }
+ return end;
+ }
+
+ /**
+ * @param {ParsedQuery} query
+ * @param {ParserState} parserState
+ * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
+ * @param {boolean} isInGenerics
+ */
+ function getNextElem(query, parserState, elems, isInGenerics) {
+ var generics = [];
+
+ var start = parserState.pos;
+ var end;
+ // We handle the strings on their own mostly to make code easier to follow.
+ if (parserState.userQuery[parserState.pos] === "\"") {
+ start += 1;
+ getStringElem(query, parserState, isInGenerics);
+ end = parserState.pos - 1;
+ } else {
+ end = getIdentEndPosition(parserState);
+ }
+ if (parserState.pos < parserState.length &&
+ parserState.userQuery[parserState.pos] === "<")
+ {
+ if (isInGenerics) {
+ throw new Error("Unexpected `<` after `<`");
+ } else if (start >= end) {
+ throw new Error("Found generics without a path");
+ }
+ parserState.pos += 1;
+ getItemsBefore(query, parserState, generics, ">");
+ }
+ if (start >= end && generics.length === 0) {
+ return;
+ }
+ elems.push(
+ createQueryElement(
+ query,
+ parserState,
+ parserState.userQuery.slice(start, end),
+ generics,
+ isInGenerics
+ )
+ );
+ }
+
+ /**
+ * This function parses the next query element until it finds `endChar`, calling `getNextElem`
+ * to collect each element.
+ *
+ * If there is no `endChar`, this function will implicitly stop at the end without raising an
+ * error.
+ *
+ * @param {ParsedQuery} query
+ * @param {ParserState} parserState
+ * @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
+ * @param {string} endChar - This function will stop when it'll encounter this
+ * character.
+ */
+ function getItemsBefore(query, parserState, elems, endChar) {
+ var foundStopChar = true;
+
+ while (parserState.pos < parserState.length) {
+ var c = parserState.userQuery[parserState.pos];
+ if (c === endChar) {
+ break;
+ } else if (isSeparatorCharacter(c)) {
+ parserState.pos += 1;
+ foundStopChar = true;
+ continue;
+ } else if (c === ":" && isPathStart(parserState)) {
+ throw new Error("Unexpected `::`: paths cannot start with `::`");
+ } else if (c === ":" || isEndCharacter(c)) {
+ var extra = "";
+ if (endChar === ">") {
+ extra = "`<`";
+ } else if (endChar === "") {
+ extra = "`->`";
+ }
+ throw new Error("Unexpected `" + c + "` after " + extra);
+ }
+ if (!foundStopChar) {
+ if (endChar !== "") {
+ throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
+ }
+ throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
+ }
+ var posBefore = parserState.pos;
+ getNextElem(query, parserState, elems, endChar === ">");
+ // This case can be encountered if `getNextElem` encounted a "stop character" right from
+ // the start. For example if you have `,,` or `<>`. In this case, we simply move up the
+ // current position to continue the parsing.
+ if (posBefore === parserState.pos) {
+ parserState.pos += 1;
+ }
+ foundStopChar = false;
+ }
+ // We are either at the end of the string or on the `endChar`` character, let's move forward
+ // in any case.
+ parserState.pos += 1;
+ }
+
+ /**
+ * Checks that the type filter doesn't have unwanted characters like `<>` (which are ignored
+ * if empty).
+ *
+ * @param {ParserState} parserState
+ */
+ function checkExtraTypeFilterCharacters(parserState) {
+ var query = parserState.userQuery;
+
+ for (var pos = 0; pos < parserState.pos; ++pos) {
+ if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
+ throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
+ }
+ }
+ }
+
+ /**
+ * Parses the provided `query` input to fill `parserState`. If it encounters an error while
+ * parsing `query`, it'll throw an error.
+ *
+ * @param {ParsedQuery} query
+ * @param {ParserState} parserState
+ */
+ function parseInput(query, parserState) {
+ var c, before;
+ var foundStopChar = true;
+
+ while (parserState.pos < parserState.length) {
+ c = parserState.userQuery[parserState.pos];
+ if (isStopCharacter(c)) {
+ foundStopChar = true;
+ if (isSeparatorCharacter(c)) {
+ parserState.pos += 1;
+ continue;
+ } else if (c === "-" || c === ">") {
+ if (isReturnArrow(parserState)) {
+ break;
+ }
+ throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
+ }
+ throw new Error(`Unexpected \`${c}\``);
+ } else if (c === ":" && !isPathStart(parserState)) {
+ if (parserState.typeFilter !== null) {
+ throw new Error("Unexpected `:`");
+ }
+ if (query.elems.length === 0) {
+ throw new Error("Expected type filter before `:`");
+ } else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
+ throw new Error("Unexpected `:`");
+ } else if (query.literalSearch) {
+ throw new Error("You cannot use quotes on type filter");
+ }
+ checkExtraTypeFilterCharacters(parserState);
+ // The type filter doesn't count as an element since it's a modifier.
+ parserState.typeFilter = query.elems.pop().name;
+ parserState.pos += 1;
+ parserState.totalElems = 0;
+ query.literalSearch = false;
+ foundStopChar = true;
+ continue;
+ }
+ if (!foundStopChar) {
+ if (parserState.typeFilter !== null) {
+ throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
+ }
+ throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
+ }
+ before = query.elems.length;
+ getNextElem(query, parserState, query.elems, false);
+ if (query.elems.length === before) {
+ // Nothing was added, weird... Let's increase the position to not remain stuck.
+ parserState.pos += 1;
+ }
+ foundStopChar = false;
+ }
+ while (parserState.pos < parserState.length) {
+ c = parserState.userQuery[parserState.pos];
+ if (isReturnArrow(parserState)) {
+ parserState.pos += 2;
+ // Get returned elements.
+ getItemsBefore(query, parserState, query.returned, "");
+ // Nothing can come afterward!
+ if (query.returned.length === 0) {
+ throw new Error("Expected at least one item after `->`");
+ }
+ break;
+ } else {
+ parserState.pos += 1;
+ }
+ }
+ }
+
+ /**
+ * Takes the user search input and returns an empty `ParsedQuery`.
+ *
+ * @param {string} userQuery
+ *
+ * @return {ParsedQuery}
+ */
+ function newParsedQuery(userQuery) {
+ return {
+ original: userQuery,
+ userQuery: userQuery.toLowerCase(),
+ typeFilter: NO_TYPE_FILTER,
+ elems: [],
+ returned: [],
+ // Total number of "top" elements (does not include generics).
+ foundElems: 0,
+ literalSearch: false,
+ error: null,
+ };
+ }
+
/**
* Build an URL with search parameters.
*
* @param {string} search - The current search being performed.
* @param {string|null} filterCrates - The current filtering crate (if any).
+ *
* @return {string}
*/
function buildUrl(search, filterCrates) {
}
/**
- * Executes the query and returns a list of results for each results tab.
- * @param {Object} query - The user query
- * @param {Array<string>} searchWords - The list of search words to query against
- * @param {string} [filterCrates] - Crate to search in
- * @return {{
- * in_args: Array<?>,
- * returned: Array<?>,
- * others: Array<?>
- * }}
+ * Parses the query.
+ *
+ * The supported syntax by this parser is as follow:
+ *
+ * ident = *(ALPHA / DIGIT / "_")
+ * path = ident *(DOUBLE-COLON ident)
+ * arg = path [generics]
+ * arg-without-generic = path
+ * type-sep = COMMA/WS *(COMMA/WS)
+ * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep)
+ * nonempty-arg-list-without-generics = *(type-sep) arg-without-generic
+ * *(type-sep arg-without-generic) *(type-sep)
+ * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep)
+ * CLOSE-ANGLE-BRACKET/EOF
+ * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
+ *
+ * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
+ * type-search = [type-filter *WS COLON] [ nonempty-arg-list ] [ return-args ]
+ *
+ * query = *WS (exact-search / type-search) *WS
+ *
+ * type-filter = (
+ * "mod" /
+ * "externcrate" /
+ * "import" /
+ * "struct" /
+ * "enum" /
+ * "fn" /
+ * "type" /
+ * "static" /
+ * "trait" /
+ * "impl" /
+ * "tymethod" /
+ * "method" /
+ * "structfield" /
+ * "variant" /
+ * "macro" /
+ * "primitive" /
+ * "associatedtype" /
+ * "constant" /
+ * "associatedconstant" /
+ * "union" /
+ * "foreigntype" /
+ * "keyword" /
+ * "existential" /
+ * "attr" /
+ * "derive" /
+ * "traitalias")
+ *
+ * OPEN-ANGLE-BRACKET = "<"
+ * CLOSE-ANGLE-BRACKET = ">"
+ * COLON = ":"
+ * DOUBLE-COLON = "::"
+ * QUOTE = %x22
+ * COMMA = ","
+ * RETURN-ARROW = "->"
+ *
+ * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+ * DIGIT = %x30-39
+ * WS = %x09 / " "
+ *
+ * @param {string} val - The user query
+ *
+ * @return {ParsedQuery} - The parsed query
*/
- function execQuery(query, searchWords, filterCrates) {
- function itemTypeFromName(typename) {
- for (var i = 0, len = itemTypes.length; i < len; ++i) {
- if (itemTypes[i] === typename) {
- return i;
+ function parseQuery(userQuery) {
+ userQuery = userQuery.trim();
+ var parserState = {
+ length: userQuery.length,
+ pos: 0,
+ // Total number of elements (includes generics).
+ totalElems: 0,
+ genericsElems: 0,
+ typeFilter: null,
+ userQuery: userQuery.toLowerCase(),
+ };
+ var query = newParsedQuery(userQuery);
+
+ try {
+ parseInput(query, parserState);
+ if (parserState.typeFilter !== null) {
+ var typeFilter = parserState.typeFilter;
+ if (typeFilter === "const") {
+ typeFilter = "constant";
}
+ query.typeFilter = itemTypeFromName(typeFilter);
}
- return NO_TYPE_FILTER;
+ } catch (err) {
+ query = newParsedQuery(userQuery);
+ query.error = err.message;
+ query.typeFilter = -1;
+ return query;
}
- var valLower = query.query.toLowerCase(),
- val = valLower,
- typeFilter = itemTypeFromName(query.type),
- results = {}, results_in_args = {}, results_returned = {},
- split = valLower.split("::");
+ if (!query.literalSearch) {
+ // If there is more than one element in the query, we switch to literalSearch in any
+ // case.
+ query.literalSearch = parserState.totalElems > 1;
+ }
+ query.foundElems = query.elems.length + query.returned.length;
+ return query;
+ }
- removeEmptyStringsFromArray(split);
+ /**
+ * Creates the query results.
+ *
+ * @param {Array<Result>} results_in_args
+ * @param {Array<Result>} results_returned
+ * @param {Array<Result>} results_in_args
+ * @param {ParsedQuery} parsedQuery
+ *
+ * @return {ResultsTable}
+ */
+ function createQueryResults(results_in_args, results_returned, results_others, parsedQuery) {
+ return {
+ "in_args": results_in_args,
+ "returned": results_returned,
+ "others": results_others,
+ "query": parsedQuery,
+ };
+ }
+
+ /**
+ * Executes the parsed query and builds a {ResultsTable}.
+ *
+ * @param {ParsedQuery} parsedQuery - The parsed user query
+ * @param {Object} searchWords - The list of search words to query against
+ * @param {Object} [filterCrates] - Crate to search in if defined
+ *
+ * @return {ResultsTable}
+ */
+ function execQuery(parsedQuery, searchWords, filterCrates) {
+ var results_others = {}, results_in_args = {}, results_returned = {};
function transformResults(results) {
var duplicates = {};
}
function sortResults(results, isType) {
+ var userQuery = parsedQuery.userQuery;
var ar = [];
for (var entry in results) {
if (hasOwnPropertyRustdoc(results, entry)) {
var a, b;
// sort by exact match with regard to the last word (mismatch goes later)
- a = (aaa.word !== val);
- b = (bbb.word !== val);
+ a = (aaa.word !== userQuery);
+ b = (bbb.word !== userQuery);
if (a !== b) { return a - b; }
// Sort by non levenshtein results and then levenshtein results by the distance
return 0;
});
+ var nameSplit = null;
+ if (parsedQuery.elems.length === 1) {
+ var hasPath = typeof parsedQuery.elems[0].path === "undefined";
+ nameSplit = hasPath ? null : parsedQuery.elems[0].path;
+ }
+
for (var i = 0, len = results.length; i < len; ++i) {
result = results[i];
path = result.item.path.toLowerCase(),
parent = result.item.parent;
- if (!isType && !validateResult(name, path, split, parent)) {
+ if (!isType && !validateResult(name, path, nameSplit, parent)) {
result.id = -1;
}
}
return transformResults(results);
}
- function extractGenerics(val) {
- val = val.toLowerCase();
- if (val.indexOf("<") !== -1) {
- var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
- return {
- name: val.substring(0, val.indexOf("<")),
- generics: values.split(/\s*,\s*/),
- };
+ /**
+ * This function checks if the object (`row`) generics match the given type (`elem`)
+ * generics. If there are no generics on `row`, `defaultLev` is returned.
+ *
+ * @param {Row} row - The object to check.
+ * @param {QueryElement} elem - The element from the parsed query.
+ * @param {integer} defaultLev - This is the value to return in case there are no generics.
+ *
+ * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
+ */
+ function checkGenerics(row, elem, defaultLev) {
+ if (row.length <= GENERICS_DATA || row[GENERICS_DATA].length === 0) {
+ return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
+ } else if (row[GENERICS_DATA].length > 0 && row[GENERICS_DATA][0][NAME] === "") {
+ if (row.length > GENERICS_DATA) {
+ return checkGenerics(row[GENERICS_DATA][0], elem, defaultLev);
+ }
+ return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
}
- return {
- name: val,
- generics: [],
- };
- }
-
- function checkGenerics(obj, val) {
// The names match, but we need to be sure that all generics kinda
// match as well.
- var tmp_lev, elem_name;
- if (val.generics.length > 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length >= val.generics.length) {
- var elems = Object.create(null);
- var elength = obj[GENERICS_DATA].length;
- for (var x = 0; x < elength; ++x) {
- if (!elems[obj[GENERICS_DATA][x][NAME]]) {
- elems[obj[GENERICS_DATA][x][NAME]] = 0;
+ var elem_name;
+ if (elem.generics.length > 0 && row[GENERICS_DATA].length >= elem.generics.length) {
+ var elems = Object.create(null);
+ for (var x = 0, length = row[GENERICS_DATA].length; x < length; ++x) {
+ elem_name = row[GENERICS_DATA][x][NAME];
+ if (elem_name === "") {
+ // Pure generic, needs to check into it.
+ if (checkGenerics(
+ row[GENERICS_DATA][x], elem, MAX_LEV_DISTANCE + 1) !== 0) {
+ return MAX_LEV_DISTANCE + 1;
}
- elems[obj[GENERICS_DATA][x][NAME]] += 1;
+ continue;
+ }
+ if (elems[elem_name] === undefined) {
+ elems[elem_name] = 0;
}
- var total = 0;
- var done = 0;
- // We need to find the type that matches the most to remove it in order
- // to move forward.
- var vlength = val.generics.length;
- for (x = 0; x < vlength; ++x) {
- var lev = MAX_LEV_DISTANCE + 1;
- var firstGeneric = val.generics[x];
- var match = null;
- if (elems[firstGeneric]) {
- match = firstGeneric;
- lev = 0;
- } else {
- for (elem_name in elems) {
- tmp_lev = levenshtein(elem_name, firstGeneric);
- if (tmp_lev < lev) {
- lev = tmp_lev;
- match = elem_name;
- }
+ elems[elem_name] += 1;
+ }
+ // We need to find the type that matches the most to remove it in order
+ // to move forward.
+ for (x = 0, length = elem.generics.length; x < length; ++x) {
+ var generic = elem.generics[x];
+ var match = null;
+ if (elems[generic.name]) {
+ match = generic.name;
+ } else {
+ for (elem_name in elems) {
+ if (!hasOwnPropertyRustdoc(elems, elem_name)) {
+ continue;
}
- }
- if (match !== null) {
- elems[match] -= 1;
- if (elems[match] == 0) {
- delete elems[match];
+ if (elem_name === generic) {
+ match = elem_name;
+ break;
}
- total += lev;
- done += 1;
- } else {
- return MAX_LEV_DISTANCE + 1;
}
}
- return Math.ceil(total / done);
+ if (match === null) {
+ return MAX_LEV_DISTANCE + 1;
+ }
+ elems[match] -= 1;
+ if (elems[match] === 0) {
+ delete elems[match];
+ }
}
+ return 0;
}
return MAX_LEV_DISTANCE + 1;
}
/**
- * This function checks if the object (`obj`) matches the given type (`val`) and its
+ * This function checks if the object (`row`) matches the given type (`elem`) and its
+ * generics (if any).
+ *
+ * @param {Row} row
+ * @param {QueryElement} elem - The element from the parsed query.
+ *
+ * @return {integer} - Returns a Levenshtein distance to the best match.
+ */
+ function checkIfInGenerics(row, elem) {
+ var lev = MAX_LEV_DISTANCE + 1;
+ for (var x = 0, length = row[GENERICS_DATA].length; x < length && lev !== 0; ++x) {
+ lev = Math.min(
+ checkType(row[GENERICS_DATA][x], elem, true),
+ lev
+ );
+ }
+ return lev;
+ }
+
+ /**
+ * This function checks if the object (`row`) matches the given type (`elem`) and its
* generics (if any).
*
- * @param {Object} obj
- * @param {string} val
+ * @param {Row} row
+ * @param {QueryElement} elem - The element from the parsed query.
* @param {boolean} literalSearch
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is
* no match, returns `MAX_LEV_DISTANCE + 1`.
*/
- function checkType(obj, val, literalSearch) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
- var tmp_lev = MAX_LEV_DISTANCE + 1;
- var len, x, firstGeneric;
- if (obj[NAME] === val.name) {
- if (literalSearch) {
- if (val.generics && val.generics.length !== 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length > 0) {
- var elems = Object.create(null);
- len = obj[GENERICS_DATA].length;
- for (x = 0; x < len; ++x) {
- if (!elems[obj[GENERICS_DATA][x][NAME]]) {
- elems[obj[GENERICS_DATA][x][NAME]] = 0;
- }
- elems[obj[GENERICS_DATA][x][NAME]] += 1;
- }
+ function checkType(row, elem, literalSearch) {
+ if (row[NAME].length === 0) {
+ // This is a pure "generic" search, no need to run other checks.
+ if (row.length > GENERICS_DATA) {
+ return checkIfInGenerics(row, elem);
+ }
+ return MAX_LEV_DISTANCE + 1;
+ }
- len = val.generics.length;
- for (x = 0; x < len; ++x) {
- firstGeneric = val.generics[x];
- if (elems[firstGeneric]) {
- elems[firstGeneric] -= 1;
- } else {
- // Something wasn't found and this is a literal search so
- // abort and return a "failing" distance.
- return MAX_LEV_DISTANCE + 1;
- }
- }
- // Everything was found, success!
+ var lev = levenshtein(row[NAME], elem.name);
+ if (literalSearch) {
+ if (lev !== 0) {
+ // The name didn't match, let's try to check if the generics do.
+ if (elem.generics.length === 0) {
+ var checkGeneric = (row.length > GENERICS_DATA &&
+ row[GENERICS_DATA].length > 0);
+ if (checkGeneric && row[GENERICS_DATA].findIndex(function(tmp_elem) {
+ return tmp_elem[NAME] === elem.name;
+ }) !== -1) {
return 0;
}
- return MAX_LEV_DISTANCE + 1;
}
- return 0;
- } else {
- // If the type has generics but don't match, then it won't return at this point.
- // Otherwise, `checkGenerics` will return 0 and it'll return.
- if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
- tmp_lev = checkGenerics(obj, val);
- if (tmp_lev <= MAX_LEV_DISTANCE) {
- return tmp_lev;
- }
- }
- }
- } else if (literalSearch) {
- var found = false;
- if ((!val.generics || val.generics.length === 0) &&
- obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- found = obj[GENERICS_DATA].some(
- function(gen) {
- return gen[NAME] === val.name;
- });
- }
- return found ? 0 : MAX_LEV_DISTANCE + 1;
- }
- lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
- if (lev_distance <= MAX_LEV_DISTANCE) {
- // The generics didn't match but the name kinda did so we give it
- // a levenshtein distance value that isn't *this* good so it goes
- // into the search results but not too high.
- lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
- }
- if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- // We can check if the type we're looking for is inside the generics!
- var olength = obj[GENERICS_DATA].length;
- for (x = 0; x < olength; ++x) {
- tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev);
+ return MAX_LEV_DISTANCE + 1;
+ } else if (elem.generics.length > 0) {
+ return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
}
- if (tmp_lev !== 0) {
- // If we didn't find a good enough result, we go check inside the generics of
- // the generics.
- for (x = 0; x < olength && tmp_lev !== 0; ++x) {
- tmp_lev = Math.min(
- checkType(obj[GENERICS_DATA][x], val, literalSearch),
- tmp_lev
- );
+ return 0;
+ } else if (row.length > GENERICS_DATA) {
+ if (elem.generics.length === 0) {
+ if (lev === 0) {
+ return 0;
+ }
+ // The name didn't match so we now check if the type we're looking for is inside
+ // the generics!
+ lev = checkIfInGenerics(row, elem);
+ // Now whatever happens, the returned distance is "less good" so we should mark
+ // it as such, and so we add 0.5 to the distance to make it "less good".
+ return lev + 0.5;
+ } else if (lev > MAX_LEV_DISTANCE) {
+ // So our item's name doesn't match at all and has generics.
+ //
+ // Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
+ // looking for "B<C>", we'll need to go down.
+ return checkIfInGenerics(row, elem);
+ } else {
+ // At this point, the name kinda match and we have generics to check, so
+ // let's go!
+ var tmp_lev = checkGenerics(row, elem, lev);
+ if (tmp_lev > MAX_LEV_DISTANCE) {
+ return MAX_LEV_DISTANCE + 1;
}
+ // We compute the median value of both checks and return it.
+ return (tmp_lev + lev) / 2;
}
+ } else if (elem.generics.length > 0) {
+ // In this case, we were expecting generics but there isn't so we simply reject this
+ // one.
+ return MAX_LEV_DISTANCE + 1;
}
- // Now whatever happens, the returned distance is "less good" so we should mark it
- // as such, and so we add 1 to the distance to make it "less good".
- return Math.min(lev_distance, tmp_lev) + 1;
+ // No generics on our query or on the target type so we can return without doing
+ // anything else.
+ return lev;
}
/**
- * This function checks if the object (`obj`) has an argument with the given type (`val`).
+ * This function checks if the object (`row`) has an argument with the given type (`elem`).
*
- * @param {Object} obj
- * @param {string} val
- * @param {boolean} literalSearch
+ * @param {Row} row
+ * @param {QueryElement} elem - The element from the parsed query.
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
* match, returns `MAX_LEV_DISTANCE + 1`.
*/
- function findArg(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
+ function findArg(row, elem, typeFilter) {
+ var lev = MAX_LEV_DISTANCE + 1;
- if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
- var length = obj.type[INPUTS_DATA].length;
+ if (row && row.type && row.type[INPUTS_DATA] && row.type[INPUTS_DATA].length > 0) {
+ var length = row.type[INPUTS_DATA].length;
for (var i = 0; i < length; i++) {
- var tmp = obj.type[INPUTS_DATA][i];
+ var tmp = row.type[INPUTS_DATA][i];
if (!typePassesFilter(typeFilter, tmp[1])) {
continue;
}
- tmp = checkType(tmp, val, literalSearch);
- if (tmp === 0) {
+ lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
+ if (lev === 0) {
return 0;
- } else if (literalSearch) {
- continue;
}
- lev_distance = Math.min(tmp, lev_distance);
}
}
- return literalSearch ? MAX_LEV_DISTANCE + 1 : lev_distance;
+ return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
}
- function checkReturned(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
+ /**
+ * This function checks if the object (`row`) returns the given type (`elem`).
+ *
+ * @param {Row} row
+ * @param {QueryElement} elem - The element from the parsed query.
+ * @param {integer} typeFilter
+ *
+ * @return {integer} - Returns a Levenshtein distance to the best match. If there is no
+ * match, returns `MAX_LEV_DISTANCE + 1`.
+ */
+ function checkReturned(row, elem, typeFilter) {
+ var lev = MAX_LEV_DISTANCE + 1;
- if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
- var ret = obj.type[OUTPUT_DATA];
+ if (row && row.type && row.type.length > OUTPUT_DATA) {
+ var ret = row.type[OUTPUT_DATA];
if (typeof ret[0] === "string") {
ret = [ret];
}
if (!typePassesFilter(typeFilter, tmp[1])) {
continue;
}
- tmp = checkType(tmp, val, literalSearch);
- if (tmp === 0) {
+ lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
+ if (lev === 0) {
return 0;
- } else if (literalSearch) {
- continue;
}
- lev_distance = Math.min(tmp, lev_distance);
}
}
- return literalSearch ? MAX_LEV_DISTANCE + 1 : lev_distance;
+ return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
}
function checkPath(contains, lastElem, ty) {
}
function handleAliases(ret, query, filterCrates) {
+ var lowerQuery = query.toLowerCase();
// We separate aliases and crate aliases because we want to have current crate
// aliases to be before the others in the displayed results.
var aliases = [];
var crateAliases = [];
if (filterCrates !== null) {
- if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
- var query_aliases = ALIASES[filterCrates][query.search];
+ if (ALIASES[filterCrates] && ALIASES[filterCrates][lowerQuery]) {
+ var query_aliases = ALIASES[filterCrates][lowerQuery];
var len = query_aliases.length;
for (var i = 0; i < len; ++i) {
aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
}
} else {
Object.keys(ALIASES).forEach(function(crate) {
- if (ALIASES[crate][query.search]) {
+ if (ALIASES[crate][lowerQuery]) {
var pushTo = crate === window.currentCrate ? crateAliases : aliases;
- var query_aliases = ALIASES[crate][query.search];
+ var query_aliases = ALIASES[crate][lowerQuery];
var len = query_aliases.length;
for (var i = 0; i < len; ++i) {
pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
aliases.sort(sortFunc);
var pushFunc = function(alias) {
- alias.alias = query.raw;
+ alias.alias = query;
var res = buildHrefAndPath(alias);
alias.displayPath = pathSplitter(res[0]);
alias.fullPath = alias.displayPath + alias.name;
}
/**
- * This function adds the given result into the provided `res` map if it matches the
+ * This function adds the given result into the provided `results` map if it matches the
* following condition:
*
- * * If it is a "literal search" (`isExact`), then `lev` must be 0.
+ * * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
* * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
*
- * The `res` map contains information which will be used to sort the search results:
+ * The `results` map contains information which will be used to sort the search results:
*
- * * `fullId` is a `string`` used as the key of the object we use for the `res` map.
+ * * `fullId` is a `string`` used as the key of the object we use for the `results` map.
* * `id` is the index in both `searchWords` and `searchIndex` arrays for this element.
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
* * `lev` is the main metric used to sort the search results.
*
- * @param {boolean} isExact
- * @param {Object} res
+ * @param {Results} results
* @param {string} fullId
* @param {integer} id
* @param {integer} index
* @param {integer} lev
*/
- function addIntoResults(isExact, res, fullId, id, index, lev) {
- if (lev === 0 || (!isExact && lev <= MAX_LEV_DISTANCE)) {
- if (res[fullId] !== undefined) {
- var result = res[fullId];
+ function addIntoResults(results, fullId, id, index, lev) {
+ if (lev === 0 || (!parsedQuery.literalSearch && lev <= MAX_LEV_DISTANCE)) {
+ if (results[fullId] !== undefined) {
+ var result = results[fullId];
if (result.dontValidate || result.lev <= lev) {
return;
}
}
- res[fullId] = {
+ results[fullId] = {
id: id,
index: index,
- dontValidate: isExact,
+ dontValidate: parsedQuery.literalSearch,
lev: lev,
};
}
}
- // quoted values mean literal search
- var nSearchWords = searchWords.length;
- var i, it;
- var ty;
- var fullId;
- var returned;
- var in_args;
- var len;
- if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
- val.charAt(val.length - 1) === val.charAt(0))
- {
- val = extractGenerics(val.substr(1, val.length - 2));
- for (i = 0; i < nSearchWords; ++i) {
- if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
- continue;
+ /**
+ * This function is called in case the query is only one element (with or without generics).
+ * This element will be compared to arguments' and returned values' items and also to items.
+ *
+ * Other important thing to note: since there is only one element, we use levenshtein
+ * distance for name comparisons.
+ *
+ * @param {Row} row
+ * @param {integer} pos - Position in the `searchIndex`.
+ * @param {QueryElement} elem - The element from the parsed query.
+ * @param {Results} results_others - Unqualified results (not in arguments nor in
+ * returned values).
+ * @param {Results} results_in_args - Matching arguments results.
+ * @param {Results} results_returned - Matching returned arguments results.
+ */
+ function handleSingleArg(
+ row,
+ pos,
+ elem,
+ results_others,
+ results_in_args,
+ results_returned
+ ) {
+ if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
+ return;
+ }
+ var lev, lev_add = 0, index = -1;
+ var fullId = row.id;
+
+ var in_args = findArg(row, elem, parsedQuery.typeFilter);
+ var returned = checkReturned(row, elem, parsedQuery.typeFilter);
+
+ addIntoResults(results_in_args, fullId, pos, index, in_args);
+ addIntoResults(results_returned, fullId, pos, index, returned);
+
+ if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
+ return;
+ }
+ var searchWord = searchWords[pos];
+
+ if (parsedQuery.literalSearch) {
+ if (searchWord === elem.name) {
+ addIntoResults(results_others, fullId, pos, -1, 0);
}
- in_args = findArg(searchIndex[i], val, true, typeFilter);
- returned = checkReturned(searchIndex[i], val, true, typeFilter);
- ty = searchIndex[i];
- fullId = ty.id;
-
- if (searchWords[i] === val.name
- && typePassesFilter(typeFilter, searchIndex[i].ty)) {
- addIntoResults(true, results, fullId, i, -1, 0);
+ return;
+ }
+
+ // No need to check anything else if it's a "pure" generics search.
+ if (elem.name.length === 0) {
+ if (row.type !== null) {
+ lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
+ addIntoResults(results_others, fullId, pos, index, lev);
}
- addIntoResults(true, results_in_args, fullId, i, -1, in_args);
- addIntoResults(true, results_returned, fullId, i, -1, returned);
- }
- query.inputs = [val];
- query.output = val;
- query.search = val;
- // searching by type
- } else if (val.search("->") > -1) {
- var trimmer = function(s) { return s.trim(); };
- var parts = val.split("->").map(trimmer);
- var input = parts[0];
- // sort inputs so that order does not matter
- var inputs = input.split(",").map(trimmer).sort();
- for (i = 0, len = inputs.length; i < len; ++i) {
- inputs[i] = extractGenerics(inputs[i]);
- }
- var output = extractGenerics(parts[1]);
-
- for (i = 0; i < nSearchWords; ++i) {
- if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
- continue;
+ return;
+ }
+
+ if (elem.fullPath.length > 1) {
+ lev = checkPath(elem.pathWithoutLast, elem.pathLast, row);
+ if (lev > MAX_LEV_DISTANCE || (parsedQuery.literalSearch && lev !== 0)) {
+ return;
+ } else if (lev > 0) {
+ lev_add = lev / 10;
}
- var type = searchIndex[i].type;
- ty = searchIndex[i];
- if (!type) {
- continue;
+ }
+
+ if (searchWord.indexOf(elem.pathLast) > -1 ||
+ row.normalizedName.indexOf(elem.pathLast) > -1)
+ {
+ // filter type: ... queries
+ if (!results_others[fullId] !== undefined) {
+ index = row.normalizedName.indexOf(elem.pathLast);
}
- fullId = ty.id;
+ }
+ lev = levenshtein(searchWord, elem.pathLast);
+ lev += lev_add;
+ if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1)
+ {
+ if (elem.pathLast.length < 6) {
+ lev = 1;
+ } else {
+ lev = 0;
+ }
+ }
+ if (lev > MAX_LEV_DISTANCE) {
+ return;
+ } else if (index !== -1 && elem.fullPath.length < 2) {
+ lev -= 1;
+ }
+ if (lev < 0) {
+ lev = 0;
+ }
+ addIntoResults(results_others, fullId, pos, index, lev);
+ }
- returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
- if (output.name === "*" || returned === 0) {
- in_args = false;
- var is_module = false;
+ /**
+ * This function is called in case the query has more than one element. In this case, it'll
+ * try to match the items which validates all the elements. For `aa -> bb` will look for
+ * functions which have a parameter `aa` and has `bb` in its returned values.
+ *
+ * @param {Row} row
+ * @param {integer} pos - Position in the `searchIndex`.
+ * @param {Object} results
+ */
+ function handleArgs(row, pos, results) {
+ if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
+ return;
+ }
- if (input === "*") {
- is_module = true;
+ var totalLev = 0;
+ var nbLev = 0;
+ var lev;
+
+ // If the result is too "bad", we return false and it ends this search.
+ function checkArgs(elems, callback) {
+ for (var i = 0, len = elems.length; i < len; ++i) {
+ var elem = elems[i];
+ // There is more than one parameter to the query so all checks should be "exact"
+ lev = callback(row, elem, NO_TYPE_FILTER);
+ if (lev <= 1) {
+ nbLev += 1;
+ totalLev += lev;
} else {
- var firstNonZeroDistance = 0;
- for (it = 0, len = inputs.length; it < len; it++) {
- var distance = checkType(type, inputs[it], true);
- if (distance > 0) {
- firstNonZeroDistance = distance;
- break;
- }
- }
- in_args = firstNonZeroDistance;
- }
- addIntoResults(true, results_in_args, fullId, i, -1, in_args);
- addIntoResults(true, results_returned, fullId, i, -1, returned);
- if (is_module) {
- addIntoResults(true, results, fullId, i, -1, 0);
+ return false;
}
}
+ return true;
+ }
+ if (!checkArgs(parsedQuery.elems, findArg)) {
+ return;
+ }
+ if (!checkArgs(parsedQuery.returned, checkReturned)) {
+ return;
}
- query.inputs = inputs.map(function(input) {
- return input.name;
- });
- query.output = output.name;
- } else {
- query.inputs = [val];
- query.output = val;
- query.search = val;
- // gather matching search results up to a certain maximum
- val = val.replace(/_/g, "");
-
- var valGenerics = extractGenerics(val);
-
- var paths = valLower.split("::");
- removeEmptyStringsFromArray(paths);
- val = paths[paths.length - 1];
- var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
-
- var lev, j;
- for (j = 0; j < nSearchWords; ++j) {
- ty = searchIndex[j];
- if (!ty || (filterCrates !== null && ty.crate !== filterCrates)) {
- continue;
- }
- var lev_add = 0;
- if (paths.length > 1) {
- lev = checkPath(contains, paths[paths.length - 1], ty);
- if (lev > MAX_LEV_DISTANCE) {
- continue;
- } else if (lev > 0) {
- lev_add = lev / 10;
- }
- }
- returned = MAX_LEV_DISTANCE + 1;
- in_args = MAX_LEV_DISTANCE + 1;
- var index = -1;
- // we want lev results to go lower than others
- lev = MAX_LEV_DISTANCE + 1;
- fullId = ty.id;
+ if (nbLev === 0) {
+ return;
+ }
+ lev = Math.round(totalLev / nbLev);
+ addIntoResults(results, row.id, pos, 0, lev);
+ }
- if (searchWords[j].indexOf(split[i]) > -1 ||
- searchWords[j].indexOf(val) > -1 ||
- ty.normalizedName.indexOf(val) > -1)
- {
- // filter type: ... queries
- if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
- index = ty.normalizedName.indexOf(val);
+ function innerRunQuery() {
+ var elem, i, nSearchWords, in_returned, row;
+
+ if (parsedQuery.foundElems === 1) {
+ if (parsedQuery.elems.length === 1) {
+ elem = parsedQuery.elems[0];
+ for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+ // It means we want to check for this element everywhere (in names, args and
+ // returned).
+ handleSingleArg(
+ searchIndex[i],
+ i,
+ elem,
+ results_others,
+ results_in_args,
+ results_returned
+ );
}
- }
- if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
- if (typePassesFilter(typeFilter, ty.ty)) {
- lev += 1;
- } else {
- lev = MAX_LEV_DISTANCE + 1;
+ } else if (parsedQuery.returned.length === 1) {
+ // We received one returned argument to check, so looking into returned values.
+ elem = parsedQuery.returned[0];
+ for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+ row = searchIndex[i];
+ in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
+ addIntoResults(results_returned, row.id, i, -1, in_returned);
}
}
- in_args = findArg(ty, valGenerics, false, typeFilter);
- returned = checkReturned(ty, valGenerics, false, typeFilter);
-
- lev += lev_add;
- if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
- if (val.length < 6) {
- lev -= 1;
- } else {
- lev = 0;
- }
+ } else if (parsedQuery.foundElems > 0) {
+ var container = results_others;
+ // In the special case where only a "returned" information is available, we want to
+ // put the information into the "results_returned" dict.
+ if (parsedQuery.returned.length !== 0 && parsedQuery.elems.length === 0) {
+ container = results_returned;
}
- addIntoResults(false, results_in_args, fullId, j, index, in_args);
- addIntoResults(false, results_returned, fullId, j, index, returned);
- if (typePassesFilter(typeFilter, ty.ty) &&
- (index !== -1 || lev <= MAX_LEV_DISTANCE)) {
- if (index !== -1 && paths.length < 2) {
- lev = 0;
- }
- addIntoResults(false, results, fullId, j, index, lev);
+ for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
+ handleArgs(searchIndex[i], i, container);
}
}
}
- var ret = {
- "in_args": sortResults(results_in_args, true),
- "returned": sortResults(results_returned, true),
- "others": sortResults(results, false),
- };
- handleAliases(ret, query, filterCrates);
+ if (parsedQuery.error === null) {
+ innerRunQuery();
+ }
+
+ var ret = createQueryResults(
+ sortResults(results_in_args, true),
+ sortResults(results_returned, true),
+ sortResults(results_others, false),
+ parsedQuery);
+ handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates);
+ if (parsedQuery.error !== null && ret.others.length !== 0) {
+ // It means some doc aliases were found so let's "remove" the error!
+ ret.query.error = null;
+ }
return ret;
}
* @param {string} path - The path of the result
* @param {string} keys - The keys to be used (["file", "open"])
* @param {Object} parent - The parent of the result
+ *
* @return {boolean} - Whether the result is valid or not
*/
function validateResult(name, path, keys, parent) {
+ if (!keys || !keys.length) {
+ return true;
+ }
for (var i = 0, len = keys.length; i < len; ++i) {
// each check is for validation so we negate the conditions and invalidate
if (!(
return true;
}
- /**
- * Parse a string into a query object.
- *
- * @param {string} raw - The text that the user typed.
- * @returns {ParsedQuery}
- */
- function getQuery(raw) {
- var matches, type = "", query;
- query = raw;
-
- matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
- if (matches) {
- type = matches[1].replace(/^const$/, "constant");
- query = query.substring(matches[0].length);
- }
-
- return {
- raw: raw,
- query: query,
- type: type,
- id: query + type
- };
- }
-
function nextTab(direction) {
var next = (searchState.currentTab + direction + 3) % searchState.focusedByTab.length;
searchState.focusedByTab[searchState.currentTab] = document.activeElement;
link.appendChild(wrapper);
output.appendChild(link);
});
- } else {
+ } else if (query.error === null) {
output.className = "search-failed" + extraClass;
output.innerHTML = "No results :(<br/>" +
"Try on <a href=\"https://duckduckgo.com/?q=" +
- encodeURIComponent("rust " + query.query) +
+ encodeURIComponent("rust " + query.userQuery) +
"\">DuckDuckGo</a>?<br/><br/>" +
"Or try looking in one of these:<ul><li>The <a " +
"href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
}
+ /**
+ * @param {ResultsTable} results
+ * @param {boolean} go_to_first
+ * @param {string} filterCrates
+ */
function showResults(results, go_to_first, filterCrates) {
var search = searchState.outputElement();
if (go_to_first || (results.others.length === 1
elem.click();
return;
}
- var query = getQuery(searchState.input.value);
+ if (results.query === undefined) {
+ results.query = parseQuery(searchState.input.value);
+ }
- currentResults = query.id;
+ currentResults = results.query.userQuery;
- var ret_others = addTab(results.others, query, true);
- var ret_in_args = addTab(results.in_args, query, false);
- var ret_returned = addTab(results.returned, query, false);
+ var ret_others = addTab(results.others, results.query, true);
+ var ret_in_args = addTab(results.in_args, results.query, false);
+ var ret_returned = addTab(results.returned, results.query, false);
// Navigate to the relevant tab if the current tab is empty, like in case users search
// for "-> String". If they had selected another tab previously, they have to click on
}
crates += `</select>`;
}
- var output = `<div id="search-settings">
- <h1 class="search-results-title">Results for ${escape(query.query)} ` +
- (query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
- crates +
- `</div><div id="titles">` +
+
+ var typeFilter = "";
+ if (results.query.typeFilter !== NO_TYPE_FILTER) {
+ typeFilter = " (type: " + escape(itemTypes[results.query.typeFilter]) + ")";
+ }
+
+ var output = `<div id="search-settings">` +
+ `<h1 class="search-results-title">Results for ${escape(results.query.userQuery)}` +
+ `${typeFilter}</h1> in ${crates} </div>`;
+ if (results.query.error !== null) {
+ output += `<h3>Query parser error: "${results.query.error}".</h3>`;
+ }
+ output += `<div id="titles">` +
makeTabHeader(0, "In Names", ret_others[1]) +
makeTabHeader(1, "In Parameters", ret_in_args[1]) +
makeTabHeader(2, "In Return Types", ret_returned[1]) +
printTab(currentTab);
}
- function execSearch(query, searchWords, filterCrates) {
- query = query.raw.trim();
- var results = {
- "in_args": [],
- "returned": [],
- "others": [],
- };
-
- if (query.length !== 0) {
- var tmp = execQuery(getQuery(query), searchWords, filterCrates);
-
- results.in_args.push(tmp.in_args);
- results.returned.push(tmp.returned);
- results.others.push(tmp.others);
- }
- return {
- "in_args": results.in_args[0],
- "returned": results.returned[0],
- "others": results.others[0],
- };
- }
-
/**
* Perform a search based on the current state of the search input element
* and display the results.
*/
function search(e, forced) {
var params = searchState.getQueryStringParams();
- var query = getQuery(searchState.input.value.trim());
+ var query = parseQuery(searchState.input.value.trim());
if (e) {
e.preventDefault();
}
- if (query.query.length === 0) {
- return;
- }
- if (!forced && query.id === currentResults) {
- if (query.query.length > 0) {
+ if (!forced && query.userQuery === currentResults) {
+ if (query.userQuery.length > 0) {
putBackSearch();
}
return;
}
// Update document title to maintain a meaningful browser history
- searchState.title = "Results for " + query.query + " - Rust";
+ searchState.title = "Results for " + query.original + " - Rust";
// Because searching is incremental by character, only the most
// recent search query is added to the browser history.
if (searchState.browserSupportsHistoryApi()) {
- var newURL = buildUrl(query.raw, filterCrates);
-
+ var newURL = buildUrl(query.original, filterCrates);
if (!history.state && !params.search) {
history.pushState(null, "", newURL);
} else {
}
}
- showResults(execSearch(query, searchWords, filterCrates),
- params["go_to_first"], filterCrates);
+ showResults(
+ execQuery(query, searchWords, filterCrates),
+ params.go_to_first,
+ filterCrates);
}
function buildIndex(rawSearchIndex) {
use rustc_ast::ast;
use rustc_hir::{def::CtorKind, def_id::DefId};
use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::Pos;
use rustc_target::spec::abi::Abi as RustcAbi;
let links = self
.cache
.intra_doc_links
- .get(&item.def_id)
+ .get(&item.item_id)
.into_iter()
.flatten()
.map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
.map(rustc_ast_pretty::pprust::attribute_to_string)
.collect();
let span = item.span(self.tcx);
- let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
+ let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item;
let inner = match *item.kind {
clean::StrippedItem(_) => return None,
_ => from_clean_item(item, self.tcx),
};
Some(Item {
- id: from_item_id(def_id),
- crate_id: def_id.krate().as_u32(),
+ id: from_item_id(item_id),
+ crate_id: item_id.krate().as_u32(),
name: name.map(|sym| sym.to_string()),
span: self.convert_span(span),
visibility: self.convert_visibility(visibility),
match v {
Public => Visibility::Public,
Inherited => Visibility::Default,
- Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
+ Restricted(did) if did.is_crate_root() => Visibility::Crate,
Restricted(did) => Visibility::Restricted {
parent: from_item_id(did.into()),
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
}
}
-crate fn from_item_id(did: ItemId) -> Id {
+crate fn from_item_id(item_id: ItemId) -> Id {
struct DisplayDefId(DefId);
impl fmt::Display for DisplayDefId {
}
}
- match did {
+ match item_id {
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
ItemId::Blanket { for_, impl_id } => {
Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
}
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
- items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
+ items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.item_id)).collect()
}
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
- from_item_id(item.def_id)
+ from_item_id(item.item_id)
})
.collect()
})
}
}
- if item.def_id.is_local() || is_primitive_impl {
+ if item.item_id.is_local() || is_primitive_impl {
self.item(item.clone()).unwrap();
- Some(from_item_id(item.def_id))
+ Some(from_item_id(item.item_id))
} else {
None
}
// Flatten items that recursively store other items
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
- let id = item.def_id;
+ let item_id = item.item_id;
if let Some(mut new_item) = self.convert_item(item) {
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
- t.implementations = self.get_trait_implementors(id.expect_def_id())
+ t.implementations = self.get_trait_implementors(item_id.expect_def_id())
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
- s.impls = self.get_impls(id.expect_def_id())
+ s.impls = self.get_impls(item_id.expect_def_id())
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
- e.impls = self.get_impls(id.expect_def_id())
+ e.impls = self.get_impls(item_id.expect_def_id())
} else if let types::ItemEnum::Union(ref mut u) = new_item.inner {
- u.impls = self.get_impls(id.expect_def_id())
+ u.impls = self.get_impls(item_id.expect_def_id())
}
- let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
+ let removed = self.index.borrow_mut().insert(from_item_id(item_id), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
// to make sure the items are unique. The main place this happens is when an item, is
let resolver_caches = resolver.borrow_mut().access(|resolver| {
collect_intra_doc_links::early_resolve_intra_doc_links(
resolver,
+ sess,
krate,
externs,
document_private,
impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
- let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.def_id)
+ let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id)
else {
// If non-local, no need to check anything.
return;
impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
fn visit_item(&mut self, i: &clean::Item) {
- if !i.def_id.is_local() {
+ if !i.item_id.is_local() {
// non-local items are skipped because they can be out of the users control,
// especially in the case of trait impls, which rustdoc eagerly inlines
return;
.ctx
.tcx
.hir()
- .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
+ .local_def_id_to_hir_id(i.item_id.expect_def_id().expect_local());
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
// In case we have:
// there is no need to require documentation on the fields of tuple variants and
// tuple structs.
let should_be_ignored = i
- .def_id
+ .item_id
.as_def_id()
.and_then(|def_id| self.ctx.tcx.parent(def_id))
.and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
return;
}
- let Some(local_id) = item.def_id.as_def_id().and_then(|x| x.as_local())
+ let Some(local_id) = item.item_id.as_def_id().and_then(|x| x.as_local())
else {
// We don't need to check the syntax for other crates so returning
// without doing anything should not be a problem.
let sp = item.attr_span(self.cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new_did(
self.cx.tcx,
- item.def_id.expect_def_id(),
+ item.item_id.expect_def_id(),
sp,
);
for code_block in markdown::rust_code_blocks(dox, &extra) {
}
crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
- if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
+ if !cx.cache.access_levels.is_public(item.item_id.expect_def_id())
|| matches!(
*item.kind,
clean::StructFieldItem(_)
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_id.expect_def_id().expect_local());
// check if parent is trait impl
if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
}
crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
- let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.def_id)
+ let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id)
else {
// If non-local, no need to check anything.
return;
);
}
} else if tests.found_tests > 0
- && !cx.cache.access_levels.is_exported(item.def_id.expect_def_id())
+ && !cx.cache.access_levels.is_exported(item.item_id.expect_def_id())
{
cx.tcx.struct_span_lint_hir(
crate::lint::PRIVATE_DOC_TESTS,
//! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
use pulldown_cmark::LinkType;
+use rustc_ast::util::comments::may_have_doc_links;
use rustc_data_structures::{fx::FxHashMap, intern::Interned, stable_set::FxHashSet};
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir::def::Namespace::*;
}
/// A link failed to resolve.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
enum ResolutionFailure<'a> {
/// This resolved, but with the wrong namespace.
WrongNamespace {
Dummy,
}
-#[derive(Debug)]
+#[derive(Clone, Debug)]
enum MalformedGenerics {
/// This link has unbalanced angle brackets.
///
}
}
+#[derive(Clone, Copy)]
enum AnchorFailure {
/// User error: `[std#x#y]` is not valid
MultipleAnchors,
// Resolver doesn't know about true, false, and types that aren't paths (e.g. `()`).
let result = self
.cx
- .enter_resolver(|resolver| resolver.resolve_rustdoc_path(path_str, ns, module_id))
+ .resolver_caches
+ .doc_link_resolutions
+ .get(&(Symbol::intern(path_str), ns, module_id))
+ .copied()
+ .unwrap_or_else(|| {
+ self.cx.enter_resolver(|resolver| {
+ resolver.resolve_rustdoc_path(path_str, ns, module_id)
+ })
+ })
.and_then(|res| res.try_into().ok())
.or_else(|| resolve_primitive(path_str, ns))
.or_else(|| self.resolve_macro_rules(path_str, ns));
impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
let parent_node =
- item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
+ item.item_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
if parent_node.is_some() {
- trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
+ trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.item_id);
}
let inner_docs = item.inner_docs(self.cx.tcx);
if item.is_mod() && inner_docs {
- self.mod_ids.push(item.def_id.expect_def_id());
+ self.mod_ids.push(item.item_id.expect_def_id());
}
// We want to resolve in the lexical scope of the documentation.
// In the presence of re-exports, this is not the same as the module of the item.
// Rather than merging all documentation into one, resolve it one attribute at a time
// so we know which module it came from.
- for (parent_module, doc) in item.attrs.collapsed_doc_value_by_module_level() {
+ for (parent_module, doc) in item.attrs.prepare_to_doc_link_resolution() {
+ if !may_have_doc_links(&doc) {
+ continue;
+ }
debug!("combined_docs={}", doc);
// NOTE: if there are links that start in one crate and end in another, this will not resolve them.
// This is a degenerate case and it's not supported by rustdoc.
let parent_node = parent_module.or(parent_node);
- for md_link in markdown_links(&doc) {
+ let mut tmp_links = self
+ .cx
+ .resolver_caches
+ .markdown_links
+ .take()
+ .expect("`markdown_links` are already borrowed");
+ if !tmp_links.contains_key(&doc) {
+ tmp_links.insert(doc.clone(), preprocessed_markdown_links(&doc));
+ }
+ for md_link in &tmp_links[&doc] {
let link = self.resolve_link(&item, &doc, parent_node, md_link);
if let Some(link) = link {
- self.cx.cache.intra_doc_links.entry(item.def_id).or_default().push(link);
+ self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
}
}
+ self.cx.resolver_caches.markdown_links = Some(tmp_links);
}
if item.is_mod() {
if !inner_docs {
- self.mod_ids.push(item.def_id.expect_def_id());
+ self.mod_ids.push(item.item_id.expect_def_id());
}
self.visit_item_recur(item);
}
}
-enum PreprocessingError<'a> {
+enum PreprocessingError {
Anchor(AnchorFailure),
Disambiguator(Range<usize>, String),
- Resolution(ResolutionFailure<'a>, String, Option<Disambiguator>),
+ Resolution(ResolutionFailure<'static>, String, Option<Disambiguator>),
}
-impl From<AnchorFailure> for PreprocessingError<'_> {
+impl From<AnchorFailure> for PreprocessingError {
fn from(err: AnchorFailure) -> Self {
Self::Anchor(err)
}
}
+#[derive(Clone)]
struct PreprocessingInfo {
path_str: String,
disambiguator: Option<Disambiguator>,
link_text: String,
}
+// Not a typedef to avoid leaking several private structures from this module.
+crate struct PreprocessedMarkdownLink(Result<PreprocessingInfo, PreprocessingError>, MarkdownLink);
+
/// Returns:
/// - `None` if the link should be ignored.
/// - `Some(Err)` if the link should emit an error
/// - `Some(Ok)` if the link is valid
///
/// `link_buffer` is needed for lifetime reasons; it will always be overwritten and the contents ignored.
-fn preprocess_link<'a>(
- ori_link: &'a MarkdownLink,
-) -> Option<Result<PreprocessingInfo, PreprocessingError<'a>>> {
+fn preprocess_link(
+ ori_link: &MarkdownLink,
+) -> Option<Result<PreprocessingInfo, PreprocessingError>> {
// [] is mostly likely not supposed to be a link
if ori_link.link.is_empty() {
return None;
}))
}
+fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
+ markdown_links(s, |link| {
+ preprocess_link(&link).map(|pp_link| PreprocessedMarkdownLink(pp_link, link))
+ })
+}
+
impl LinkCollector<'_, '_> {
/// This is the entry point for resolving an intra-doc link.
///
item: &Item,
dox: &str,
parent_node: Option<DefId>,
- ori_link: MarkdownLink,
+ link: &PreprocessedMarkdownLink,
) -> Option<ItemLink> {
+ let PreprocessedMarkdownLink(pp_link, ori_link) = link;
trace!("considering link '{}'", ori_link.link);
let diag_info = DiagnosticInfo {
link_range: ori_link.range.clone(),
};
- let PreprocessingInfo { ref path_str, disambiguator, extra_fragment, link_text } =
- match preprocess_link(&ori_link)? {
- Ok(x) => x,
- Err(err) => {
- match err {
- PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, err),
- PreprocessingError::Disambiguator(range, msg) => {
- disambiguator_error(self.cx, diag_info, range, &msg)
- }
- PreprocessingError::Resolution(err, path_str, disambiguator) => {
- resolution_failure(
- self,
- diag_info,
- &path_str,
- disambiguator,
- smallvec![err],
- );
- }
+ let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = match pp_link
+ {
+ Ok(x) => x,
+ Err(err) => {
+ match err {
+ PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, *err),
+ PreprocessingError::Disambiguator(range, msg) => {
+ disambiguator_error(self.cx, diag_info, range.clone(), msg)
+ }
+ PreprocessingError::Resolution(err, path_str, disambiguator) => {
+ resolution_failure(
+ self,
+ diag_info,
+ path_str,
+ *disambiguator,
+ smallvec![err.clone()],
+ );
}
- return None;
}
- };
+ return None;
+ }
+ };
+ let disambiguator = *disambiguator;
let inner_docs = item.inner_docs(self.cx.tcx);
let (mut res, fragment) = self.resolve_with_disambiguator_cached(
ResolutionInfo {
- item_id: item.def_id,
+ item_id: item.item_id,
module_id,
dis: disambiguator,
path_str: path_str.to_owned(),
- extra_fragment,
+ extra_fragment: extra_fragment.clone(),
},
diag_info.clone(), // this struct should really be Copy, but Range is not :(
matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
// FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
// However I'm not sure how to check that across crates.
if prim == PrimitiveType::RawPointer
- && item.def_id.is_local()
+ && item.item_id.is_local()
&& !self.cx.tcx.features().intra_doc_pointers
{
self.report_rawptr_assoc_feature_gate(dox, &ori_link, item);
}
Some(ItemLink {
- link: ori_link.link,
- link_text,
+ link: ori_link.link.clone(),
+ link_text: link_text.clone(),
did: res.def_id(self.cx.tcx),
fragment,
})
&diag_info,
)?;
let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
- Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
+ Some(ItemLink {
+ link: ori_link.link.clone(),
+ link_text: link_text.clone(),
+ did: id,
+ fragment,
+ })
}
}
}
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
.and_then(|dst_id| {
- item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
+ item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
})
{
if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
) {
- let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
+ let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
else {
// If non-local, no need to check anything.
info!("ignoring warning from parent crate: {}", msg);
use crate::clean::Attributes;
use crate::core::ResolverCaches;
-use crate::html::markdown::markdown_links;
-use crate::passes::collect_intra_doc_links::preprocess_link;
+use crate::passes::collect_intra_doc_links::preprocessed_markdown_links;
+use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink;
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::{self as ast, ItemKind};
use rustc_ast_lowering::ResolverAstLowering;
-use rustc_hir::def::Namespace::TypeNS;
-use rustc_hir::def::{DefKind, Res};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::Namespace::*;
+use rustc_hir::def::{DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, CRATE_DEF_ID};
use rustc_hir::TraitCandidate;
use rustc_middle::ty::{DefIdTree, Visibility};
use rustc_resolve::{ParentScope, Resolver};
use rustc_session::config::Externs;
-use rustc_span::SyntaxContext;
+use rustc_session::Session;
+use rustc_span::{Symbol, SyntaxContext};
use std::collections::hash_map::Entry;
use std::mem;
crate fn early_resolve_intra_doc_links(
resolver: &mut Resolver<'_>,
+ sess: &Session,
krate: &ast::Crate,
externs: Externs,
document_private_items: bool,
) -> ResolverCaches {
let mut link_resolver = EarlyDocLinkResolver {
resolver,
+ sess,
current_mod: CRATE_DEF_ID,
visited_mods: Default::default(),
+ markdown_links: Default::default(),
+ doc_link_resolutions: Default::default(),
traits_in_scope: Default::default(),
all_traits: Default::default(),
all_trait_impls: Default::default(),
// Overridden `visit_item` below doesn't apply to the crate root,
// so we have to visit its attributes and reexports separately.
- link_resolver.load_links_in_attrs(&krate.attrs);
+ link_resolver.resolve_doc_links_local(&krate.attrs);
link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id());
visit::walk_crate(&mut link_resolver, krate);
link_resolver.process_extern_impls();
}
ResolverCaches {
+ markdown_links: Some(link_resolver.markdown_links),
+ doc_link_resolutions: link_resolver.doc_link_resolutions,
traits_in_scope: link_resolver.traits_in_scope,
all_traits: Some(link_resolver.all_traits),
all_trait_impls: Some(link_resolver.all_trait_impls),
}
}
+fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes {
+ Attributes::from_ast_iter(attrs.map(|attr| (attr, None)), true)
+}
+
struct EarlyDocLinkResolver<'r, 'ra> {
resolver: &'r mut Resolver<'ra>,
+ sess: &'r Session,
current_mod: LocalDefId,
visited_mods: DefIdSet,
+ markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
+ doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
all_traits: Vec<DefId>,
all_trait_impls: Vec<DefId>,
}
}
- fn add_traits_in_parent_scope(&mut self, def_id: DefId) {
- if let Some(module_id) = self.resolver.parent(def_id) {
- self.add_traits_in_scope(module_id);
- }
- }
-
/// Add traits in scope for links in impls collected by the `collect-intra-doc-links` pass.
/// That pass filters impls using type-based information, but we don't yet have such
/// information here, so we just conservatively calculate traits in scope for *all* modules
/// having impls in them.
fn process_extern_impls(&mut self) {
- // FIXME: Need to resolve doc links on all these impl and trait items below.
// Resolving links in already existing crates may trigger loading of new crates.
let mut start_cnum = 0;
loop {
// the current crate, and links in their doc comments are not resolved.
for &def_id in &all_traits {
if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public {
- self.add_traits_in_parent_scope(def_id);
+ self.resolve_doc_links_extern_impl(def_id, false);
}
}
for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
== Visibility::Public
})
{
- self.add_traits_in_parent_scope(impl_def_id);
+ self.resolve_doc_links_extern_impl(impl_def_id, false);
}
}
for (ty_def_id, impl_def_id) in all_inherent_impls {
if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public
{
- self.add_traits_in_parent_scope(impl_def_id);
+ self.resolve_doc_links_extern_impl(impl_def_id, true);
}
}
- for def_id in all_incoherent_impls {
- self.add_traits_in_parent_scope(def_id);
+ for impl_def_id in all_incoherent_impls {
+ self.resolve_doc_links_extern_impl(impl_def_id, true);
}
self.all_traits.extend(all_traits);
}
}
- fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute]) {
+ fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) {
+ self.resolve_doc_links_extern_outer(def_id, def_id);
+ let assoc_item_def_ids = Vec::from_iter(
+ self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess),
+ );
+ for assoc_def_id in assoc_item_def_ids {
+ if !is_inherent
+ || self.resolver.cstore().visibility_untracked(assoc_def_id) == Visibility::Public
+ {
+ self.resolve_doc_links_extern_outer(assoc_def_id, def_id);
+ }
+ }
+ }
+
+ fn resolve_doc_links_extern_outer(&mut self, def_id: DefId, scope_id: DefId) {
+ if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
+ return;
+ }
+ // FIXME: actually resolve links, not just add traits in scope.
+ if let Some(parent_id) = self.resolver.parent(scope_id) {
+ self.add_traits_in_scope(parent_id);
+ }
+ }
+
+ fn resolve_doc_links_extern_inner(&mut self, def_id: DefId) {
+ if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
+ return;
+ }
+ // FIXME: actually resolve links, not just add traits in scope.
+ self.add_traits_in_scope(def_id);
+ }
+
+ fn resolve_doc_links_local(&mut self, attrs: &[ast::Attribute]) {
+ if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
+ return;
+ }
let module_id = self.current_mod.to_def_id();
+ self.resolve_doc_links(doc_attrs(attrs.iter()), module_id);
+ }
+
+ fn resolve_doc_links(&mut self, attrs: Attributes, module_id: DefId) {
let mut need_traits_in_scope = false;
- for (doc_module, doc) in
- Attributes::from_ast(attrs, None).collapsed_doc_value_by_module_level()
- {
+ for (doc_module, doc) in attrs.prepare_to_doc_link_resolution() {
assert_eq!(doc_module, None);
- for link in markdown_links(&doc.as_str()) {
- if let Some(Ok(pinfo)) = preprocess_link(&link) {
- self.resolver.resolve_rustdoc_path(&pinfo.path_str, TypeNS, module_id);
+ let links = self
+ .markdown_links
+ .entry(doc)
+ .or_insert_with_key(|doc| preprocessed_markdown_links(doc));
+ for PreprocessedMarkdownLink(pp_link, _) in links {
+ if let Ok(pinfo) = pp_link {
+ // FIXME: Resolve the path in all namespaces and resolve its prefixes too.
+ let ns = TypeNS;
+ self.doc_link_resolutions
+ .entry((Symbol::intern(&pinfo.path_str), ns, module_id))
+ .or_insert_with_key(|(path, ns, module_id)| {
+ self.resolver.resolve_rustdoc_path(path.as_str(), *ns, *module_id)
+ });
need_traits_in_scope = true;
}
}
&& module_id.is_local()
{
if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
- // FIXME: Need to resolve doc links on all these extern items
- // reached through reexports.
let scope_id = match child.res {
Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id).unwrap(),
_ => def_id,
};
- self.add_traits_in_parent_scope(scope_id); // Outer attribute scope
+ self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope
if let Res::Def(DefKind::Mod, ..) = child.res {
- self.add_traits_in_scope(def_id); // Inner attribute scope
+ self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope
}
// Traits are processed in `add_extern_traits_in_scope`.
if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res {
impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
fn visit_item(&mut self, item: &ast::Item) {
- self.load_links_in_attrs(&item.attrs); // Outer attribute scope
+ self.resolve_doc_links_local(&item.attrs); // Outer attribute scope
if let ItemKind::Mod(..) = item.kind {
let old_mod = mem::replace(&mut self.current_mod, self.resolver.local_def_id(item.id));
- self.load_links_in_attrs(&item.attrs); // Inner attribute scope
+ self.resolve_doc_links_local(&item.attrs); // Inner attribute scope
self.process_module_children_or_reexports(self.current_mod.to_def_id());
visit::walk_item(self, item);
self.current_mod = old_mod;
}
fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: AssocCtxt) {
- self.load_links_in_attrs(&item.attrs);
+ self.resolve_doc_links_local(&item.attrs);
visit::walk_assoc_item(self, item, ctxt)
}
fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
- self.load_links_in_attrs(&item.attrs);
+ self.resolve_doc_links_local(&item.attrs);
visit::walk_foreign_item(self, item)
}
fn visit_variant(&mut self, v: &ast::Variant) {
- self.load_links_in_attrs(&v.attrs);
+ self.resolve_doc_links_local(&v.attrs);
visit::walk_variant(self, v)
}
fn visit_field_def(&mut self, field: &ast::FieldDef) {
- self.load_links_in_attrs(&field.attrs);
+ self.resolve_doc_links_local(&field.attrs);
visit::walk_field_def(self, field)
}
}
});
- // Also try to inline primitive impls from other crates.
cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
for def_id in PrimitiveType::all_impls(cx.tcx) {
+ // Try to inline primitive impls from other crates.
if !def_id.is_local() {
inline::build_impl(cx, None, def_id, None, &mut new_items);
-
- // FIXME(eddyb) is this `doc(hidden)` check needed?
- if !cx.tcx.is_doc_hidden(def_id) {
+ }
+ }
+ for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) {
+ // Do not calculate blanket impl list for docs that are not going to be rendered.
+ // While the `impl` blocks themselves are only in `libcore`, the module with `doc`
+ // attached is directly included in `libstd` as well.
+ if did.is_local() {
+ for def_id in prim.impls(cx.tcx) {
let impls = get_auto_trait_and_blanket_impls(cx, def_id);
- new_items.extend(impls.filter(|i| cx.inlined.insert(i.def_id)));
+ new_items.extend(impls.filter(|i| cx.inlined.insert(i.item_id)));
}
}
}
fn visit_item(&mut self, i: &Item) {
if i.is_struct() || i.is_enum() || i.is_union() {
// FIXME(eddyb) is this `doc(hidden)` check needed?
- if !self.cx.tcx.is_doc_hidden(i.def_id.expect_def_id()) {
+ if !self.cx.tcx.is_doc_hidden(i.item_id.expect_def_id()) {
self.impls
- .extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
+ .extend(get_auto_trait_and_blanket_impls(self.cx, i.item_id.expect_def_id()));
}
}
impl DocVisitor for ItemCollector {
fn visit_item(&mut self, i: &Item) {
- self.items.insert(i.def_id);
+ self.items.insert(i.item_id);
self.visit_item_recur(i)
}
}
}
- fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
- self.items.contains(&did)
+ fn keep_impl_with_def_id(&self, item_id: ItemId) -> bool {
+ self.items.contains(&item_id)
}
}
impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
fn visit_item(&mut self, item: &Item) {
let tcx = self.cx.tcx;
- let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.def_id)
+ let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id)
// If non-local, no need to check anything.
else { return };
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
if let Some(Some(generics_start)) = (is_open_tag
- && dox[..range.end].ends_with(">"))
+ && dox[..range.end].ends_with('>'))
.then(|| extract_path_backwards(&dox, range.start))
{
let generics_sp = match super::source_span_for_markdown_range(
mod strip_priv_imports;
crate use self::strip_priv_imports::STRIP_PRIV_IMPORTS;
-mod unindent_comments;
-crate use self::unindent_comments::UNINDENT_COMMENTS;
-
mod propagate_doc_cfg;
crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
crate const PASSES: &[Pass] = &[
CHECK_DOC_TEST_VISIBILITY,
STRIP_HIDDEN,
- UNINDENT_COMMENTS,
STRIP_PRIVATE,
STRIP_PRIV_IMPORTS,
PROPAGATE_DOC_CFG,
/// The list of passes run by default.
crate const DEFAULT_PASSES: &[ConditionalPass] = &[
ConditionalPass::always(COLLECT_TRAIT_IMPLS),
- ConditionalPass::always(UNINDENT_COMMENTS),
ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate),
}
} else {
if self.update_retained {
- self.retained.insert(i.def_id);
+ self.retained.insert(i.item_id);
}
}
Some(self.fold_item_recur(i))
| clean::TraitAliasItem(..)
| clean::MacroItem(..)
| clean::ForeignTypeItem => {
- if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id.expect_def_id())
+ if i.item_id.is_local()
+ && !self.access_levels.is_exported(i.item_id.expect_def_id())
{
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
return None;
}
clean::ModuleItem(..) => {
- if i.def_id.is_local() && !i.visibility.is_public() {
+ if i.item_id.is_local() && !i.visibility.is_public() {
debug!("Stripper: stripping module {:?}", i.name);
let old = mem::replace(&mut self.update_retained, false);
let ret = strip_item(self.fold_item_recur(i));
let i = if fastreturn {
if self.update_retained {
- self.retained.insert(i.def_id);
+ self.retained.insert(i.item_id);
}
return Some(i);
} else {
};
if self.update_retained {
- self.retained.insert(i.def_id);
+ self.retained.insert(i.item_id);
}
Some(i)
}
+++ /dev/null
-//! Removes excess indentation on comments in order for the Markdown
-//! to be parsed correctly. This is necessary because the convention for
-//! writing documentation is to provide a space between the /// or //! marker
-//! and the doc text, but Markdown is whitespace-sensitive. For example,
-//! a block of text with four-space indentation is parsed as a code block,
-//! so if we didn't unindent comments, these list items
-//!
-//! /// A list:
-//! ///
-//! /// - Foo
-//! /// - Bar
-//!
-//! would be parsed as if they were in a code block, which is likely not what the user intended.
-use std::cmp;
-
-use rustc_span::symbol::kw;
-
-use crate::clean::{self, DocFragment, DocFragmentKind, Item};
-use crate::core::DocContext;
-use crate::fold::{self, DocFolder};
-use crate::passes::Pass;
-
-#[cfg(test)]
-mod tests;
-
-crate const UNINDENT_COMMENTS: Pass = Pass {
- name: "unindent-comments",
- run: unindent_comments,
- description: "removes excess indentation on comments in order for markdown to like it",
-};
-
-crate fn unindent_comments(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
- CommentCleaner.fold_crate(krate)
-}
-
-struct CommentCleaner;
-
-impl fold::DocFolder for CommentCleaner {
- fn fold_item(&mut self, mut i: Item) -> Option<Item> {
- i.attrs.unindent_doc_comments();
- Some(self.fold_item_recur(i))
- }
-}
-
-impl clean::Attributes {
- crate fn unindent_doc_comments(&mut self) {
- unindent_fragments(&mut self.doc_strings);
- }
-}
-
-fn unindent_fragments(docs: &mut Vec<DocFragment>) {
- // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
- // fragments kind's lines are never starting with a whitespace unless they are using some
- // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
- // we need to take into account the fact that the minimum indent minus one (to take this
- // whitespace into account).
- //
- // For example:
- //
- // /// hello!
- // #[doc = "another"]
- //
- // In this case, you want "hello! another" and not "hello! another".
- let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
- && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
- {
- // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
- // "decide" how much the minimum indent will be.
- 1
- } else {
- 0
- };
-
- // `min_indent` is used to know how much whitespaces from the start of each lines must be
- // removed. Example:
- //
- // /// hello!
- // #[doc = "another"]
- //
- // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
- // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
- // (5 - 1) whitespaces.
- let Some(min_indent) = docs
- .iter()
- .map(|fragment| {
- fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
- if line.chars().all(|c| c.is_whitespace()) {
- min_indent
- } else {
- // Compare against either space or tab, ignoring whether they are
- // mixed or not.
- let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
- cmp::min(min_indent, whitespace)
- + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
- }
- })
- })
- .min()
- else {
- return;
- };
-
- for fragment in docs {
- if fragment.doc == kw::Empty {
- continue;
- }
-
- let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
- min_indent - add
- } else {
- min_indent
- };
-
- fragment.indent = min_indent;
- }
-}
+++ /dev/null
-use super::*;
-
-use crate::clean::collapse_doc_fragments;
-
-use rustc_span::create_default_session_globals_then;
-use rustc_span::source_map::DUMMY_SP;
-use rustc_span::symbol::Symbol;
-
-fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
- vec![DocFragment {
- span: DUMMY_SP,
- parent_module: None,
- doc: Symbol::intern(s),
- kind: DocFragmentKind::SugaredDoc,
- indent: 0,
- }]
-}
-
-#[track_caller]
-fn run_test(input: &str, expected: &str) {
- create_default_session_globals_then(|| {
- let mut s = create_doc_fragment(input);
- unindent_fragments(&mut s);
- assert_eq!(collapse_doc_fragments(&s), expected);
- });
-}
-
-#[test]
-fn should_unindent() {
- run_test(" line1\n line2", "line1\nline2");
-}
-
-#[test]
-fn should_unindent_multiple_paragraphs() {
- run_test(" line1\n\n line2", "line1\n\nline2");
-}
-
-#[test]
-fn should_leave_multiple_indent_levels() {
- // Line 2 is indented another level beyond the
- // base indentation and should be preserved
- run_test(" line1\n\n line2", "line1\n\n line2");
-}
-
-#[test]
-fn should_ignore_first_line_indent() {
- run_test("line1\n line2", "line1\n line2");
-}
-
-#[test]
-fn should_not_ignore_first_line_indent_in_a_single_line_para() {
- run_test("line1\n\n line2", "line1\n\n line2");
-}
-
-#[test]
-fn should_unindent_tabs() {
- run_test("\tline1\n\tline2", "line1\nline2");
-}
-
-#[test]
-fn should_trim_mixed_indentation() {
- run_test("\t line1\n\t line2", "line1\nline2");
- run_test(" \tline1\n \tline2", "line1\nline2");
-}
-
-#[test]
-fn should_not_trim() {
- run_test("\t line1 \n\t line2", "line1 \nline2");
- run_test(" \tline1 \n \tline2", "line1 \nline2");
-}
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId};
use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
use rustc_middle::ty::TyCtxt;
}
crate fn visit_lib(&mut self, cnum: CrateNum) {
- let did = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+ let did = cnum.as_def_id();
self.update(did, Some(AccessLevel::Public));
self.visit_mod(did);
}
-Subproject commit 9168e236c548d1d0e9938ee6dd4cdbd308fdfd72
+Subproject commit fd336816c3a6d228dcef22171c43140f6fa7656f
// only-x86_64
+// only-linux
// assembly-output: emit-asm
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
-#![feature(asm_const)]
+#![feature(asm_const, asm_sym)]
#![crate_type = "rlib"]
use std::arch::global_asm;
+#[no_mangle]
+fn my_func() {}
+
+#[no_mangle]
+static MY_STATIC: i32 = 0;
+
// CHECK: mov eax, eax
global_asm!("mov eax, eax");
// CHECK: mov ebx, 5
global_asm!("mov ebx, {}", const 5);
// CHECK: mov ecx, 5
global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
+// CHECK: call my_func
+global_asm!("call {}", sym my_func);
+// CHECK: lea rax, [rip + MY_STATIC]
+global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
use std::arch::asm;
// CHECK-LABEL: @clobber_sysv64
-// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
#[no_mangle]
pub unsafe fn clobber_sysv64() {
asm!("", clobber_abi("sysv64"));
}
// CHECK-LABEL: @clobber_win64
-// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
#[no_mangle]
pub unsafe fn clobber_win64() {
asm!("", clobber_abi("win64"));
}
// CHECK-LABEL: @clobber_sysv64
-// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
#[no_mangle]
pub unsafe fn clobber_sysv64_edx() {
let foo: i32;
}
// CHECK-LABEL: @clobber_win64
-// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
#[no_mangle]
pub unsafe fn clobber_win64_edx() {
let foo: i32;
#[no_mangle]
fn into_error(self, error: Self::Source) -> Error {
Error::Api {
- source: (|v| v)(error),
+ source: error,
}
}
}
--- /dev/null
+// compile-flags: -C no-prepopulate-passes
+// only-64bit (because the LLVM type of i64 for usize shows up)
+//
+
+#![crate_type = "lib"]
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+ pub(crate) fn simd_arith_offset<T, U>(ptrs: T, offsets: U) -> T;
+}
+
+/// A vector of *const T.
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
+
+#[derive(Debug, Copy, Clone)]
+#[repr(simd)]
+pub struct Simd<T, const LANES: usize>([T; LANES]);
+
+// CHECK-LABEL: smoke
+#[no_mangle]
+pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
+ // CHECK: getelementptr i8, <8 x i8*> %_3, <8 x i64> %_4
+ unsafe { simd_arith_offset(ptrs, offsets) }
+}
+++ /dev/null
-// compile-flags: -O
-
-#![crate_type = "lib"]
-
-// CHECK-LABEL: @vec_clear
-#[no_mangle]
-pub fn vec_clear(x: &mut Vec<u32>) {
- // CHECK-NOT: load
- // CHECK-NOT: icmp
- x.clear()
-}
+// min-llvm-version: 14.0
// ignore-debug: the debug assertions get in the way
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
#![crate_type = "lib"]
// Ensure that trivial casts of vec elements are O(1)
-// CHECK-LABEL: @vec_iterator_cast
+pub struct Wrapper<T>(T);
+
+#[repr(C)]
+pub struct Foo {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+}
+
+// Going from an aggregate struct to another type currently requires Copy to
+// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
+// reliably recognize the loops as noop for for repr(C) or non-Copy structs.
+#[derive(Copy, Clone)]
+pub struct Bar {
+ a: u64,
+ b: u64,
+ c: u64,
+ d: u64,
+}
+
+// CHECK-LABEL: @vec_iterator_cast_primitive
+#[no_mangle]
+pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
+ vec.into_iter().map(|e| e as u8).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_wrapper
+#[no_mangle]
+pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
+ vec.into_iter().map(|e| Wrapper(e)).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_unwrap
+#[no_mangle]
+pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
+ vec.into_iter().map(|e| e.0).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_aggregate
#[no_mangle]
-pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> {
+pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
// CHECK-NOT: loop
// CHECK-NOT: call
- vec.into_iter().map(|e| e as usize).collect()
+ vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
+}
+
+// CHECK-LABEL: @vec_iterator_cast_deaggregate
+#[no_mangle]
+pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> {
+ // CHECK-NOT: loop
+ // CHECK-NOT: call
+
+ // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
+ // This currently is not guaranteed for repr(Rust) types, but it happens to work here and
+ // the UCG may add additional guarantees for homogenous types in the future that would make this
+ // correct.
+ vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
}
--- /dev/null
+// compile-flags:-g
+
+// We only test Rust-aware versions of GDB:
+// min-gdb-version: 8.2
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print _ref
+// gdb-check: $1 = (*mut ()) 0x[...]
+
+// gdb-command: print _ptr
+// gdb-check: $2 = (*mut ()) 0x[...]
+
+// gdb-command: print _local
+// gdb-check: $3 = ()
+
+// gdb-command: print _field
+// gdb-check: $4 = unit_type::_TypeContainingUnitField {_a: 123, _unit: (), _b: 456}
+
+// Check that we can cast "void pointers" to their actual type in the debugger
+// gdb-command: print /x *(_ptr as *const u64)
+// gdb-check: $5 = 0x1122334455667788
+
+// === CDB TESTS ===================================================================================
+
+// cdb-command: g
+// cdb-check: Breakpoint 0 hit
+
+// cdb-command: dx _ref
+// cdb-check: _ref : 0x[...] : () [Type: tuple$<> *]
+
+// cdb-command: dx _ptr
+// cdb-check: _ptr : 0x[...] : () [Type: tuple$<> *]
+
+// cdb-command: dx _local
+// cdb-check: _local : () [Type: tuple$<>]
+
+// cdb-command: dx _field,d
+// cdb-check: _field,d [Type: unit_type::_TypeContainingUnitField]
+// cdb-check: [+0x[...]] _a : 123 [Type: unsigned int]
+// cdb-check: [+0x[...]] _unit : () [Type: tuple$<>]
+// cdb-check: [+0x[...]] _b : 456 [Type: unsigned __int64]
+
+// Check that we can cast "void pointers" to their actual type in the debugger
+// cdb-command: dx ((__int64 *)_ptr),x
+// cdb-check: ((__int64 *)_ptr),x : 0x[...] : 0x1122334455667788 [Type: __int64 *]
+// cdb-check: 0x1122334455667788 [Type: __int64]
+
+struct _TypeContainingUnitField {
+ _a: u32,
+ _unit: (),
+ _b: u64,
+}
+
+fn foo(_ref: &(), _ptr: *const ()) {
+ let _local = ();
+ let _field = _TypeContainingUnitField { _a: 123, _unit: (), _b: 456 };
+
+ zzz(); // #break
+}
+
+fn main() {
+ let pointee = 0x1122_3344_5566_7788i64;
+
+ foo(&(), &pointee as *const i64 as *const ());
+}
+
+#[inline(never)]
+fn zzz() {}
// Change enum visibility -----------------------------------------------------
#[cfg(any(cfail1,cfail4))]
-enum EnumVisibility { A }
+enum EnumVisibility { A }
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
-pub enum EnumVisibility {
- A
-}
+pub enum EnumVisibility { A }
// Change Method Privacy -------------------------------------------------------
#[cfg(any(cfail1,cfail4))]
impl Foo {
- //------------------------------------------------------------------------------
+ //----------------------------------------------------
//--------------------------
//------------------------------------------------------------------------------
//--------------------------
#[rustc_clean(cfg="cfail5")]
#[rustc_clean(cfg="cfail6")]
impl Foo {
- #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail2", except="associated_item")]
#[rustc_clean(cfg="cfail3")]
- #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item")]
#[rustc_clean(cfg="cfail6")]
fn method_privacy() { }
}
// Change static visibility
#[cfg(any(cfail1,cfail4))]
-static STATIC_VISIBILITY: u8 = 0;
+static STATIC_VISIBILITY: u8 = 0;
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
// Tuple Struct Field Visibility -----------------------------------------------
#[cfg(any(cfail1,cfail4))]
-struct TupleStructFieldVisibility(char);
+struct TupleStructFieldVisibility( char);
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="type_of")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail6")]
struct TupleStructFieldVisibility(pub char);
// Record Struct Field Visibility ----------------------------------------------
#[cfg(any(cfail1,cfail4))]
-struct RecordStructFieldVisibility { x: f32 }
+struct RecordStructFieldVisibility { x: f32 }
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="type_of")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
#[rustc_clean(cfg="cfail6")]
-struct RecordStructFieldVisibility {
- pub x: f32
-}
+struct RecordStructFieldVisibility { pub x: f32 }
// Add Lifetime Parameter ------------------------------------------------------
// Visibility ------------------------------------------------------------------
#[cfg(any(cfail1,cfail4))]
-struct Visibility;
+struct Visibility;
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
pub struct Visibility;
trait TraitVisibility { }
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
pub trait TraitVisibility { }
-// compile-flags: -C opt-level=0 -Z inline_mir=no
+// unit-test: InstCombine
// ignore-wasm32 compiled with panic=abort by default
// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
}
bb0: {
+ StorageLive(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
_2 = &((*_1).0: T); // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+ StorageLive(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
_3 = &((*_1).1: u64); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ StorageLive(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
_4 = &((*_1).2: [f32; 3]); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ StorageLive(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+ StorageLive(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+ StorageLive(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
- _7 = &(*_2); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
- _6 = &(*_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+ _7 = _2; // scope 1 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
}
bb1: {
+ StorageDead(_6); // scope 1 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9
+ StorageLive(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ StorageLive(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ StorageLive(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _10 = &(*_3); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _9 = &(*_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- _8 = <u64 as Clone>::clone(move _9) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
}
bb2: {
+ StorageDead(_9); // scope 1 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11
+ StorageLive(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ StorageLive(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ StorageLive(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _13 = &(*_4); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _12 = &(*_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- _11 = <[f32; 3] as Clone>::clone(move _12) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
}
bb3: {
+ StorageDead(_12); // scope 1 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
Deinit(_0); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.0: T) = move _5; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.1: u64) = move _8; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
(_0.2: [f32; 3]) = move _11; // scope 1 at $DIR/combine_clone_of_primitives.rs:6:10: 6:15
+ StorageDead(_13); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_11); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_10); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_8); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_7); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_5); // scope 1 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_4); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_3); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
+ StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:6:14: 6:15
return; // scope 0 at $DIR/combine_clone_of_primitives.rs:6:15: 6:15
}
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2
-+ }
-+
+ }
+
+- bb5 (cleanup): {
+- resume; // scope 0 at $DIR/early_otherwise_branch.rs:3:1: 8:2
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
-- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb7]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2
}
-- bb7: {
-- unreachable; // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
+- bb7 (cleanup): {
+- resume; // scope 0 at $DIR/early_otherwise_branch.rs:11:1: 17:2
+ bb5: {
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:26:1: 26:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:26:2: 26:2
-+ }
-+
+ }
+
+- bb5 (cleanup): {
+- resume; // scope 0 at $DIR/early_otherwise_branch.rs:21:1: 26:2
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:22:5: 22:17
-// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
// EMIT_MIR early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>) -> u32 {
match (x, y) {
+ bb4: {
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:1: 9:2
return; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:9:2: 9:2
-+ }
-+
+ }
+
+- bb6 (cleanup): {
+- resume; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:4:1: 9:2
+ bb5: {
+ StorageDead(_15); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
+ switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
-// compile-flags: -Z mir-opt-level=4 -Z unsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
// EMIT_MIR early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
fn opt1(x: Option<u32>, y: Option<u32>, z: Option<u32>) -> u32 {
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
- switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+ switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
}
bb1: {
_6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
- switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+ switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
}
bb2: {
_0 = const 3_u32; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
- goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
+ goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
}
bb3: {
- _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
- switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+ unreachable; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
}
bb4: {
+ _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
+ switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
+ }
+
+ bb5: {
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:15: 9:16
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:24: 9:25
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
- goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
+ goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
}
- bb5: {
+ bb6: {
StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
_11 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
_0 = const 1_u32; // scope 2 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
- goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
+ goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
}
- bb6: {
+ bb7: {
StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
_12 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
_0 = const 2_u32; // scope 3 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
- goto -> bb7; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
+ goto -> bb8; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
}
- bb7: {
+ bb8: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:1: 14:2
return; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:14:2: 14:2
}
+
+ bb9 (cleanup): {
+ resume; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:7:1: 14:2
+ }
}
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
// must not optimize as it does not follow the pattern of
// left and right hand side being the same variant
bb1: {
_0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
- return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
+ goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:25:14: 25:15
}
bb2: {
bb3: {
_0 = const 0_i32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
- return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
+ goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:23:18: 23:19
}
bb4: {
_5 = (((*_2) as Some).0: i32); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:18: 22:19
_0 = _5; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
- return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
+ goto -> bb5; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:22:24: 22:25
+ }
+
+ bb5: {
+ return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:27:2: 27:2
+ }
+
+ bb6 (cleanup): {
+ resume; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:18:1: 27:2
}
}
bb2: {
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39
- return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
}
bb3: {
_0 = const 2_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:49: 13:50
- return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
+ }
+
+ bb4: {
+ return; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:14:2: 14:2
+ }
+
+ bb5 (cleanup): {
+ resume; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:12:1: 14:2
}
}
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
+// unit-test: EarlyOtherwiseBranch
// Tests various cases that the `early_otherwise_branch` opt should *not* optimize
-// compile-flags: -O
+// unit-test: SimplifyComparisonIntegral
// EMIT_MIR if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
// EMIT_MIR if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
// EMIT_MIR if_condition_int.opt_char.SimplifyComparisonIntegral.diff
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:17:25: 17:26
return; // scope 0 at $DIR/if-condition-int.rs:18:2: 18:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:16:1: 18:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:53:34: 53:35
return; // scope 0 at $DIR/if-condition-int.rs:54:2: 54:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:52:1: 54:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:49:1: 49:2
return; // scope 0 at $DIR/if-condition-int.rs:49:2: 49:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:43:1: 49:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:21:32: 21:33
return; // scope 0 at $DIR/if-condition-int.rs:22:2: 22:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:20:1: 22:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:25:31: 25:32
return; // scope 0 at $DIR/if-condition-int.rs:26:2: 26:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:24:1: 26:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:39:5: 39:6
return; // scope 0 at $DIR/if-condition-int.rs:40:2: 40:2
}
+
+ bb7 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:32:1: 40:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:29:32: 29:33
return; // scope 0 at $DIR/if-condition-int.rs:30:2: 30:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:28:1: 30:2
+ }
}
StorageDead(_2); // scope 0 at $DIR/if-condition-int.rs:12:31: 12:32
return; // scope 0 at $DIR/if-condition-int.rs:13:2: 13:2
}
+
+ bb4 (cleanup): {
+ resume; // scope 0 at $DIR/if-condition-int.rs:11:1: 13:2
+ }
}
fn h() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+ let mut _9: (); // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
-+ let mut _10: (); // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
++ let mut _2: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++ let mut _3: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++ let mut _10: (); // in scope 0 at $DIR/inline-diverging.rs:27:13: 27:16
++ let mut _11: (); // in scope 0 at $DIR/inline-diverging.rs:28:13: 28:16
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
-+ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
-+ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+ let mut _6: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
-+ let mut _7: !; // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
-+ let mut _8: !; // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
++ debug f => _3; // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
++ let _4: !; // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++ let mut _5: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++ let mut _7: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
++ let mut _8: !; // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
++ let mut _9: !; // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
+ scope 2 {
-+ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
-+ let _5: !; // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
++ debug a => _4; // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
++ let _6: !; // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
+ scope 3 {
-+ debug b => _5; // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
++ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
+ }
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
+ scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep) -> bb1; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
+- call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
+ StorageLive(_2); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
-+ _2 = sleep; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++ StorageLive(_3); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
++ _3 = sleep; // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
// mir::Constant
- // + span: $DIR/inline-diverging.rs:22:5: 22:15
- // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(Scalar(<ZST>)) }
- // mir::Constant
// + span: $DIR/inline-diverging.rs:22:16: 22:21
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
-+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
-+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
-+ StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
-+ _9 = const (); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++ StorageLive(_5); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++ _5 = &_3; // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++ StorageLive(_10); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++ _10 = const (); // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
- }
-
- bb1: {
-- StorageDead(_1); // scope 0 at $DIR/inline-diverging.rs:22:22: 22:23
-- _0 = const (); // scope 0 at $DIR/inline-diverging.rs:21:12: 23:2
-- return; // scope 0 at $DIR/inline-diverging.rs:23:2: 23:2
++ }
++
++ bb1: {
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
}
}
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
// mir::Constant
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
- // + user_ty: UserType(1)
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
// mir::Constant
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
- // + user_ty: UserType(1)
StorageLive(_2); // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
StorageLive(_3); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
_3 = (); // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
- _2 = transmute::<(), Void>(move _3) -> [return: bb1, unwind: bb4]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
+ transmute::<(), Void>(move _3) -> bb4; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
// mir::Constant
// + span: $DIR/issue-72181-1.rs:17:9: 17:40
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
-// compile-flags: -Z mir-opt-level=3
+// unit-test: LowerSliceLenCalls
// EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
pub fn bound(index: usize, slice: &[u8]) -> u8 {
| '_#2r live at {bb0[0..=1]}
| '_#3r live at {bb0[0..=1]}
| '_#4r live at {bb0[0..=1]}
-| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
-| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
-| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
-| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
-| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27)
-| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43)
-| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55)
-| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67)
+| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
+| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
|
fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> bool {
debug w => _1; // in scope 0 at $DIR/named-lifetimes-basic.rs:12:26: 12:27
| '_#3r live at {bb1[0]}
| '_#4r live at {bb1[1..=3]}
| '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0])
-| '_#4r: '_#5r due to Assignment at Single(bb1[3])
+| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
| '_#3r live at {bb1[0]}
| '_#4r live at {bb1[1..=3]}
| '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0])
-| '_#4r: '_#5r due to Assignment at Single(bb1[3])
+| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
-// compile-flags: -Zmir-opt-level=1
+// unit-test: RenameReturnPlace
// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
- StorageDead(_2); // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2
return; // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2
}
+
+ bb2 (cleanup): {
+ resume; // scope 0 at $DIR/nrvo-simple.rs:4:1: 8:2
+ }
}
| '_#1r live at {bb0[0..=22]}
| '_#3r live at {bb0[10]}
| '_#4r live at {bb0[11]}
-| '_#3r: '_#4r due to Assignment at Single(bb0[10])
+| '_#3r: '_#4r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0)
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/storage_ranges.rs:3:11: 3:11
// pretty-mode:hir
// pp-exact:hir-pretty-loop.pp
-pub fn foo() { loop { break; } }
+fn foo() { loop { break; } }
// #4264 fixed-length vector types
-pub fn foo(_: [i32; (3 as usize)]) ({ } as ())
+fn foo(_: [i32; (3 as usize)]) ({ } as ())
-pub fn bar() ({
+fn bar() ({
const FOO: usize = ((5 as usize) - (4 as usize) as usize);
let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]);
(res as String)
} as String);
} as ())
-pub type Foo = [i32; (3 as usize)];
-pub struct Bar {
- pub x: [i32; (3 as usize)],
+type Foo = [i32; (3 as usize)];
+struct Bar {
+ x: [i32; (3 as usize)],
}
-pub struct TupleBar([i32; (4 as usize)]);
-pub enum Baz { BazVariant([i32; (5 as usize)]), }
-pub fn id<T>(x: T) -> T ({ (x as T) } as T)
-pub fn use_id() ({
+struct TupleBar([i32; (4 as usize)]);
+enum Baz { BazVariant([i32; (5 as usize)]), }
+fn id<T>(x: T) -> T ({ (x as T) } as T)
+fn use_id() ({
let _ =
((id::<[i32; (3 as usize)]> as
fn([i32; 3]) -> [i32; 3] {id::<[i32; 3]>})(([(1 as i32),
// pp-exact
#![feature(box_syntax)]
+#![feature(inline_const)]
+#![feature(inline_const_pat)]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#[rustc_dummy]
unsafe {
+ #![rustc_dummy]
// code
}
}
let _ = ();
()
};
+ let const {
+ #![rustc_dummy]
+ } =
+ #[rustc_dummy] const {
+ #![rustc_dummy]
+ };
let mut x = 0;
let _ = #[rustc_dummy] x = 15;
let _ = #[rustc_dummy] x += 15;
# ignore-stage1
+# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen
+# backends and that this external codegen backend is only included in the dep info if
+# -Zbinary-dep-depinfo is used.
+
all:
/bin/echo || exit 0 # This test requires /bin/echo to exist
$(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
-o $(TMPDIR)/the_backend.dylib
+
+ $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
+ -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
+ --emit link,dep-info
+ grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
+ # don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used.
+ grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d
+
$(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \
- -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options
- grep -x "This has been \"compiled\" successfully." $(TMPDIR)/some_crate
+ -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \
+ --emit link,dep-info -Zbinary-dep-depinfo
+ grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib
+ # but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used.
+ grep "the_backend.dylib" $(TMPDIR)/some_crate.d
// Just to be sure we're comparing the correct "item-info":
assert-text: (
".item-info",
- "This is supported on Android or Linux or Emscripten or DragonFly BSD",
+ "Available on Android or Linux or Emscripten or DragonFly BSD",
STARTS_WITH,
)
// Just to be sure we're comparing the correct "item-info":
assert-text: (
"#impl-SimpleTrait .item-info",
- "This is supported on Android or Linux or Emscripten or DragonFly BSD",
+ "Available on Android or Linux or Emscripten or DragonFly BSD",
STARTS_WITH,
)
size: (1100, 800)
// We check that ".item-info" is bigger than its content.
assert-css: (".item-info", {"width": "790px"})
-assert-css: (".item-info .stab", {"width": "340px"})
+assert-css: (".item-info .stab", {"width": "289px"})
assert-position: (".item-info .stab", {"x": 295})
// exact-check
-const QUERY = 'hashmap';
+const QUERY = '"hashmap"';
const FILTER_CRATE = 'core';
const EXPECTED = {
--- /dev/null
+const QUERY = [
+ '<P>',
+ '-> <P>',
+ 'a<"P">',
+ '"P" "P"',
+ 'P "P"',
+ '"p" p',
+ '"const": p',
+ "a<:a>",
+ "a<::a>",
+ "((a))",
+ "(p -> p",
+ "::a::b",
+ "a::::b",
+ "a::b::",
+ ":a",
+ "a b:",
+ "a (b:",
+ "_:",
+ "a-bb",
+ "a>bb",
+ "ab'",
+ "a->",
+ '"p" <a>',
+ '"p" a<a>',
+ "a,<",
+ "aaaaa<>b",
+ "fn:aaaaa<>b",
+ "->a<>b",
+ "a<->",
+ "a:: a",
+ "a ::a",
+ "a<a>:",
+ "a<>:",
+ "a,:",
+ " a<> :",
+ "mod : :",
+];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 0,
+ original: "<P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "<p>",
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "-> <P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "-> <p>",
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<\"P\">",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<\"p\">",
+ error: "`\"` cannot be used in generics",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"P\" \"P\"",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"p\" \"p\"",
+ error: "Cannot have more than one literal search element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "P \"P\"",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "p \"p\"",
+ error: "Cannot use literal search when there is more than one element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"p\" p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"p\" p",
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "\"const\": p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "\"const\": p",
+ error: "You cannot use quotes on type filter",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<:a>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<:a>",
+ error: "Unexpected `:` after `<`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<::a>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<::a>",
+ error: "Unexpected `::`: paths cannot start with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "((a))",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "((a))",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "(p -> p",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "(p -> p",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "::a::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "::a::b",
+ error: "Paths cannot start with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a::::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::::b",
+ error: "Unexpected `::::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a::b::",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::b::",
+ error: "Paths cannot end with `::`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: ":a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: ":a",
+ error: "Expected type filter before `:`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a b:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b:",
+ error: "Unexpected `:`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a (b:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a (b:",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "_:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "_:",
+ error: "Unknown type filter `_`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a-bb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a-bb",
+ error: "Unexpected `-` (did you mean `->`?)",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a>bb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a>bb",
+ error: "Unexpected `>` (did you mean `->`?)",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "ab'",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "ab'",
+ error: "Unexpected `'`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a->",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a->",
+ error: "Expected at least one item after `->`",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" <a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" <a>',
+ error: "Found generics without a path",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" a<a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" a<a>',
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a,<',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a,<',
+ error: 'Found generics without a path',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'aaaaa<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'aaaaa<>b',
+ error: 'Expected `,`, ` `, `:` or `->`, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'fn:aaaaa<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'fn:aaaaa<>b',
+ error: 'Expected `,`, ` ` or `->`, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '->a<>b',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '->a<>b',
+ error: 'Expected `,` or ` `, found `b`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a<->',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a<->',
+ error: 'Unexpected `-` after `<`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a:: a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a:: a',
+ error: 'Paths cannot end with `::`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'a ::a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a ::a',
+ error: 'Paths cannot start with `::`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<a>:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<a>:",
+ error: 'Unexpected `:`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<>:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<>:",
+ error: 'Unexpected `<` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a,:",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,:",
+ error: 'Unexpected `,` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<> :",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<> :",
+ error: 'Unexpected `<` in type filter',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "mod : :",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "mod : :",
+ error: 'Unexpected `:`',
+ },
+];
--- /dev/null
+const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "foo",
+ fullPath: ["foo"],
+ pathWithoutLast: [],
+ pathLast: "foo",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "fn:foo",
+ returned: [],
+ typeFilter: 5,
+ userQuery: "fn:foo",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "foo",
+ fullPath: ["foo"],
+ pathWithoutLast: [],
+ pathLast: "foo",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "enum : foo",
+ returned: [],
+ typeFilter: 4,
+ userQuery: "enum : foo",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "macro<f>:foo",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "macro<f>:foo",
+ error: "Unexpected `:`",
+ },
+];
--- /dev/null
+const QUERY = ['A<B<C<D>, E>', 'p<> u8', '"p"<a>'];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'A<B<C<D>, E>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a<b<c<d>, e>',
+ error: 'Unexpected `<` after `<`',
+ },
+ {
+ elems: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ {
+ name: "u8",
+ fullPath: ["u8"],
+ pathWithoutLast: [],
+ pathLast: "u8",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "p<> u8",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "p<> u8",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: '"p"<a>',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p"<a>',
+ error: null,
+ },
+];
--- /dev/null
+const QUERY = ['R<P>'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "r",
+ fullPath: ["r"],
+ pathWithoutLast: [],
+ pathLast: "r",
+ generics: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ ],
+ }],
+ foundElems: 1,
+ original: "R<P>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "r<p>",
+ error: null,
+ }
+];
--- /dev/null
+const QUERY = ['A::B', 'A::B,C', 'A::B<f>,C', 'mod::a'];
+
+const PARSED = [
+ {
+ elems: [{
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "A::B",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a::b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [],
+ },
+ {
+ name: "c",
+ fullPath: ["c"],
+ pathWithoutLast: [],
+ pathLast: "c",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: 'A::B,C',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a::b,c',
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a::b",
+ fullPath: ["a", "b"],
+ pathWithoutLast: ["a"],
+ pathLast: "b",
+ generics: [
+ {
+ name: "f",
+ fullPath: ["f"],
+ pathWithoutLast: [],
+ pathLast: "f",
+ generics: [],
+ },
+ ],
+ },
+ {
+ name: "c",
+ fullPath: ["c"],
+ pathWithoutLast: [],
+ pathLast: "c",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: 'A::B<f>,C',
+ returned: [],
+ typeFilter: -1,
+ userQuery: 'a::b<f>,c',
+ error: null,
+ },
+ {
+ elems: [{
+ name: "mod::a",
+ fullPath: ["mod", "a"],
+ pathWithoutLast: ["mod"],
+ pathLast: "a",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "mod::a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "mod::a",
+ error: null,
+ },
+];
--- /dev/null
+const QUERY = [
+ '-> "p"',
+ '"p",',
+ '"p" -> a',
+ '"a" -> "p"',
+ '->"-"',
+ '"a',
+ '""',
+];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 1,
+ original: '-> "p"',
+ returned: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: '-> "p"',
+ error: null,
+ },
+ {
+ elems: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: '"p",',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p",',
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"p" -> a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"p" -> a',
+ error: "You cannot have more than one element if you use quotes",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"a" -> "p"',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"a" -> "p"',
+ error: "Cannot have more than one literal search element",
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '->"-"',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '->"-"',
+ error: 'Unexpected `-` in a string element',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '"a',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '"a',
+ error: 'Unclosed `"`',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: '""',
+ returned: [],
+ typeFilter: -1,
+ userQuery: '""',
+ error: 'Cannot have empty string element',
+ },
+];
--- /dev/null
+const QUERY = ['-> F<P>', '-> P', '->,a', 'aaaaa->a'];
+
+const PARSED = [
+ {
+ elems: [],
+ foundElems: 1,
+ original: "-> F<P>",
+ returned: [{
+ name: "f",
+ fullPath: ["f"],
+ pathWithoutLast: [],
+ pathLast: "f",
+ generics: [
+ {
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ },
+ ],
+ }],
+ typeFilter: -1,
+ userQuery: "-> f<p>",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 1,
+ original: "-> P",
+ returned: [{
+ name: "p",
+ fullPath: ["p"],
+ pathWithoutLast: [],
+ pathLast: "p",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "-> p",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 1,
+ original: "->,a",
+ returned: [{
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "->,a",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "aaaaa",
+ fullPath: ["aaaaa"],
+ pathWithoutLast: [],
+ pathLast: "aaaaa",
+ generics: [],
+ }],
+ foundElems: 2,
+ original: "aaaaa->a",
+ returned: [{
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ }],
+ typeFilter: -1,
+ userQuery: "aaaaa->a",
+ error: null,
+ },
+];
--- /dev/null
+// ignore-tidy-tab
+
+const QUERY = [
+ 'aaaaaa b',
+ 'a b',
+ 'a,b',
+ 'a\tb',
+ 'a<b c>',
+ 'a<b,c>',
+ 'a<b\tc>',
+];
+
+const PARSED = [
+ {
+ elems: [
+ {
+ name: 'aaaaaa',
+ fullPath: ['aaaaaa'],
+ pathWithoutLast: [],
+ pathLast: 'aaaaaa',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "aaaaaa b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "aaaaaa b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a,b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [],
+ },
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a\tb",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a\tb",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b c>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b c>",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b,c>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b,c>",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: 'a',
+ fullPath: ['a'],
+ pathWithoutLast: [],
+ pathLast: 'a',
+ generics: [
+ {
+ name: 'b',
+ fullPath: ['b'],
+ pathWithoutLast: [],
+ pathLast: 'b',
+ generics: [],
+ },
+ {
+ name: 'c',
+ fullPath: ['c'],
+ pathWithoutLast: [],
+ pathLast: 'c',
+ generics: [],
+ },
+ ],
+ },
+ ],
+ foundElems: 1,
+ original: "a<b\tc>",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<b\tc>",
+ error: null,
+ },
+];
--- /dev/null
+// This test is mostly to check that the parser still kinda outputs something
+// (and doesn't enter an infinite loop!) even though the query is completely
+// invalid.
+const QUERY = [
+ 'a b',
+ 'a b',
+ 'a,b(c)',
+ 'aaa,a',
+ ',,,,',
+ 'mod :',
+ 'mod\t:',
+];
+
+const PARSED = [
+ {
+ elems: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ {
+ name: "b",
+ fullPath: ["b"],
+ pathWithoutLast: [],
+ pathLast: "b",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ {
+ name: "b",
+ fullPath: ["b"],
+ pathWithoutLast: [],
+ pathLast: "b",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "a b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a b",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a,b(c)",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a,b(c)",
+ error: "Unexpected `(`",
+ },
+ {
+ elems: [
+ {
+ name: "aaa",
+ fullPath: ["aaa"],
+ pathWithoutLast: [],
+ pathLast: "aaa",
+ generics: [],
+ },
+ {
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ },
+ ],
+ foundElems: 2,
+ original: "aaa,a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "aaa,a",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: ",,,,",
+ returned: [],
+ typeFilter: -1,
+ userQuery: ",,,,",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'mod :',
+ returned: [],
+ typeFilter: 0,
+ userQuery: 'mod :',
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: 'mod\t:',
+ returned: [],
+ typeFilter: 0,
+ userQuery: 'mod\t:',
+ error: null,
+ },
+];
+// ignore-order
+
const QUERY = '"error"';
+const FILTER_CRATE = 'std';
const EXPECTED = {
'others': [
{ 'path': 'std::fmt', 'name': 'Error' },
{ 'path': 'std::io', 'name': 'Error' },
],
- 'in_args': [],
+ 'in_args': [
+ { 'path': 'std::fmt::Error', 'name': 'eq' },
+ { 'path': 'std::fmt::Error', 'name': 'cmp' },
+ { 'path': 'std::fmt::Error', 'name': 'partial_cmp' },
+
+ ],
'returned': [
{ 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
],
-const QUERY = 'struct:Vec';
+const QUERY = 'struct:VecD';
const EXPECTED = {
'others': [
- { 'path': 'std::vec', 'name': 'Vec' },
{ 'path': 'std::collections', 'name': 'VecDeque' },
+ { 'path': 'std::vec', 'name': 'Vec' },
],
};
// exact-check
const QUERY = 'macro:print';
+const FILTER_CRATE = 'std';
const EXPECTED = {
'others': [
{ 'path': 'std', 'name': 'println' },
{ 'path': 'std', 'name': 'eprintln' },
{ 'path': 'std::pin', 'name': 'pin' },
- { 'path': 'core::pin', 'name': 'pin' },
+ { 'path': 'std::future', 'name': 'join' },
+ { 'path': 'std', 'name': 'line' },
+ { 'path': 'std', 'name': 'write' },
],
};
'others': [
{ 'path': 'std::vec::Vec', 'name': 'new' },
{ 'path': 'std::vec::Vec', 'name': 'ne' },
- { 'path': 'std::rc::Rc', 'name': 'ne' },
+ { 'path': 'alloc::vec::Vec', 'name': 'ne' },
],
};
// exact-check
-const QUERY = 'true';
+const QUERY = '"true"';
const FILTER_CRATE = 'doc_alias_filter';
const EXPECTED = [
{
+ // StructItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // StructFieldItem
'others': [
{
'path': 'doc_alias::Struct',
],
},
{
+ // StructMethodItem
'others': [
{
'path': 'doc_alias::Struct',
],
},
{
+ // ImplTraitFunction
'others': [
{
'path': 'doc_alias::Struct',
],
},
{
+ // EnumItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // VariantItem
'others': [
{
'path': 'doc_alias::Enum',
],
},
{
+ // EnumMethodItem
'others': [
{
'path': 'doc_alias::Enum',
],
},
{
+ // TypedefItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // TraitItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // TraitTypeItem
'others': [
{
'path': 'doc_alias::Trait',
],
},
{
+ // AssociatedConstItem
'others': [
{
'path': 'doc_alias::Trait',
],
},
{
+ // TraitFunctionItem
'others': [
{
'path': 'doc_alias::Trait',
],
},
{
+ // FunctionItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // ModuleItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // ConstItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // StaticItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // UnionItem
'others': [
{
'path': 'doc_alias',
],
},
{
+ // UnionFieldItem
'others': [
{
'path': 'doc_alias::Union',
],
},
{
+ // UnionMethodItem
'others': [
{
'path': 'doc_alias::Union',
],
},
{
+ // MacroItem
'others': [
{
'path': 'doc_alias',
// exact-check
const QUERY = [
- '"R<P>"',
+ 'R<P>',
'"P"',
'P',
- '"ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>"',
+ 'ExtraCreditStructMulti<ExtraCreditInnerMulti, ExtraCreditInnerMulti>',
'TraitCat',
'TraitDog',
+ 'Result<String>',
];
const EXPECTED = [
{
+ // R<P>
'returned': [
{ 'path': 'generics', 'name': 'alef' },
],
],
},
{
+ // "P"
'others': [
{ 'path': 'generics', 'name': 'P' },
],
],
},
{
+ // P
'returned': [
{ 'path': 'generics', 'name': 'alef' },
- { 'path': 'generics', 'name': 'bet' },
],
'in_args': [
{ 'path': 'generics', 'name': 'alpha' },
- { 'path': 'generics', 'name': 'beta' },
],
},
{
+ // "ExtraCreditStructMulti"<ExtraCreditInnerMulti, ExtraCreditInnerMulti>
'in_args': [
{ 'path': 'generics', 'name': 'extracreditlabhomework' },
],
'returned': [],
},
{
+ // TraitCat
'in_args': [
{ 'path': 'generics', 'name': 'gamma' },
],
},
{
+ // TraitDog
'in_args': [
{ 'path': 'generics', 'name': 'gamma' },
],
},
+ {
+ // Result<String>
+ 'others': [],
+ 'returned': [
+ { 'path': 'generics', 'name': 'super_soup' },
+ ],
+ 'in_args': [
+ { 'path': 'generics', 'name': 'super_soup' },
+ ],
+ },
];
pub trait TraitDog {}
pub fn gamma<T: TraitCat + TraitDog>(t: T) {}
+
+pub fn super_soup(s: Result<String, i32>) -> Result<String, i32> { s }
// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
+// check-pass
#![deny(warnings)]
//! Email me at <hello@localhost>.
-//~^ ERROR unknown disambiguator `hello`
//! This should *not* warn: <hello@example.com>.
+++ /dev/null
-error: unknown disambiguator `hello`
- --> $DIR/email-address-localhost.rs:4:18
- |
-LL | //! Email me at <hello@localhost>.
- | ^^^^^
- |
-note: the lint level is defined here
- --> $DIR/email-address-localhost.rs:2:9
- |
-LL | #![deny(warnings)]
- | ^^^^^^^^
- = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
- = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
-
-error: aborting due to previous error
-
--- /dev/null
+// Regression test for issue #95879.
+
+use unresolved_crate::module::Name; //~ ERROR failed to resolve
+
+/// [Name]
+pub struct S;
--- /dev/null
+error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
+ --> $DIR/unresolved-import-recovery.rs:3:5
+ |
+LL | use unresolved_crate::module::Name;
+ | ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
Available passes for running rustdoc:
check_doc_test_visibility - run various visibility-related lints on doctests
strip-hidden - strips all `#[doc(hidden)]` items from the output
- unindent-comments - removes excess indentation on comments in order for markdown to like it
strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports
strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate
propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items
Default passes for rustdoc:
collect-trait-impls
- unindent-comments
check_doc_test_visibility
strip-hidden (when not --document-hidden-items)
strip-private (when not --document-private-items)
// @has doc_cfg/struct.Portable.html
// @!has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' ''
// @has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()'
-// @has - '//*[@class="stab portability"]' 'This is supported on Unix and ARM only.'
+// @has - '//*[@class="stab portability"]' 'Available on Unix and ARM only.'
// @has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()'
-// @has - '//*[@class="stab portability"]' 'This is supported on WASI and WebAssembly only.'
+// @has - '//*[@class="stab portability"]' 'Available on WASI and WebAssembly only.'
pub struct Portable;
// @has doc_cfg/unix_only/index.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-// 'This is supported on Unix only.'
+// 'Available on Unix only.'
// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z'
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(unix))]
pub mod unix_only {
// @has doc_cfg/unix_only/fn.unix_only_function.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
- // 'This is supported on Unix only.'
+ // 'Available on Unix only.'
// @count - '//*[@class="stab portability"]' 1
pub fn unix_only_function() {
content::should::be::irrelevant();
// @has doc_cfg/unix_only/trait.ArmOnly.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
- // 'This is supported on Unix and ARM only.'
+ // 'Available on Unix and ARM only.'
// @count - '//*[@class="stab portability"]' 1
#[doc(cfg(target_arch = "arm"))]
pub trait ArmOnly {
// @has doc_cfg/wasi_only/index.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-// 'This is supported on WASI only.'
+// 'Available on WASI only.'
// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(target_os = "wasi"))]
pub mod wasi_only {
// @has doc_cfg/wasi_only/fn.wasi_only_function.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
- // 'This is supported on WASI only.'
+ // 'Available on WASI only.'
// @count - '//*[@class="stab portability"]' 1
pub fn wasi_only_function() {
content::should::be::irrelevant();
// @has doc_cfg/wasi_only/trait.Wasm32Only.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
- // 'This is supported on WASI and WebAssembly only.'
+ // 'Available on WASI and WebAssembly only.'
// @count - '//*[@class="stab portability"]' 1
#[doc(cfg(target_arch = "wasm32"))]
pub trait Wasm32Only {
// @has doc_cfg/fn.uses_target_feature.html
// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-// 'This is supported with target feature avx only.'
+// 'Available with target feature avx only.'
#[target_feature(enable = "avx")]
pub unsafe fn uses_target_feature() {
content::should::be::irrelevant();
// @has doc_cfg/fn.uses_cfg_target_feature.html
// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-// 'This is supported with target feature avx only.'
+// 'Available with target feature avx only.'
#[doc(cfg(target_feature = "avx"))]
pub fn uses_cfg_target_feature() {
uses_target_feature();
// multiple attributes should be allowed
// @has doc_cfg/fn.multiple_attrs.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
-// 'This is supported on x and y and z only.'
+// 'Available on x and y and z only.'
#[doc(cfg(x))]
#[doc(cfg(y), cfg(z))]
pub fn multiple_attrs() {}
// @has 'foo/index.html'
// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$'
-// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
+// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
// @has 'foo/struct.Foo.html'
// @has '-' '//*[@class="stab portability"]' 'sync'
pub struct Foo;
// @has 'foo/bar/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub mod bar {
// @has 'foo/bar/struct.Bar.html'
- // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub struct Bar;
}
// @has 'foo/baz/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
#[doc(cfg(all(feature = "sync", feature = "send")))]
pub mod baz {
// @has 'foo/baz/struct.Baz.html'
- // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
#[doc(cfg(feature = "sync"))]
pub struct Baz;
}
// @has 'foo/qux/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub mod qux {
// @has 'foo/qux/struct.Qux.html'
- // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.'
#[doc(cfg(all(feature = "sync", feature = "send")))]
pub struct Qux;
}
// @has 'foo/quux/index.html'
-// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
+// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo only.'
#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
pub mod quux {
// @has 'foo/quux/struct.Quux.html'
- // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
+ // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo and bar only.'
#[doc(cfg(all(feature = "send", feature = "sync", bar)))]
pub struct Quux;
}
--- /dev/null
+// This test ensures that the same implementation doesn't show more than once.
+// It's a regression test for https://github.com/rust-lang/rust/issues/96036.
+
+#![crate_name = "foo"]
+
+// We check that there is only one "impl<T> Something<Whatever> for T" listed in the
+// blanket implementations.
+
+// @has 'foo/struct.Whatever.html'
+// @count - '//*[@id="blanket-implementations-list"]/section[@class="impl has-srclink"]' 1
+
+pub trait Something<T> { }
+pub struct Whatever;
+impl<T> Something<Whatever> for T {}
--- /dev/null
+// This is a regression for https://github.com/rust-lang/rust/issues/96079.
+
+#![crate_name = "foo"]
+
+pub mod app {
+ pub struct S;
+
+ impl S {
+ // @has 'foo/app/struct.S.html'
+ // @has - '//a[@href="../enums/enum.Foo.html#method.by_name"]' 'Foo::by_name'
+ /**
+ Doc comment hello! [`Foo::by_name`](`crate::enums::Foo::by_name`).
+ */
+ pub fn whatever(&self) {}
+ }
+}
+
+pub mod enums {
+ pub enum Foo {
+ Bar,
+ }
+
+ impl Foo {
+ pub fn by_name(&self) {}
+ }
+}
--- /dev/null
+<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Simd<T>(_) <br /><span class="where">where<br />    T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div>
\ No newline at end of file
--- /dev/null
+<div class="docblock item-decl"><pre class="rust trait"><code>pub trait TraitWhere {
+ type <a href="#associatedtype.Item" class="associatedtype">Item</a><'a><br />    <span class="where">where<br />        Self: 'a</span>;
+}</code></pre></div>
\ No newline at end of file
+#![feature(generic_associated_types)]
#![crate_name = "foo"]
pub trait MyTrait { fn dummy(&self) { } }
pub struct Echo<E>(E);
+// @has 'foo/struct.Simd.html'
+// @snapshot SWhere_Simd_item-decl - '//div[@class="docblock item-decl"]'
+pub struct Simd<T>([T; 1])
+where
+ T: MyTrait;
+
+// @has 'foo/trait.TraitWhere.html'
+// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="docblock item-decl"]'
+pub trait TraitWhere {
+ type Item<'a> where Self: 'a;
+}
+
// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<E> MyTrait for Echo<E> where E: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
+++ /dev/null
-// error-pattern: arguments were supplied
-
-fn f(x: isize) { }
-
-fn main() { let i: (); i = f(); }
+++ /dev/null
-error[E0061]: this function takes 1 argument but 0 arguments were supplied
- --> $DIR/arg-count-mismatch.rs:5:28
- |
-LL | fn main() { let i: (); i = f(); }
- | ^-- supplied 0 arguments
- | |
- | expected 1 argument
- |
-note: function defined here
- --> $DIR/arg-count-mismatch.rs:3:4
- |
-LL | fn f(x: isize) { }
- | ^ --------
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0061`.
+++ /dev/null
-// error-pattern: mismatched types
-
-fn f(x: isize) { }
-
-fn main() { let i: (); i = f(()); }
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/arg-type-mismatch.rs:5:30
- |
-LL | fn main() { let i: (); i = f(()); }
- | ^^ expected `isize`, found `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Some basic "obvious" cases for the heuristic error messages added for #65853
+// One for each of the detected cases
+
+enum E { X, Y }
+enum F { X2, Y2 }
+struct G {}
+struct H {}
+struct X {}
+struct Y {}
+struct Z {}
+
+
+fn invalid(_i: u32) {}
+fn extra() {}
+fn missing(_i: u32) {}
+fn swapped(_i: u32, _s: &str) {}
+fn permuted(_x: X, _y: Y, _z: Z) {}
+
+fn main() {
+ invalid(1.0); //~ ERROR mismatched types
+ extra(""); //~ ERROR this function takes
+ missing(); //~ ERROR this function takes
+ swapped("", 1); //~ ERROR arguments to this function are incorrect
+ permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/basic.rs:20:13
+ |
+LL | invalid(1.0);
+ | ------- ^^^ expected `u32`, found floating-point number
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/basic.rs:13:4
+ |
+LL | fn invalid(_i: u32) {}
+ | ^^^^^^^ -------
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/basic.rs:21:5
+ |
+LL | extra("");
+ | ^^^^^ -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/basic.rs:14:4
+ |
+LL | fn extra() {}
+ | ^^^^^
+help: remove the extra argument
+ |
+LL | extra();
+ | ~~~~~~~
+
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/basic.rs:22:5
+ |
+LL | missing();
+ | ^^^^^^^-- an argument of type `u32` is missing
+ |
+note: function defined here
+ --> $DIR/basic.rs:15:4
+ |
+LL | fn missing(_i: u32) {}
+ | ^^^^^^^ -------
+help: provide the argument
+ |
+LL | missing({u32});
+ | ~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/basic.rs:23:5
+ |
+LL | swapped("", 1);
+ | ^^^^^^^ -- - expected `&str`,found `{integer}`
+ | |
+ | expected `u32`,found `&'static str`
+ |
+note: function defined here
+ --> $DIR/basic.rs:16:4
+ |
+LL | fn swapped(_i: u32, _s: &str) {}
+ | ^^^^^^^ ------- --------
+help: swap these arguments
+ |
+LL | swapped(1, "");
+ | ~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/basic.rs:24:5
+ |
+LL | permuted(Y {}, Z {}, X {});
+ | ^^^^^^^^ ---- ---- ---- expected `Z`,found `X`
+ | | |
+ | | expected `Y`,found `Z`
+ | expected `X`,found `Y`
+ |
+note: function defined here
+ --> $DIR/basic.rs:17:4
+ |
+LL | fn permuted(_x: X, _y: Y, _z: Z) {}
+ | ^^^^^^^^ ----- ----- -----
+help: reorder these arguments
+ |
+LL | permuted(X {}, Y {}, Z {});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
--- /dev/null
+// A complex case with mixed suggestions from #65853
+
+enum E { X, Y }
+enum F { X2, Y2 }
+struct G {}
+struct H {}
+struct X {}
+struct Y {}
+struct Z {}
+
+fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {}
+
+fn main() {
+ complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {});
+ //~^ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/complex.rs:14:3
+ |
+LL | complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {});
+ | ^^^^^^^ --- expected `u32`, found floating-point number
+ |
+note: function defined here
+ --> $DIR/complex.rs:11:4
+ |
+LL | fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {}
+ | ^^^^^^^ ------- -------- ----- ----- ----- ----- ----- ------
+help: did you mean
+ |
+LL | complex({u32}, &"", {E}, F::X2, G{}, X {}, Y {}, Z {});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+fn empty() {}
+fn one_arg(_a: i32) {}
+fn two_arg_same(_a: i32, _b: i32) {}
+fn two_arg_diff(_a: i32, _b: &str) {}
+
+fn main() {
+ empty(""); //~ ERROR this function takes
+
+ one_arg(1, 1); //~ ERROR this function takes
+ one_arg(1, ""); //~ ERROR this function takes
+ one_arg(1, "", 1.0); //~ ERROR this function takes
+
+ two_arg_same(1, 1, 1); //~ ERROR this function takes
+ two_arg_same(1, 1, 1.0); //~ ERROR this function takes
+
+ two_arg_diff(1, 1, ""); //~ ERROR this function takes
+ two_arg_diff(1, "", ""); //~ ERROR this function takes
+ two_arg_diff(1, 1, "", ""); //~ ERROR this function takes
+ two_arg_diff(1, "", 1, ""); //~ ERROR this function takes
+
+ // Check with weird spacing and newlines
+ two_arg_same(1, 1, ""); //~ ERROR this function takes
+ two_arg_diff(1, 1, ""); //~ ERROR this function takes
+ two_arg_same( //~ ERROR this function takes
+ 1,
+ 1,
+ ""
+ );
+
+ two_arg_diff( //~ ERROR this function takes
+ 1,
+ 1,
+ ""
+ );
+}
--- /dev/null
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/extra_arguments.rs:7:3
+ |
+LL | empty("");
+ | ^^^^^ -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:1:4
+ |
+LL | fn empty() {}
+ | ^^^^^
+help: remove the extra argument
+ |
+LL | empty();
+ | ~~~~~~~
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/extra_arguments.rs:9:3
+ |
+LL | one_arg(1, 1);
+ | ^^^^^^^ - argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:2:4
+ |
+LL | fn one_arg(_a: i32) {}
+ | ^^^^^^^ -------
+help: remove the extra argument
+ |
+LL | one_arg(1);
+ | ~~~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/extra_arguments.rs:10:3
+ |
+LL | one_arg(1, "");
+ | ^^^^^^^ -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:2:4
+ |
+LL | fn one_arg(_a: i32) {}
+ | ^^^^^^^ -------
+help: remove the extra argument
+ |
+LL | one_arg(1);
+ | ~~~~~~~~~~
+
+error[E0061]: this function takes 1 argument but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:11:3
+ |
+LL | one_arg(1, "", 1.0);
+ | ^^^^^^^ -- --- argument unexpected
+ | |
+ | argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:2:4
+ |
+LL | fn one_arg(_a: i32) {}
+ | ^^^^^^^ -------
+help: remove the extra arguments
+ |
+LL | one_arg(1);
+ | ~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:13:3
+ |
+LL | two_arg_same(1, 1, 1);
+ | ^^^^^^^^^^^^ - argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:3:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+help: remove the extra argument
+ |
+LL | two_arg_same(1, 1);
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:14:3
+ |
+LL | two_arg_same(1, 1, 1.0);
+ | ^^^^^^^^^^^^ --- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:3:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+help: remove the extra argument
+ |
+LL | two_arg_same(1, 1);
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:16:3
+ |
+LL | two_arg_diff(1, 1, "");
+ | ^^^^^^^^^^^^ - argument of type `&str` unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra argument
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:17:3
+ |
+LL | two_arg_diff(1, "", "");
+ | ^^^^^^^^^^^^ -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra argument
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 4 arguments were supplied
+ --> $DIR/extra_arguments.rs:18:3
+ |
+LL | two_arg_diff(1, 1, "", "");
+ | ^^^^^^^^^^^^ - -- argument unexpected
+ | |
+ | argument of type `&str` unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra arguments
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 4 arguments were supplied
+ --> $DIR/extra_arguments.rs:19:3
+ |
+LL | two_arg_diff(1, "", 1, "");
+ | ^^^^^^^^^^^^ - -- argument unexpected
+ | |
+ | argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra arguments
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:22:3
+ |
+LL | two_arg_same(1, 1, "");
+ | ^^^^^^^^^^^^ -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:3:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+help: remove the extra argument
+ |
+LL | two_arg_same(1, 1);
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:23:3
+ |
+LL | two_arg_diff(1, 1, "");
+ | ^^^^^^^^^^^^ - argument of type `&str` unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra argument
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:24:3
+ |
+LL | two_arg_same(
+ | ^^^^^^^^^^^^
+...
+LL | ""
+ | -- argument unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:3:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+help: remove the extra argument
+ |
+LL | two_arg_same(1, 1);
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/extra_arguments.rs:30:3
+ |
+LL | two_arg_diff(
+ | ^^^^^^^^^^^^
+LL | 1,
+LL | 1,
+ | - argument of type `&str` unexpected
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:4:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: &str) {}
+ | ^^^^^^^^^^^^ ------- --------
+help: remove the extra argument
+ |
+LL | two_arg_diff(1, "");
+ | ~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
--- /dev/null
+// More nuanced test cases for invalid arguments #65853
+
+struct X {}
+
+fn one_arg(_a: i32) {}
+fn two_arg_same(_a: i32, _b: i32) {}
+fn two_arg_diff(_a: i32, _b: f32) {}
+fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+
+fn main() {
+ // Providing an incorrect argument for a single parameter function
+ one_arg(1.0); //~ ERROR mismatched types
+
+ // Providing one or two invalid arguments to a two parameter function
+ two_arg_same(1, ""); //~ ERROR mismatched types
+ two_arg_same("", 1); //~ ERROR mismatched types
+ two_arg_same("", ""); //~ ERROR arguments to this function are incorrect
+ two_arg_diff(1, ""); //~ ERROR mismatched types
+ two_arg_diff("", 1.0); //~ ERROR mismatched types
+ two_arg_diff("", ""); //~ ERROR arguments to this function are incorrect
+
+ // Providing invalid arguments to a three parameter function
+ three_arg_diff(X{}, 1.0, ""); //~ ERROR mismatched types
+ three_arg_diff(1, X {}, ""); //~ ERROR mismatched types
+ three_arg_diff(1, 1.0, X {}); //~ ERROR mismatched types
+
+ three_arg_diff(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect
+ three_arg_diff(X {}, 1.0, X {}); //~ ERROR arguments to this function are incorrect
+ three_arg_diff(1, X {}, X {}); //~ ERROR arguments to this function are incorrect
+
+ three_arg_diff(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect
+
+ three_arg_repeat(X {}, 1, ""); //~ ERROR mismatched types
+ three_arg_repeat(1, X {}, ""); //~ ERROR mismatched types
+ three_arg_repeat(1, 1, X {}); //~ ERROR mismatched types
+
+ three_arg_repeat(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect
+ three_arg_repeat(X {}, 1, X {}); //~ ERROR arguments to this function are incorrect
+ three_arg_repeat(1, X {}, X{}); //~ ERROR arguments to this function are incorrect
+
+ three_arg_repeat(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:13:11
+ |
+LL | one_arg(1.0);
+ | ------- ^^^ expected `i32`, found floating-point number
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:5:4
+ |
+LL | fn one_arg(_a: i32) {}
+ | ^^^^^^^ -------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:16:19
+ |
+LL | two_arg_same(1, "");
+ | ------------ ^^ expected `i32`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:6:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:17:16
+ |
+LL | two_arg_same("", 1);
+ | ------------ ^^ expected `i32`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:6:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:18:3
+ |
+LL | two_arg_same("", "");
+ | ^^^^^^^^^^^^ -- -- expected `i32`, found `&str`
+ | |
+ | expected `i32`, found `&str`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:6:4
+ |
+LL | fn two_arg_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:19:19
+ |
+LL | two_arg_diff(1, "");
+ | ------------ ^^ expected `f32`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:7:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:20:16
+ |
+LL | two_arg_diff("", 1.0);
+ | ------------ ^^ expected `i32`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:7:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:21:3
+ |
+LL | two_arg_diff("", "");
+ | ^^^^^^^^^^^^ -- -- expected `f32`, found `&str`
+ | |
+ | expected `i32`, found `&str`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:7:4
+ |
+LL | fn two_arg_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^^^^^ ------- -------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:24:18
+ |
+LL | three_arg_diff(X{}, 1.0, "");
+ | -------------- ^^^ expected `i32`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:25:21
+ |
+LL | three_arg_diff(1, X {}, "");
+ | -------------- ^^^^ expected `f32`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:26:26
+ |
+LL | three_arg_diff(1, 1.0, X {});
+ | -------------- ^^^^ expected `&str`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:28:3
+ |
+LL | three_arg_diff(X {}, X {}, "");
+ | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found struct `X`
+ | |
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:29:3
+ |
+LL | three_arg_diff(X {}, 1.0, X {});
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | |
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:30:3
+ |
+LL | three_arg_diff(1, X {}, X {});
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | |
+ | expected `f32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:32:3
+ |
+LL | three_arg_diff(X {}, X {}, X {});
+ | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | | |
+ | | expected `f32`, found struct `X`
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:8:4
+ |
+LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:34:20
+ |
+LL | three_arg_repeat(X {}, 1, "");
+ | ---------------- ^^^^ expected `i32`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:35:23
+ |
+LL | three_arg_repeat(1, X {}, "");
+ | ---------------- ^^^^ expected `i32`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: mismatched types
+ --> $DIR/invalid_arguments.rs:36:26
+ |
+LL | three_arg_repeat(1, 1, X {});
+ | ---------------- ^^^^ expected `&str`, found struct `X`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:38:3
+ |
+LL | three_arg_repeat(X {}, X {}, "");
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found struct `X`
+ | |
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:39:3
+ |
+LL | three_arg_repeat(X {}, 1, X {});
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | |
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:40:3
+ |
+LL | three_arg_repeat(1, X {}, X{});
+ | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found struct `X`
+ | |
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/invalid_arguments.rs:42:3
+ |
+LL | three_arg_repeat(X {}, X {}, X {});
+ | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | | |
+ | | expected `i32`, found struct `X`
+ | expected `i32`, found struct `X`
+ |
+note: function defined here
+ --> $DIR/invalid_arguments.rs:9:4
+ |
+LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
+ | ^^^^^^^^^^^^^^^^ ------- ------- --------
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+fn one_arg(_a: i32) {}
+fn two_same(_a: i32, _b: i32) {}
+fn two_diff(_a: i32, _b: f32) {}
+fn three_same(_a: i32, _b: i32, _c: i32) {}
+fn three_diff(_a: i32, _b: f32, _c: &str) {}
+fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+
+fn main() {
+ one_arg(); //~ ERROR this function takes
+ // The headers here show the types expected,
+ // with formatting to emphasize which arguments are missing
+ /* i32 f32 */
+ two_same( ); //~ ERROR this function takes
+ two_same( 1 ); //~ ERROR this function takes
+ two_diff( ); //~ ERROR this function takes
+ two_diff( 1 ); //~ ERROR this function takes
+ two_diff( 1.0 ); //~ ERROR this function takes
+
+ /* i32 i32 i32 */
+ three_same( ); //~ ERROR this function takes
+ three_same( 1 ); //~ ERROR this function takes
+ three_same( 1, 1 ); //~ ERROR this function takes
+
+ /* i32 f32 &str */
+ three_diff( 1.0, "" ); //~ ERROR this function takes
+ three_diff( 1, "" ); //~ ERROR this function takes
+ three_diff( 1, 1.0 ); //~ ERROR this function takes
+ three_diff( "" ); //~ ERROR this function takes
+ three_diff( 1.0 ); //~ ERROR this function takes
+ three_diff( 1 ); //~ ERROR this function takes
+
+ /* i32 f32 f32 &str */
+ four_repeated( ); //~ ERROR this function takes
+ four_repeated( 1, "" ); //~ ERROR this function takes
+
+ /* i32 f32 i32 f32 &str */
+ complex( ); //~ ERROR this function takes
+ complex( 1, "" ); //~ ERROR this function takes
+}
--- /dev/null
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:10:3
+ |
+LL | one_arg();
+ | ^^^^^^^-- an argument of type `i32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:1:4
+ |
+LL | fn one_arg(_a: i32) {}
+ | ^^^^^^^ -------
+help: provide the argument
+ |
+LL | one_arg({i32});
+ | ~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:14:3
+ |
+LL | two_same( );
+ | ^^^^^^^^----------------- two arguments of type `i32` and `i32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:2:4
+ |
+LL | fn two_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^ ------- -------
+help: provide the arguments
+ |
+LL | two_same({i32}, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:15:3
+ |
+LL | two_same( 1 );
+ | ^^^^^^^^----------------- an argument of type `i32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:2:4
+ |
+LL | fn two_same(_a: i32, _b: i32) {}
+ | ^^^^^^^^ ------- -------
+help: provide the argument
+ |
+LL | two_same(1, {i32});
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:16:3
+ |
+LL | two_diff( );
+ | ^^^^^^^^----------------- two arguments of type `i32` and `f32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:3:4
+ |
+LL | fn two_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^ ------- -------
+help: provide the arguments
+ |
+LL | two_diff({i32}, {f32});
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:17:3
+ |
+LL | two_diff( 1 );
+ | ^^^^^^^^----------------- an argument of type `f32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:3:4
+ |
+LL | fn two_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^ ------- -------
+help: provide the argument
+ |
+LL | two_diff(1, {f32});
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:18:3
+ |
+LL | two_diff( 1.0 );
+ | ^^^^^^^^ --- an argument of type `i32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:3:4
+ |
+LL | fn two_diff(_a: i32, _b: f32) {}
+ | ^^^^^^^^ ------- -------
+help: provide the argument
+ |
+LL | two_diff({i32}, 1.0);
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:21:3
+ |
+LL | three_same( );
+ | ^^^^^^^^^^------------------------- three arguments of type `i32`, `i32`, and `i32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:4:4
+ |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+ | ^^^^^^^^^^ ------- ------- -------
+help: provide the arguments
+ |
+LL | three_same({i32}, {i32}, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:22:3
+ |
+LL | three_same( 1 );
+ | ^^^^^^^^^^------------------------- two arguments of type `i32` and `i32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:4:4
+ |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+ | ^^^^^^^^^^ ------- ------- -------
+help: provide the arguments
+ |
+LL | three_same(1, {i32}, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:23:3
+ |
+LL | three_same( 1, 1 );
+ | ^^^^^^^^^^------------------------- an argument of type `i32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:4:4
+ |
+LL | fn three_same(_a: i32, _b: i32, _c: i32) {}
+ | ^^^^^^^^^^ ------- ------- -------
+help: provide the argument
+ |
+LL | three_same(1, 1, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:26:3
+ |
+LL | three_diff( 1.0, "" );
+ | ^^^^^^^^^^ --- an argument of type `i32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the argument
+ |
+LL | three_diff({i32}, 1.0, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:27:3
+ |
+LL | three_diff( 1, "" );
+ | ^^^^^^^^^^ -- an argument of type `f32` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the argument
+ |
+LL | three_diff(1, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:28:3
+ |
+LL | three_diff( 1, 1.0 );
+ | ^^^^^^^^^^------------------------- an argument of type `&str` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the argument
+ |
+LL | three_diff(1, 1.0, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:29:3
+ |
+LL | three_diff( "" );
+ | ^^^^^^^^^^------------------------- two arguments of type `i32` and `f32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the arguments
+ |
+LL | three_diff({i32}, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:30:3
+ |
+LL | three_diff( 1.0 );
+ | ^^^^^^^^^^-------------------------
+ | | |
+ | | an argument of type `i32` is missing
+ | an argument of type `&str` is missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the arguments
+ |
+LL | three_diff({i32}, 1.0, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 1 argument was supplied
+ --> $DIR/missing_arguments.rs:31:3
+ |
+LL | three_diff( 1 );
+ | ^^^^^^^^^^------------------------- two arguments of type `f32` and `&str` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:5:4
+ |
+LL | fn three_diff(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the arguments
+ |
+LL | three_diff(1, {f32}, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 4 arguments but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:34:3
+ |
+LL | four_repeated( );
+ | ^^^^^^^^^^^^^--------------------------------- multiple arguments are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:6:4
+ |
+LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+ | ^^^^^^^^^^^^^ ------- ------- ------- --------
+help: provide the arguments
+ |
+LL | four_repeated({i32}, {f32}, {f32}, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 4 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:35:3
+ |
+LL | four_repeated( 1, "" );
+ | ^^^^^^^^^^^^^--------------------------------- two arguments of type `f32` and `f32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:6:4
+ |
+LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {}
+ | ^^^^^^^^^^^^^ ------- ------- ------- --------
+help: provide the arguments
+ |
+LL | four_repeated(1, {f32}, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 5 arguments but 0 arguments were supplied
+ --> $DIR/missing_arguments.rs:38:3
+ |
+LL | complex( );
+ | ^^^^^^^--------------------------------- multiple arguments are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:7:4
+ |
+LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+ | ^^^^^^^ ------- ------- ------- ------- --------
+help: provide the arguments
+ |
+LL | complex({i32}, {f32}, {i32}, {f32}, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 5 arguments but 2 arguments were supplied
+ --> $DIR/missing_arguments.rs:39:3
+ |
+LL | complex( 1, "" );
+ | ^^^^^^^--------------------------------- three arguments of type `f32`, `i32`, and `i32` are missing
+ |
+note: function defined here
+ --> $DIR/missing_arguments.rs:7:4
+ |
+LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {}
+ | ^^^^^^^ ------- ------- ------- ------- --------
+help: provide the arguments
+ |
+LL | complex(1, {f32}, {i32}, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 19 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
--- /dev/null
+// Cases where multiple argument suggestions are mixed
+
+struct X {}
+
+fn two_args(_a: i32, _b: f32) {}
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+
+fn main() {
+ // Extra + Invalid
+ two_args(1, "", X {}); //~ ERROR this function takes
+ three_args(1, "", X {}, ""); //~ ERROR this function takes
+
+ // Missing and Invalid
+ three_args(1, X {}); //~ ERROR this function takes
+
+ // Missing and Extra
+ three_args(1, "", X {}); //~ ERROR arguments to this function are incorrect
+
+ // Swapped and Invalid
+ three_args("", X {}, 1); //~ ERROR arguments to this function are incorrect
+
+ // Swapped and missing
+ three_args("", 1); //~ ERROR this function takes
+}
--- /dev/null
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
+ --> $DIR/mixed_cases.rs:10:3
+ |
+LL | two_args(1, "", X {});
+ | ^^^^^^^^ -- ---- argument unexpected
+ | |
+ | expected `f32`, found `&str`
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:5:4
+ |
+LL | fn two_args(_a: i32, _b: f32) {}
+ | ^^^^^^^^ ------- -------
+help: remove the extra argument
+ |
+LL | two_args(1, {f32});
+ | ~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 4 arguments were supplied
+ --> $DIR/mixed_cases.rs:11:3
+ |
+LL | three_args(1, "", X {}, "");
+ | ^^^^^^^^^^ -- ---- -- argument unexpected
+ | | |
+ | | argument of type `&str` unexpected
+ | an argument of type `f32` is missing
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:6:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: did you mean
+ |
+LL | three_args(1, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/mixed_cases.rs:14:3
+ |
+LL | three_args(1, X {});
+ | ^^^^^^^^^^---------
+ | | |
+ | | expected `f32`, found struct `X`
+ | an argument of type `&str` is missing
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:6:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: provide the argument
+ |
+LL | three_args(1, {f32}, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/mixed_cases.rs:17:3
+ |
+LL | three_args(1, "", X {});
+ | ^^^^^^^^^^ -- ---- argument of type `&str` unexpected
+ | |
+ | an argument of type `f32` is missing
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:6:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: did you mean
+ |
+LL | three_args(1, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/mixed_cases.rs:20:3
+ |
+LL | three_args("", X {}, 1);
+ | ^^^^^^^^^^ -- ---- - expected `&str`,found `{integer}`
+ | | |
+ | | expected `f32`, found struct `X`
+ | expected `i32`,found `&'static str`
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:6:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: swap these arguments
+ |
+LL | three_args(1, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0061]: this function takes 3 arguments but 2 arguments were supplied
+ --> $DIR/mixed_cases.rs:23:3
+ |
+LL | three_args("", 1);
+ | ^^^^^^^^^^ -- -
+ | | |
+ | | an argument of type `f32` is missing
+ | | expected `&str`,found `{integer}`
+ | expected `i32`,found `&'static str`
+ |
+note: function defined here
+ --> $DIR/mixed_cases.rs:6:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: did you mean
+ |
+LL | three_args(1, {f32}, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
--- /dev/null
+// More complicated permutations
+struct X {}
+struct Y {}
+
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {}
+
+fn main() {
+ // b, c, a
+ three_args(1.0, "", 1); //~ ERROR arguments to this function are incorrect
+ // d, e, b, a, c
+ many_args(X {}, Y {}, 1, 1.0, ""); //~ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/permuted_arguments.rs:10:3
+ |
+LL | three_args(1.0, "", 1);
+ | ^^^^^^^^^^ --- -- - expected `&str`,found `{integer}`
+ | | |
+ | | expected `f32`,found `&'static str`
+ | expected `i32`,found `{float}`
+ |
+note: function defined here
+ --> $DIR/permuted_arguments.rs:5:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: reorder these arguments
+ |
+LL | three_args(1, 1.0, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/permuted_arguments.rs:12:3
+ |
+LL | many_args(X {}, Y {}, 1, 1.0, "");
+ | ^^^^^^^^^ ---- ---- - --- -- expected `Y`,found `&'static str`
+ | | | | |
+ | | | | expected `X`,found `{float}`
+ | | | expected `&str`,found `{integer}`
+ | | expected `f32`,found `Y`
+ | expected `i32`,found `X`
+ |
+note: function defined here
+ --> $DIR/permuted_arguments.rs:6:4
+ |
+LL | fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {}
+ | ^^^^^^^^^ ------- ------- -------- ----- -----
+help: reorder these arguments
+ |
+LL | many_args(1, 1.0, "", X {}, Y {});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+struct X {}
+
+fn two_args(_a: i32, _b: f32) {}
+fn three_args(_a: i32, _b: f32, _c: &str) {}
+fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {}
+
+fn main() {
+ two_args(1.0, 1); //~ ERROR arguments to this function are incorrect
+ three_args(1.0, 1, ""); //~ ERROR arguments to this function are incorrect
+ three_args( 1, "", 1.0); //~ ERROR arguments to this function are incorrect
+ three_args( "", 1.0, 1); //~ ERROR arguments to this function are incorrect
+
+ four_args(1.0, 1, X {}, ""); //~ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/swapped_arguments.rs:8:3
+ |
+LL | two_args(1.0, 1);
+ | ^^^^^^^^ --- - expected `f32`,found `{integer}`
+ | |
+ | expected `i32`,found `{float}`
+ |
+note: function defined here
+ --> $DIR/swapped_arguments.rs:3:4
+ |
+LL | fn two_args(_a: i32, _b: f32) {}
+ | ^^^^^^^^ ------- -------
+help: swap these arguments
+ |
+LL | two_args(1, 1.0);
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/swapped_arguments.rs:9:3
+ |
+LL | three_args(1.0, 1, "");
+ | ^^^^^^^^^^ --- - expected `f32`,found `{integer}`
+ | |
+ | expected `i32`,found `{float}`
+ |
+note: function defined here
+ --> $DIR/swapped_arguments.rs:4:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: swap these arguments
+ |
+LL | three_args(1, 1.0, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/swapped_arguments.rs:10:3
+ |
+LL | three_args( 1, "", 1.0);
+ | ^^^^^^^^^^ -- --- expected `&str`,found `{float}`
+ | |
+ | expected `f32`,found `&'static str`
+ |
+note: function defined here
+ --> $DIR/swapped_arguments.rs:4:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: swap these arguments
+ |
+LL | three_args(1, 1.0, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/swapped_arguments.rs:11:3
+ |
+LL | three_args( "", 1.0, 1);
+ | ^^^^^^^^^^ -- - expected `&str`,found `{integer}`
+ | |
+ | expected `i32`,found `&'static str`
+ |
+note: function defined here
+ --> $DIR/swapped_arguments.rs:4:4
+ |
+LL | fn three_args(_a: i32, _b: f32, _c: &str) {}
+ | ^^^^^^^^^^ ------- ------- --------
+help: swap these arguments
+ |
+LL | three_args(1, 1.0, "");
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/swapped_arguments.rs:13:3
+ |
+LL | four_args(1.0, 1, X {}, "");
+ | ^^^^^^^^^ --- - ---- -- expected `X`,found `&'static str`
+ | | | |
+ | | | expected `&str`,found `X`
+ | | expected `f32`,found `{integer}`
+ | expected `i32`,found `{float}`
+ |
+note: function defined here
+ --> $DIR/swapped_arguments.rs:5:4
+ |
+LL | fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {}
+ | ^^^^^^^^^ ------- ------- -------- -----
+help: did you mean
+ |
+LL | four_args(1, 1.0, "", X {});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
asm!("{}", in(reg) foo => bar);
//~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
asm!("{}", sym foo + bar);
- //~^ ERROR argument to `sym` must be a path expression
+ //~^ ERROR expected a path for argument to `sym`
asm!("", options(foo));
//~^ ERROR expected one of
asm!("", options(nomem foo));
LL | asm!("{}", in(reg) foo => bar);
| ^^ expected one of 7 possible tokens
-error: argument to `sym` must be a path expression
+error: expected a path for argument to `sym`
--> $DIR/parse-error.rs:31:24
|
LL | asm!("{}", sym foo + bar);
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-error: expected one of `clobber_abi`, `const`, or `options`, found `""`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
--> $DIR/parse-error.rs:126:28
|
LL | global_asm!("", options(), "");
- | ^^ expected one of `clobber_abi`, `const`, or `options`
+ | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
-error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
--> $DIR/parse-error.rs:128:30
|
LL | global_asm!("{}", const FOO, "{}", const FOO);
- | ^^^^ expected one of `clobber_abi`, `const`, or `options`
+ | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
error: asm template must be a string literal
--> $DIR/parse-error.rs:130:13
#![feature(repr_simd, never_type, asm_sym)]
-use std::arch::asm;
+use std::arch::{asm, global_asm};
#[repr(simd)]
#[derive(Clone, Copy)]
asm!("{}", sym S);
asm!("{}", sym main);
asm!("{}", sym C);
- //~^ ERROR asm `sym` operand must point to a fn or static
- asm!("{}", sym x);
- //~^ ERROR asm `sym` operand must point to a fn or static
+ //~^ ERROR invalid `sym` operand
// Register operands must be Copy
asm!("{}", in(reg) u);
}
}
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
error: arguments for inline assembly must be copyable
- --> $DIR/type-check-2.rs:48:31
+ --> $DIR/type-check-2.rs:46:31
|
LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `SimdNonCopy` does not implement the Copy trait
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:60:28: 60:38]` for inline assembly
- --> $DIR/type-check-2.rs:60:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
+ --> $DIR/type-check-2.rs:58:28
|
LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly
- --> $DIR/type-check-2.rs:62:28
+ --> $DIR/type-check-2.rs:60:28
|
LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly
- --> $DIR/type-check-2.rs:64:28
+ --> $DIR/type-check-2.rs:62:28
|
LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly
- --> $DIR/type-check-2.rs:66:28
+ --> $DIR/type-check-2.rs:64:28
|
LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly
- --> $DIR/type-check-2.rs:74:31
+ --> $DIR/type-check-2.rs:72:31
|
LL | asm!("{}", inout(reg) f);
| ^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly
- --> $DIR/type-check-2.rs:77:31
+ --> $DIR/type-check-2.rs:75:31
|
LL | asm!("{}", inout(reg) r);
| ^
|
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:41:24
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:41:20
|
LL | asm!("{}", sym C);
- | ^
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:43:24
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:92:19
+ |
+LL | global_asm!("{}", sym C);
+ | ^^^^^ is an `i32`
|
-LL | asm!("{}", sym x);
- | ^
+ = help: `sym` operands must refer to either a function or a static
error[E0381]: use of possibly-uninitialized variable: `x`
--> $DIR/type-check-2.rs:19:28
// ignore-spirv
// ignore-wasm32
-#![feature(asm_const)]
+#![feature(asm_const, asm_sym)]
use std::arch::{asm, global_asm};
asm!("{}", const const_bar(0));
asm!("{}", const const_bar(x));
//~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", sym x);
+ //~^ ERROR invalid `sym` operand
// Const operands must be integers and must be constants.
}
}
+unsafe fn generic<T>() {
+ asm!("{}", sym generic::<T>);
+ //~^ generic parameters may not be used in const operations
+}
+
// Const operands must be integers and must be constants.
global_asm!("{}", const 0);
LL | asm!("{}", const const_bar(x));
| ^ non-constant value
+error: invalid `sym` operand
+ --> $DIR/type-check-1.rs:47:24
+ |
+LL | asm!("{}", sym x);
+ | ^ is a local variable
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: generic parameters may not be used in const operations
+ --> $DIR/type-check-1.rs:65:30
+ |
+LL | asm!("{}", sym generic::<T>);
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:53:26
+ --> $DIR/type-check-1.rs:55:26
|
LL | asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:55:26
+ --> $DIR/type-check-1.rs:57:26
|
LL | asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
found raw pointer `*mut u8`
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:57:26
+ --> $DIR/type-check-1.rs:59:26
|
LL | asm!("{}", const &0);
| ^^ expected integer, found `&{integer}`
= note: all inline asm arguments must have a statically known size
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:67:25
+ --> $DIR/type-check-1.rs:74:25
|
LL | global_asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:69:25
+ --> $DIR/type-check-1.rs:76:25
|
LL | global_asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
= note: expected type `{integer}`
found raw pointer `*mut u8`
-error: aborting due to 13 previous errors
+error: aborting due to 15 previous errors
Some errors have detailed explanations: E0277, E0308, E0435.
For more information about an error, try `rustc --explain E0277`.
//~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
asm!("", in("ip") foo);
//~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
- asm!("", in("k0") foo);
- //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
asm!("", in("st(2)") foo);
//~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
asm!("", in("mm0") foo);
//~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ asm!("", in("k0") foo);
+ //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output
asm!("", out("st(2)") _);
asm!("", out("mm0") _);
asm!("{}", in(x87_reg) foo);
LL | asm!("", in("ip") foo);
| ^^^^^^^^^^^^
-error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:32:18
- |
-LL | asm!("", in("k0") foo);
- | ^^^^^^^^^^^^
-
error: register class `x87_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:35:18
+ --> $DIR/bad-reg.rs:33:18
|
LL | asm!("", in("st(2)") foo);
| ^^^^^^^^^^^^^^^
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:37:18
+ --> $DIR/bad-reg.rs:35:18
|
LL | asm!("", in("mm0") foo);
| ^^^^^^^^^^^^^
+error: register class `kreg0` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:37:18
+ |
+LL | asm!("", in("k0") foo);
+ | ^^^^^^^^^^^^
+
error: register class `x87_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:41:20
|
asm!("{}", in(reg) foo => bar);
//~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
asm!("{}", sym foo + bar);
- //~^ ERROR argument to `sym` must be a path expression
+ //~^ ERROR expected a path for argument to `sym`
asm!("", options(foo));
//~^ ERROR expected one of
asm!("", options(nomem foo));
LL | asm!("{}", in(reg) foo => bar);
| ^^ expected one of 7 possible tokens
-error: argument to `sym` must be a path expression
+error: expected a path for argument to `sym`
--> $DIR/parse-error.rs:31:24
|
LL | asm!("{}", sym foo + bar);
|
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-error: expected one of `clobber_abi`, `const`, or `options`, found `""`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
--> $DIR/parse-error.rs:130:28
|
LL | global_asm!("", options(), "");
- | ^^ expected one of `clobber_abi`, `const`, or `options`
+ | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
-error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
--> $DIR/parse-error.rs:132:30
|
LL | global_asm!("{}", const FOO, "{}", const FOO);
- | ^^^^ expected one of `clobber_abi`, `const`, or `options`
+ | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
error: asm template must be a string literal
--> $DIR/parse-error.rs:134:13
#![feature(repr_simd, never_type, asm_sym)]
-use std::arch::asm;
+use std::arch::{asm, global_asm};
#[repr(simd)]
struct SimdNonCopy(f32, f32, f32, f32);
asm!("{}", sym S);
asm!("{}", sym main);
asm!("{}", sym C);
- //~^ ERROR asm `sym` operand must point to a fn or static
- asm!("{}", sym x);
- //~^ ERROR asm `sym` operand must point to a fn or static
+ //~^ ERROR invalid `sym` operand
// Register operands must be Copy
asm!("{}", in(reg) u);
}
}
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
error: arguments for inline assembly must be copyable
- --> $DIR/type-check-2.rs:44:32
+ --> $DIR/type-check-2.rs:42:32
|
LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `SimdNonCopy` does not implement the Copy trait
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:56:28: 56:38]` for inline assembly
- --> $DIR/type-check-2.rs:56:28
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
+ --> $DIR/type-check-2.rs:54:28
|
LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly
- --> $DIR/type-check-2.rs:58:28
+ --> $DIR/type-check-2.rs:56:28
|
LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly
- --> $DIR/type-check-2.rs:60:28
+ --> $DIR/type-check-2.rs:58:28
|
LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly
- --> $DIR/type-check-2.rs:62:28
+ --> $DIR/type-check-2.rs:60:28
|
LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly
- --> $DIR/type-check-2.rs:70:31
+ --> $DIR/type-check-2.rs:68:31
|
LL | asm!("{}", inout(reg) f);
| ^
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly
- --> $DIR/type-check-2.rs:73:31
+ --> $DIR/type-check-2.rs:71:31
|
LL | asm!("{}", inout(reg) r);
| ^
|
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:37:24
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:37:20
|
LL | asm!("{}", sym C);
- | ^
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:39:24
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:88:19
+ |
+LL | global_asm!("{}", sym C);
+ | ^^^^^ is an `i32`
|
-LL | asm!("{}", sym x);
- | ^
+ = help: `sym` operands must refer to either a function or a static
error[E0381]: use of possibly-uninitialized variable: `x`
--> $DIR/type-check-2.rs:15:28
--> $DIR/associated-type-projection-from-supertrait.rs:27:23
|
LL | fn b() { dent(ModelT, Blue); }
- | ^^^^ expected struct `Black`, found struct `Blue`
+ | ---- ^^^^ expected struct `Black`, found struct `Blue`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/associated-type-projection-from-supertrait.rs:25:4
+ |
+LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+ | ^^^^ ---- ---------------
error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:28:23
|
LL | fn c() { dent(ModelU, Black); }
- | ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---- ^^^^^ expected struct `Blue`, found struct `Black`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/associated-type-projection-from-supertrait.rs:25:4
+ |
+LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+ | ^^^^ ---- ---------------
error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:32:28
|
LL | fn f() { ModelT.chip_paint(Blue); }
- | ^^^^ expected struct `Black`, found struct `Blue`
+ | ---------- ^^^^ expected struct `Black`, found struct `Blue`
+ | |
+ | arguments to this function are incorrect
+ |
+note: associated function defined here
+ --> $DIR/associated-type-projection-from-supertrait.rs:12:8
+ |
+LL | fn chip_paint(&self, c: Self::Color) { }
+ | ^^^^^^^^^^ ----- --------------
error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:33:28
|
LL | fn g() { ModelU.chip_paint(Black); }
- | ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---------- ^^^^^ expected struct `Blue`, found struct `Black`
+ | |
+ | arguments to this function are incorrect
+ |
+note: associated function defined here
+ --> $DIR/associated-type-projection-from-supertrait.rs:12:8
+ |
+LL | fn chip_paint(&self, c: Self::Color) { }
+ | ^^^^^^^^^^ ----- --------------
error: aborting due to 4 previous errors
--> $DIR/associated-types-path-2.rs:19:14
|
LL | f1(2i32, 4i32);
- | ^^^^ expected `u32`, found `i32`
+ | -- ^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/associated-types-path-2.rs:13:8
|
+LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
+ | ^^ ---- -------
help: change the type of the numeric literal from `i32` to `u32`
|
LL | f1(2i32, 4u32);
--> $DIR/async-fn-path-elision.rs:5:20
|
LL | async fn error(lt: HasLifetime) {
- | ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+ | ^^^^^^^^^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | async fn error(lt: HasLifetime<'_>) {
+ | ++++
error: aborting due to previous error
--> $DIR/dont-suggest-missing-await.rs:14:18
|
LL | take_u32(x)
- | ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
|
note: while checking the return type of the `async fn`
--> $DIR/dont-suggest-missing-await.rs:7:24
| ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/dont-suggest-missing-await.rs:5:4
+ |
+LL | fn take_u32(x: u32) {}
+ | ^^^^^^^^ ------
help: consider `await`ing on the `Future`
|
LL | take_u32(x.await)
--> $DIR/generator-desc.rs:10:25
|
LL | fun(async {}, async {});
- | -- ^^ expected `async` block, found a different `async` block
- | |
+ | -- ^^
+ | | |
+ | | expected `async` block, found a different `async` block
+ | | arguments to this function are incorrect
| the expected `async` block
|
= note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
+note: function defined here
+ --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+ |
+LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
+ | ^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/generator-desc.rs:12:16
|
LL | fun(one(), two());
- | ^^^^^ expected opaque type, found a different opaque type
- |
-note: while checking the return type of the `async fn`
- --> $DIR/generator-desc.rs:5:16
+ | --- ^^^^^ expected opaque type, found a different opaque type
+ | |
+ | arguments to this function are incorrect
|
-LL | async fn one() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
note: while checking the return type of the `async fn`
--> $DIR/generator-desc.rs:6:16
|
LL | async fn two() {}
| ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
+ = note: expected type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
+ found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
+note: function defined here
+ --> $DIR/generator-desc.rs:8:4
+ |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+ | ^^^ ----- -----
error[E0308]: mismatched types
--> $DIR/generator-desc.rs:14:26
|
LL | fun((async || {})(), (async || {})());
- | -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
- | |
- | the expected `async` closure body
+ | --- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
+ | |
+ | arguments to this function are incorrect
|
::: $SRC_DIR/core/src/future/mod.rs:LL:COL
|
LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | -------------------------------
- | |
- | the expected opaque type
- | the found opaque type
+ | ------------------------------- the found opaque type
+ |
+ = note: expected type `impl Future<Output = ()>` (`async` closure body)
+ found opaque type `impl Future<Output = ()>` (`async` closure body)
+note: function defined here
+ --> $DIR/generator-desc.rs:8:4
+ |
+LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
+ | ^^^ ----- -----
+help: consider `await`ing on the `Future`
|
- = note: expected opaque type `impl Future<Output = ()>` (`async` closure body)
- found opaque type `impl Future<Output = ()>` (`async` closure body)
+LL | fun((async || {})(), (async || {})().await);
+ | ++++++
error: aborting due to 3 previous errors
fn main() {
g(issue_67893::run())
- //~^ ERROR generator cannot be sent between threads safely
+ //~^ ERROR future cannot be sent between threads safely
}
-error: generator cannot be sent between threads safely
+error: future cannot be sent between threads safely
--> $DIR/issue-67893.rs:9:7
|
LL | g(issue_67893::run())
- | ^^^^^^^^^^^^^^^^^^ generator is not `Send`
+ | ^^^^^^^^^^^^^^^^^^ future is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/auxiliary/issue_67893.rs:9:26
+ |
+LL | f(*x.lock().unwrap()).await;
+ | ----------------- ^^^^^^ 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
|
--> $DIR/suggest-missing-await-closure.rs:16:18
|
LL | take_u32(x)
- | ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
|
note: while checking the return type of the `async fn`
--> $DIR/suggest-missing-await-closure.rs:8:24
| ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/suggest-missing-await-closure.rs:6:4
+ |
+LL | fn take_u32(_x: u32) {}
+ | ^^^^^^^^ -------
help: consider `await`ing on the `Future`
|
LL | take_u32(x.await)
--> $DIR/suggest-missing-await.rs:12:14
|
LL | take_u32(x)
- | ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found opaque type
+ | |
+ | arguments to this function are incorrect
|
note: while checking the return type of the `async fn`
--> $DIR/suggest-missing-await.rs:5:24
| ^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected type `u32`
found opaque type `impl Future<Output = u32>`
+note: function defined here
+ --> $DIR/suggest-missing-await.rs:3:4
+ |
+LL | fn take_u32(_x: u32) {}
+ | ^^^^^^^^ -------
help: consider `await`ing on the `Future`
|
LL | take_u32(x.await)
let u1 = U { a: I(0) };
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
- let _ = &p.b; //~ WARN reference to packed field
+ let _ = &p.b; //~ ERROR reference to packed field
//~^ WARN will become a hard error
let _ = u1.a; // #53114: should eventually signal error as well
let _ = &u2.a; //~ ERROR [E0133]
// variation on above with `_` in substructure
- let (_,) = (&p.b,); //~ WARN reference to packed field
+ let (_,) = (&p.b,); //~ ERROR reference to packed field
//~^ WARN will become a hard error
let (_,) = (u1.a,); //~ ERROR [E0133]
let (_,) = (&u2.a,); //~ ERROR [E0133]
let u1 = U { a: I(0) };
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
- match &p.b { _ => { } } //~ WARN reference to packed field
+ match &p.b { _ => { } } //~ ERROR reference to packed field
//~^ WARN will become a hard error
match u1.a { _ => { } } //~ ERROR [E0133]
match &u2.a { _ => { } } //~ ERROR [E0133]
// variation on above with `_` in substructure
- match (&p.b,) { (_,) => { } } //~ WARN reference to packed field
+ match (&p.b,) { (_,) => { } } //~ ERROR reference to packed field
//~^ WARN will become a hard error
match (u1.a,) { (_,) => { } } //~ ERROR [E0133]
match (&u2.a,) { (_,) => { } } //~ ERROR [E0133]
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:23:13
|
LL | let _ = &p.b;
| ^^^^
|
- = note: `#[warn(unaligned_references)]` on by default
+ = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:29:17
|
LL | let (_,) = (&p.b,);
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:39:11
|
LL | match &p.b { _ => { } }
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-warning: reference to packed field is unaligned
+error: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:45:12
|
LL | match (&p.b,) { (_,) => { } }
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
-error: aborting due to 7 previous errors; 4 warnings emitted
+error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0133`.
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:23:13
+ |
+LL | let _ = &p.b;
+ | ^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:29:17
+ |
+LL | let (_,) = (&p.b,);
+ | ^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:39:11
+ |
+LL | match &p.b { _ => { } }
+ | ^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:45:12
+ |
+LL | match (&p.b,) { (_,) => { } }
+ | ^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
--> $DIR/variadic-ffi-1.rs:20:9
|
LL | foo();
- | ^^^-- supplied 0 arguments
- | |
- | expected at least 2 arguments
+ | ^^^-- two arguments of type `isize` and `u8` are missing
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:13:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
+help: provide the arguments
+ |
+LL | foo({isize}, {u8});
+ | ~~~~~~~~~~~~~~~~~~
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
--> $DIR/variadic-ffi-1.rs:21:9
|
LL | foo(1);
- | ^^^ - supplied 1 argument
- | |
- | expected at least 2 arguments
+ | ^^^--- an argument of type `u8` is missing
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:13:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
+help: provide the argument
+ |
+LL | foo(1, {u8});
+ | ~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:23:56
--> $DIR/cast-int-to-char.rs:4:16
|
LL | foo::<u32>('0');
- | ^^^ expected `u32`, found `char`
+ | ---------- ^^^ expected `u32`, found `char`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/cast-int-to-char.rs:1:4
+ |
+LL | fn foo<T>(_t: T) {}
+ | ^^^ -----
help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes
|
LL | foo::<u32>('0' as u32);
--> $DIR/cast-int-to-char.rs:5:16
|
LL | foo::<i32>('0');
- | ^^^ expected `i32`, found `char`
+ | ---------- ^^^ expected `i32`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/cast-int-to-char.rs:1:4
|
+LL | fn foo<T>(_t: T) {}
+ | ^^^ -----
help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes
|
LL | foo::<i32>('0' as i32);
--> $DIR/cast-int-to-char.rs:6:16
|
LL | foo::<u64>('0');
- | ^^^ expected `u64`, found `char`
+ | ---------- ^^^ expected `u64`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/cast-int-to-char.rs:1:4
|
+LL | fn foo<T>(_t: T) {}
+ | ^^^ -----
help: you can cast a `char` to a `u64`, since a `char` always occupies 4 bytes
|
LL | foo::<u64>('0' as u64);
--> $DIR/cast-int-to-char.rs:7:16
|
LL | foo::<i64>('0');
- | ^^^ expected `i64`, found `char`
+ | ---------- ^^^ expected `i64`, found `char`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/cast-int-to-char.rs:1:4
+ |
+LL | fn foo<T>(_t: T) {}
+ | ^^^ -----
help: you can cast a `char` to an `i64`, since a `char` always occupies 4 bytes
|
LL | foo::<i64>('0' as i64);
--> $DIR/cast-int-to-char.rs:8:17
|
LL | foo::<char>(0u32);
- | ^^^^ expected `char`, found `u32`
+ | ----------- ^^^^ expected `char`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/cast-int-to-char.rs:1:4
+ |
+LL | fn foo<T>(_t: T) {}
+ | ^^^ -----
error: aborting due to 5 previous errors
// edition:2021
-// check-pass
-
// Given how the closure desugaring is implemented (at least at the time of writing this test),
// we don't need to truncate the captured path to a reference into a packed-struct if the field
// being referenced will be moved into the closure, since it's safe to move out a field from a
// inlined we will truncate the capture to access just the struct regardless of if the field
// might get moved into the closure.
//
-// It is possible for someone to try writing the code that relies on the desugaring to access a ref
-// into a packed-struct without explicity using unsafe. Here we test that the compiler warns the
-// user that such an access is still unsafe.
+// It is possible for someone to try writing the code that relies on the desugaring to create a ref
+// into a packed-struct. Here we test that the compiler still detects that case.
fn test_missing_unsafe_warning_on_repr_packed() {
#[repr(packed)]
struct Foo { x: String }
let c = || {
println!("{}", foo.x);
- //~^ WARNING: reference to packed field is unaligned
+ //~^ ERROR: reference to packed field is unaligned
//~| WARNING: this was previously accepted by the compiler but is being phased out
let _z = foo.x;
};
-warning: reference to packed field is unaligned
- --> $DIR/repr_packed.rs:24:24
+error: reference to packed field is unaligned
+ --> $DIR/repr_packed.rs:21:24
|
LL | println!("{}", foo.x);
| ^^^^^
|
- = note: `#[warn(unaligned_references)]` on by default
+ = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: this warning originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
-warning: 1 warning emitted
+error: aborting due to previous error
+
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/repr_packed.rs:21:24
+ |
+LL | println!("{}", foo.x);
+ | ^^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+ = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
LL | let f = |s: &str| println!("{}{}", s, string);
| ------------------------------------- the found closure
LL | call_bare(f)
- | ^ expected fn pointer, found closure
+ | --------- ^ expected fn pointer, found closure
+ | |
+ | arguments to this function are incorrect
|
= note: expected fn pointer `for<'r> fn(&'r str)`
found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]`
|
LL | let f = |s: &str| println!("{}{}", s, string);
| ^^^^^^ `string` captured here
+note: function defined here
+ --> $DIR/closure-reform-bad.rs:4:4
+ |
+LL | fn call_bare(f: fn(&str)) {
+ | ^^^^^^^^^ -----------
error: aborting due to previous error
--> $DIR/issue-84128.rs:13:13
|
LL | Foo(())
- | ^^ expected integer, found `()`
+ | --- ^^ expected integer, found `()`
+ | |
+ | arguments to this struct are incorrect
|
note: return type inferred to be `{integer}` here
--> $DIR/issue-84128.rs:10:20
|
LL | return Foo(0);
| ^^^^^^
+note: tuple struct defined here
+ --> $DIR/issue-84128.rs:5:8
+ |
+LL | struct Foo<T>(T);
+ | ^^^
error: aborting due to previous error
--> $DIR/issue-87461.rs:10:8
|
LL | Ok(())
- | ^^ expected `u16`, found `()`
+ | -- ^^ expected `u16`, found `()`
+ | |
+ | arguments to this enum variant are incorrect
error[E0308]: mismatched types
--> $DIR/issue-87461.rs:17:8
|
LL | Ok(())
- | ^^ expected `u16`, found `()`
+ | -- ^^ expected `u16`, found `()`
+ | |
+ | arguments to this enum variant are incorrect
error[E0308]: mismatched types
--> $DIR/issue-87461.rs:26:12
|
LL | Ok(())
- | ^^ expected `u16`, found `()`
+ | -- ^^ expected `u16`, found `()`
+ | |
+ | arguments to this enum variant are incorrect
error: aborting due to 3 previous errors
--> $DIR/coerce-mut.rs:5:7
|
LL | f(&x);
- | ^^ types differ in mutability
+ | - ^^ types differ in mutability
+ | |
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut i32`
found reference `&{integer}`
+note: function defined here
+ --> $DIR/coerce-mut.rs:1:4
+ |
+LL | fn f(x: &mut i32) {}
+ | ^ -----------
error: aborting due to previous error
--> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18
|
LL | test(&mut 7, &7);
- | ^^ types differ in mutability
+ | ---- ^^ types differ in mutability
+ | |
+ | arguments to this function are incorrect
|
- = note: expected mutable reference `&mut {integer}`
- found reference `&{integer}`
+ = note: expected type `&mut {integer}`
+ found reference `&{integer}`
+note: function defined here
+ --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4
+ |
+LL | fn test<T>(_a: T, _b: T) {}
+ | ^^^^ ----- -----
error: aborting due to previous error
--> $DIR/coerce-to-bang.rs:6:17
|
LL | foo(return, 22, 44);
- | ^^ expected `!`, found integer
+ | --- ^^ expected `!`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found type `{integer}`
+note: function defined here
+ --> $DIR/coerce-to-bang.rs:3:4
+ |
+LL | fn foo(x: usize, y: !, z: usize) { }
+ | ^^^ -------- ---- --------
error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:18:13
|
LL | foo(22, 44, return);
- | ^^ expected `!`, found integer
+ | --- ^^ expected `!`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found type `{integer}`
+note: function defined here
+ --> $DIR/coerce-to-bang.rs:3:4
+ |
+LL | fn foo(x: usize, y: !, z: usize) { }
+ | ^^^ -------- ---- --------
error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:26:12
|
LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
- | ^ expected `!`, found integer
+ | --- ^ expected `!`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found type `{integer}`
+note: function defined here
+ --> $DIR/coerce-to-bang.rs:3:4
+ |
+LL | fn foo(x: usize, y: !, z: usize) { }
+ | ^^^ -------- ---- --------
error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:36:12
|
LL | foo(a, b, c);
- | ^ expected `!`, found integer
+ | --- ^ expected `!`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found type `{integer}`
+note: function defined here
+ --> $DIR/coerce-to-bang.rs:3:4
+ |
+LL | fn foo(x: usize, y: !, z: usize) { }
+ | ^^^ -------- ---- --------
error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:45:12
|
LL | foo(a, b, c);
- | ^ expected `!`, found integer
+ | --- ^ expected `!`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found type `{integer}`
+note: function defined here
+ --> $DIR/coerce-to-bang.rs:3:4
+ |
+LL | fn foo(x: usize, y: !, z: usize) { }
+ | ^^^ -------- ---- --------
error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:50:21
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-cow.rs:18:1
|
LL | impl<T> Remote for Pair<T,Cover<T>> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-cow.rs:22:1
|
LL | impl<T> Remote for Pair<Cover<T>,T> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-cow.rs:26:1
|
LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/coherence-impls-copy.rs:5:1
|
LL | impl Copy for i32 {}
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/coherence-orphan.rs:10:1
|
LL | impl TheTrait<usize> for isize { }
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-orphan.rs:17:1
|
LL | impl !Send for Vec<isize> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-overlapping-pairs.rs:8:1
|
LL | impl<T> Remote for lib::Pair<T,Foo> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/coherence-pair-covered-uncovered-1.rs:12:1
|
LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-pair-covered-uncovered.rs:8:1
|
LL | impl<T,U> Remote for Pair<T,Local<U>> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-vec-local-2.rs:11:1
|
LL | impl<T> Remote for Vec<Local<T>> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence-vec-local.rs:11:1
|
LL | impl Remote for Vec<Local> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/coherence_local_err_struct.rs:14:1
|
LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign-for-foreign.rs:10:1
|
LL | impl Remote for i32 {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign-for-foreign[foreign].rs:10:1
|
LL | impl Remote1<Rc<i32>> for i32 {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign-for-foreign[foreign].rs:14:1
|
LL | impl Remote1<Rc<Local>> for f64 {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign-for-foreign[foreign].rs:18:1
|
LL | impl<T> Remote1<Rc<T>> for f32 {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/impl-foreign-for-fundamental[foreign].rs:10:1
|
LL | impl Remote for Box<i32> {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/impl-foreign-for-fundamental[foreign].rs:14:1
|
LL | impl<T> Remote for Box<Rc<T>> {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign[foreign]-for-foreign.rs:10:1
|
LL | impl Remote1<u32> for f64 {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:11:1
|
LL | impl Remote1<Box<String>> for i32 {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:15:1
|
LL | impl Remote1<Box<Rc<i32>>> for f64 {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:19:1
|
LL | impl<T> Remote1<Box<Rc<T>>> for f32 {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/impl[t]-foreign-for-foreign[t].rs:11:1
|
LL | impl Remote for Rc<Local> {
|
= note: define and implement a trait or new type instead
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/impl[t]-foreign-for-foreign[t].rs:16:1
|
LL | impl<T> Remote for Arc<T> {
--- /dev/null
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/const-argument-cross-crate-mismatch.rs:7:41
+ |
+LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^----------^
+ | |
+ | expected `[u8; 3]`, found `[u8; 2]`
+ |
+help: provide an argument of the correct type
+ |
+LL | let _ = const_generic_lib::function(({[u8; 3]}));
+ | ^^^^^^^^^^^
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/const-argument-cross-crate-mismatch.rs:9:39
+ |
+LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^
+ | |
+ | expected `[u8; 2]`, found `[u8; 3]`
+ |
+help: provide an argument of the correct type
+ |
+LL | let _: const_generic_lib::Alias = ({[u8; 2]});
+ | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/const-argument-cross-crate-mismatch.rs:6:67
|
LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
- | ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+ | ------------------------- ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+ | |
+ | arguments to this struct are incorrect
error[E0308]: mismatched types
--> $DIR/const-argument-cross-crate-mismatch.rs:8:65
|
LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
- | ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
+ | ------------------------- ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
+ | |
+ | arguments to this struct are incorrect
error: aborting due to 2 previous errors
+error: constant expression depends on a generic parameter
+ --> $DIR/issue-62504.rs:18:25
+ |
+LL | ArrayHolder([0; Self::SIZE])
+ | ^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
error[E0308]: mismatched types
--> $DIR/issue-62504.rs:18:21
|
LL | ArrayHolder([0; Self::SIZE])
- | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+ | ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+ | |
+ | arguments to this struct are incorrect
|
= note: expected array `[u32; X]`
found array `[u32; _]`
-
-error: constant expression depends on a generic parameter
- --> $DIR/issue-62504.rs:18:25
+note: tuple struct defined here
+ --> $DIR/issue-62504.rs:14:8
|
-LL | ArrayHolder([0; Self::SIZE])
- | ^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
+LL | struct ArrayHolder<const X: usize>([u32; X]);
+ | ^^^^^^^^^^^
error: aborting due to 2 previous errors
--> $DIR/issue-87493.rs:8:8
|
LL | T: MyTrait<Assoc == S::Assoc>,
- | ^^^^^^^------------------- help: remove these generics
+ | ^^^^^^^ ----------------- help: replace the generic bound with the associated type: `Assoc = Assoc == S::Assoc`
| |
| expected 0 generic arguments
|
78 00 00 00 ff ff ff ff │ x.......
}
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:92:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:92:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
- |
- = 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) {
- 00 00 00 00 00 00 00 00 │ ........
- }
+ | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:94:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:94:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
- |
- = 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) {
- 00 00 00 00 00 00 00 00 │ ........
- }
+ | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
error: aborting due to 13 previous errors
78 00 00 00 ff ff ff ff │ x.......
}
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:92:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:92:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
- |
- = 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) {
- 00 00 00 00 00 00 00 00 │ ........
- }
+ | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:94:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:94:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<enum-variant(Ok)>.0.1: encountered a value of the never type `!`
- |
- = 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) {
- 00 00 00 00 00 00 00 00 │ ........
- }
+ | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
error: aborting due to 13 previous errors
// All variants are uninhabited but also have data.
// Use `0` as constant to make behavior endianess-independent.
const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-//~^ ERROR is undefined behavior
+//~^ ERROR evaluation of constant value failed
const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-//~^ ERROR is undefined behavior
+//~^ ERROR evaluation of constant value failed
fn main() {
}
| transmuting to uninhabited type
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
...
-LL | const FOO: [Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
+LL | const FOO: [empty::Empty; 3] = [foo(); 3];
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:16:1
+ --> $DIR/validate_uninhabited_zsts.rs:23:1
|
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0].0: encountered a value of uninhabited type empty::Void
|
= 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: 0, align: 1) {}
= note: `#[warn(invalid_value)]` on by default
= note: the `!` type has no valid value
-warning: the type `Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:16:35
+warning: the type `empty::Empty` does not permit zero-initialization
+ --> $DIR/validate_uninhabited_zsts.rs:23:42
|
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
- = note: enums with no variants have no valid value
+note: enums with no variants have no valid value (in this struct field)
+ --> $DIR/validate_uninhabited_zsts.rs:16:22
+ |
+LL | pub struct Empty(Void);
+ | ^^^^
error: aborting due to 2 previous errors; 2 warnings emitted
| transmuting to uninhabited type
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
...
-LL | const FOO: [Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:13:26
+LL | const FOO: [empty::Empty; 3] = [foo(); 3];
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:16:1
+ --> $DIR/validate_uninhabited_zsts.rs:23:1
|
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0].0: encountered a value of uninhabited type empty::Void
|
= 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: 0, align: 1) {}
= note: `#[warn(invalid_value)]` on by default
= note: the `!` type has no valid value
-warning: the type `Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:16:35
+warning: the type `empty::Empty` does not permit zero-initialization
+ --> $DIR/validate_uninhabited_zsts.rs:23:42
|
-LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
- = note: enums with no variants have no valid value
+note: enums with no variants have no valid value (in this struct field)
+ --> $DIR/validate_uninhabited_zsts.rs:16:22
+ |
+LL | pub struct Empty(Void);
+ | ^^^^
error: aborting due to 2 previous errors; 2 warnings emitted
//~| WARN the type `!` does not permit zero-initialization [invalid_value]
}
-#[derive(Clone, Copy)]
-enum Empty { }
+// Type defined in a submodule, so that it is not "visibly"
+// uninhabited (which would change interpreter behavior).
+pub mod empty {
+ #[derive(Clone, Copy)]
+ enum Void {}
+
+ #[derive(Clone, Copy)]
+ pub struct Empty(Void);
+}
#[warn(const_err)]
-const FOO: [Empty; 3] = [foo(); 3];
+const FOO: [empty::Empty; 3] = [foo(); 3];
#[warn(const_err)]
-const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
//~^ ERROR it is undefined behavior to use this value
-//~| WARN the type `Empty` does not permit zero-initialization
+//~| WARN the type `empty::Empty` does not permit zero-initialization
fn main() {
FOO;
-// Check that `const extern fn` and `const unsafe extern fn` are feature-gated.
+// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
+// for certain ABIs.
-const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable
-const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "C" fn bar2() {} //~ ERROR `const extern fn` definitions are unstable
-const unsafe extern "Rust" fn bar3() {} //~ ERROR `const extern fn` definitions are unstable
+const extern fn foo1() {}
+const extern "C" fn foo2() {}
+const extern "Rust" fn foo3() {}
+const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
+const unsafe extern fn bar1() {}
+const unsafe extern "C" fn bar2() {}
+const unsafe extern "Rust" fn bar3() {}
+const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
fn main() {}
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:3:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+ --> $DIR/feature-gate-const_extern_fn.rs:7:14
|
-LL | const extern fn foo1() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const extern "cdecl" fn foo4() {}
+ | ^^^^^^^
|
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:4:1
+error[E0658]: `cdecl` as a `const fn` ABI is unstable
+ --> $DIR/feature-gate-const_extern_fn.rs:11:21
|
-LL | const extern "C" fn foo2() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const unsafe extern "cdecl" fn bar4() {}
+ | ^^^^^^^
|
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
= help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:5:1
- |
-LL | const extern "Rust" fn foo3() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:6:1
- |
-LL | const unsafe extern fn bar1() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:7:1
- |
-LL | const unsafe extern "C" fn bar2() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error[E0658]: `const extern fn` definitions are unstable
- --> $DIR/feature-gate-const_extern_fn.rs:8:1
- |
-LL | const unsafe extern "Rust" fn bar3() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
- = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.
const_assert!(f32::from_bits(0x44a72000), 1337.0);
const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0);
const_assert!(f32::from_bits(0xc1640000), -14.25);
-
- // Check that NaNs roundtrip their bits regardless of signalingness
- // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
- const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
- const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
-
- const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
- const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
-
- // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
- // In practice, this seems to only cause a problem on x86, since the most widely used calling
- // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
- if !cfg!(target_arch = "x86") {
- const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- }
}
fn f64() {
const_assert!(f64::from_bits(0x4094e40000000000), 1337.0);
const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0);
const_assert!(f64::from_bits(0xc02c800000000000), -14.25);
-
- // Check that NaNs roundtrip their bits regardless of signalingness
- // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
- const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
- const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-
- const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
- const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
-
- // See comment above.
- if !cfg!(target_arch = "x86") {
- const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- }
}
fn main() {
--- /dev/null
+// compile-flags: -Zmir-opt-level=0
+#![feature(const_float_bits_conv)]
+#![feature(const_float_classify)]
+
+// Don't promote
+const fn nop<T>(x: T) -> T { x }
+
+macro_rules! const_assert {
+ ($a:expr) => {
+ {
+ const _: () = assert!($a);
+ assert!(nop($a));
+ }
+ };
+ ($a:expr, $b:expr) => {
+ {
+ const _: () = assert!($a == $b);
+ assert_eq!(nop($a), nop($b));
+ }
+ };
+}
+
+fn f32() {
+ // Check that NaNs roundtrip their bits regardless of signalingness
+ // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+ // ...actually, let's just check that these break. :D
+ const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+ const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
+
+ const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+ const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+
+ // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
+ // In practice, this seems to only cause a problem on x86, since the most widely used calling
+ // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
+ if !cfg!(target_arch = "x86") {
+ const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+ const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+ }
+}
+
+fn f64() {
+ // Check that NaNs roundtrip their bits regardless of signalingness
+ // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
+ // ...actually, let's just check that these break. :D
+ const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
+ const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+
+ const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+ const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+
+ // See comment above.
+ if !cfg!(target_arch = "x86") {
+ const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+ const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+ }
+}
+
+fn main() {
+ f32();
+ f64();
+}
--- /dev/null
+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
+ |
+ ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+ | ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+ ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+LL | called_in_const.call_once(arg)
+ | ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+ ::: $DIR/const-float-bits-reject-conv.rs:27:30
+ |
+LL | const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
+ | ------------------ inside `f32::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:27:30
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (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
+ |
+ ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+ | ------------------------------------------------------------------ inside `<fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32} as FnOnce<(f32,)>>::call_once - shim(fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+ ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+LL | called_in_const.call_once(arg)
+ | ------------------------------ inside `const_eval_select::<(f32,), fn(f32) -> u32 {core::f32::<impl f32>::to_bits::ct_f32_to_u32}, [closure@core::f32::<impl f32>::to_bits::{closure#0}], u32>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+ ::: $DIR/const-float-bits-reject-conv.rs:28:30
+ |
+LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
+ | ------------------ inside `f32::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:28:30
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (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
+ |
+ ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+ | ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+ ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+LL | called_in_const.call_once(arg)
+ | ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+ ::: $DIR/const-float-bits-reject-conv.rs:46: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:46:30
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (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
+ |
+ ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+ | ------------------------------------------------------------------ inside `<fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64} as FnOnce<(f64,)>>::call_once - shim(fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64})` at $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+ ::: $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+LL | called_in_const.call_once(arg)
+ | ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+ |
+ ::: $DIR/const-float-bits-reject-conv.rs:47: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:47:30
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
-LL | impl<I: Iterator> IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const 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> IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const 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: aborting due to 4 previous errors
+Future incompatibility report: Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
+ --> $DIR/deriving-with-repr-packed.rs:8:16
+ |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/deriving-with-repr-packed.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
+ --> $DIR/deriving-with-repr-packed.rs:8:23
+ |
+LL | #[derive(Copy, Clone, PartialEq, Eq)]
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/deriving-with-repr-packed.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
+ --> $DIR/deriving-with-repr-packed.rs:16:10
+ |
+LL | #[derive(PartialEq, Eq)]
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/deriving-with-repr-packed.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
+ --> $DIR/deriving-with-repr-packed.rs:25:10
+ |
+LL | #[derive(PartialEq)]
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/deriving-with-repr-packed.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
--> $DIR/issue-42764.rs:11:43
|
LL | this_function_expects_a_double_option(n);
- | ^ expected enum `DoubleOption`, found `usize`
+ | ------------------------------------- ^ expected enum `DoubleOption`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected enum `DoubleOption<_>`
found type `usize`
+note: function defined here
+ --> $DIR/issue-42764.rs:7:4
+ |
+LL | fn this_function_expects_a_double_option<T>(d: DoubleOption<T>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------
help: try wrapping the expression in a variant of `DoubleOption`
|
LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n));
--- /dev/null
+// run-rustfix
+#![allow(unused)]
+
+trait Foo<T>: Sized {
+ fn bar(i: i32, t: T, s: &Self) -> (T, i32);
+}
+
+impl Foo<usize> for () {
+ fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+ (1, 2)
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+#![allow(unused)]
+
+trait Foo<T>: Sized {
+ fn bar(i: i32, t: T, s: &Self) -> (T, i32);
+}
+
+impl Foo<usize> for () {
+ fn bar(i: _, t: _, s: _) -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+ (1, 2)
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+ --> $DIR/replace-impl-infer-ty-from-trait.rs:9:15
+ |
+LL | fn bar(i: _, t: _, s: _) -> _ {
+ | ^ ^ ^ ^ not allowed in type signatures
+ | | | |
+ | | | not allowed in type signatures
+ | | not allowed in type signatures
+ | not allowed in type signatures
+ |
+help: try replacing `_` with the types in the corresponding trait method signature
+ |
+LL | fn bar(i: i32, t: usize, s: &()) -> (usize, i32) {
+ | ~~~ ~~~~~ ~~~ ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
--> $DIR/disambiguate-identical-names.rs:13:10
|
LL | test(&v);
- | ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+ | ---- ^^ expected struct `std::vec::Vec`, found struct `HashMap`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&std::vec::Vec<std::vec::Vec<u32>>`
found reference `&HashMap<u8, u8>`
+note: function defined here
+ --> $DIR/disambiguate-identical-names.rs:6:4
+ |
+LL | fn test(_v: &Vec<Vec<u32>>) {
+ | ^^^^ ------------------
error: aborting due to previous error
--> $DIR/E0057.rs:3:13
|
LL | let a = f();
- | ^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^-- an argument is missing
+ |
+help: provide the argument
+ |
+LL | let a = f({_});
+ | ~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/E0057.rs:5:13
|
LL | let c = f(2, 3);
- | ^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^ - argument unexpected
+ |
+help: remove the extra argument
+ |
+LL | let c = f(2);
+ | ~~~~
error: aborting due to 2 previous errors
fn main() {
unsafe { printf(); }
//~^ ERROR E0060
- //~| expected at least 1 argument
}
--> $DIR/E0060.rs:6:14
|
LL | unsafe { printf(); }
- | ^^^^^^-- supplied 0 arguments
- | |
- | expected at least 1 argument
+ | ^^^^^^-- an argument of type `*const u8` is missing
|
note: function defined here
--> $DIR/E0060.rs:2:8
|
LL | fn printf(_: *const u8, ...) -> u32;
| ^^^^^^
+help: provide the argument
+ |
+LL | unsafe { printf({*const u8}); }
+ | ~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
fn main() {
f(0);
//~^ ERROR E0061
- //~| expected 2 arguments
f2();
//~^ ERROR E0061
- //~| expected 1 argument
}
--> $DIR/E0061.rs:6:5
|
LL | f(0);
- | ^ - supplied 1 argument
- | |
- | expected 2 arguments
+ | ^--- an argument of type `&str` is missing
|
note: function defined here
--> $DIR/E0061.rs:1:4
|
LL | fn f(a: u16, b: &str) {}
| ^ ------ -------
+help: provide the argument
+ |
+LL | f(0, {&str});
+ | ~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
- --> $DIR/E0061.rs:10:5
+ --> $DIR/E0061.rs:9:5
|
LL | f2();
- | ^^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^-- an argument of type `u16` is missing
|
note: function defined here
--> $DIR/E0061.rs:3:4
|
LL | fn f2(a: u16) {}
| ^^ ------
+help: provide the argument
+ |
+LL | f2({u16});
+ | ~~~~~~~~~
error: aborting due to 2 previous errors
//~| HELP remove this lifetime argument
}
+pub trait T {
+ type A;
+ type B;
+}
+
+fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
+ //~^ ERROR this trait takes 0 generic arguments
+ //~| HELP replace the generic bounds with the associated types
+}
+
fn main() {}
LL | struct Quux<T>(T);
| ^^^^
-error: aborting due to 9 previous errors
+error[E0107]: this trait takes 0 generic arguments but 2 generic arguments were supplied
+ --> $DIR/E0107.rs:55:27
+ |
+LL | fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
+ | ^ expected 0 generic arguments
+ |
+note: trait defined here, with 0 generic parameters
+ --> $DIR/E0107.rs:50:11
+ |
+LL | pub trait T {
+ | ^
+help: replace the generic bounds with the associated types
+ |
+LL | fn trait_bound_generic<I: T<A = u8, B = u16>>(_i: I) {
+ | ~~~~~~ ~~~~~~~
+
+error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0107`.
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/E0117.rs:1:1
|
LL | impl Drop for u32 {}
--- /dev/null
+fn wants_uniq(x: String) { }
+fn wants_slice(x: &str) { }
+
+fn has_uniq(x: String) {
+ wants_uniq(x);
+ wants_slice(&*x);
+}
+
+fn has_slice(x: &str) {
+ wants_uniq(x); //~ ERROR mismatched types
+ wants_slice(x);
+}
+
+fn main() {
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/estr-subtyping.rs:10:15
+ |
+LL | wants_uniq(x);
+ | ---------- ^- help: try using a conversion method: `.to_string()`
+ | | |
+ | | expected struct `String`, found `&str`
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/estr-subtyping.rs:1:4
+ |
+LL | fn wants_uniq(x: String) { }
+ | ^^^^^^^^^^ ---------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// aux-crate:somedep=somedep.rs
+// compile-flags: -Zunstable-options -Dunused-crate-dependencies
+// edition:2018
+
+fn main() { //~ ERROR external crate `somedep` unused in `no_nounused`
+}
--- /dev/null
+error: external crate `somedep` unused in `no_nounused`: remove the dependency or add `use somedep as _;`
+ --> $DIR/no-nounused.rs:5:1
+ |
+LL | fn main() {
+ | ^
+ |
+ = note: requested on the command line with `-D unused-crate-dependencies`
+
+error: aborting due to previous error
+
--- /dev/null
+// check-pass
+// aux-crate:nounused:somedep=somedep.rs
+// compile-flags: -Zunstable-options -Dunused-crate-dependencies
+// edition:2018
+
+fn main() {
+}
--> $DIR/ifmt-bad-arg.rs:78:32
|
LL | println!("{} {:.*} {}", 1, 3.2, 4);
- | ^^^ expected `usize`, found floating-point number
+ | ---------------------------^^^----
+ | | |
+ | | expected `usize`, found floating-point number
+ | arguments to this function are incorrect
|
= note: expected reference `&usize`
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` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/ifmt-bad-arg.rs:81:35
|
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
- | ^^^ expected `usize`, found floating-point number
+ | ------------------------------^^^----
+ | | |
+ | | expected `usize`, found floating-point number
+ | arguments to this function are incorrect
|
= note: expected reference `&usize`
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` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 36 previous errors
fn main() {
eq(foo::<u8>, bar::<u8>);
//~^ ERROR mismatched types
- //~| expected fn item `fn(_) -> _ {foo::<u8>}`
+ //~| expected type `fn(_) -> _ {foo::<u8>}`
//~| found fn item `fn(_) -> _ {bar::<u8>}`
//~| expected fn item, found a different fn item
//~| different `fn` items always have unique types, even if their signatures are the same
eq(bar::<String>, bar::<Vec<u8>>);
//~^ ERROR mismatched types
- //~| expected fn item `fn(_) -> _ {bar::<String>}`
+ //~| expected type `fn(_) -> _ {bar::<String>}`
//~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
//~| expected struct `String`, found struct `Vec`
//~| different `fn` items always have unique types, even if their signatures are the same
eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
//~^ ERROR mismatched types
- //~| expected fn item `fn(_) -> _ {foo::<u8>}`
+ //~| expected type `fn(_) -> _ {foo::<u8>}`
//~| found fn pointer `fn(_) -> _`
//~| expected fn item, found fn pointer
//~| change the expected type to be function pointer
--> $DIR/fn-item-type.rs:13:19
|
LL | eq(foo::<u8>, bar::<u8>);
- | ^^^^^^^^^ expected fn item, found a different fn item
+ | -- ^^^^^^^^^ expected fn item, found a different fn item
+ | |
+ | arguments to this function are incorrect
|
- = note: expected fn item `fn(_) -> _ {foo::<u8>}`
- found fn item `fn(_) -> _ {bar::<u8>}`
+ = note: expected type `fn(_) -> _ {foo::<u8>}`
+ found fn item `fn(_) -> _ {bar::<u8>}`
= note: different `fn` items always have unique types, even if their signatures are the same
= help: change the expected type to be function pointer `fn(isize) -> isize`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ---- ----
error[E0308]: mismatched types
--> $DIR/fn-item-type.rs:22:19
|
LL | eq(foo::<u8>, foo::<i8>);
- | ^^^^^^^^^ expected `u8`, found `i8`
+ | -- ^^^^^^^^^ expected `u8`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
- = note: expected fn item `fn(_) -> _ {foo::<u8>}`
- found fn item `fn(_) -> _ {foo::<i8>}`
+ = note: expected type `fn(_) -> _ {foo::<u8>}`
+ found fn item `fn(_) -> _ {foo::<i8>}`
= note: different `fn` items always have unique types, even if their signatures are the same
= help: change the expected type to be function pointer `fn(isize) -> isize`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ---- ----
error[E0308]: mismatched types
--> $DIR/fn-item-type.rs:29:23
|
LL | eq(bar::<String>, bar::<Vec<u8>>);
- | ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+ | -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+ | |
+ | arguments to this function are incorrect
|
- = note: expected fn item `fn(_) -> _ {bar::<String>}`
- found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
+ = note: expected type `fn(_) -> _ {bar::<String>}`
+ found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
= note: different `fn` items always have unique types, even if their signatures are the same
= help: change the expected type to be function pointer `fn(isize) -> isize`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<String> as fn(isize) -> isize`
+note: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ---- ----
error[E0308]: mismatched types
--> $DIR/fn-item-type.rs:39:26
|
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
- | ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+ | -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
- = note: expected fn item `fn() {<u8 as Foo>::foo}`
- found fn item `fn() {<u16 as Foo>::foo}`
+ = note: expected type `fn() {<u8 as Foo>::foo}`
+ found fn item `fn() {<u16 as Foo>::foo}`
= note: different `fn` items always have unique types, even if their signatures are the same
= help: change the expected type to be function pointer `fn()`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
+note: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ---- ----
error[E0308]: mismatched types
--> $DIR/fn-item-type.rs:46:19
|
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
+ | |
+ | arguments to this function are incorrect
|
- = note: expected fn item `fn(_) -> _ {foo::<u8>}`
+ = note: expected type `fn(_) -> _ {foo::<u8>}`
found fn pointer `fn(_) -> _`
= help: change the expected type to be function pointer `fn(isize) -> isize`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+note: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ---- ----
error: aborting due to 5 previous errors
// edition:2021
// run-pass
+// compile-flags: -Zdrop-tracking
#![feature(never_type)]
}
async fn includes_never(crash: bool, x: u32) -> u32 {
- let mut result = async { x * x }.await;
+ let result = async { x * x }.await;
if !crash {
return result;
}
--> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:35
|
LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
- | - ^^ undeclared lifetime
- | |
- | help: consider introducing lifetime `'x` here: `<'x>`
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'x` lifetime
+ |
+LL | fn _f(arg : Box<dyn for<'x, 'a> X<Y<'x> = &'a [u32]>>) {}
+ | +++
+help: consider introducing lifetime `'x` here
+ |
+LL | fn _f<'x>(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+ | ++++
error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
--> $DIR/gat-in-trait-path-undeclared-lifetime.rs:8:33
LL | + Deref<Target = Self::Item<'b>>;
| ^^ undeclared lifetime
|
-help: consider introducing lifetime `'b` here
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
|
-LL | trait Iterable<'b> {
- | ++++
+LL | + for<'b> Deref<Target = Self::Item<'b>>;
+ | +++++++
help: consider introducing lifetime `'b` here
|
LL | type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>>
| +++
+help: consider introducing lifetime `'b` here
+ |
+LL | trait Iterable<'b> {
+ | ++++
error[E0261]: use of undeclared lifetime name `'undeclared`
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:41
|
help: consider introducing lifetime `'undeclared` here
|
-LL | trait Iterable<'undeclared> {
- | +++++++++++++
-help: consider introducing lifetime `'undeclared` here
- |
LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>;
| ++++++++++++
+help: consider introducing lifetime `'undeclared` here
+ |
+LL | trait Iterable<'undeclared> {
+ | +++++++++++++
error: aborting due to 2 previous errors
type Y<'a>;
}
-fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
- //~^ ERROR: use of undeclared lifetime name `'a`
- //~| ERROR: use of undeclared lifetime name `'a`
-
+fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+//~^ ERROR: use of undeclared lifetime name `'a`
+//~| ERROR: use of undeclared lifetime name `'a`
+//~| ERROR: the trait `X` cannot be made into an object [E0038]
fn main() {}
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/issue-67510.rs:7:21
|
-LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
- | - ^^ undeclared lifetime
- | |
- | help: consider introducing lifetime `'a` here: `<'a>`
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
+ | +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+ | ++++
error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/issue-67510.rs:7:26
+ --> $DIR/issue-67510.rs:7:28
+ |
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+ | ^^ undeclared lifetime
+ |
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | fn f(x: Box<dyn for<'a> X<Y<'a> = &'a ()>>) {}
+ | +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+ | ++++
+
+error[E0038]: the trait `X` cannot be made into an object
+ --> $DIR/issue-67510.rs:7:13
+ |
+LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^ `X` 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-67510.rs:4:10
|
-LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
- | - ^^ undeclared lifetime
- | |
- | help: consider introducing lifetime `'a` here: `<'a>`
+LL | trait X {
+ | - this trait cannot be made into an object...
+LL | type Y<'a>;
+ | ^ ...because it contains the generic associated type `Y`
+ = help: consider moving `Y` to another trait
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0038, E0261.
+For more information about an error, try `rustc --explain E0038`.
LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
| - this type parameter
LL | T::identity(())
- | ^^ expected type parameter `T`, found `()`
+ | ----------- ^^ expected type parameter `T`, found `()`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found unit type `()`
+note: associated function defined here
+ --> $DIR/issue-68648-2.rs:6:8
+ |
+LL | fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+ | ^^^^^^^^ --------------
error: aborting due to previous error
type Cursor<'a> = DocCursorImpl<'a>;
fn cursor(&self) -> Self::Cursor<'_> {
- DocCursorImpl {
- document: &self,
- }
+ DocCursorImpl { document: &self }
}
}
-
trait DocCursor<'a> {}
struct DocCursorImpl<'a> {
_phantom: std::marker::PhantomData<&'d ()>,
}
-
impl<'d, Cursor> Lexer<'d, Cursor>
where
Cursor: DocCursor<'d>,
where
Doc: Document<Cursor<'d> = Cursor>,
{
- Lexer {
- cursor: document.cursor(),
- _phantom: std::marker::PhantomData,
- }
+ Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData }
}
}
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
- //~^ ERROR: missing lifetime specifier
+ //~^ ERROR: missing lifetime specifier
DocumentImpl {}
}
error[E0106]: missing lifetime specifier
- --> $DIR/issue-70304.rs:54:41
+ --> $DIR/issue-70304.rs:47:41
|
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
| ^^ expected named lifetime parameter
| - this type parameter
...
LL | A(self.0 + rhs.0)
- | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | |
+ | arguments to this struct are incorrect
|
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
+note: tuple struct defined here
+ --> $DIR/missing-bounds.rs:5:8
+ |
+LL | struct A<B>(B);
+ | ^
help: consider further restricting this bound
|
LL | impl<B> Add for A<B> where B: Add + Add<Output = B> {
| - this type parameter
...
LL | Self(self.0 + rhs.0)
- | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
+note: tuple struct defined here
+ --> $DIR/missing-bounds.rs:15:8
+ |
+LL | struct C<B>(B);
+ | ^
help: consider further restricting this bound
|
LL | impl<B: Add + Add<Output = B>> Add for C<B> {
| - this type parameter
...
LL | Self(self.0 + rhs.0)
- | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
+note: tuple struct defined here
+ --> $DIR/missing-bounds.rs:35:8
+ |
+LL | struct E<B>(B);
+ | ^
help: consider further restricting type parameter `B`
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
--> $DIR/generic-extern-lifetime.rs:6:26
|
LL | pub fn life2<'b>(x: &'a i32, y: &'b i32);
- | ^^ undeclared lifetime
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `'a,`
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic-extern-lifetime.rs:8:37
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the type lifetime-generic with a new `'a` lifetime
|
-LL | pub fn life4<'b>(x: for<'c, 'a> fn(&'a i32));
- | ++++
+LL | pub fn life4<'b>(x: for<'a, 'c> fn(&'a i32));
+ | +++
+help: consider introducing lifetime `'a` here
+ |
+LL | pub fn life4<'a, 'b>(x: for<'c> fn(&'a i32));
+ | +++
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/generic-extern-lifetime.rs:11:39
LL | pub fn life7<'b>() -> for<'c> fn(&'a i32);
| ^^ undeclared lifetime
|
- = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the type lifetime-generic with a new `'a` lifetime
|
-LL | pub fn life7<'b>() -> for<'c, 'a> fn(&'a i32);
- | ++++
+LL | pub fn life7<'b>() -> for<'a, 'c> fn(&'a i32);
+ | +++
+help: consider introducing lifetime `'a` here
+ |
+LL | pub fn life7<'a, 'b>() -> for<'c> fn(&'a i32);
+ | +++
error: aborting due to 3 previous errors
--- /dev/null
+#![crate_type = "lib"]
+
+struct S<T = (), 'a>(&'a T);
+//~^ ERROR lifetime parameters must be declared prior to type parameters
--- /dev/null
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18
+ |
+LL | struct S<T = (), 'a>(&'a T);
+ | ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>`
+
+error: aborting due to previous error
+
--> $DIR/issue-58451.rs:12:9
|
LL | f(&[f()]);
- | ^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^-- an argument is missing
|
note: function defined here
--> $DIR/issue-58451.rs:5:4
|
LL | fn f<I>(i: I)
| ^ ----
+help: provide the argument
+ |
+LL | f(&[f({_})]);
+ | ~~~~~~
error: aborting due to previous error
--> $DIR/path-elided.rs:7:18
|
LL | impl MyTrait for Foo {
- | ^^^- help: indicate the anonymous lifetime: `<'_>`
+ | ^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | impl MyTrait for Foo<'_> {
+ | ++++
error: aborting due to previous error
#![allow(warnings)]
-trait MyTrait<'a> { }
+trait MyTrait<'a> {}
-impl MyTrait for u32 {
- //~^ ERROR implicit elided lifetime not allowed here
-}
+impl MyTrait for u32 {}
+//~^ ERROR implicit elided lifetime not allowed here
fn main() {}
error[E0726]: implicit elided lifetime not allowed here
--> $DIR/trait-elided.rs:5:6
|
-LL | impl MyTrait for u32 {
- | ^^^^^^^- help: indicate the anonymous lifetime: `<'_>`
+LL | impl MyTrait for u32 {}
+ | ^^^^^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | impl MyTrait<'_> for u32 {}
+ | ++++
error: aborting due to previous error
| ---------------- the expected opaque type
...
LL | Anonymous(|| {
- | _______________^
+ | _____---------_^
+ | | |
+ | | arguments to this struct are incorrect
LL | | 3
LL | | })
| |_____^ expected closure, found a different closure
found closure `[closure@$DIR/issue-74282.rs:8:15: 10:6]`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
+note: tuple struct defined here
+ --> $DIR/issue-74282.rs:4:8
+ |
+LL | struct Anonymous(Closure);
+ | ^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/issue-74282.rs:8:5
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/must_outlive_least_region_or_bound.rs:41:5
|
+LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
+ | -- help: consider adding an explicit lifetime bound...: `T: 'static +`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 9 previous errors
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/type_parameters_captured.rs:10:5
|
+LL | fn foo<T>(x: T) -> impl Any + 'static {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
--> $DIR/indexing-requires-a-uint.rs:12:18
|
LL | bar::<isize>(i); // i should not be re-coerced back to an isize
- | ^ expected `isize`, found `usize`
+ | ------------ ^ expected `isize`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
-help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
+note: function defined here
+ --> $DIR/indexing-requires-a-uint.rs:5:8
|
-LL | bar::<isize>(i.try_into().unwrap()); // i should not be re-coerced back to an isize
- | ++++++++++++++++++++
+LL | fn bar<T>(_: T) {}
+ | ^^^ ----
error: aborting due to 2 previous errors
--> $DIR/deref-suggestion.rs:8:9
|
LL | foo(s);
- | ^- help: try using a conversion method: `.to_string()`
- | |
- | expected struct `String`, found `&String`
+ | --- ^- help: try using a conversion method: `.to_string()`
+ | | |
+ | | expected struct `String`, found `&String`
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/deref-suggestion.rs:5:4
+ |
+LL | fn foo(_: String) {}
+ | ^^^ ---------
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:14:10
|
LL | foo3(u);
- | ^ expected `u32`, found `&u32`
+ | ---- ^ expected `u32`, found `&u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/deref-suggestion.rs:12:4
|
+LL | fn foo3(_: u32) {}
+ | ^^^^ ------
help: consider dereferencing the borrow
|
LL | foo3(*u);
--> $DIR/deref-suggestion.rs:30:9
|
LL | foo(&"aaa".to_owned());
- | ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/deref-suggestion.rs:5:4
+ |
+LL | fn foo(_: String) {}
+ | ^^^ ---------
help: consider removing the borrow
|
LL - foo(&"aaa".to_owned());
--> $DIR/deref-suggestion.rs:32:9
|
LL | foo(&mut "aaa".to_owned());
- | ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/deref-suggestion.rs:5:4
|
+LL | fn foo(_: String) {}
+ | ^^^ ---------
help: consider removing the borrow
|
LL - foo(&mut "aaa".to_owned());
| ^^^ expected `u32`, found `&{integer}`
...
LL | foo3(borrow!(0));
- | ---------- in this macro invocation
+ | ---- ---------- in this macro invocation
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/deref-suggestion.rs:12:4
|
+LL | fn foo3(_: u32) {}
+ | ^^^^ ------
= note: this error originates in the macro `borrow` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/tutorial-suffix-inference-test.rs:9:18
|
LL | identity_u16(x);
- | ^ expected `u16`, found `u8`
+ | ------------ ^ expected `u16`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/tutorial-suffix-inference-test.rs:6:8
+ |
+LL | fn identity_u16(n: u16) -> u16 { n }
+ | ^^^^^^^^^^^^ ------
help: you can convert a `u8` to a `u16`
|
LL | identity_u16(x.into());
--> $DIR/tutorial-suffix-inference-test.rs:12:18
|
LL | identity_u16(y);
- | ^ expected `u16`, found `i32`
+ | ------------ ^ expected `u16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/tutorial-suffix-inference-test.rs:6:8
|
+LL | fn identity_u16(n: u16) -> u16 { n }
+ | ^^^^^^^^^^^^ ------
help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
|
LL | identity_u16(y.try_into().unwrap());
--> $DIR/tutorial-suffix-inference-test.rs:21:18
|
LL | identity_u16(a);
- | ^ expected `u16`, found `isize`
+ | ------------ ^ expected `u16`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/tutorial-suffix-inference-test.rs:6:8
|
+LL | fn identity_u16(n: u16) -> u16 { n }
+ | ^^^^^^^^^^^^ ------
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
LL | identity_u16(a.try_into().unwrap());
-trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
- fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
- fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
+trait Serializable<'self, T> {
+ //~^ ERROR lifetimes cannot use keyword names
+ fn serialize(val: &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
+ fn deserialize(repr: &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
}
-impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
+impl<'self> Serializable<str> for &'self str {
//~^ ERROR lifetimes cannot use keyword names
+ //~| ERROR lifetimes cannot use keyword names
//~| ERROR implicit elided lifetime not allowed here
- //~| ERROR the size for values of type `str` cannot be known at compilation time
- fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
+ //~| ERROR the size for values of type `str` cannot be known at compilation time [E0277]
+ fn serialize(val: &'self str) -> Vec<u8> {
+ //~^ ERROR lifetimes cannot use keyword names
vec![1]
}
- fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR lifetimes cannot use keyword names
+ fn deserialize(repr: &[u8]) -> &'self str {
+ //~^ ERROR lifetimes cannot use keyword names
"hi"
}
}
| ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:2:25
+ --> $DIR/issue-10412.rs:3:24
|
-LL | fn serialize(val : &'self T) -> Vec<u8>;
- | ^^^^^
+LL | fn serialize(val: &'self T) -> Vec<u8>;
+ | ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:3:38
+ --> $DIR/issue-10412.rs:4:37
|
-LL | fn deserialize(repr : &[u8]) -> &'self T;
- | ^^^^^
+LL | fn deserialize(repr: &[u8]) -> &'self T;
+ | ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:6:6
+ --> $DIR/issue-10412.rs:7:6
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:6:36
+ --> $DIR/issue-10412.rs:7:36
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:10:25
+ --> $DIR/issue-10412.rs:12:24
|
-LL | fn serialize(val : &'self str) -> Vec<u8> {
- | ^^^^^
+LL | fn serialize(val: &'self str) -> Vec<u8> {
+ | ^^^^^
error: lifetimes cannot use keyword names
- --> $DIR/issue-10412.rs:13:37
+ --> $DIR/issue-10412.rs:16:37
|
LL | fn deserialize(repr: &[u8]) -> &'self str {
| ^^^^^
error[E0726]: implicit elided lifetime not allowed here
- --> $DIR/issue-10412.rs:6:13
+ --> $DIR/issue-10412.rs:7:13
|
LL | impl<'self> Serializable<str> for &'self str {
- | ^^^^^^^^^^^^^^^^^ help: indicate the anonymous lifetime: `Serializable<'_, str>`
+ | ^^^^^^^^^^^^^^^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | impl<'self> Serializable<'_, str> for &'self str {
+ | +++
error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/issue-10412.rs:6:13
+ --> $DIR/issue-10412.rs:7:13
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
--> $DIR/issue-10764.rs:4:15
|
LL | fn main() { f(bar) }
- | ^^^ expected "Rust" fn, found "C" fn
+ | - ^^^ expected "Rust" fn, found "C" fn
+ | |
+ | arguments to this function are incorrect
|
= note: expected fn pointer `fn()`
found fn item `extern "C" fn() {bar}`
+note: function defined here
+ --> $DIR/issue-10764.rs:1:4
+ |
+LL | fn f(_: extern "Rust" fn()) {}
+ | ^ ---------------------
error: aborting due to previous error
--> $DIR/issue-11374.rs:26:15
|
LL | c.read_to(v);
- | ^
- | |
- | expected `&mut [u8]`, found struct `Vec`
- | help: consider mutably borrowing here: `&mut v`
+ | ------- ^
+ | | |
+ | | expected `&mut [u8]`, found struct `Vec`
+ | | help: consider mutably borrowing here: `&mut v`
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut [u8]`
found struct `Vec<_>`
+note: associated function defined here
+ --> $DIR/issue-11374.rs:13:12
+ |
+LL | pub fn read_to(&mut self, vec: &mut [u8]) {
+ | ^^^^^^^ --------- --------------
error: aborting due to previous error
LL | #[bench]
| -------- in this procedural macro expansion
LL | fn bar(x: isize) { }
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&mut Bencher`
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected `isize`, found `&mut Bencher`
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/issue-12997-2.rs:8:4
+ |
+LL | fn bar(x: isize) { }
+ | ^^^ --------
= note: this error originates in the attribute macro `bench` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
--> $DIR/issue-13359.rs:6:9
|
LL | foo(1*(1 as isize));
- | ^^^^^^^^^^^^^^ expected `i16`, found `isize`
+ | --- ^^^^^^^^^^^^^^ expected `i16`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
-help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
+note: function defined here
+ --> $DIR/issue-13359.rs:1:4
|
-LL | foo((1*(1 as isize)).try_into().unwrap());
- | + +++++++++++++++++++++
+LL | fn foo(_s: i16) { }
+ | ^^^ -------
error[E0308]: mismatched types
--> $DIR/issue-13359.rs:10:9
|
LL | bar(1*(1 as usize));
- | ^^^^^^^^^^^^^^ expected `u32`, found `usize`
+ | --- ^^^^^^^^^^^^^^ expected `u32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
-help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
+note: function defined here
+ --> $DIR/issue-13359.rs:3:4
|
-LL | bar((1*(1 as usize)).try_into().unwrap());
- | + +++++++++++++++++++++
+LL | fn bar(_s: u32) { }
+ | ^^^ -------
error: aborting due to 2 previous errors
--> $DIR/issue-13853.rs:37:13
|
LL | iterate(graph);
- | ^^^^^
- | |
- | expected reference, found struct `Vec`
- | help: consider borrowing here: `&graph`
+ | ------- ^^^^^
+ | | |
+ | | expected reference, found struct `Vec`
+ | | help: consider borrowing here: `&graph`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `Vec<Stuff>`
+note: function defined here
+ --> $DIR/issue-13853.rs:26:4
+ |
+LL | fn iterate<N: Node, G: Graph<N>>(graph: &G) {
+ | ^^^^^^^ ---------
error: aborting due to 3 previous errors
--> $DIR/issue-1448-2.rs:6:24
|
LL | println!("{}", foo(10i32));
- | ^^^^^ expected `u32`, found `i32`
+ | --- ^^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/issue-1448-2.rs:3:4
+ |
+LL | fn foo(a: u32) -> u32 { a }
+ | ^^^ ------
help: change the type of the numeric literal from `i32` to `u32`
|
LL | println!("{}", foo(10u32));
--> $DIR/issue-15783.rs:8:19
|
LL | let msg = foo(x);
- | ^ expected slice `[&str]`, found array `[&str; 1]`
+ | --- ^ expected slice `[&str]`, found array `[&str; 1]`
+ | |
+ | arguments to this function are incorrect
|
= note: expected enum `Option<&[&str]>`
found enum `Option<&[&str; 1]>`
+note: function defined here
+ --> $DIR/issue-15783.rs:1:8
+ |
+LL | pub fn foo(params: Option<&[&str]>) -> usize {
+ | ^^^ -----------------------
error: aborting due to previous error
--> $DIR/issue-16939.rs:5:9
|
LL | |t| f(t);
- | ^ - supplied 1 argument
- | |
- | expected 0 arguments
+ | ^ - argument unexpected
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
LL | extern "rust-call" fn call(&self, args: Args) -> Self::Output;
| ^^^^
+help: remove the extra argument
+ |
+LL | |t| f();
+ | ~~~
error: aborting due to previous error
--> $DIR/issue-17033.rs:2:10
|
LL | (*p)(())
- | ^^
- | |
- | expected `&mut ()`, found `()`
- | help: consider mutably borrowing here: `&mut ()`
+ | ---- ^^
+ | | |
+ | | expected `&mut ()`, found `()`
+ | | help: consider mutably borrowing here: `&mut ()`
+ | arguments to this function are incorrect
error: aborting due to previous error
+++ /dev/null
-// build-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-#![warn(clashing_extern_declarations)]
-
-// pretty-expanded FIXME #23616
-
-mod a {
- pub type rust_task = usize;
- pub mod rustrt {
- use super::rust_task;
- extern "C" {
- pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
- }
- }
-}
-
-mod b {
- pub type rust_task = bool;
- pub mod rustrt {
- use super::rust_task;
- extern "C" {
- pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
- //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
- }
- }
-}
-
-pub fn main() {}
+++ /dev/null
-warning: `rust_task_is_unwinding` redeclared with a different signature
- --> $DIR/issue-1866.rs:23:13
- |
-LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
- | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here
-...
-LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
- |
-note: the lint level is defined here
- --> $DIR/issue-1866.rs:4:9
- |
-LL | #![warn(clashing_extern_declarations)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn(*const usize) -> bool`
- found `unsafe extern "C" fn(*const bool) -> bool`
-
-warning: 1 warning emitted
-
--> $DIR/issue-18819.rs:16:5
|
LL | print_x(X);
- | ^^^^^^^ - supplied 1 argument
- | |
- | expected 2 arguments
+ | ^^^^^^^---
+ | ||
+ | |expected reference, found struct `X`
+ | an argument of type `&str` is missing
|
+ = note: expected reference `&dyn Foo<Item = bool>`
+ found struct `X`
note: function defined here
--> $DIR/issue-18819.rs:11:4
|
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
| ^^^^^^^ ---------------------- -----------
+help: consider borrowing here
+ |
+LL | print_x(&X);
+ | ~~
+help: provide the argument
+ |
+LL | print_x({&dyn Foo<Item = bool>}, {&str});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
+++ /dev/null
-// run-pass
-#![allow(unused_variables)]
-// Regression test for Issue #20343.
-
-// pretty-expanded FIXME #23616
-
-#![deny(dead_code)]
-
-struct B { b: u32 }
-struct C;
-struct D;
-
-trait T<A> { fn dummy(&self, a: A) { } }
-impl<A> T<A> for () {}
-
-impl B {
- // test for unused code in arguments
- fn foo(B { b }: B) -> u32 { b }
-
- // test for unused code in return type
- fn bar() -> C { unsafe { ::std::mem::transmute(()) } }
-
- // test for unused code in generics
- fn baz<A: T<D>>() {}
-}
-
-pub fn main() {
- let b = B { b: 3 };
- B::foo(b);
- B::bar();
- B::baz::<()>();
-}
--> $DIR/issue-24819.rs:5:9
|
LL | foo(&mut v);
- | ^^^^^^ expected struct `HashSet`, found struct `Vec`
+ | --- ^^^^^^ expected struct `HashSet`, found struct `Vec`
+ | |
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut HashSet<u32>`
found mutable reference `&mut Vec<_>`
+note: function defined here
+ --> $DIR/issue-24819.rs:10:4
+ |
+LL | fn foo(h: &mut HashSet<u32>) {
+ | ^^^ --------------------
error: aborting due to previous error
macro_rules! some_macro {
($other: expr) => ({
- $other(None) //~ NOTE supplied 1 argument
+ $other(None) //~ NOTE argument unexpected
})
}
fn main() {
some_macro!(some_function);
//~^ ERROR this function takes 0 arguments but 1 argument was supplied
- //~| NOTE expected 0 arguments
+ //~| NOTE in this expansion of some_macro!
}
--> $DIR/issue-26094.rs:10:17
|
LL | $other(None)
- | ---- supplied 1 argument
+ | ---- argument unexpected
...
LL | some_macro!(some_function);
- | ^^^^^^^^^^^^^ expected 0 arguments
+ | ^^^^^^^^^^^^^
|
note: function defined here
--> $DIR/issue-26094.rs:7:4
|
LL | fn some_function() {}
| ^^^^^^^^^^^^^
+help: remove the extra argument
+ |
+LL | some_function()
+ | ~~~~~~~~~~~~~~~
error: aborting due to previous error
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads support
-
-use std::thread;
-
-struct Foo;
-
-impl Drop for Foo {
- fn drop(&mut self) {
- println!("test2");
- }
-}
-
-thread_local!(static FOO: Foo = Foo);
-
-fn main() {
- // Off the main thread due to #28129, be sure to initialize FOO first before
- // calling `println!`
- thread::spawn(|| {
- FOO.with(|_| {});
- println!("test1");
- }).join().unwrap();
-}
let needlesArr: Vec<char> = vec!['a', 'f'];
needlesArr.iter().fold(|x, y| {
});
- //~^^ ERROR this function takes 2 arguments but 1 argument was supplied
+ //~^^ ERROR mismatched types
+ //~| ERROR this function takes 2 arguments but 1 argument was supplied
}
+error[E0308]: mismatched types
+ --> $DIR/issue-3044.rs:3:35
+ |
+LL | needlesArr.iter().fold(|x, y| {
+ | ___________________________________^
+LL | | });
+ | |_____^ expected closure, found `()`
+ |
+ = note: expected closure `[closure@$DIR/issue-3044.rs:3:28: 4:6]`
+ found unit type `()`
+
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/issue-3044.rs:3:23
|
LL | needlesArr.iter().fold(|x, y| {
- | _______________________^^^^_-
- | | |
- | | expected 2 arguments
+ | _______________________^^^^-
LL | | });
- | |_____- supplied 1 argument
+ | |______- an argument is missing
|
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| {
+LL ~ }, {_});
+ |
-error: aborting due to previous error
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0061`.
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
+++ /dev/null
-fn main() {
- include!(line!()); //~ ERROR argument must be a string literal
-}
+++ /dev/null
-error: argument must be a string literal
- --> $DIR/issue-41776.rs:2:14
- |
-LL | include!(line!());
- | ^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-#![allow(unused)]
-
-fn main() {
-}
-
-fn foo() {
- let b = mk::<
- Forward<(Box<dyn Future<Error = u32>>,)>,
- >();
- b.map_err(|_| ()).join();
-}
-
-fn mk<T>() -> T {
- loop {}
-}
-
-impl<I: Future<Error = E>, E> Future for (I,) {
- type Error = E;
-}
-
-struct Forward<T: Future> {
- _a: T,
-}
-
-impl<T: Future> Future for Forward<T>
-where
- T::Error: From<u32>,
-{
- type Error = T::Error;
-}
-
-trait Future {
- type Error;
-
- fn map_err<F, E>(self, _: F) -> (Self, F)
- where
- F: FnOnce(Self::Error) -> E,
- Self: Sized,
- {
- loop {}
- }
-
- fn join(self) -> (MaybeDone<Self>, ())
- where
- Self: Sized,
- {
- loop {}
- }
-}
-
-impl<S: ?Sized + Future> Future for Box<S> {
- type Error = S::Error;
-}
-
-enum MaybeDone<A: Future> {
- _Done(A::Error),
-}
-
-impl<U, A: Future, F> Future for (A, F)
-where
- F: FnOnce(A::Error) -> U,
-{
- type Error = U;
-}
--> $DIR/issue-43420-no-over-suggest.rs:8:9
|
LL | foo(&a);
- | ^^ expected slice `[u16]`, found struct `Vec`
+ | --- ^^ expected slice `[u16]`, found struct `Vec`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&[u16]`
found reference `&Vec<u8>`
+note: function defined here
+ --> $DIR/issue-43420-no-over-suggest.rs:4:4
+ |
+LL | fn foo(b: &[u16]) {}
+ | ^^^ ---------
error: aborting due to previous error
+++ /dev/null
-// run-pass
-
-#![feature(decl_macro)]
-
-pub struct Foo {
- bar: u32,
-}
-pub macro pattern($a:pat) {
- Foo { bar: $a }
-}
-
-fn main() {
- match (Foo { bar: 3 }) {
- pattern!(3) => println!("Test OK"),
- _ => unreachable!(),
- }
-}
--> $DIR/issue-4517.rs:5:9
|
LL | bar(foo);
- | ^^^ expected `usize`, found array `[u8; 4]`
+ | --- ^^^ expected `usize`, found array `[u8; 4]`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-4517.rs:1:4
+ |
+LL | fn bar(int_param: usize) {}
+ | ^^^ ----------------
error: aborting due to previous error
--> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:12:42
|
LL | light_flows_our_war_of_mocking_words(behold as usize);
- | ^^^^^^^^^^^^^^^
- | |
- | expected `&usize`, found `usize`
- | help: consider borrowing here: `&(behold as usize)`
+ | ------------------------------------ ^^^^^^^^^^^^^^^
+ | | |
+ | | expected `&usize`, found `usize`
+ | | help: consider borrowing here: `&(behold as usize)`
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4
+ |
+LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------
error[E0308]: mismatched types
--> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:14:42
|
LL | light_flows_our_war_of_mocking_words(with_tears + 4);
- | ^^^^^^^^^^^^^^
- | |
- | expected `&usize`, found `usize`
- | help: consider borrowing here: `&(with_tears + 4)`
+ | ------------------------------------ ^^^^^^^^^^^^^^
+ | | |
+ | | expected `&usize`, found `usize`
+ | | help: consider borrowing here: `&(with_tears + 4)`
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4
+ |
+LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------
error: aborting due to 2 previous errors
--> $DIR/issue-48364.rs:2:21
|
LL | b"".starts_with(stringify!(foo))
- | ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&[u8]`
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
--> $DIR/issue-4935.rs:5:13
|
LL | fn main() { foo(5, 6) }
- | ^^^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^ - argument unexpected
|
note: function defined here
--> $DIR/issue-4935.rs:3:4
|
LL | fn foo(a: usize) {}
| ^^^ --------
+help: remove the extra argument
+ |
+LL | fn main() { foo(5) }
+ | ~~~~~~
error: aborting due to previous error
LL | fn foo<F: FnMut()>() {
| - this type parameter
LL | let _: Box<F> = Box::new(|| ());
- | ^^^^^ expected type parameter `F`, found closure
+ | -------- ^^^^^ expected type parameter `F`, found closure
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `F`
found closure `[closure@$DIR/issue-51154.rs:2:30: 2:35]`
= 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
--> $DIR/issue-5216.rs:3:21
|
LL | pub static C: S = S(f);
- | ^ expected struct `Box`, found fn item
+ | - ^ expected struct `Box`, found fn item
+ | |
+ | arguments to this struct are incorrect
|
= note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
found fn item `fn() {f}`
+note: tuple struct defined here
+ --> $DIR/issue-5216.rs:2:8
+ |
+LL | struct S(Box<dyn FnMut() + Sync>);
+ | ^
error[E0308]: mismatched types
--> $DIR/issue-5216.rs:8:19
+++ /dev/null
-fn main() {
- let items = vec![1, 2, 3];
- let ref_items: &[i32] = &items;
- let items_clone: Vec<i32> = ref_items.clone();
-//~^ ERROR mismatched types
-
- // in that case no suggestion will be triggered
- let items_clone_2:Vec<i32> = items.clone();
-
- let s = "hi";
- let string: String = s.clone();
-//~^ ERROR mismatched types
-
- // in that case no suggestion will be triggered
- let s2 = "hi";
- let string_2: String = s2.to_string();
-}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/issue-53692.rs:4:37
- |
-LL | let items_clone: Vec<i32> = ref_items.clone();
- | -------- ^^^^^^^^^^^^^^^^^
- | | |
- | | expected struct `Vec`, found `&[i32]`
- | | help: try using a conversion method: `ref_items.to_vec()`
- | expected due to this
- |
- = note: expected struct `Vec<i32>`
- found reference `&[i32]`
-
-error[E0308]: mismatched types
- --> $DIR/issue-53692.rs:11:30
- |
-LL | let string: String = s.clone();
- | ------ ^^^^^^^^^
- | | |
- | | expected struct `String`, found `&str`
- | | help: try using a conversion method: `s.to_string()`
- | expected due to this
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
--> $DIR/issue-61106.rs:3:9
|
LL | foo(x.clone());
- | ^^^^^^^^^
- | |
- | expected `&str`, found struct `String`
- | help: consider borrowing here: `&x`
+ | --- ^^^^^^^^^
+ | | |
+ | | expected `&str`, found struct `String`
+ | | help: consider borrowing here: `&x`
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-61106.rs:6:4
+ |
+LL | fn foo(_: &str) {}
+ | ^^^ -------
error: aborting due to previous error
+++ /dev/null
-fn main() {
- (if foobar) //~ ERROR expected `{`, found `)`
-}
+++ /dev/null
-error: expected `{`, found `)`
- --> $DIR/issue-61858.rs:2:15
- |
-LL | (if foobar)
- | -- ^ expected `{`
- | |
- | this `if` expression has a condition, but no block
-
-error: aborting due to previous error
-
LL | impl<T> S0<T> {
| - this type parameter
LL | const C: S0<u8> = Self(0);
- | ^ expected type parameter `T`, found integer
+ | ---- ^ expected type parameter `T`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found type `{integer}`
+note: tuple struct defined here
+ --> $DIR/issue-69306.rs:3:8
+ |
+LL | struct S0<T>(T);
+ | ^^
error[E0308]: mismatched types
--> $DIR/issue-69306.rs:5:23
| - this type parameter
...
LL | Self(0);
- | ^ expected type parameter `T`, found integer
+ | ---- ^ expected type parameter `T`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found type `{integer}`
+note: tuple struct defined here
+ --> $DIR/issue-69306.rs:3:8
+ |
+LL | struct S0<T>(T);
+ | ^^
error[E0308]: mismatched types
--> $DIR/issue-69306.rs:27:14
| - this type parameter
LL | fn foo() {
LL | Self(0);
- | ^ expected type parameter `T`, found integer
+ | ---- ^ expected type parameter `T`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found type `{integer}`
+note: tuple struct defined here
+ --> $DIR/issue-69306.rs:3:8
+ |
+LL | struct S0<T>(T);
+ | ^^
error[E0308]: mismatched types
--> $DIR/issue-69306.rs:33:32
LL | impl<T> S1<T, u8> {
| - this type parameter
LL | const C: S1<u8, u8> = Self(0, 1);
- | ^ expected type parameter `T`, found integer
+ | ---- ^ expected type parameter `T`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found type `{integer}`
+note: tuple struct defined here
+ --> $DIR/issue-69306.rs:31:8
+ |
+LL | struct S1<T, U>(T, U);
+ | ^^
error[E0308]: mismatched types
--> $DIR/issue-69306.rs:33:27
LL | fn map<U>(x: U) -> S2<U> {
| - found type parameter
LL | Self(x)
- | ^ expected type parameter `T`, found type parameter `U`
+ | ---- ^ expected type parameter `T`, found type parameter `U`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found type parameter `U`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+note: tuple struct defined here
+ --> $DIR/issue-69306.rs:38:8
+ |
+LL | struct S2<T>(T);
+ | ^^
error[E0308]: mismatched types
--> $DIR/issue-69306.rs:41:9
+++ /dev/null
-#![feature(unsize, dispatch_from_dyn)]
-
-use std::marker::Unsize;
-use std::ops::DispatchFromDyn;
-
-#[allow(unused)]
-struct Foo<'a, T: ?Sized> {
- _inner: &'a &'a T,
-}
-
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
-//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
-//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
-//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
-//~| NOTE required because of the requirements on the impl
-
-fn main() {}
+++ /dev/null
-error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
- --> $DIR/issue-71036.rs:11:1
- |
-LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
- |
- = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
- = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
+++ /dev/null
-#![crate_type = "lib"]
-
-struct S<T = (), 'a>(&'a T);
-//~^ ERROR lifetime parameters must be declared prior to type parameters
+++ /dev/null
-error: lifetime parameters must be declared prior to type parameters
- --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18
- |
-LL | struct S<T = (), 'a>(&'a T);
- | ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>`
-
-error: aborting due to previous error
-
--- /dev/null
+// normalize-stderr-test "pref: Align \{\n *pow2: [1-3],\n *\}" -> "pref: $$PREF_ALIGN"
+#![crate_type = "lib"]
+#![feature(rustc_attrs)]
+
+use std::mem::MaybeUninit;
+
+enum HasNiche {
+ A,
+ B,
+ C,
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since the u8 payload will be uninit for `None`.
+#[rustc_layout(debug)]
+pub enum MissingPayloadField { //~ ERROR: layout_of
+ Some(u8),
+ None
+}
+
+// This should result in ScalarPair(Initialized, Initialized),
+// since the u8 field is present in all variants,
+// and hence will always be initialized.
+#[rustc_layout(debug)]
+pub enum CommonPayloadField { //~ ERROR: layout_of
+ A(u8),
+ B(u8),
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since, though a u8-sized field is present in all variants, it might be uninit.
+#[rustc_layout(debug)]
+pub enum CommonPayloadFieldIsMaybeUninit { //~ ERROR: layout_of
+ A(u8),
+ B(MaybeUninit<u8>),
+}
+
+// This should result in ScalarPair(Initialized, Union),
+// since only the niche field (used for the tag) is guaranteed to be initialized.
+#[rustc_layout(debug)]
+pub enum NicheFirst { //~ ERROR: layout_of
+ A(HasNiche, u8),
+ B,
+ C
+}
+
+// This should result in ScalarPair(Union, Initialized),
+// since only the niche field (used for the tag) is guaranteed to be initialized.
+#[rustc_layout(debug)]
+pub enum NicheSecond { //~ ERROR: layout_of
+ A(u8, HasNiche),
+ B,
+ C,
+}
--- /dev/null
+error: layout_of(MissingPayloadField) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 1,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 1,
+ },
+ },
+ ],
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ Union {
+ value: Int(
+ I8,
+ false,
+ ),
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ }
+ --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1
+ |
+LL | / pub enum MissingPayloadField {
+LL | | Some(u8),
+LL | | None
+LL | | }
+ | |_^
+
+error: layout_of(CommonPayloadField) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Single {
+ index: 1,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ ],
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=255,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ }
+ --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1
+ |
+LL | / pub enum CommonPayloadField {
+LL | | A(u8),
+LL | | B(u8),
+LL | | }
+ | |_^
+
+error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Single {
+ index: 1,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ ],
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ Union {
+ value: Int(
+ I8,
+ false,
+ ),
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=1,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ }
+ --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1
+ |
+LL | / pub enum CommonPayloadFieldIsMaybeUninit {
+LL | | A(u8),
+LL | | B(MaybeUninit<u8>),
+LL | | }
+ | |_^
+
+error: layout_of(NicheFirst) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ tag_encoding: Niche {
+ dataful_variant: 0,
+ niche_variants: 1..=2,
+ niche_start: 3,
+ },
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ 1,
+ ],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=2,
+ },
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=255,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=2,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 1,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 0,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 2,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 0,
+ },
+ },
+ ],
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ Union {
+ value: Int(
+ I8,
+ false,
+ ),
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ }
+ --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1
+ |
+LL | / pub enum NicheFirst {
+LL | | A(HasNiche, u8),
+LL | | B,
+LL | | C
+LL | | }
+ | |_^
+
+error: layout_of(NicheSecond) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ tag_encoding: Niche {
+ dataful_variant: 0,
+ niche_variants: 1..=2,
+ niche_start: 3,
+ },
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ Size {
+ raw: 1,
+ },
+ ],
+ memory_index: [
+ 0,
+ 1,
+ ],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: ScalarPair(
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=255,
+ },
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=2,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 1,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=2,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 1,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 0,
+ },
+ },
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 2,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 0,
+ },
+ },
+ ],
+ },
+ abi: ScalarPair(
+ Union {
+ value: Int(
+ I8,
+ false,
+ ),
+ },
+ Initialized {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 1,
+ },
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=4,
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: $PREF_ALIGN,
+ },
+ size: Size {
+ raw: 2,
+ },
+ }
+ --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1
+ |
+LL | / pub enum NicheSecond {
+LL | | A(u8, HasNiche),
+LL | | B,
+LL | | C,
+LL | | }
+ | |_^
+
+error: aborting due to 5 previous errors
+
--> $DIR/issue-91763.rs:8:20
|
LL | fn f() -> Ptr<Thing>;
- | ^ expected named lifetime parameter
+ | ^ expected lifetime parameter
|
note: the lint level is defined here
--> $DIR/issue-91763.rs:3:9
|
LL | #![deny(elided_lifetimes_in_paths)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: indicate the anonymous lifetime
+ |
+LL | fn f() -> Ptr<Thing><'_>;
+ | ++++
error: aborting due to previous error
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/issue_74400.rs:12:5
|
+LL | fn g<T>(data: &[T]) {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | f(data, identity)
- | ^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0308]: mismatched types
--> $DIR/issue_74400.rs:12:5
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
|
+LL | #[derive(Eq, PartialEq)]
+ | -- lifetime `'b` is missing in item created through this procedural macro
LL | struct Test {
| - help: consider introducing lifetime `'b` here: `<'b>`
LL | a: &'b str,
|
help: consider introducing lifetime `'b` here
|
-LL | impl<'b> T for Test {
- | ++++
-help: consider introducing lifetime `'b` here
- |
LL | fn foo<'b>(&'b self) {}
| ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b> T for Test {
+ | ++++
error: aborting due to 3 previous errors
--> $DIR/allowed-by-default-lint.rs:9:12
|
LL | fn foo(x: &Foo) {}
- | ^^^ expected named lifetime parameter
+ | ^^^ expected lifetime parameter
|
= note: requested on the command line with `--force-warn elided-lifetimes-in-paths`
-help: consider using the `'_` lifetime
+help: indicate the anonymous lifetime
|
LL | fn foo(x: &Foo<'_>) {}
- | ~~~~~~~
+ | ++++
warning: 1 warning emitted
--- /dev/null
+// build-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+#![warn(clashing_extern_declarations)]
+
+// pretty-expanded FIXME #23616
+
+mod a {
+ pub type rust_task = usize;
+ pub mod rustrt {
+ use super::rust_task;
+ extern "C" {
+ pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+ }
+ }
+}
+
+mod b {
+ pub type rust_task = bool;
+ pub mod rustrt {
+ use super::rust_task;
+ extern "C" {
+ pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+ //~^ WARN `rust_task_is_unwinding` redeclared with a different signature
+ }
+ }
+}
+
+pub fn main() {}
--- /dev/null
+warning: `rust_task_is_unwinding` redeclared with a different signature
+ --> $DIR/issue-1866.rs:23:13
+ |
+LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+ | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here
+...
+LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+ |
+note: the lint level is defined here
+ --> $DIR/issue-1866.rs:4:9
+ |
+LL | #![warn(clashing_extern_declarations)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `unsafe extern "C" fn(*const usize) -> bool`
+ found `unsafe extern "C" fn(*const bool) -> bool`
+
+warning: 1 warning emitted
+
--- /dev/null
+// run-pass
+#![allow(unused_variables)]
+// Regression test for Issue #20343.
+
+// pretty-expanded FIXME #23616
+
+#![deny(dead_code)]
+
+struct B { b: u32 }
+struct C;
+struct D;
+
+trait T<A> { fn dummy(&self, a: A) { } }
+impl<A> T<A> for () {}
+
+impl B {
+ // test for unused code in arguments
+ fn foo(B { b }: B) -> u32 { b }
+
+ // test for unused code in return type
+ fn bar() -> C { unsafe { ::std::mem::transmute(()) } }
+
+ // test for unused code in generics
+ fn baz<A: T<D>>() {}
+}
+
+pub fn main() {
+ let b = B { b: 3 };
+ B::foo(b);
+ B::bar();
+ B::baz::<()>();
+}
fn option_fn(x: Option<extern "C" fn()>);
fn nonnull(x: Option<std::ptr::NonNull<u8>>);
fn unique(x: Option<std::ptr::Unique<u8>>);
- //~^ ERROR `extern` block uses type `Option<Unique<u8>>`
fn nonzero_u8(x: Option<num::NonZeroU8>);
fn nonzero_u16(x: Option<num::NonZeroU16>);
fn nonzero_u32(x: Option<num::NonZeroU32>);
LL | | }
| |_^
-error: `extern` block uses type `Option<Unique<u8>>`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:69:17
- |
-LL | fn unique(x: Option<std::ptr::Unique<u8>>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
- |
- = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
- = note: enum has no representation hint
-
error: `extern` block uses type `u128`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:75:23
+ --> $DIR/lint-ctypes-enum.rs:74:23
|
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:82:23
+ --> $DIR/lint-ctypes-enum.rs:81:23
|
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:87:28
+ --> $DIR/lint-ctypes-enum.rs:86:28
|
LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
= note: enum has no representation hint
error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:89:20
+ --> $DIR/lint-ctypes-enum.rs:88:20
|
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
= note: enum has no representation hint
error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe
- --> $DIR/lint-ctypes-enum.rs:90:20
+ --> $DIR/lint-ctypes-enum.rs:89:20
|
LL | fn no_result(x: Result<(), num::NonZeroI32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
|
LL | let dangling = (...).with_addr(16_usize);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ++++++++++++++++ ~
error: aborting due to previous error
let addr_32bit = &x as *const u8 as u32;
//~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+
+ // don't add unnecessary parens in the suggestion
+ let ptr = &x as *const u8;
+ let ptr_addr = ptr as usize;
+ //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+ let ptr_addr_32bit = ptr as u32;
+ //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
}
--> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
|
LL | let addr: usize = &x as *const u8 as usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
LL | #![deny(lossy_provenance_casts)]
| ^^^^^^^^^^^^^^^^^^^^^^
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+help: use `.addr()` to obtain the address of a pointer
+ |
+LL | let addr: usize = (&x as *const u8).addr();
+ | + ~~~~~~~~
error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
--> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
|
LL | let addr_32bit = &x as *const u8 as u32;
- | ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+help: use `.addr()` to obtain the address of a pointer
+ |
+LL | let addr_32bit = (&x as *const u8).addr() as u32;
+ | + ~~~~~~~~~~~~~~~
+
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+ --> $DIR/lint-strict-provenance-lossy-casts.rs:14:20
+ |
+LL | let ptr_addr = ptr as usize;
+ | ^^^---------
+ | |
+ | help: use `.addr()` to obtain the address of a pointer: `.addr()`
+ |
+ = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
+
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+ --> $DIR/lint-strict-provenance-lossy-casts.rs:16:26
+ |
+LL | let ptr_addr_32bit = ptr as u32;
+ | ^^^-------
+ | |
+ | help: use `.addr()` to obtain the address of a pointer: `.addr() as u32`
|
= help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
impl fmt::Debug for CheaterDetectionMechanism {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
//~^ WARN hidden lifetime parameters in types are deprecated
- //~| NOTE expected named lifetime parameter
+ //~| NOTE expected lifetime parameter
//~| NOTE explicit anonymous lifetimes aid
- //~| HELP consider using the `'_` lifetime
+ //~| HELP indicate the anonymous lifetime
fmt.debug_struct("CheaterDetectionMechanism").finish()
}
}
--> $DIR/reasons.rs:20:34
|
LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- | ^^^^^^^^^ expected named lifetime parameter
+ | -----^^^^^^^^^
+ | |
+ | expected lifetime parameter
|
= note: explicit anonymous lifetimes aid reasoning about ownership
note: the lint level is defined here
|
LL | #![warn(elided_lifetimes_in_paths,
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider using the `'_` lifetime
+help: indicate the anonymous lifetime
|
LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- | ~~~~~~~~~~~~~
+ | ++++
warning: variable `Social_exchange_psychology` should have a snake case name
--> $DIR/reasons.rs:30:9
error: aborting due to 7 previous errors
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:22:17
+ |
+LL | let _ = &good.ptr;
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:24:17
+ |
+LL | let _ = &good.data;
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:27:17
+ |
+LL | let _ = &good.data as *const _;
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:29:27
+ |
+LL | let _: *const _ = &good.data;
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:32:17
+ |
+LL | let _ = good.data.clone();
+ | ^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:35:17
+ |
+LL | let _ = &good.data2[0];
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:45:17
+ |
+LL | let _ = &packed2.x;
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references.rs:1:9
+ |
+LL | #![deny(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
error: aborting due to previous error
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/unaligned_references_external_macro.rs:5:1
+ |
+LL | / unaligned_references_external_crate::mac! {
+LL | |
+LL | | #[repr(packed)]
+LL | | pub struct X {
+LL | | pub field: u16
+LL | | }
+LL | | }
+ | |_^
+ |
+note: the lint level is defined here
+ --> $DIR/unaligned_references_external_macro.rs:5:1
+ |
+LL | / unaligned_references_external_crate::mac! {
+LL | |
+LL | | #[repr(packed)]
+LL | | pub struct X {
+LL | | pub field: u16
+LL | | }
+LL | | }
+ | |_^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+ = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
+
pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
pub(crate) fn count_electrons(&self) -> usize { self.electrons }
}
+ impl Clone for Hydrogen {
+ fn clone(&self) -> Hydrogen {
+ Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
+ }
+ }
pub enum Helium {} //~ WARNING unreachable_pub
pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
| help: consider restricting its visibility: `pub(crate)`
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:30:5
+ --> $DIR/unreachable_pub-pub_crate.rs:35:5
|
LL | pub enum Helium {}
| ---^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:31:5
+ --> $DIR/unreachable_pub-pub_crate.rs:36:5
|
LL | pub union Lithium { c1: usize, c2: u8 }
| ---^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:32:5
+ --> $DIR/unreachable_pub-pub_crate.rs:37:5
|
LL | pub fn beryllium() {}
| ---^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:33:5
+ --> $DIR/unreachable_pub-pub_crate.rs:38:5
|
LL | pub trait Boron {}
| ---^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:34:5
+ --> $DIR/unreachable_pub-pub_crate.rs:39:5
|
LL | pub const CARBON: usize = 1;
| ---^^^^^^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:35:5
+ --> $DIR/unreachable_pub-pub_crate.rs:40:5
|
LL | pub static NITROGEN: usize = 2;
| ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:36:5
+ --> $DIR/unreachable_pub-pub_crate.rs:41:5
|
LL | pub type Oxygen = bool;
| ---^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:39:47
+ --> $DIR/unreachable_pub-pub_crate.rs:44:47
|
LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: unreachable `pub` item
- --> $DIR/unreachable_pub-pub_crate.rs:45:9
+ --> $DIR/unreachable_pub-pub_crate.rs:50:9
|
LL | pub fn catalyze() -> bool;
| ---^^^^^^^^^^^^^^^^^^^^^^^
pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub
crate fn count_electrons(&self) -> usize { self.electrons }
}
+ impl Clone for Hydrogen {
+ fn clone(&self) -> Hydrogen {
+ Hydrogen { neutrons: self.neutrons, electrons: self.electrons }
+ }
+ }
pub enum Helium {} //~ WARNING unreachable_pub
pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub
| help: consider restricting its visibility: `crate`
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:26:5
+ --> $DIR/unreachable_pub.rs:31:5
|
LL | pub enum Helium {}
| ---^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:27:5
+ --> $DIR/unreachable_pub.rs:32:5
|
LL | pub union Lithium { c1: usize, c2: u8 }
| ---^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:28:5
+ --> $DIR/unreachable_pub.rs:33:5
|
LL | pub fn beryllium() {}
| ---^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:29:5
+ --> $DIR/unreachable_pub.rs:34:5
|
LL | pub trait Boron {}
| ---^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:30:5
+ --> $DIR/unreachable_pub.rs:35:5
|
LL | pub const CARBON: usize = 1;
| ---^^^^^^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:31:5
+ --> $DIR/unreachable_pub.rs:36:5
|
LL | pub static NITROGEN: usize = 2;
| ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:32:5
+ --> $DIR/unreachable_pub.rs:37:5
|
LL | pub type Oxygen = bool;
| ---^^^^^^^^^^^^^^^^^^^^
= help: or consider exporting it for use by other crates
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:35:47
+ --> $DIR/unreachable_pub.rs:40:47
|
LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: unreachable `pub` item
- --> $DIR/unreachable_pub.rs:41:9
+ --> $DIR/unreachable_pub.rs:46:9
|
LL | pub fn catalyze() -> bool;
| ---^^^^^^^^^^^^^^^^^^^^^^^
--> $DIR/issue-29084.rs:4:13
|
LL | bar(&mut $d);
- | ^^^^^^^ expected `u8`, found `&mut u8`
+ | --- ^^^^^^^ expected `u8`, found `&mut u8`
+ | |
+ | arguments to this function are incorrect
...
LL | foo!(0u8);
| --------- in this macro invocation
|
+note: function defined here
+ --> $DIR/issue-29084.rs:3:12
+ |
+LL | fn bar(d: u8) { }
+ | ^^^ -----
+...
+LL | foo!(0u8);
+ | --------- in this macro invocation
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
--- /dev/null
+fn main() {
+ include!(line!()); //~ ERROR argument must be a string literal
+}
--- /dev/null
+error: argument must be a string literal
+ --> $DIR/issue-41776.rs:2:14
+ |
+LL | include!(line!());
+ | ^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+#![feature(decl_macro)]
+
+pub struct Foo {
+ bar: u32,
+}
+pub macro pattern($a:pat) {
+ Foo { bar: $a }
+}
+
+fn main() {
+ match (Foo { bar: 3 }) {
+ pattern!(3) => println!("Test OK"),
+ _ => unreachable!(),
+ }
+}
// compile-flags: -Zunpretty=hir,typed
// check-pass
-pub fn main() ({
+fn main() ({
(if (true as bool)
({ } as
()) else if (let Some(a) =
--- /dev/null
+fn main() {
+ let arr = &[0,1,2,3];
+ for _i in 0..arr.len().rev() { //~ERROR not an iterator
+ // The above error used to say “the method `rev` exists for type `usize`”.
+ // This regression test ensures it doesn't say that any more.
+ }
+}
--- /dev/null
+error[E0599]: `usize` is not an iterator
+ --> $DIR/issue-90315.rs:3:26
+ |
+LL | for _i in 0..arr.len().rev() {
+ | ^^^ `usize` is not an iterator
+ |
+ = note: the following trait bounds were not satisfied:
+ `usize: Iterator`
+ which is required by `&mut usize: Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
--> $DIR/method-call-err-msg.rs:13:7
|
LL | x.zero(0)
- | ^^^^ - supplied 1 argument
- | |
- | expected 0 arguments
+ | ^^^^ - argument unexpected
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:5:8
|
LL | fn zero(self) -> Foo { self }
| ^^^^ ----
+help: remove the extra argument
+ |
+LL | x.zero()
+ | ~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/method-call-err-msg.rs:14:7
|
LL | .one()
- | ^^^- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^^-- an argument of type `isize` is missing
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:6:8
|
LL | fn one(self, _: isize) -> Foo { self }
| ^^^ ---- --------
+help: provide the argument
+ |
+LL | .one({isize})
+ | ~~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/method-call-err-msg.rs:15:7
|
LL | .two(0);
- | ^^^ - supplied 1 argument
- | |
- | expected 2 arguments
+ | ^^^--- an argument of type `isize` is missing
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:7:8
|
LL | fn two(self, _: isize, _: isize) -> Foo { self }
| ^^^ ---- -------- --------
+help: provide the argument
+ |
+LL | .two(0, {isize});
+ | ~~~~~~~~~~~~~~~
error[E0599]: `Foo` is not an iterator
--> $DIR/method-call-err-msg.rs:19:7
--> $DIR/method-call-err-msg.rs:21:7
|
LL | y.three::<usize>();
- | ^^^^^--------- supplied 0 arguments
- | |
- | expected 3 arguments
+ | ^^^^^^^^^^^^^^-- three arguments of type `usize`, `usize`, and `usize` are missing
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:8:8
|
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
| ^^^^^ ---- ---- ---- ----
+help: provide the arguments
+ |
+LL | y.three::<usize>({usize}, {usize}, {usize});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 5 previous errors
fn main() {
- 0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a`
+ 0.clone::<'a>();
+ //~^ ERROR use of undeclared lifetime name `'a`
+ //~| WARN cannot specify lifetime arguments explicitly if late bound
+ //~| WARN this was previously accepted by the compiler
}
LL | 0.clone::<'a>();
| ^^ undeclared lifetime
-error: aborting due to previous error
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/method-call-lifetime-args-unresolved.rs:2:15
+ |
+LL | 0.clone::<'a>();
+ | ^^
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | fn clone(&self) -> Self;
+ | - the late bound lifetime parameter is introduced here
+ |
+ = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0261`.
--> $DIR/method-self-arg-1.rs:11:14
|
LL | Foo::bar(x);
- | ^
- | |
- | expected `&Foo`, found struct `Foo`
- | help: consider borrowing here: `&x`
+ | -------- ^
+ | | |
+ | | expected `&Foo`, found struct `Foo`
+ | | help: consider borrowing here: `&x`
+ | arguments to this function are incorrect
+ |
+note: associated function defined here
+ --> $DIR/method-self-arg-1.rs:6:8
+ |
+LL | fn bar(&self) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/method-self-arg-1.rs:13:14
|
LL | Foo::bar(&42);
- | ^^^ expected struct `Foo`, found integer
+ | -------- ^^^ expected struct `Foo`, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo`
found reference `&{integer}`
+note: associated function defined here
+ --> $DIR/method-self-arg-1.rs:6:8
+ |
+LL | fn bar(&self) {}
+ | ^^^ -----
error: aborting due to 2 previous errors
--- /dev/null
+// check-pass
+// compile-flags: -Zvalidate-mir
+
+fn foo(_a: &str) {}
+
+fn main() {
+ let x = foo as fn(&'static str);
+
+ let _ = x == foo;
+}
error[E0308]: mismatched types
--> $DIR/issue-26480.rs:16:19
|
+LL | write(stdout, $arr.as_ptr() as *const i8,
+ | ----- arguments to this function are incorrect
LL | $arr.len() * size_of($arr[0]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
...
LL | write!(hello);
| ------------- in this macro invocation
|
- = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
+note: function defined here
+ --> $DIR/issue-26480.rs:2:8
|
-LL | ($arr.len() * size_of($arr[0])).try_into().unwrap());
- | + +++++++++++++++++++++
+LL | fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64;
+ | ^^^^^
+ = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0605]: non-primitive cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:22:19
| ---- this type parameter
LL | fn parse(text: &str) -> Option<bool> {
LL | Some(true)
- | ^^^^ expected type parameter `bool`, found `bool`
+ | ---- ^^^^ expected type parameter `bool`, found `bool`
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected type parameter `bool` (type parameter `bool`)
found type `bool` (`bool`)
--> $DIR/numeric-literal-cast.rs:6:9
|
LL | foo(1u8);
- | ^^^ expected `u16`, found `u8`
+ | --- ^^^ expected `u16`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-literal-cast.rs:1:4
+ |
+LL | fn foo(_: u16) {}
+ | ^^^ ------
help: change the type of the numeric literal from `u8` to `u16`
|
LL | foo(1u16);
--> $DIR/numeric-literal-cast.rs:8:10
|
LL | foo1(2f32);
- | ^^^^ expected `f64`, found `f32`
+ | ---- ^^^^ expected `f64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-literal-cast.rs:2:4
|
+LL | fn foo1(_: f64) {}
+ | ^^^^ ------
help: change the type of the numeric literal from `f32` to `f64`
|
LL | foo1(2f64);
--> $DIR/numeric-literal-cast.rs:10:10
|
LL | foo2(3i16);
- | ^^^^ expected `i32`, found `i16`
+ | ---- ^^^^ expected `i32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-literal-cast.rs:3:4
|
+LL | fn foo2(_: i32) {}
+ | ^^^^ ------
help: change the type of the numeric literal from `i16` to `i32`
|
LL | foo2(3i32);
//~^ ERROR this function takes 1 argument but 0 arguments were supplied
let ans = s("burma", "shave");
//~^ ERROR this function takes 1 argument but 2 arguments were supplied
- //~| ERROR mismatched types
}
--> $DIR/overloaded-calls-bad.rs:28:17
|
LL | let ans = s("what");
- | ^^^^^^ expected `isize`, found `&str`
+ | - ^^^^^^ expected `isize`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: associated function defined here
+ --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+ |
+LL | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+ | ^^^^^^^^
error[E0057]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/overloaded-calls-bad.rs:29:15
|
LL | let ans = s();
- | ^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^-- an argument of type `isize` is missing
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
LL | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
| ^^^^^^^^
-
-error[E0308]: mismatched types
- --> $DIR/overloaded-calls-bad.rs:31:17
+help: provide the argument
|
-LL | let ans = s("burma", "shave");
- | ^^^^^^^ expected `isize`, found `&str`
+LL | let ans = s({isize});
+ | ~~~~~~~~~~
error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/overloaded-calls-bad.rs:31:15
|
LL | let ans = s("burma", "shave");
- | ^ ------- ------- supplied 2 arguments
- | |
- | expected 1 argument
+ | ^ ------- ------- argument unexpected
+ | |
+ | expected `isize`, found `&str`
|
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
LL | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
| ^^^^^^^^
+help: remove the extra argument
+ |
+LL | let ans = s({isize});
+ | ~~~~~~~~~~
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
Some errors have detailed explanations: E0057, E0308.
For more information about an error, try `rustc --explain E0057`.
--> $DIR/trait-bounds-cant-coerce.rs:13:7
|
LL | a(x);
- | ^ expected trait `Foo + Send`, found trait `Foo`
+ | - ^ expected trait `Foo + Send`, found trait `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Box<(dyn Foo + Send + 'static)>`
found struct `Box<(dyn Foo + 'static)>`
+note: function defined here
+ --> $DIR/trait-bounds-cant-coerce.rs:5:4
+ |
+LL | fn a(_x: Box<dyn Foo + Send>) {
+ | ^ -----------------------
error: aborting due to previous error
--> $DIR/mut-cross-borrowing.rs:7:7
|
LL | f(x)
- | ^
- | |
- | expected `&mut isize`, found struct `Box`
- | help: consider mutably borrowing here: `&mut x`
+ | - ^
+ | | |
+ | | expected `&mut isize`, found struct `Box`
+ | | help: consider mutably borrowing here: `&mut x`
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut isize`
found struct `Box<{integer}>`
+note: function defined here
+ --> $DIR/mut-cross-borrowing.rs:1:4
+ |
+LL | fn f(_: &mut isize) {}
+ | ^ -------------
error: aborting due to previous error
--> $DIR/call-fn-never-arg-wrong-type.rs:10:9
|
LL | foo("wow");
- | ^^^^^ expected `!`, found `&str`
+ | --- ^^^^^ expected `!`, found `&str`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `!`
found reference `&'static str`
+note: function defined here
+ --> $DIR/call-fn-never-arg-wrong-type.rs:5:4
+ |
+LL | fn foo(x: !) -> ! {
+ | ^^^ ----
error: aborting due to previous error
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
-LL | impl<I: Iterator> IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: ~const 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
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:32:36
|
+LL | fn supply<'a, T>(value: T)
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | establish_relationships(value, |value| {
| ____________________________________^
LL | |
... |
LL | | require(value);
LL | | });
- | |_____^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | |_____^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/impl-trait-outlives.rs:11:5
|
+LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/impl-trait-outlives.rs:26:5
|
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 2 previous errors
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/projection-implied-bounds.rs:30:18
|
+LL | fn generic2<T: Iterator>(value: T) {
+ | -- help: consider adding an explicit lifetime bound...: `T: 'static +`
LL | twice(value, |value_ref, item| invoke2(value_ref, item));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+ = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-no-regions-closure.rs:34:23
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+ = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-no-regions-closure.rs:52:23
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+ = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-fn.rs:28:5
| ^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
+ = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
error: aborting due to 2 previous errors
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:45:29
|
+LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | with_signature(cell, t, |cell, t| require(cell, t));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:45:39
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:56:29
|
+LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | with_signature(cell, t, |cell, t| require(cell, t));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:56:39
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
+ = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
+ = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:61:29
| ^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
+ = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
error: aborting due to previous error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
+ = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-where-clause-none.rs:16:5
|
+LL | fn foo<'a, T>() -> &'a ()
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | bar::<T::Output>()
- | ^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
|
+LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | twice(cell, value, |a, b| invoke(a, b));
- | ^^^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
|
+LL | fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | with_signature(x, |y| y)
- | ^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5
|
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 2 previous errors
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26
|
+LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) {
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | with_signature(a, b, |x, y| {
| __________________________^
LL | |
... |
LL | | require(&x, &y)
LL | | })
- | |_____^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | |_____^ ...so that the type `T` will meet its required lifetime bounds
note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26
|
+LL | fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T)
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | with_signature(a, b, |x, y| {
| __________________________^
LL | |
LL | | // See `correct_region`
LL | | require(&x, &y)
LL | | })
- | |_____^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | |_____^ ...so that the type `T` will meet its required lifetime bounds
note: external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn-body.rs:19:5
|
+LL | fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | outlives(cell, t)
- | ^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn.rs:11:5
|
+LL | fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/ty-param-fn.rs:26:5
|
+LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | x
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 2 previous errors
--> $DIR/not-enough-arguments.rs:27:3
|
LL | foo(1, 2, 3);
- | ^^^ - - - supplied 3 arguments
- | |
- | expected 4 arguments
+ | ^^^--------- an argument of type `isize` is missing
|
note: function defined here
--> $DIR/not-enough-arguments.rs:5:4
|
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
| ^^^ -------- -------- -------- -------
+help: provide the argument
+ |
+LL | foo(1, 2, 3, {isize});
+ | ~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 6 arguments but 3 arguments were supplied
--> $DIR/not-enough-arguments.rs:29:3
|
LL | bar(1, 2, 3);
- | ^^^ - - - supplied 3 arguments
- | |
- | expected 6 arguments
+ | ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing
|
note: function defined here
--> $DIR/not-enough-arguments.rs:10:4
| ------
LL | f: i32,
| ------
+help: provide the arguments
+ |
+LL | bar(1, 2, 3, {i32}, {i32}, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
--> $DIR/integer-literal-suffix-inference.rs:38:11
|
LL | id_i8(a16);
- | ^^^ expected `i8`, found `i16`
+ | ----- ^^^ expected `i8`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
+ |
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a16.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:41:11
|
LL | id_i8(a32);
- | ^^^ expected `i8`, found `i32`
+ | ----- ^^^ expected `i8`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
|
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:44:11
|
LL | id_i8(a64);
- | ^^^ expected `i8`, found `i64`
+ | ----- ^^^ expected `i8`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
+ |
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(a64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:47:11
|
LL | id_i8(asize);
- | ^^^^^ expected `i8`, found `isize`
+ | ----- ^^^^^ expected `i8`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
|
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(asize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:51:12
|
LL | id_i16(a8);
- | ^^ expected `i16`, found `i8`
+ | ------ ^^ expected `i16`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
+ |
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i16`
|
LL | id_i16(a8.into());
--> $DIR/integer-literal-suffix-inference.rs:55:12
|
LL | id_i16(a32);
- | ^^^ expected `i16`, found `i32`
+ | ------ ^^^ expected `i16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
|
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(a32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:58:12
|
LL | id_i16(a64);
- | ^^^ expected `i16`, found `i64`
+ | ------ ^^^ expected `i16`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
|
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(a64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:61:12
|
LL | id_i16(asize);
- | ^^^^^ expected `i16`, found `isize`
+ | ------ ^^^^^ expected `i16`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
+ |
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(asize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:65:12
|
LL | id_i32(a8);
- | ^^ expected `i32`, found `i8`
+ | ------ ^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
|
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i32`
|
LL | id_i32(a8.into());
--> $DIR/integer-literal-suffix-inference.rs:68:12
|
LL | id_i32(a16);
- | ^^^ expected `i32`, found `i16`
+ | ------ ^^^ expected `i32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
|
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i16` to an `i32`
|
LL | id_i32(a16.into());
--> $DIR/integer-literal-suffix-inference.rs:72:12
|
LL | id_i32(a64);
- | ^^^ expected `i32`, found `i64`
+ | ------ ^^^ expected `i32`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
+ |
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(a64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:75:12
|
LL | id_i32(asize);
- | ^^^^^ expected `i32`, found `isize`
+ | ------ ^^^^^ expected `i32`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
|
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(asize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:79:12
|
LL | id_i64(a8);
- | ^^ expected `i64`, found `i8`
+ | ------ ^^ expected `i64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
|
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i64`
|
LL | id_i64(a8.into());
--> $DIR/integer-literal-suffix-inference.rs:82:12
|
LL | id_i64(a16);
- | ^^^ expected `i64`, found `i16`
+ | ------ ^^^ expected `i64`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
+ |
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i16` to an `i64`
|
LL | id_i64(a16.into());
--> $DIR/integer-literal-suffix-inference.rs:85:12
|
LL | id_i64(a32);
- | ^^^ expected `i64`, found `i32`
+ | ------ ^^^ expected `i64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
|
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i32` to an `i64`
|
LL | id_i64(a32.into());
--> $DIR/integer-literal-suffix-inference.rs:89:12
|
LL | id_i64(asize);
- | ^^^^^ expected `i64`, found `isize`
+ | ------ ^^^^^ expected `i64`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
+ |
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
LL | id_i64(asize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:93:14
|
LL | id_isize(a8);
- | ^^ expected `isize`, found `i8`
+ | -------- ^^ expected `isize`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:19:8
|
+LL | fn id_isize(n: isize) -> isize { n }
+ | ^^^^^^^^ --------
help: you can convert an `i8` to an `isize`
|
LL | id_isize(a8.into());
--> $DIR/integer-literal-suffix-inference.rs:96:14
|
LL | id_isize(a16);
- | ^^^ expected `isize`, found `i16`
+ | -------- ^^^ expected `isize`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:19:8
+ |
+LL | fn id_isize(n: isize) -> isize { n }
+ | ^^^^^^^^ --------
help: you can convert an `i16` to an `isize`
|
LL | id_isize(a16.into());
--> $DIR/integer-literal-suffix-inference.rs:99:14
|
LL | id_isize(a32);
- | ^^^ expected `isize`, found `i32`
+ | -------- ^^^ expected `isize`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:19:8
|
+LL | fn id_isize(n: isize) -> isize { n }
+ | ^^^^^^^^ --------
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
LL | id_isize(a32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:102:14
|
LL | id_isize(a64);
- | ^^^ expected `isize`, found `i64`
+ | -------- ^^^ expected `isize`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:19:8
|
+LL | fn id_isize(n: isize) -> isize { n }
+ | ^^^^^^^^ --------
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
LL | id_isize(a64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:108:11
|
LL | id_i8(c16);
- | ^^^ expected `i8`, found `i16`
+ | ----- ^^^ expected `i8`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
+ |
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c16.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:111:11
|
LL | id_i8(c32);
- | ^^^ expected `i8`, found `i32`
+ | ----- ^^^ expected `i8`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
|
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:114:11
|
LL | id_i8(c64);
- | ^^^ expected `i8`, found `i64`
+ | ----- ^^^ expected `i8`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:15:8
|
+LL | fn id_i8(n: i8) -> i8 { n }
+ | ^^^^^ -----
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | id_i8(c64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:118:12
|
LL | id_i16(c8);
- | ^^ expected `i16`, found `i8`
+ | ------ ^^ expected `i16`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
+ |
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i16`
|
LL | id_i16(c8.into());
--> $DIR/integer-literal-suffix-inference.rs:122:12
|
LL | id_i16(c32);
- | ^^^ expected `i16`, found `i32`
+ | ------ ^^^ expected `i16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
|
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(c32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:125:12
|
LL | id_i16(c64);
- | ^^^ expected `i16`, found `i64`
+ | ------ ^^^ expected `i16`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:16:8
|
+LL | fn id_i16(n: i16) -> i16 { n }
+ | ^^^^^^ ------
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | id_i16(c64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:129:12
|
LL | id_i32(c8);
- | ^^ expected `i32`, found `i8`
+ | ------ ^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
+ |
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i32`
|
LL | id_i32(c8.into());
--> $DIR/integer-literal-suffix-inference.rs:132:12
|
LL | id_i32(c16);
- | ^^^ expected `i32`, found `i16`
+ | ------ ^^^ expected `i32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
|
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i16` to an `i32`
|
LL | id_i32(c16.into());
--> $DIR/integer-literal-suffix-inference.rs:136:12
|
LL | id_i32(c64);
- | ^^^ expected `i32`, found `i64`
+ | ------ ^^^ expected `i32`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:17:8
+ |
+LL | fn id_i32(n: i32) -> i32 { n }
+ | ^^^^^^ ------
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | id_i32(c64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:140:12
|
LL | id_i64(a8);
- | ^^ expected `i64`, found `i8`
+ | ------ ^^ expected `i64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
|
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i8` to an `i64`
|
LL | id_i64(a8.into());
--> $DIR/integer-literal-suffix-inference.rs:143:12
|
LL | id_i64(a16);
- | ^^^ expected `i64`, found `i16`
+ | ------ ^^^ expected `i64`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
+ |
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i16` to an `i64`
|
LL | id_i64(a16.into());
--> $DIR/integer-literal-suffix-inference.rs:146:12
|
LL | id_i64(a32);
- | ^^^ expected `i64`, found `i32`
+ | ------ ^^^ expected `i64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:18:8
|
+LL | fn id_i64(n: i64) -> i64 { n }
+ | ^^^^^^ ------
help: you can convert an `i32` to an `i64`
|
LL | id_i64(a32.into());
--> $DIR/integer-literal-suffix-inference.rs:152:11
|
LL | id_u8(b16);
- | ^^^ expected `u8`, found `u16`
+ | ----- ^^^ expected `u8`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:27:8
|
+LL | fn id_u8(n: u8) -> u8 { n }
+ | ^^^^^ -----
help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b16.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:155:11
|
LL | id_u8(b32);
- | ^^^ expected `u8`, found `u32`
+ | ----- ^^^ expected `u8`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:27:8
+ |
+LL | fn id_u8(n: u8) -> u8 { n }
+ | ^^^^^ -----
help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:158:11
|
LL | id_u8(b64);
- | ^^^ expected `u8`, found `u64`
+ | ----- ^^^ expected `u8`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:27:8
|
+LL | fn id_u8(n: u8) -> u8 { n }
+ | ^^^^^ -----
help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(b64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:161:11
|
LL | id_u8(bsize);
- | ^^^^^ expected `u8`, found `usize`
+ | ----- ^^^^^ expected `u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:27:8
|
+LL | fn id_u8(n: u8) -> u8 { n }
+ | ^^^^^ -----
help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
|
LL | id_u8(bsize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:165:12
|
LL | id_u16(b8);
- | ^^ expected `u16`, found `u8`
+ | ------ ^^ expected `u16`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:28:8
+ |
+LL | fn id_u16(n: u16) -> u16 { n }
+ | ^^^^^^ ------
help: you can convert a `u8` to a `u16`
|
LL | id_u16(b8.into());
--> $DIR/integer-literal-suffix-inference.rs:169:12
|
LL | id_u16(b32);
- | ^^^ expected `u16`, found `u32`
+ | ------ ^^^ expected `u16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:28:8
|
+LL | fn id_u16(n: u16) -> u16 { n }
+ | ^^^^^^ ------
help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(b32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:172:12
|
LL | id_u16(b64);
- | ^^^ expected `u16`, found `u64`
+ | ------ ^^^ expected `u16`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:28:8
|
+LL | fn id_u16(n: u16) -> u16 { n }
+ | ^^^^^^ ------
help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(b64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:175:12
|
LL | id_u16(bsize);
- | ^^^^^ expected `u16`, found `usize`
+ | ------ ^^^^^ expected `u16`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:28:8
+ |
+LL | fn id_u16(n: u16) -> u16 { n }
+ | ^^^^^^ ------
help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
|
LL | id_u16(bsize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:179:12
|
LL | id_u32(b8);
- | ^^ expected `u32`, found `u8`
+ | ------ ^^ expected `u32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:29:8
|
+LL | fn id_u32(n: u32) -> u32 { n }
+ | ^^^^^^ ------
help: you can convert a `u8` to a `u32`
|
LL | id_u32(b8.into());
--> $DIR/integer-literal-suffix-inference.rs:182:12
|
LL | id_u32(b16);
- | ^^^ expected `u32`, found `u16`
+ | ------ ^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:29:8
+ |
+LL | fn id_u32(n: u32) -> u32 { n }
+ | ^^^^^^ ------
help: you can convert a `u16` to a `u32`
|
LL | id_u32(b16.into());
--> $DIR/integer-literal-suffix-inference.rs:186:12
|
LL | id_u32(b64);
- | ^^^ expected `u32`, found `u64`
+ | ------ ^^^ expected `u32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:29:8
|
+LL | fn id_u32(n: u32) -> u32 { n }
+ | ^^^^^^ ------
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
|
LL | id_u32(b64.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:189:12
|
LL | id_u32(bsize);
- | ^^^^^ expected `u32`, found `usize`
+ | ------ ^^^^^ expected `u32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:29:8
+ |
+LL | fn id_u32(n: u32) -> u32 { n }
+ | ^^^^^^ ------
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | id_u32(bsize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:193:12
|
LL | id_u64(b8);
- | ^^ expected `u64`, found `u8`
+ | ------ ^^ expected `u64`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:30:8
|
+LL | fn id_u64(n: u64) -> u64 { n }
+ | ^^^^^^ ------
help: you can convert a `u8` to a `u64`
|
LL | id_u64(b8.into());
--> $DIR/integer-literal-suffix-inference.rs:196:12
|
LL | id_u64(b16);
- | ^^^ expected `u64`, found `u16`
+ | ------ ^^^ expected `u64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:30:8
|
+LL | fn id_u64(n: u64) -> u64 { n }
+ | ^^^^^^ ------
help: you can convert a `u16` to a `u64`
|
LL | id_u64(b16.into());
--> $DIR/integer-literal-suffix-inference.rs:199:12
|
LL | id_u64(b32);
- | ^^^ expected `u64`, found `u32`
+ | ------ ^^^ expected `u64`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:30:8
+ |
+LL | fn id_u64(n: u64) -> u64 { n }
+ | ^^^^^^ ------
help: you can convert a `u32` to a `u64`
|
LL | id_u64(b32.into());
--> $DIR/integer-literal-suffix-inference.rs:203:12
|
LL | id_u64(bsize);
- | ^^^^^ expected `u64`, found `usize`
+ | ------ ^^^^^ expected `u64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:30:8
|
+LL | fn id_u64(n: u64) -> u64 { n }
+ | ^^^^^^ ------
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | id_u64(bsize.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:207:14
|
LL | id_usize(b8);
- | ^^ expected `usize`, found `u8`
+ | -------- ^^ expected `usize`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:31:8
|
+LL | fn id_usize(n: usize) -> usize { n }
+ | ^^^^^^^^ --------
help: you can convert a `u8` to a `usize`
|
LL | id_usize(b8.into());
--> $DIR/integer-literal-suffix-inference.rs:210:14
|
LL | id_usize(b16);
- | ^^^ expected `usize`, found `u16`
+ | -------- ^^^ expected `usize`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:31:8
+ |
+LL | fn id_usize(n: usize) -> usize { n }
+ | ^^^^^^^^ --------
help: you can convert a `u16` to a `usize`
|
LL | id_usize(b16.into());
--> $DIR/integer-literal-suffix-inference.rs:213:14
|
LL | id_usize(b32);
- | ^^^ expected `usize`, found `u32`
+ | -------- ^^^ expected `usize`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:31:8
|
+LL | fn id_usize(n: usize) -> usize { n }
+ | ^^^^^^^^ --------
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
LL | id_usize(b32.try_into().unwrap());
--> $DIR/integer-literal-suffix-inference.rs:216:14
|
LL | id_usize(b64);
- | ^^^ expected `usize`, found `u64`
+ | -------- ^^^ expected `usize`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/integer-literal-suffix-inference.rs:31:8
|
+LL | fn id_usize(n: usize) -> usize { n }
+ | ^^^^^^^^ --------
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
LL | id_usize(b64.try_into().unwrap());
--> $DIR/len.rs:3:10
|
LL | test(array.len());
- | ^^^^^^^^^^^ expected `u32`, found `usize`
+ | ---- ^^^^^^^^^^^ expected `u32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/len.rs:6:4
+ |
+LL | fn test(length: u32) {
+ | ^^^^ -----------
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | test(array.len().try_into().unwrap());
--> $DIR/numeric-cast-without-suggestion.rs:17:18
|
LL | foo::<usize>(x_f64);
- | ^^^^^ expected `usize`, found `f64`
+ | ------------ ^^^^^ expected `usize`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:18:18
|
LL | foo::<usize>(x_f32);
- | ^^^^^ expected `usize`, found `f32`
+ | ------------ ^^^^^ expected `usize`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:19:18
|
LL | foo::<isize>(x_f64);
- | ^^^^^ expected `isize`, found `f64`
+ | ------------ ^^^^^ expected `isize`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:20:18
|
LL | foo::<isize>(x_f32);
- | ^^^^^ expected `isize`, found `f32`
+ | ------------ ^^^^^ expected `isize`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:21:16
|
LL | foo::<u64>(x_f64);
- | ^^^^^ expected `u64`, found `f64`
+ | ---------- ^^^^^ expected `u64`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:22:16
|
LL | foo::<u64>(x_f32);
- | ^^^^^ expected `u64`, found `f32`
+ | ---------- ^^^^^ expected `u64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:23:16
|
LL | foo::<i64>(x_f64);
- | ^^^^^ expected `i64`, found `f64`
+ | ---------- ^^^^^ expected `i64`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:24:16
|
LL | foo::<i64>(x_f32);
- | ^^^^^ expected `i64`, found `f32`
+ | ---------- ^^^^^ expected `i64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:25:16
|
LL | foo::<u32>(x_f64);
- | ^^^^^ expected `u32`, found `f64`
+ | ---------- ^^^^^ expected `u32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:26:16
|
LL | foo::<u32>(x_f32);
- | ^^^^^ expected `u32`, found `f32`
+ | ---------- ^^^^^ expected `u32`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:27:16
|
LL | foo::<i32>(x_f64);
- | ^^^^^ expected `i32`, found `f64`
+ | ---------- ^^^^^ expected `i32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:28:16
|
LL | foo::<i32>(x_f32);
- | ^^^^^ expected `i32`, found `f32`
+ | ---------- ^^^^^ expected `i32`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:29:16
|
LL | foo::<u16>(x_f64);
- | ^^^^^ expected `u16`, found `f64`
+ | ---------- ^^^^^ expected `u16`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:30:16
|
LL | foo::<u16>(x_f32);
- | ^^^^^ expected `u16`, found `f32`
+ | ---------- ^^^^^ expected `u16`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:31:16
|
LL | foo::<i16>(x_f64);
- | ^^^^^ expected `i16`, found `f64`
+ | ---------- ^^^^^ expected `i16`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:32:16
|
LL | foo::<i16>(x_f32);
- | ^^^^^ expected `i16`, found `f32`
+ | ---------- ^^^^^ expected `i16`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:33:15
|
LL | foo::<u8>(x_f64);
- | ^^^^^ expected `u8`, found `f64`
+ | --------- ^^^^^ expected `u8`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:34:15
|
LL | foo::<u8>(x_f32);
- | ^^^^^ expected `u8`, found `f32`
+ | --------- ^^^^^ expected `u8`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:35:15
|
LL | foo::<i8>(x_f64);
- | ^^^^^ expected `i8`, found `f64`
+ | --------- ^^^^^ expected `i8`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:36:15
|
LL | foo::<i8>(x_f32);
- | ^^^^^ expected `i8`, found `f32`
+ | --------- ^^^^^ expected `i8`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error[E0308]: mismatched types
--> $DIR/numeric-cast-without-suggestion.rs:37:16
|
LL | foo::<f32>(x_f64);
- | ^^^^^ expected `f32`, found `f64`
+ | ---------- ^^^^^ expected `f32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast-without-suggestion.rs:1:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
error: aborting due to 21 previous errors
--> $DIR/numeric-cast.rs:23:18
|
LL | foo::<usize>(x_u64);
- | ^^^^^ expected `usize`, found `u64`
+ | ------------ ^^^^^ expected `usize`, found `u64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:25:18
|
LL | foo::<usize>(x_u32);
- | ^^^^^ expected `usize`, found `u32`
+ | ------------ ^^^^^ expected `usize`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:27:18
|
LL | foo::<usize>(x_u16);
- | ^^^^^ expected `usize`, found `u16`
+ | ------------ ^^^^^ expected `usize`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to a `usize`
|
LL | foo::<usize>(x_u16.into());
--> $DIR/numeric-cast.rs:29:18
|
LL | foo::<usize>(x_u8);
- | ^^^^ expected `usize`, found `u8`
+ | ------------ ^^^^ expected `usize`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to a `usize`
|
LL | foo::<usize>(x_u8.into());
--> $DIR/numeric-cast.rs:31:18
|
LL | foo::<usize>(x_isize);
- | ^^^^^^^ expected `usize`, found `isize`
+ | ------------ ^^^^^^^ expected `usize`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:33:18
|
LL | foo::<usize>(x_i64);
- | ^^^^^ expected `usize`, found `i64`
+ | ------------ ^^^^^ expected `usize`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:35:18
|
LL | foo::<usize>(x_i32);
- | ^^^^^ expected `usize`, found `i32`
+ | ------------ ^^^^^ expected `usize`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:37:18
|
LL | foo::<usize>(x_i16);
- | ^^^^^ expected `usize`, found `i16`
+ | ------------ ^^^^^ expected `usize`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:39:18
|
LL | foo::<usize>(x_i8);
- | ^^^^ expected `usize`, found `i8`
+ | ------------ ^^^^ expected `usize`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
|
LL | foo::<usize>(x_i8.try_into().unwrap());
--> $DIR/numeric-cast.rs:44:18
|
LL | foo::<isize>(x_usize);
- | ^^^^^^^ expected `isize`, found `usize`
+ | ------------ ^^^^^^^ expected `isize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:46:18
|
LL | foo::<isize>(x_u64);
- | ^^^^^ expected `isize`, found `u64`
+ | ------------ ^^^^^ expected `isize`, found `u64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:48:18
|
LL | foo::<isize>(x_u32);
- | ^^^^^ expected `isize`, found `u32`
+ | ------------ ^^^^^ expected `isize`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:50:18
|
LL | foo::<isize>(x_u16);
- | ^^^^^ expected `isize`, found `u16`
+ | ------------ ^^^^^ expected `isize`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_u16.try_into().unwrap());
--> $DIR/numeric-cast.rs:52:18
|
LL | foo::<isize>(x_u8);
- | ^^^^ expected `isize`, found `u8`
+ | ------------ ^^^^ expected `isize`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `isize`
|
LL | foo::<isize>(x_u8.into());
--> $DIR/numeric-cast.rs:55:18
|
LL | foo::<isize>(x_i64);
- | ^^^^^ expected `isize`, found `i64`
+ | ------------ ^^^^^ expected `isize`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:57:18
|
LL | foo::<isize>(x_i32);
- | ^^^^^ expected `isize`, found `i32`
+ | ------------ ^^^^^ expected `isize`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
|
LL | foo::<isize>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:59:18
|
LL | foo::<isize>(x_i16);
- | ^^^^^ expected `isize`, found `i16`
+ | ------------ ^^^^^ expected `isize`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `isize`
|
LL | foo::<isize>(x_i16.into());
--> $DIR/numeric-cast.rs:61:18
|
LL | foo::<isize>(x_i8);
- | ^^^^ expected `isize`, found `i8`
+ | ------------ ^^^^ expected `isize`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `isize`
|
LL | foo::<isize>(x_i8.into());
--> $DIR/numeric-cast.rs:66:16
|
LL | foo::<u64>(x_usize);
- | ^^^^^^^ expected `u64`, found `usize`
+ | ---------- ^^^^^^^ expected `u64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:69:16
|
LL | foo::<u64>(x_u32);
- | ^^^^^ expected `u64`, found `u32`
+ | ---------- ^^^^^ expected `u64`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to a `u64`
|
LL | foo::<u64>(x_u32.into());
--> $DIR/numeric-cast.rs:71:16
|
LL | foo::<u64>(x_u16);
- | ^^^^^ expected `u64`, found `u16`
+ | ---------- ^^^^^ expected `u64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to a `u64`
|
LL | foo::<u64>(x_u16.into());
--> $DIR/numeric-cast.rs:73:16
|
LL | foo::<u64>(x_u8);
- | ^^^^ expected `u64`, found `u8`
+ | ---------- ^^^^ expected `u64`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to a `u64`
|
LL | foo::<u64>(x_u8.into());
--> $DIR/numeric-cast.rs:75:16
|
LL | foo::<u64>(x_isize);
- | ^^^^^^^ expected `u64`, found `isize`
+ | ---------- ^^^^^^^ expected `u64`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:77:16
|
LL | foo::<u64>(x_i64);
- | ^^^^^ expected `u64`, found `i64`
+ | ---------- ^^^^^ expected `u64`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:79:16
|
LL | foo::<u64>(x_i32);
- | ^^^^^ expected `u64`, found `i32`
+ | ---------- ^^^^^ expected `u64`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:81:16
|
LL | foo::<u64>(x_i16);
- | ^^^^^ expected `u64`, found `i16`
+ | ---------- ^^^^^ expected `u64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:83:16
|
LL | foo::<u64>(x_i8);
- | ^^^^ expected `u64`, found `i8`
+ | ---------- ^^^^ expected `u64`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
|
LL | foo::<u64>(x_i8.try_into().unwrap());
--> $DIR/numeric-cast.rs:88:16
|
LL | foo::<i64>(x_usize);
- | ^^^^^^^ expected `i64`, found `usize`
+ | ---------- ^^^^^^^ expected `i64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:90:16
|
LL | foo::<i64>(x_u64);
- | ^^^^^ expected `i64`, found `u64`
+ | ---------- ^^^^^ expected `i64`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:92:16
|
LL | foo::<i64>(x_u32);
- | ^^^^^ expected `i64`, found `u32`
+ | ---------- ^^^^^ expected `i64`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `i64`
|
LL | foo::<i64>(x_u32.into());
--> $DIR/numeric-cast.rs:94:16
|
LL | foo::<i64>(x_u16);
- | ^^^^^ expected `i64`, found `u16`
+ | ---------- ^^^^^ expected `i64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `i64`
|
LL | foo::<i64>(x_u16.into());
--> $DIR/numeric-cast.rs:96:16
|
LL | foo::<i64>(x_u8);
- | ^^^^ expected `i64`, found `u8`
+ | ---------- ^^^^ expected `i64`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `i64`
|
LL | foo::<i64>(x_u8.into());
--> $DIR/numeric-cast.rs:98:16
|
LL | foo::<i64>(x_isize);
- | ^^^^^^^ expected `i64`, found `isize`
+ | ---------- ^^^^^^^ expected `i64`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
|
LL | foo::<i64>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:101:16
|
LL | foo::<i64>(x_i32);
- | ^^^^^ expected `i64`, found `i32`
+ | ---------- ^^^^^ expected `i64`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `i64`
|
LL | foo::<i64>(x_i32.into());
--> $DIR/numeric-cast.rs:103:16
|
LL | foo::<i64>(x_i16);
- | ^^^^^ expected `i64`, found `i16`
+ | ---------- ^^^^^ expected `i64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `i64`
|
LL | foo::<i64>(x_i16.into());
--> $DIR/numeric-cast.rs:105:16
|
LL | foo::<i64>(x_i8);
- | ^^^^ expected `i64`, found `i8`
+ | ---------- ^^^^ expected `i64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `i64`
|
LL | foo::<i64>(x_i8.into());
--> $DIR/numeric-cast.rs:110:16
|
LL | foo::<u32>(x_usize);
- | ^^^^^^^ expected `u32`, found `usize`
+ | ---------- ^^^^^^^ expected `u32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:112:16
|
LL | foo::<u32>(x_u64);
- | ^^^^^ expected `u32`, found `u64`
+ | ---------- ^^^^^ expected `u32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:115:16
|
LL | foo::<u32>(x_u16);
- | ^^^^^ expected `u32`, found `u16`
+ | ---------- ^^^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to a `u32`
|
LL | foo::<u32>(x_u16.into());
--> $DIR/numeric-cast.rs:117:16
|
LL | foo::<u32>(x_u8);
- | ^^^^ expected `u32`, found `u8`
+ | ---------- ^^^^ expected `u32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to a `u32`
|
LL | foo::<u32>(x_u8.into());
--> $DIR/numeric-cast.rs:119:16
|
LL | foo::<u32>(x_isize);
- | ^^^^^^^ expected `u32`, found `isize`
+ | ---------- ^^^^^^^ expected `u32`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:121:16
|
LL | foo::<u32>(x_i64);
- | ^^^^^ expected `u32`, found `i64`
+ | ---------- ^^^^^ expected `u32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:123:16
|
LL | foo::<u32>(x_i32);
- | ^^^^^ expected `u32`, found `i32`
+ | ---------- ^^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:125:16
|
LL | foo::<u32>(x_i16);
- | ^^^^^ expected `u32`, found `i16`
+ | ---------- ^^^^^ expected `u32`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:127:16
|
LL | foo::<u32>(x_i8);
- | ^^^^ expected `u32`, found `i8`
+ | ---------- ^^^^ expected `u32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
|
LL | foo::<u32>(x_i8.try_into().unwrap());
--> $DIR/numeric-cast.rs:132:16
|
LL | foo::<i32>(x_usize);
- | ^^^^^^^ expected `i32`, found `usize`
+ | ---------- ^^^^^^^ expected `i32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:134:16
|
LL | foo::<i32>(x_u64);
- | ^^^^^ expected `i32`, found `u64`
+ | ---------- ^^^^^ expected `i32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:136:16
|
LL | foo::<i32>(x_u32);
- | ^^^^^ expected `i32`, found `u32`
+ | ---------- ^^^^^ expected `i32`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:138:16
|
LL | foo::<i32>(x_u16);
- | ^^^^^ expected `i32`, found `u16`
+ | ---------- ^^^^^ expected `i32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `i32`
|
LL | foo::<i32>(x_u16.into());
--> $DIR/numeric-cast.rs:140:16
|
LL | foo::<i32>(x_u8);
- | ^^^^ expected `i32`, found `u8`
+ | ---------- ^^^^ expected `i32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `i32`
|
LL | foo::<i32>(x_u8.into());
--> $DIR/numeric-cast.rs:142:16
|
LL | foo::<i32>(x_isize);
- | ^^^^^^^ expected `i32`, found `isize`
+ | ---------- ^^^^^^^ expected `i32`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:144:16
|
LL | foo::<i32>(x_i64);
- | ^^^^^ expected `i32`, found `i64`
+ | ---------- ^^^^^ expected `i32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
LL | foo::<i32>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:147:16
|
LL | foo::<i32>(x_i16);
- | ^^^^^ expected `i32`, found `i16`
+ | ---------- ^^^^^ expected `i32`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `i32`
|
LL | foo::<i32>(x_i16.into());
--> $DIR/numeric-cast.rs:149:16
|
LL | foo::<i32>(x_i8);
- | ^^^^ expected `i32`, found `i8`
+ | ---------- ^^^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `i32`
|
LL | foo::<i32>(x_i8.into());
--> $DIR/numeric-cast.rs:154:16
|
LL | foo::<u16>(x_usize);
- | ^^^^^^^ expected `u16`, found `usize`
+ | ---------- ^^^^^^^ expected `u16`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:156:16
|
LL | foo::<u16>(x_u64);
- | ^^^^^ expected `u16`, found `u64`
+ | ---------- ^^^^^ expected `u16`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:158:16
|
LL | foo::<u16>(x_u32);
- | ^^^^^ expected `u16`, found `u32`
+ | ---------- ^^^^^ expected `u16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:161:16
|
LL | foo::<u16>(x_u8);
- | ^^^^ expected `u16`, found `u8`
+ | ---------- ^^^^ expected `u16`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to a `u16`
|
LL | foo::<u16>(x_u8.into());
--> $DIR/numeric-cast.rs:163:16
|
LL | foo::<u16>(x_isize);
- | ^^^^^^^ expected `u16`, found `isize`
+ | ---------- ^^^^^^^ expected `u16`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:165:16
|
LL | foo::<u16>(x_i64);
- | ^^^^^ expected `u16`, found `i64`
+ | ---------- ^^^^^ expected `u16`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:167:16
|
LL | foo::<u16>(x_i32);
- | ^^^^^ expected `u16`, found `i32`
+ | ---------- ^^^^^ expected `u16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:169:16
|
LL | foo::<u16>(x_i16);
- | ^^^^^ expected `u16`, found `i16`
+ | ---------- ^^^^^ expected `u16`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:171:16
|
LL | foo::<u16>(x_i8);
- | ^^^^ expected `u16`, found `i8`
+ | ---------- ^^^^ expected `u16`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
|
LL | foo::<u16>(x_i8.try_into().unwrap());
--> $DIR/numeric-cast.rs:176:16
|
LL | foo::<i16>(x_usize);
- | ^^^^^^^ expected `i16`, found `usize`
+ | ---------- ^^^^^^^ expected `i16`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:178:16
|
LL | foo::<i16>(x_u64);
- | ^^^^^ expected `i16`, found `u64`
+ | ---------- ^^^^^ expected `i16`, found `u64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:180:16
|
LL | foo::<i16>(x_u32);
- | ^^^^^ expected `i16`, found `u32`
+ | ---------- ^^^^^ expected `i16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:182:16
|
LL | foo::<i16>(x_u16);
- | ^^^^^ expected `i16`, found `u16`
+ | ---------- ^^^^^ expected `i16`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_u16.try_into().unwrap());
--> $DIR/numeric-cast.rs:184:16
|
LL | foo::<i16>(x_u8);
- | ^^^^ expected `i16`, found `u8`
+ | ---------- ^^^^ expected `i16`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `i16`
|
LL | foo::<i16>(x_u8.into());
--> $DIR/numeric-cast.rs:186:16
|
LL | foo::<i16>(x_isize);
- | ^^^^^^^ expected `i16`, found `isize`
+ | ---------- ^^^^^^^ expected `i16`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:188:16
|
LL | foo::<i16>(x_i64);
- | ^^^^^ expected `i16`, found `i64`
+ | ---------- ^^^^^ expected `i16`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:190:16
|
LL | foo::<i16>(x_i32);
- | ^^^^^ expected `i16`, found `i32`
+ | ---------- ^^^^^ expected `i16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
|
LL | foo::<i16>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:193:16
|
LL | foo::<i16>(x_i8);
- | ^^^^ expected `i16`, found `i8`
+ | ---------- ^^^^ expected `i16`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `i16`
|
LL | foo::<i16>(x_i8.into());
--> $DIR/numeric-cast.rs:198:15
|
LL | foo::<u8>(x_usize);
- | ^^^^^^^ expected `u8`, found `usize`
+ | --------- ^^^^^^^ expected `u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:200:15
|
LL | foo::<u8>(x_u64);
- | ^^^^^ expected `u8`, found `u64`
+ | --------- ^^^^^ expected `u8`, found `u64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:202:15
|
LL | foo::<u8>(x_u32);
- | ^^^^^ expected `u8`, found `u32`
+ | --------- ^^^^^ expected `u8`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:204:15
|
LL | foo::<u8>(x_u16);
- | ^^^^^ expected `u8`, found `u16`
+ | --------- ^^^^^ expected `u8`, found `u16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_u16.try_into().unwrap());
--> $DIR/numeric-cast.rs:207:15
|
LL | foo::<u8>(x_isize);
- | ^^^^^^^ expected `u8`, found `isize`
+ | --------- ^^^^^^^ expected `u8`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:209:15
|
LL | foo::<u8>(x_i64);
- | ^^^^^ expected `u8`, found `i64`
+ | --------- ^^^^^ expected `u8`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:211:15
|
LL | foo::<u8>(x_i32);
- | ^^^^^ expected `u8`, found `i32`
+ | --------- ^^^^^ expected `u8`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:213:15
|
LL | foo::<u8>(x_i16);
- | ^^^^^ expected `u8`, found `i16`
+ | --------- ^^^^^ expected `u8`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:215:15
|
LL | foo::<u8>(x_i8);
- | ^^^^ expected `u8`, found `i8`
+ | --------- ^^^^ expected `u8`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
|
LL | foo::<u8>(x_i8.try_into().unwrap());
--> $DIR/numeric-cast.rs:220:15
|
LL | foo::<i8>(x_usize);
- | ^^^^^^^ expected `i8`, found `usize`
+ | --------- ^^^^^^^ expected `i8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_usize.try_into().unwrap());
--> $DIR/numeric-cast.rs:222:15
|
LL | foo::<i8>(x_u64);
- | ^^^^^ expected `i8`, found `u64`
+ | --------- ^^^^^ expected `i8`, found `u64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u64.try_into().unwrap());
--> $DIR/numeric-cast.rs:224:15
|
LL | foo::<i8>(x_u32);
- | ^^^^^ expected `i8`, found `u32`
+ | --------- ^^^^^ expected `i8`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u32.try_into().unwrap());
--> $DIR/numeric-cast.rs:226:15
|
LL | foo::<i8>(x_u16);
- | ^^^^^ expected `i8`, found `u16`
+ | --------- ^^^^^ expected `i8`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u16.try_into().unwrap());
--> $DIR/numeric-cast.rs:228:15
|
LL | foo::<i8>(x_u8);
- | ^^^^ expected `i8`, found `u8`
+ | --------- ^^^^ expected `i8`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_u8.try_into().unwrap());
--> $DIR/numeric-cast.rs:230:15
|
LL | foo::<i8>(x_isize);
- | ^^^^^^^ expected `i8`, found `isize`
+ | --------- ^^^^^^^ expected `i8`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_isize.try_into().unwrap());
--> $DIR/numeric-cast.rs:232:15
|
LL | foo::<i8>(x_i64);
- | ^^^^^ expected `i8`, found `i64`
+ | --------- ^^^^^ expected `i8`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i64.try_into().unwrap());
--> $DIR/numeric-cast.rs:234:15
|
LL | foo::<i8>(x_i32);
- | ^^^^^ expected `i8`, found `i32`
+ | --------- ^^^^^ expected `i8`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i32.try_into().unwrap());
--> $DIR/numeric-cast.rs:236:15
|
LL | foo::<i8>(x_i16);
- | ^^^^^ expected `i8`, found `i16`
+ | --------- ^^^^^ expected `i8`, found `i16`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
|
LL | foo::<i8>(x_i16.try_into().unwrap());
--> $DIR/numeric-cast.rs:242:16
|
LL | foo::<f64>(x_usize);
- | ^^^^^^^ expected `f64`, found `usize`
+ | ---------- ^^^^^^^ expected `f64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_usize as f64);
--> $DIR/numeric-cast.rs:244:16
|
LL | foo::<f64>(x_u64);
- | ^^^^^ expected `f64`, found `u64`
+ | ---------- ^^^^^ expected `f64`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_u64 as f64);
--> $DIR/numeric-cast.rs:246:16
|
LL | foo::<f64>(x_u32);
- | ^^^^^ expected `f64`, found `u32`
+ | ---------- ^^^^^ expected `f64`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u32.into());
--> $DIR/numeric-cast.rs:248:16
|
LL | foo::<f64>(x_u16);
- | ^^^^^ expected `f64`, found `u16`
+ | ---------- ^^^^^ expected `f64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u16.into());
--> $DIR/numeric-cast.rs:250:16
|
LL | foo::<f64>(x_u8);
- | ^^^^ expected `f64`, found `u8`
+ | ---------- ^^^^ expected `f64`, found `u8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_u8.into());
--> $DIR/numeric-cast.rs:252:16
|
LL | foo::<f64>(x_isize);
- | ^^^^^^^ expected `f64`, found `isize`
+ | ---------- ^^^^^^^ expected `f64`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_isize as f64);
--> $DIR/numeric-cast.rs:254:16
|
LL | foo::<f64>(x_i64);
- | ^^^^^ expected `f64`, found `i64`
+ | ---------- ^^^^^ expected `f64`, found `i64`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f64>(x_i64 as f64);
--> $DIR/numeric-cast.rs:256:16
|
LL | foo::<f64>(x_i32);
- | ^^^^^ expected `f64`, found `i32`
+ | ---------- ^^^^^ expected `f64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i32.into());
--> $DIR/numeric-cast.rs:258:16
|
LL | foo::<f64>(x_i16);
- | ^^^^^ expected `f64`, found `i16`
+ | ---------- ^^^^^ expected `f64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i16.into());
--> $DIR/numeric-cast.rs:260:16
|
LL | foo::<f64>(x_i8);
- | ^^^^ expected `f64`, found `i8`
+ | ---------- ^^^^ expected `f64`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
|
LL | foo::<f64>(x_i8.into());
--> $DIR/numeric-cast.rs:263:16
|
LL | foo::<f64>(x_f32);
- | ^^^^^ expected `f64`, found `f32`
+ | ---------- ^^^^^ expected `f64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `f32` to an `f64`
|
LL | foo::<f64>(x_f32.into());
--> $DIR/numeric-cast.rs:266:16
|
LL | foo::<f32>(x_usize);
- | ^^^^^^^ expected `f32`, found `usize`
+ | ---------- ^^^^^^^ expected `f32`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_usize as f32);
--> $DIR/numeric-cast.rs:268:16
|
LL | foo::<f32>(x_u64);
- | ^^^^^ expected `f32`, found `u64`
+ | ---------- ^^^^^ expected `f32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_u64 as f32);
--> $DIR/numeric-cast.rs:270:16
|
LL | foo::<f32>(x_u32);
- | ^^^^^ expected `f32`, found `u32`
+ | ---------- ^^^^^ expected `f32`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_u32 as f32);
--> $DIR/numeric-cast.rs:272:16
|
LL | foo::<f32>(x_u16);
- | ^^^^^ expected `f32`, found `u16`
+ | ---------- ^^^^^ expected `f32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_u16.into());
--> $DIR/numeric-cast.rs:274:16
|
LL | foo::<f32>(x_u8);
- | ^^^^ expected `f32`, found `u8`
+ | ---------- ^^^^ expected `f32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_u8.into());
--> $DIR/numeric-cast.rs:276:16
|
LL | foo::<f32>(x_isize);
- | ^^^^^^^ expected `f32`, found `isize`
+ | ---------- ^^^^^^^ expected `f32`, found `isize`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_isize as f32);
--> $DIR/numeric-cast.rs:278:16
|
LL | foo::<f32>(x_i64);
- | ^^^^^ expected `f32`, found `i64`
+ | ---------- ^^^^^ expected `f32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_i64 as f32);
--> $DIR/numeric-cast.rs:280:16
|
LL | foo::<f32>(x_i32);
- | ^^^^^ expected `f32`, found `i32`
+ | ---------- ^^^^^ expected `f32`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
|
LL | foo::<f32>(x_i32 as f32);
--> $DIR/numeric-cast.rs:282:16
|
LL | foo::<f32>(x_i16);
- | ^^^^^ expected `f32`, found `i16`
+ | ---------- ^^^^^ expected `f32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_i16.into());
--> $DIR/numeric-cast.rs:284:16
|
LL | foo::<f32>(x_i8);
- | ^^^^ expected `f32`, found `i8`
+ | ---------- ^^^^ expected `f32`, found `i8`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
|
LL | foo::<f32>(x_i8.into());
--> $DIR/numeric-cast.rs:289:16
|
LL | foo::<u32>(x_u8 as u16);
- | ^^^^^^^^^^^ expected `u32`, found `u16`
+ | ---------- ^^^^^^^^^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert a `u16` to a `u32`
|
LL | foo::<u32>((x_u8 as u16).into());
--> $DIR/numeric-cast.rs:291:16
|
LL | foo::<i32>(-x_i8);
- | ^^^^^ expected `i32`, found `i8`
+ | ---------- ^^^^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-cast.rs:6:4
|
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
help: you can convert an `i8` to an `i32`
|
LL | foo::<i32>((-x_i8).into());
+++ /dev/null
-// run-rustfix
-
-fn foo<N>(_x: N) {}
-
-fn main() {
- foo::<usize>(42_usize);
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42_usize);
- //~^ ERROR mismatched types
- foo::<usize>(42usize);
- //~^ ERROR mismatched types
- foo::<usize>(42usize);
- //~^ ERROR mismatched types
-
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- //~^ ERROR mismatched types
- foo::<isize>(42isize);
- //~^ ERROR mismatched types
- foo::<isize>(42isize);
- //~^ ERROR mismatched types
-
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- //~^ ERROR mismatched types
- foo::<u64>(42u64);
- //~^ ERROR mismatched types
- foo::<u64>(42u64);
- //~^ ERROR mismatched types
-
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- //~^ ERROR mismatched types
- foo::<i64>(42i64);
- //~^ ERROR mismatched types
- foo::<i64>(42i64);
- //~^ ERROR mismatched types
-
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- //~^ ERROR mismatched types
- foo::<u32>(42u32);
- //~^ ERROR mismatched types
- foo::<u32>(42u32);
- //~^ ERROR mismatched types
-
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- //~^ ERROR mismatched types
- foo::<i32>(42i32);
- //~^ ERROR mismatched types
- foo::<i32>(42i32);
- //~^ ERROR mismatched types
-
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- //~^ ERROR mismatched types
- foo::<u16>(42u16);
- //~^ ERROR mismatched types
- foo::<u16>(42u16);
- //~^ ERROR mismatched types
-
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- foo::<i16>(42_i16);
- //~^ ERROR mismatched types
- foo::<i16>(42i16);
- //~^ ERROR mismatched types
- foo::<i16>(42i16);
- //~^ ERROR mismatched types
-
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- //~^ ERROR mismatched types
- foo::<u8>(42u8);
- //~^ ERROR mismatched types
- foo::<u8>(42u8);
- //~^ ERROR mismatched types
-
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- foo::<i8>(42i8);
- //~^ ERROR mismatched types
- foo::<i8>(42i8);
- //~^ ERROR mismatched types
-
- foo::<f64>(42_f64);
- //~^ ERROR mismatched types
- foo::<f64>(42_f64);
- //~^ ERROR mismatched types
- foo::<f64>(42_u32.into());
- //~^ ERROR mismatched types
- foo::<f64>(42_u16.into());
- //~^ ERROR mismatched types
- foo::<f64>(42_u8.into());
- //~^ ERROR mismatched types
- foo::<f64>(42_f64);
- //~^ ERROR mismatched types
- foo::<f64>(42_f64);
- //~^ ERROR mismatched types
- foo::<f64>(42_i32.into());
- //~^ ERROR mismatched types
- foo::<f64>(42_i16.into());
- //~^ ERROR mismatched types
- foo::<f64>(42_i8.into());
- //~^ ERROR mismatched types
- foo::<f64>(42.0_f64);
- foo::<f64>(42.0_f64);
- //~^ ERROR mismatched types
-
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_u16.into());
- //~^ ERROR mismatched types
- foo::<f32>(42_u8.into());
- //~^ ERROR mismatched types
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42_i16.into());
- //~^ ERROR mismatched types
- foo::<f32>(42_i8.into());
- //~^ ERROR mismatched types
- foo::<f32>(42.0_f32);
- //~^ ERROR mismatched types
- foo::<f32>(42.0_f32);
-
- foo::<u32>((42_u8 as u16).into());
- //~^ ERROR mismatched types
- foo::<i32>((-42_i8).into());
- //~^ ERROR mismatched types
-}
+++ /dev/null
-// run-rustfix
-
-fn foo<N>(_x: N) {}
-
-fn main() {
- foo::<usize>(42_usize);
- foo::<usize>(42_u64);
- //~^ ERROR mismatched types
- foo::<usize>(42_u32);
- //~^ ERROR mismatched types
- foo::<usize>(42_u16);
- //~^ ERROR mismatched types
- foo::<usize>(42_u8);
- //~^ ERROR mismatched types
- foo::<usize>(42_isize);
- //~^ ERROR mismatched types
- foo::<usize>(42_i64);
- //~^ ERROR mismatched types
- foo::<usize>(42_i32);
- //~^ ERROR mismatched types
- foo::<usize>(42_i16);
- //~^ ERROR mismatched types
- foo::<usize>(42_i8);
- //~^ ERROR mismatched types
- foo::<usize>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<usize>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<isize>(42_usize);
- //~^ ERROR mismatched types
- foo::<isize>(42_u64);
- //~^ ERROR mismatched types
- foo::<isize>(42_u32);
- //~^ ERROR mismatched types
- foo::<isize>(42_u16);
- //~^ ERROR mismatched types
- foo::<isize>(42_u8);
- //~^ ERROR mismatched types
- foo::<isize>(42_isize);
- foo::<isize>(42_i64);
- //~^ ERROR mismatched types
- foo::<isize>(42_i32);
- //~^ ERROR mismatched types
- foo::<isize>(42_i16);
- //~^ ERROR mismatched types
- foo::<isize>(42_i8);
- //~^ ERROR mismatched types
- foo::<isize>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<isize>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<u64>(42_usize);
- //~^ ERROR mismatched types
- foo::<u64>(42_u64);
- foo::<u64>(42_u32);
- //~^ ERROR mismatched types
- foo::<u64>(42_u16);
- //~^ ERROR mismatched types
- foo::<u64>(42_u8);
- //~^ ERROR mismatched types
- foo::<u64>(42_isize);
- //~^ ERROR mismatched types
- foo::<u64>(42_i64);
- //~^ ERROR mismatched types
- foo::<u64>(42_i32);
- //~^ ERROR mismatched types
- foo::<u64>(42_i16);
- //~^ ERROR mismatched types
- foo::<u64>(42_i8);
- //~^ ERROR mismatched types
- foo::<u64>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<u64>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<i64>(42_usize);
- //~^ ERROR mismatched types
- foo::<i64>(42_u64);
- //~^ ERROR mismatched types
- foo::<i64>(42_u32);
- //~^ ERROR mismatched types
- foo::<i64>(42_u16);
- //~^ ERROR mismatched types
- foo::<i64>(42_u8);
- //~^ ERROR mismatched types
- foo::<i64>(42_isize);
- //~^ ERROR mismatched types
- foo::<i64>(42_i64);
- foo::<i64>(42_i32);
- //~^ ERROR mismatched types
- foo::<i64>(42_i16);
- //~^ ERROR mismatched types
- foo::<i64>(42_i8);
- //~^ ERROR mismatched types
- foo::<i64>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<i64>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<u32>(42_usize);
- //~^ ERROR mismatched types
- foo::<u32>(42_u64);
- //~^ ERROR mismatched types
- foo::<u32>(42_u32);
- foo::<u32>(42_u16);
- //~^ ERROR mismatched types
- foo::<u32>(42_u8);
- //~^ ERROR mismatched types
- foo::<u32>(42_isize);
- //~^ ERROR mismatched types
- foo::<u32>(42_i64);
- //~^ ERROR mismatched types
- foo::<u32>(42_i32);
- //~^ ERROR mismatched types
- foo::<u32>(42_i16);
- //~^ ERROR mismatched types
- foo::<u32>(42_i8);
- //~^ ERROR mismatched types
- foo::<u32>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<u32>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<i32>(42_usize);
- //~^ ERROR mismatched types
- foo::<i32>(42_u64);
- //~^ ERROR mismatched types
- foo::<i32>(42_u32);
- //~^ ERROR mismatched types
- foo::<i32>(42_u16);
- //~^ ERROR mismatched types
- foo::<i32>(42_u8);
- //~^ ERROR mismatched types
- foo::<i32>(42_isize);
- //~^ ERROR mismatched types
- foo::<i32>(42_i64);
- //~^ ERROR mismatched types
- foo::<i32>(42_i32);
- foo::<i32>(42_i16);
- //~^ ERROR mismatched types
- foo::<i32>(42_i8);
- //~^ ERROR mismatched types
- foo::<i32>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<i32>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<u16>(42_usize);
- //~^ ERROR mismatched types
- foo::<u16>(42_u64);
- //~^ ERROR mismatched types
- foo::<u16>(42_u32);
- //~^ ERROR mismatched types
- foo::<u16>(42_u16);
- foo::<u16>(42_u8);
- //~^ ERROR mismatched types
- foo::<u16>(42_isize);
- //~^ ERROR mismatched types
- foo::<u16>(42_i64);
- //~^ ERROR mismatched types
- foo::<u16>(42_i32);
- //~^ ERROR mismatched types
- foo::<u16>(42_i16);
- //~^ ERROR mismatched types
- foo::<u16>(42_i8);
- //~^ ERROR mismatched types
- foo::<u16>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<u16>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<i16>(42_usize);
- //~^ ERROR mismatched types
- foo::<i16>(42_u64);
- //~^ ERROR mismatched types
- foo::<i16>(42_u32);
- //~^ ERROR mismatched types
- foo::<i16>(42_u16);
- //~^ ERROR mismatched types
- foo::<i16>(42_u8);
- //~^ ERROR mismatched types
- foo::<i16>(42_isize);
- //~^ ERROR mismatched types
- foo::<i16>(42_i64);
- //~^ ERROR mismatched types
- foo::<i16>(42_i32);
- //~^ ERROR mismatched types
- foo::<i16>(42_i16);
- foo::<i16>(42_i8);
- //~^ ERROR mismatched types
- foo::<i16>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<i16>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<u8>(42_usize);
- //~^ ERROR mismatched types
- foo::<u8>(42_u64);
- //~^ ERROR mismatched types
- foo::<u8>(42_u32);
- //~^ ERROR mismatched types
- foo::<u8>(42_u16);
- //~^ ERROR mismatched types
- foo::<u8>(42_u8);
- foo::<u8>(42_isize);
- //~^ ERROR mismatched types
- foo::<u8>(42_i64);
- //~^ ERROR mismatched types
- foo::<u8>(42_i32);
- //~^ ERROR mismatched types
- foo::<u8>(42_i16);
- //~^ ERROR mismatched types
- foo::<u8>(42_i8);
- //~^ ERROR mismatched types
- foo::<u8>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<u8>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<i8>(42_usize);
- //~^ ERROR mismatched types
- foo::<i8>(42_u64);
- //~^ ERROR mismatched types
- foo::<i8>(42_u32);
- //~^ ERROR mismatched types
- foo::<i8>(42_u16);
- //~^ ERROR mismatched types
- foo::<i8>(42_u8);
- //~^ ERROR mismatched types
- foo::<i8>(42_isize);
- //~^ ERROR mismatched types
- foo::<i8>(42_i64);
- //~^ ERROR mismatched types
- foo::<i8>(42_i32);
- //~^ ERROR mismatched types
- foo::<i8>(42_i16);
- //~^ ERROR mismatched types
- foo::<i8>(42_i8);
- foo::<i8>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<i8>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<f64>(42_usize);
- //~^ ERROR mismatched types
- foo::<f64>(42_u64);
- //~^ ERROR mismatched types
- foo::<f64>(42_u32);
- //~^ ERROR mismatched types
- foo::<f64>(42_u16);
- //~^ ERROR mismatched types
- foo::<f64>(42_u8);
- //~^ ERROR mismatched types
- foo::<f64>(42_isize);
- //~^ ERROR mismatched types
- foo::<f64>(42_i64);
- //~^ ERROR mismatched types
- foo::<f64>(42_i32);
- //~^ ERROR mismatched types
- foo::<f64>(42_i16);
- //~^ ERROR mismatched types
- foo::<f64>(42_i8);
- //~^ ERROR mismatched types
- foo::<f64>(42.0_f64);
- foo::<f64>(42.0_f32);
- //~^ ERROR mismatched types
-
- foo::<f32>(42_usize);
- //~^ ERROR mismatched types
- foo::<f32>(42_u64);
- //~^ ERROR mismatched types
- foo::<f32>(42_u32);
- //~^ ERROR mismatched types
- foo::<f32>(42_u16);
- //~^ ERROR mismatched types
- foo::<f32>(42_u8);
- //~^ ERROR mismatched types
- foo::<f32>(42_isize);
- //~^ ERROR mismatched types
- foo::<f32>(42_i64);
- //~^ ERROR mismatched types
- foo::<f32>(42_i32);
- //~^ ERROR mismatched types
- foo::<f32>(42_i16);
- //~^ ERROR mismatched types
- foo::<f32>(42_i8);
- //~^ ERROR mismatched types
- foo::<f32>(42.0_f64);
- //~^ ERROR mismatched types
- foo::<f32>(42.0_f32);
-
- foo::<u32>(42_u8 as u16);
- //~^ ERROR mismatched types
- foo::<i32>(-42_i8);
- //~^ ERROR mismatched types
-}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:7:18
- |
-LL | foo::<usize>(42_u64);
- | ^^^^^^ expected `usize`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:9:18
- |
-LL | foo::<usize>(42_u32);
- | ^^^^^^ expected `usize`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:11:18
- |
-LL | foo::<usize>(42_u16);
- | ^^^^^^ expected `usize`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:13:18
- |
-LL | foo::<usize>(42_u8);
- | ^^^^^ expected `usize`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:15:18
- |
-LL | foo::<usize>(42_isize);
- | ^^^^^^^^ expected `usize`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:17:18
- |
-LL | foo::<usize>(42_i64);
- | ^^^^^^ expected `usize`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:19:18
- |
-LL | foo::<usize>(42_i32);
- | ^^^^^^ expected `usize`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:21:18
- |
-LL | foo::<usize>(42_i16);
- | ^^^^^^ expected `usize`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:23:18
- |
-LL | foo::<usize>(42_i8);
- | ^^^^^ expected `usize`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `usize`
- |
-LL | foo::<usize>(42_usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:25:18
- |
-LL | foo::<usize>(42.0_f64);
- | ^^^^^^^^ expected `usize`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `usize`
- |
-LL | foo::<usize>(42usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:27:18
- |
-LL | foo::<usize>(42.0_f32);
- | ^^^^^^^^ expected `usize`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `usize`
- |
-LL | foo::<usize>(42usize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:30:18
- |
-LL | foo::<isize>(42_usize);
- | ^^^^^^^^ expected `isize`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:32:18
- |
-LL | foo::<isize>(42_u64);
- | ^^^^^^ expected `isize`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:34:18
- |
-LL | foo::<isize>(42_u32);
- | ^^^^^^ expected `isize`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:36:18
- |
-LL | foo::<isize>(42_u16);
- | ^^^^^^ expected `isize`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:38:18
- |
-LL | foo::<isize>(42_u8);
- | ^^^^^ expected `isize`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:41:18
- |
-LL | foo::<isize>(42_i64);
- | ^^^^^^ expected `isize`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:43:18
- |
-LL | foo::<isize>(42_i32);
- | ^^^^^^ expected `isize`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:45:18
- |
-LL | foo::<isize>(42_i16);
- | ^^^^^^ expected `isize`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:47:18
- |
-LL | foo::<isize>(42_i8);
- | ^^^^^ expected `isize`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `isize`
- |
-LL | foo::<isize>(42_isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:49:18
- |
-LL | foo::<isize>(42.0_f64);
- | ^^^^^^^^ expected `isize`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `isize`
- |
-LL | foo::<isize>(42isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:51:18
- |
-LL | foo::<isize>(42.0_f32);
- | ^^^^^^^^ expected `isize`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `isize`
- |
-LL | foo::<isize>(42isize);
- | ~~~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:54:16
- |
-LL | foo::<u64>(42_usize);
- | ^^^^^^^^ expected `u64`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:57:16
- |
-LL | foo::<u64>(42_u32);
- | ^^^^^^ expected `u64`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:59:16
- |
-LL | foo::<u64>(42_u16);
- | ^^^^^^ expected `u64`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:61:16
- |
-LL | foo::<u64>(42_u8);
- | ^^^^^ expected `u64`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:63:16
- |
-LL | foo::<u64>(42_isize);
- | ^^^^^^^^ expected `u64`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:65:16
- |
-LL | foo::<u64>(42_i64);
- | ^^^^^^ expected `u64`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:67:16
- |
-LL | foo::<u64>(42_i32);
- | ^^^^^^ expected `u64`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:69:16
- |
-LL | foo::<u64>(42_i16);
- | ^^^^^^ expected `u64`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:71:16
- |
-LL | foo::<u64>(42_i8);
- | ^^^^^ expected `u64`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `u64`
- |
-LL | foo::<u64>(42_u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:73:16
- |
-LL | foo::<u64>(42.0_f64);
- | ^^^^^^^^ expected `u64`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `u64`
- |
-LL | foo::<u64>(42u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:75:16
- |
-LL | foo::<u64>(42.0_f32);
- | ^^^^^^^^ expected `u64`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `u64`
- |
-LL | foo::<u64>(42u64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:78:16
- |
-LL | foo::<i64>(42_usize);
- | ^^^^^^^^ expected `i64`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:80:16
- |
-LL | foo::<i64>(42_u64);
- | ^^^^^^ expected `i64`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:82:16
- |
-LL | foo::<i64>(42_u32);
- | ^^^^^^ expected `i64`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:84:16
- |
-LL | foo::<i64>(42_u16);
- | ^^^^^^ expected `i64`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:86:16
- |
-LL | foo::<i64>(42_u8);
- | ^^^^^ expected `i64`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:88:16
- |
-LL | foo::<i64>(42_isize);
- | ^^^^^^^^ expected `i64`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:91:16
- |
-LL | foo::<i64>(42_i32);
- | ^^^^^^ expected `i64`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:93:16
- |
-LL | foo::<i64>(42_i16);
- | ^^^^^^ expected `i64`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:95:16
- |
-LL | foo::<i64>(42_i8);
- | ^^^^^ expected `i64`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `i64`
- |
-LL | foo::<i64>(42_i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:97:16
- |
-LL | foo::<i64>(42.0_f64);
- | ^^^^^^^^ expected `i64`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `i64`
- |
-LL | foo::<i64>(42i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:99:16
- |
-LL | foo::<i64>(42.0_f32);
- | ^^^^^^^^ expected `i64`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `i64`
- |
-LL | foo::<i64>(42i64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:102:16
- |
-LL | foo::<u32>(42_usize);
- | ^^^^^^^^ expected `u32`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:104:16
- |
-LL | foo::<u32>(42_u64);
- | ^^^^^^ expected `u32`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:107:16
- |
-LL | foo::<u32>(42_u16);
- | ^^^^^^ expected `u32`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:109:16
- |
-LL | foo::<u32>(42_u8);
- | ^^^^^ expected `u32`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:111:16
- |
-LL | foo::<u32>(42_isize);
- | ^^^^^^^^ expected `u32`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:113:16
- |
-LL | foo::<u32>(42_i64);
- | ^^^^^^ expected `u32`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:115:16
- |
-LL | foo::<u32>(42_i32);
- | ^^^^^^ expected `u32`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:117:16
- |
-LL | foo::<u32>(42_i16);
- | ^^^^^^ expected `u32`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:119:16
- |
-LL | foo::<u32>(42_i8);
- | ^^^^^ expected `u32`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `u32`
- |
-LL | foo::<u32>(42_u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:121:16
- |
-LL | foo::<u32>(42.0_f64);
- | ^^^^^^^^ expected `u32`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `u32`
- |
-LL | foo::<u32>(42u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:123:16
- |
-LL | foo::<u32>(42.0_f32);
- | ^^^^^^^^ expected `u32`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `u32`
- |
-LL | foo::<u32>(42u32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:126:16
- |
-LL | foo::<i32>(42_usize);
- | ^^^^^^^^ expected `i32`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:128:16
- |
-LL | foo::<i32>(42_u64);
- | ^^^^^^ expected `i32`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:130:16
- |
-LL | foo::<i32>(42_u32);
- | ^^^^^^ expected `i32`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:132:16
- |
-LL | foo::<i32>(42_u16);
- | ^^^^^^ expected `i32`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:134:16
- |
-LL | foo::<i32>(42_u8);
- | ^^^^^ expected `i32`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:136:16
- |
-LL | foo::<i32>(42_isize);
- | ^^^^^^^^ expected `i32`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:138:16
- |
-LL | foo::<i32>(42_i64);
- | ^^^^^^ expected `i32`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:141:16
- |
-LL | foo::<i32>(42_i16);
- | ^^^^^^ expected `i32`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:143:16
- |
-LL | foo::<i32>(42_i8);
- | ^^^^^ expected `i32`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `i32`
- |
-LL | foo::<i32>(42_i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:145:16
- |
-LL | foo::<i32>(42.0_f64);
- | ^^^^^^^^ expected `i32`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `i32`
- |
-LL | foo::<i32>(42i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:147:16
- |
-LL | foo::<i32>(42.0_f32);
- | ^^^^^^^^ expected `i32`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `i32`
- |
-LL | foo::<i32>(42i32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:150:16
- |
-LL | foo::<u16>(42_usize);
- | ^^^^^^^^ expected `u16`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:152:16
- |
-LL | foo::<u16>(42_u64);
- | ^^^^^^ expected `u16`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:154:16
- |
-LL | foo::<u16>(42_u32);
- | ^^^^^^ expected `u16`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:157:16
- |
-LL | foo::<u16>(42_u8);
- | ^^^^^ expected `u16`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:159:16
- |
-LL | foo::<u16>(42_isize);
- | ^^^^^^^^ expected `u16`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:161:16
- |
-LL | foo::<u16>(42_i64);
- | ^^^^^^ expected `u16`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:163:16
- |
-LL | foo::<u16>(42_i32);
- | ^^^^^^ expected `u16`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:165:16
- |
-LL | foo::<u16>(42_i16);
- | ^^^^^^ expected `u16`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:167:16
- |
-LL | foo::<u16>(42_i8);
- | ^^^^^ expected `u16`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `u16`
- |
-LL | foo::<u16>(42_u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:169:16
- |
-LL | foo::<u16>(42.0_f64);
- | ^^^^^^^^ expected `u16`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `u16`
- |
-LL | foo::<u16>(42u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:171:16
- |
-LL | foo::<u16>(42.0_f32);
- | ^^^^^^^^ expected `u16`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `u16`
- |
-LL | foo::<u16>(42u16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:174:16
- |
-LL | foo::<i16>(42_usize);
- | ^^^^^^^^ expected `i16`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:176:16
- |
-LL | foo::<i16>(42_u64);
- | ^^^^^^ expected `i16`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:178:16
- |
-LL | foo::<i16>(42_u32);
- | ^^^^^^ expected `i16`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:180:16
- |
-LL | foo::<i16>(42_u16);
- | ^^^^^^ expected `i16`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:182:16
- |
-LL | foo::<i16>(42_u8);
- | ^^^^^ expected `i16`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:184:16
- |
-LL | foo::<i16>(42_isize);
- | ^^^^^^^^ expected `i16`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:186:16
- |
-LL | foo::<i16>(42_i64);
- | ^^^^^^ expected `i16`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:188:16
- |
-LL | foo::<i16>(42_i32);
- | ^^^^^^ expected `i16`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:191:16
- |
-LL | foo::<i16>(42_i8);
- | ^^^^^ expected `i16`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `i16`
- |
-LL | foo::<i16>(42_i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:193:16
- |
-LL | foo::<i16>(42.0_f64);
- | ^^^^^^^^ expected `i16`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `i16`
- |
-LL | foo::<i16>(42i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:195:16
- |
-LL | foo::<i16>(42.0_f32);
- | ^^^^^^^^ expected `i16`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `i16`
- |
-LL | foo::<i16>(42i16);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:198:15
- |
-LL | foo::<u8>(42_usize);
- | ^^^^^^^^ expected `u8`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:200:15
- |
-LL | foo::<u8>(42_u64);
- | ^^^^^^ expected `u8`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:202:15
- |
-LL | foo::<u8>(42_u32);
- | ^^^^^^ expected `u8`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:204:15
- |
-LL | foo::<u8>(42_u16);
- | ^^^^^^ expected `u8`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:207:15
- |
-LL | foo::<u8>(42_isize);
- | ^^^^^^^^ expected `u8`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:209:15
- |
-LL | foo::<u8>(42_i64);
- | ^^^^^^ expected `u8`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:211:15
- |
-LL | foo::<u8>(42_i32);
- | ^^^^^^ expected `u8`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:213:15
- |
-LL | foo::<u8>(42_i16);
- | ^^^^^^ expected `u8`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:215:15
- |
-LL | foo::<u8>(42_i8);
- | ^^^^^ expected `u8`, found `i8`
- |
-help: change the type of the numeric literal from `i8` to `u8`
- |
-LL | foo::<u8>(42_u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:217:15
- |
-LL | foo::<u8>(42.0_f64);
- | ^^^^^^^^ expected `u8`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `u8`
- |
-LL | foo::<u8>(42u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:219:15
- |
-LL | foo::<u8>(42.0_f32);
- | ^^^^^^^^ expected `u8`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `u8`
- |
-LL | foo::<u8>(42u8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:222:15
- |
-LL | foo::<i8>(42_usize);
- | ^^^^^^^^ expected `i8`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:224:15
- |
-LL | foo::<i8>(42_u64);
- | ^^^^^^ expected `i8`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:226:15
- |
-LL | foo::<i8>(42_u32);
- | ^^^^^^ expected `i8`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:228:15
- |
-LL | foo::<i8>(42_u16);
- | ^^^^^^ expected `i8`, found `u16`
- |
-help: change the type of the numeric literal from `u16` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:230:15
- |
-LL | foo::<i8>(42_u8);
- | ^^^^^ expected `i8`, found `u8`
- |
-help: change the type of the numeric literal from `u8` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:232:15
- |
-LL | foo::<i8>(42_isize);
- | ^^^^^^^^ expected `i8`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:234:15
- |
-LL | foo::<i8>(42_i64);
- | ^^^^^^ expected `i8`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:236:15
- |
-LL | foo::<i8>(42_i32);
- | ^^^^^^ expected `i8`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:238:15
- |
-LL | foo::<i8>(42_i16);
- | ^^^^^^ expected `i8`, found `i16`
- |
-help: change the type of the numeric literal from `i16` to `i8`
- |
-LL | foo::<i8>(42_i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:241:15
- |
-LL | foo::<i8>(42.0_f64);
- | ^^^^^^^^ expected `i8`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `i8`
- |
-LL | foo::<i8>(42i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:243:15
- |
-LL | foo::<i8>(42.0_f32);
- | ^^^^^^^^ expected `i8`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `i8`
- |
-LL | foo::<i8>(42i8);
- | ~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:246:16
- |
-LL | foo::<f64>(42_usize);
- | ^^^^^^^^ expected `f64`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `f64`
- |
-LL | foo::<f64>(42_f64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:248:16
- |
-LL | foo::<f64>(42_u64);
- | ^^^^^^ expected `f64`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `f64`
- |
-LL | foo::<f64>(42_f64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:250:16
- |
-LL | foo::<f64>(42_u32);
- | ^^^^^^ expected `f64`, found `u32`
- |
-help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_u32.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:252:16
- |
-LL | foo::<f64>(42_u16);
- | ^^^^^^ expected `f64`, found `u16`
- |
-help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_u16.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:254:16
- |
-LL | foo::<f64>(42_u8);
- | ^^^^^ expected `f64`, found `u8`
- |
-help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_u8.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:256:16
- |
-LL | foo::<f64>(42_isize);
- | ^^^^^^^^ expected `f64`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `f64`
- |
-LL | foo::<f64>(42_f64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:258:16
- |
-LL | foo::<f64>(42_i64);
- | ^^^^^^ expected `f64`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `f64`
- |
-LL | foo::<f64>(42_f64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:260:16
- |
-LL | foo::<f64>(42_i32);
- | ^^^^^^ expected `f64`, found `i32`
- |
-help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_i32.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:262:16
- |
-LL | foo::<f64>(42_i16);
- | ^^^^^^ expected `f64`, found `i16`
- |
-help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_i16.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:264:16
- |
-LL | foo::<f64>(42_i8);
- | ^^^^^ expected `f64`, found `i8`
- |
-help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
- |
-LL | foo::<f64>(42_i8.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:267:16
- |
-LL | foo::<f64>(42.0_f32);
- | ^^^^^^^^ expected `f64`, found `f32`
- |
-help: change the type of the numeric literal from `f32` to `f64`
- |
-LL | foo::<f64>(42.0_f64);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:270:16
- |
-LL | foo::<f32>(42_usize);
- | ^^^^^^^^ expected `f32`, found `usize`
- |
-help: change the type of the numeric literal from `usize` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:272:16
- |
-LL | foo::<f32>(42_u64);
- | ^^^^^^ expected `f32`, found `u64`
- |
-help: change the type of the numeric literal from `u64` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:274:16
- |
-LL | foo::<f32>(42_u32);
- | ^^^^^^ expected `f32`, found `u32`
- |
-help: change the type of the numeric literal from `u32` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:276:16
- |
-LL | foo::<f32>(42_u16);
- | ^^^^^^ expected `f32`, found `u16`
- |
-help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
- |
-LL | foo::<f32>(42_u16.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:278:16
- |
-LL | foo::<f32>(42_u8);
- | ^^^^^ expected `f32`, found `u8`
- |
-help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
- |
-LL | foo::<f32>(42_u8.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:280:16
- |
-LL | foo::<f32>(42_isize);
- | ^^^^^^^^ expected `f32`, found `isize`
- |
-help: change the type of the numeric literal from `isize` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:282:16
- |
-LL | foo::<f32>(42_i64);
- | ^^^^^^ expected `f32`, found `i64`
- |
-help: change the type of the numeric literal from `i64` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:284:16
- |
-LL | foo::<f32>(42_i32);
- | ^^^^^^ expected `f32`, found `i32`
- |
-help: change the type of the numeric literal from `i32` to `f32`
- |
-LL | foo::<f32>(42_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:286:16
- |
-LL | foo::<f32>(42_i16);
- | ^^^^^^ expected `f32`, found `i16`
- |
-help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
- |
-LL | foo::<f32>(42_i16.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:288:16
- |
-LL | foo::<f32>(42_i8);
- | ^^^^^ expected `f32`, found `i8`
- |
-help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
- |
-LL | foo::<f32>(42_i8.into());
- | +++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:290:16
- |
-LL | foo::<f32>(42.0_f64);
- | ^^^^^^^^ expected `f32`, found `f64`
- |
-help: change the type of the numeric literal from `f64` to `f32`
- |
-LL | foo::<f32>(42.0_f32);
- | ~~~
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:294:16
- |
-LL | foo::<u32>(42_u8 as u16);
- | ^^^^^^^^^^^^ expected `u32`, found `u16`
- |
-help: you can convert a `u16` to a `u32`
- |
-LL | foo::<u32>((42_u8 as u16).into());
- | + ++++++++
-
-error[E0308]: mismatched types
- --> $DIR/numeric-suffix.rs:296:16
- |
-LL | foo::<i32>(-42_i8);
- | ^^^^^^ expected `i32`, found `i8`
- |
-help: you can convert an `i8` to an `i32`
- |
-LL | foo::<i32>((-42_i8).into());
- | + ++++++++
-
-error: aborting due to 134 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<i32>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i32);
+ foo::<i32>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:28:16
+ |
+LL | foo::<i32>(42_usize);
+ | ---------- ^^^^^^^^ expected `i32`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:32:16
+ |
+LL | foo::<i32>(42_u64);
+ | ---------- ^^^^^^ expected `i32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:36:16
+ |
+LL | foo::<i32>(42_u32);
+ | ---------- ^^^^^^ expected `i32`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:40:16
+ |
+LL | foo::<i32>(42_u16);
+ | ---------- ^^^^^^ expected `i32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:44:16
+ |
+LL | foo::<i32>(42_u8);
+ | ---------- ^^^^^ expected `i32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:48:16
+ |
+LL | foo::<i32>(42_isize);
+ | ---------- ^^^^^^^^ expected `i32`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:52:16
+ |
+LL | foo::<i32>(42_i64);
+ | ---------- ^^^^^^ expected `i32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:57:16
+ |
+LL | foo::<i32>(42_i16);
+ | ---------- ^^^^^^ expected `i32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:61:16
+ |
+LL | foo::<i32>(42_i8);
+ | ---------- ^^^^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `i32`
+ |
+LL | foo::<i32>(42_i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:65:16
+ |
+LL | foo::<i32>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `i32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `i32`
+ |
+LL | foo::<i32>(42i32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i32.rs:69:16
+ |
+LL | foo::<i32>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `i32`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `i32`
+ |
+LL | foo::<i32>(42i32);
+ | ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<i64>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i64);
+ foo::<i64>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i64>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:28:16
+ |
+LL | foo::<i64>(42_usize);
+ | ---------- ^^^^^^^^ expected `i64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:32:16
+ |
+LL | foo::<i64>(42_u64);
+ | ---------- ^^^^^^ expected `i64`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:36:16
+ |
+LL | foo::<i64>(42_u32);
+ | ---------- ^^^^^^ expected `i64`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:40:16
+ |
+LL | foo::<i64>(42_u16);
+ | ---------- ^^^^^^ expected `i64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:44:16
+ |
+LL | foo::<i64>(42_u8);
+ | ---------- ^^^^^ expected `i64`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:48:16
+ |
+LL | foo::<i64>(42_isize);
+ | ---------- ^^^^^^^^ expected `i64`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:53:16
+ |
+LL | foo::<i64>(42_i32);
+ | ---------- ^^^^^^ expected `i64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:57:16
+ |
+LL | foo::<i64>(42_i16);
+ | ---------- ^^^^^^ expected `i64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:61:16
+ |
+LL | foo::<i64>(42_i8);
+ | ---------- ^^^^^ expected `i64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `i64`
+ |
+LL | foo::<i64>(42_i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:65:16
+ |
+LL | foo::<i64>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `i64`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `i64`
+ |
+LL | foo::<i64>(42i64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-i64.rs:69:16
+ |
+LL | foo::<i64>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `i64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-i64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `i64`
+ |
+LL | foo::<i64>(42i64);
+ | ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<isize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_isize);
+ foo::<isize>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<isize>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:28:18
+ |
+LL | foo::<isize>(42_usize);
+ | ------------ ^^^^^^^^ expected `isize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:32:18
+ |
+LL | foo::<isize>(42_u64);
+ | ------------ ^^^^^^ expected `isize`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:36:18
+ |
+LL | foo::<isize>(42_u32);
+ | ------------ ^^^^^^ expected `isize`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:40:18
+ |
+LL | foo::<isize>(42_u16);
+ | ------------ ^^^^^^ expected `isize`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:44:18
+ |
+LL | foo::<isize>(42_u8);
+ | ------------ ^^^^^ expected `isize`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:49:18
+ |
+LL | foo::<isize>(42_i64);
+ | ------------ ^^^^^^ expected `isize`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:53:18
+ |
+LL | foo::<isize>(42_i32);
+ | ------------ ^^^^^^ expected `isize`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:57:18
+ |
+LL | foo::<isize>(42_i16);
+ | ------------ ^^^^^^ expected `isize`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:61:18
+ |
+LL | foo::<isize>(42_i8);
+ | ------------ ^^^^^ expected `isize`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `isize`
+ |
+LL | foo::<isize>(42_isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:65:18
+ |
+LL | foo::<isize>(42.0_f64);
+ | ------------ ^^^^^^^^ expected `isize`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `isize`
+ |
+LL | foo::<isize>(42isize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-isize.rs:69:18
+ |
+LL | foo::<isize>(42.0_f32);
+ | ------------ ^^^^^^^^ expected `isize`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-isize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `isize`
+ |
+LL | foo::<isize>(42isize);
+ | ~~~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<u32>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u32);
+ foo::<u32>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u32>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:28:16
+ |
+LL | foo::<u32>(42_usize);
+ | ---------- ^^^^^^^^ expected `u32`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:32:16
+ |
+LL | foo::<u32>(42_u64);
+ | ---------- ^^^^^^ expected `u32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:37:16
+ |
+LL | foo::<u32>(42_u16);
+ | ---------- ^^^^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:41:16
+ |
+LL | foo::<u32>(42_u8);
+ | ---------- ^^^^^ expected `u32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:45:16
+ |
+LL | foo::<u32>(42_isize);
+ | ---------- ^^^^^^^^ expected `u32`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:49:16
+ |
+LL | foo::<u32>(42_i64);
+ | ---------- ^^^^^^ expected `u32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:53:16
+ |
+LL | foo::<u32>(42_i32);
+ | ---------- ^^^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:57:16
+ |
+LL | foo::<u32>(42_i16);
+ | ---------- ^^^^^^ expected `u32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:61:16
+ |
+LL | foo::<u32>(42_i8);
+ | ---------- ^^^^^ expected `u32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `u32`
+ |
+LL | foo::<u32>(42_u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:65:16
+ |
+LL | foo::<u32>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `u32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `u32`
+ |
+LL | foo::<u32>(42u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u32.rs:69:16
+ |
+LL | foo::<u32>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `u32`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u32.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `u32`
+ |
+LL | foo::<u32>(42u32);
+ | ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<u64>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u64);
+ foo::<u64>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u64>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:28:16
+ |
+LL | foo::<u64>(42_usize);
+ | ---------- ^^^^^^^^ expected `u64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:33:16
+ |
+LL | foo::<u64>(42_u32);
+ | ---------- ^^^^^^ expected `u64`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:37:16
+ |
+LL | foo::<u64>(42_u16);
+ | ---------- ^^^^^^ expected `u64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:41:16
+ |
+LL | foo::<u64>(42_u8);
+ | ---------- ^^^^^ expected `u64`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:45:16
+ |
+LL | foo::<u64>(42_isize);
+ | ---------- ^^^^^^^^ expected `u64`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:49:16
+ |
+LL | foo::<u64>(42_i64);
+ | ---------- ^^^^^^ expected `u64`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:53:16
+ |
+LL | foo::<u64>(42_i32);
+ | ---------- ^^^^^^ expected `u64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:57:16
+ |
+LL | foo::<u64>(42_i16);
+ | ---------- ^^^^^^ expected `u64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:61:16
+ |
+LL | foo::<u64>(42_i8);
+ | ---------- ^^^^^ expected `u64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `u64`
+ |
+LL | foo::<u64>(42_u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:65:16
+ |
+LL | foo::<u64>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `u64`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `u64`
+ |
+LL | foo::<u64>(42u64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-u64.rs:69:16
+ |
+LL | foo::<u64>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `u64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-u64.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `u64`
+ |
+LL | foo::<u64>(42u64);
+ | ~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<usize>(42_usize);
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+fn main() {
+ foo::<usize>(42_usize);
+ foo::<usize>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<usize>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:29:18
+ |
+LL | foo::<usize>(42_u64);
+ | ------------ ^^^^^^ expected `usize`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:33:18
+ |
+LL | foo::<usize>(42_u32);
+ | ------------ ^^^^^^ expected `usize`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:37:18
+ |
+LL | foo::<usize>(42_u16);
+ | ------------ ^^^^^^ expected `usize`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:41:18
+ |
+LL | foo::<usize>(42_u8);
+ | ------------ ^^^^^ expected `usize`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:45:18
+ |
+LL | foo::<usize>(42_isize);
+ | ------------ ^^^^^^^^ expected `usize`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:49:18
+ |
+LL | foo::<usize>(42_i64);
+ | ------------ ^^^^^^ expected `usize`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:53:18
+ |
+LL | foo::<usize>(42_i32);
+ | ------------ ^^^^^^ expected `usize`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:57:18
+ |
+LL | foo::<usize>(42_i16);
+ | ------------ ^^^^^^ expected `usize`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:61:18
+ |
+LL | foo::<usize>(42_i8);
+ | ------------ ^^^^^ expected `usize`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `usize`
+ |
+LL | foo::<usize>(42_usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:65:18
+ |
+LL | foo::<usize>(42.0_f64);
+ | ------------ ^^^^^^^^ expected `usize`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `usize`
+ |
+LL | foo::<usize>(42usize);
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix-usize.rs:69:18
+ |
+LL | foo::<usize>(42.0_f32);
+ | ------------ ^^^^^^^^ expected `usize`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix-usize.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `usize`
+ |
+LL | foo::<usize>(42usize);
+ | ~~~~~
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+
+fn main() {
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ foo::<i16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ foo::<i8>(42i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<f64>(42_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u32.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u16.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u8.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i32.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i16.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i8.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42.0_f64);
+ foo::<f64>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u16.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u8.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i16.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i8.into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42.0_f32);
+
+ foo::<u32>((42_u8 as u16).into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>((-42_i8).into());
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+// run-rustfix
+
+fn foo<N>(_x: N) {}
+//~^ NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE function defined here
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+//~| NOTE
+
+
+fn main() {
+ foo::<u16>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_u16);
+ foo::<u16>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u16>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<i16>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42_i16);
+ foo::<i16>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i16>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<u8>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_u8);
+ foo::<u8>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<u8>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<i8>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42_i8);
+ foo::<i8>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i8>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<f64>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f64>(42.0_f64);
+ foo::<f64>(42.0_f32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+
+ foo::<f32>(42_usize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_u8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_isize);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i32);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42.0_f64);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<f32>(42.0_f32);
+
+ foo::<u32>(42_u8 as u16);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+ foo::<i32>(-42_i8);
+ //~^ ERROR mismatched types
+ //~| NOTE expected
+ //~| NOTE arguments
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:143:16
+ |
+LL | foo::<u16>(42_usize);
+ | ---------- ^^^^^^^^ expected `u16`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:147:16
+ |
+LL | foo::<u16>(42_u64);
+ | ---------- ^^^^^^ expected `u16`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:151:16
+ |
+LL | foo::<u16>(42_u32);
+ | ---------- ^^^^^^ expected `u16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:156:16
+ |
+LL | foo::<u16>(42_u8);
+ | ---------- ^^^^^ expected `u16`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:160:16
+ |
+LL | foo::<u16>(42_isize);
+ | ---------- ^^^^^^^^ expected `u16`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:164:16
+ |
+LL | foo::<u16>(42_i64);
+ | ---------- ^^^^^^ expected `u16`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:168:16
+ |
+LL | foo::<u16>(42_i32);
+ | ---------- ^^^^^^ expected `u16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:172:16
+ |
+LL | foo::<u16>(42_i16);
+ | ---------- ^^^^^^ expected `u16`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:176:16
+ |
+LL | foo::<u16>(42_i8);
+ | ---------- ^^^^^ expected `u16`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `u16`
+ |
+LL | foo::<u16>(42_u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:180:16
+ |
+LL | foo::<u16>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `u16`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `u16`
+ |
+LL | foo::<u16>(42u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:184:16
+ |
+LL | foo::<u16>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `u16`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `u16`
+ |
+LL | foo::<u16>(42u16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:189:16
+ |
+LL | foo::<i16>(42_usize);
+ | ---------- ^^^^^^^^ expected `i16`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:193:16
+ |
+LL | foo::<i16>(42_u64);
+ | ---------- ^^^^^^ expected `i16`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:197:16
+ |
+LL | foo::<i16>(42_u32);
+ | ---------- ^^^^^^ expected `i16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:201:16
+ |
+LL | foo::<i16>(42_u16);
+ | ---------- ^^^^^^ expected `i16`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:205:16
+ |
+LL | foo::<i16>(42_u8);
+ | ---------- ^^^^^ expected `i16`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:209:16
+ |
+LL | foo::<i16>(42_isize);
+ | ---------- ^^^^^^^^ expected `i16`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:213:16
+ |
+LL | foo::<i16>(42_i64);
+ | ---------- ^^^^^^ expected `i16`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:217:16
+ |
+LL | foo::<i16>(42_i32);
+ | ---------- ^^^^^^ expected `i16`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:222:16
+ |
+LL | foo::<i16>(42_i8);
+ | ---------- ^^^^^ expected `i16`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `i16`
+ |
+LL | foo::<i16>(42_i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:226:16
+ |
+LL | foo::<i16>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `i16`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `i16`
+ |
+LL | foo::<i16>(42i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:230:16
+ |
+LL | foo::<i16>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `i16`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `i16`
+ |
+LL | foo::<i16>(42i16);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:235:15
+ |
+LL | foo::<u8>(42_usize);
+ | --------- ^^^^^^^^ expected `u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:239:15
+ |
+LL | foo::<u8>(42_u64);
+ | --------- ^^^^^^ expected `u8`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:243:15
+ |
+LL | foo::<u8>(42_u32);
+ | --------- ^^^^^^ expected `u8`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:247:15
+ |
+LL | foo::<u8>(42_u16);
+ | --------- ^^^^^^ expected `u8`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:252:15
+ |
+LL | foo::<u8>(42_isize);
+ | --------- ^^^^^^^^ expected `u8`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:256:15
+ |
+LL | foo::<u8>(42_i64);
+ | --------- ^^^^^^ expected `u8`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:260:15
+ |
+LL | foo::<u8>(42_i32);
+ | --------- ^^^^^^ expected `u8`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:264:15
+ |
+LL | foo::<u8>(42_i16);
+ | --------- ^^^^^^ expected `u8`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:268:15
+ |
+LL | foo::<u8>(42_i8);
+ | --------- ^^^^^ expected `u8`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i8` to `u8`
+ |
+LL | foo::<u8>(42_u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:272:15
+ |
+LL | foo::<u8>(42.0_f64);
+ | --------- ^^^^^^^^ expected `u8`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `u8`
+ |
+LL | foo::<u8>(42u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:276:15
+ |
+LL | foo::<u8>(42.0_f32);
+ | --------- ^^^^^^^^ expected `u8`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `u8`
+ |
+LL | foo::<u8>(42u8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:281:15
+ |
+LL | foo::<i8>(42_usize);
+ | --------- ^^^^^^^^ expected `i8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:285:15
+ |
+LL | foo::<i8>(42_u64);
+ | --------- ^^^^^^ expected `i8`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:289:15
+ |
+LL | foo::<i8>(42_u32);
+ | --------- ^^^^^^ expected `i8`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:293:15
+ |
+LL | foo::<i8>(42_u16);
+ | --------- ^^^^^^ expected `i8`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u16` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:297:15
+ |
+LL | foo::<i8>(42_u8);
+ | --------- ^^^^^ expected `i8`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u8` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:301:15
+ |
+LL | foo::<i8>(42_isize);
+ | --------- ^^^^^^^^ expected `i8`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:305:15
+ |
+LL | foo::<i8>(42_i64);
+ | --------- ^^^^^^ expected `i8`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:309:15
+ |
+LL | foo::<i8>(42_i32);
+ | --------- ^^^^^^ expected `i8`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:313:15
+ |
+LL | foo::<i8>(42_i16);
+ | --------- ^^^^^^ expected `i8`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i16` to `i8`
+ |
+LL | foo::<i8>(42_i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:318:15
+ |
+LL | foo::<i8>(42.0_f64);
+ | --------- ^^^^^^^^ expected `i8`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `i8`
+ |
+LL | foo::<i8>(42i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:322:15
+ |
+LL | foo::<i8>(42.0_f32);
+ | --------- ^^^^^^^^ expected `i8`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `i8`
+ |
+LL | foo::<i8>(42i8);
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:327:16
+ |
+LL | foo::<f64>(42_usize);
+ | ---------- ^^^^^^^^ expected `f64`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `f64`
+ |
+LL | foo::<f64>(42_f64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:331:16
+ |
+LL | foo::<f64>(42_u64);
+ | ---------- ^^^^^^ expected `f64`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `f64`
+ |
+LL | foo::<f64>(42_f64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:335:16
+ |
+LL | foo::<f64>(42_u32);
+ | ---------- ^^^^^^ expected `f64`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_u32.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:339:16
+ |
+LL | foo::<f64>(42_u16);
+ | ---------- ^^^^^^ expected `f64`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_u16.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:343:16
+ |
+LL | foo::<f64>(42_u8);
+ | ---------- ^^^^^ expected `f64`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_u8.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:347:16
+ |
+LL | foo::<f64>(42_isize);
+ | ---------- ^^^^^^^^ expected `f64`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `f64`
+ |
+LL | foo::<f64>(42_f64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:351:16
+ |
+LL | foo::<f64>(42_i64);
+ | ---------- ^^^^^^ expected `f64`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `f64`
+ |
+LL | foo::<f64>(42_f64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:355:16
+ |
+LL | foo::<f64>(42_i32);
+ | ---------- ^^^^^^ expected `f64`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_i32.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:359:16
+ |
+LL | foo::<f64>(42_i16);
+ | ---------- ^^^^^^ expected `f64`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_i16.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:363:16
+ |
+LL | foo::<f64>(42_i8);
+ | ---------- ^^^^^ expected `f64`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
+ |
+LL | foo::<f64>(42_i8.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:368:16
+ |
+LL | foo::<f64>(42.0_f32);
+ | ---------- ^^^^^^^^ expected `f64`, found `f32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f32` to `f64`
+ |
+LL | foo::<f64>(42.0_f64);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:373:16
+ |
+LL | foo::<f32>(42_usize);
+ | ---------- ^^^^^^^^ expected `f32`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `usize` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:377:16
+ |
+LL | foo::<f32>(42_u64);
+ | ---------- ^^^^^^ expected `f32`, found `u64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u64` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:381:16
+ |
+LL | foo::<f32>(42_u32);
+ | ---------- ^^^^^^ expected `f32`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `u32` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:385:16
+ |
+LL | foo::<f32>(42_u16);
+ | ---------- ^^^^^^ expected `f32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
+ |
+LL | foo::<f32>(42_u16.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:389:16
+ |
+LL | foo::<f32>(42_u8);
+ | ---------- ^^^^^ expected `f32`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
+ |
+LL | foo::<f32>(42_u8.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:393:16
+ |
+LL | foo::<f32>(42_isize);
+ | ---------- ^^^^^^^^ expected `f32`, found `isize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `isize` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:397:16
+ |
+LL | foo::<f32>(42_i64);
+ | ---------- ^^^^^^ expected `f32`, found `i64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i64` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:401:16
+ |
+LL | foo::<f32>(42_i32);
+ | ---------- ^^^^^^ expected `f32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `i32` to `f32`
+ |
+LL | foo::<f32>(42_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:405:16
+ |
+LL | foo::<f32>(42_i16);
+ | ---------- ^^^^^^ expected `f32`, found `i16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
+ |
+LL | foo::<f32>(42_i16.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:409:16
+ |
+LL | foo::<f32>(42_i8);
+ | ---------- ^^^^^ expected `f32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
+ |
+LL | foo::<f32>(42_i8.into());
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:413:16
+ |
+LL | foo::<f32>(42.0_f64);
+ | ---------- ^^^^^^^^ expected `f32`, found `f64`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: change the type of the numeric literal from `f64` to `f32`
+ |
+LL | foo::<f32>(42.0_f32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:419:16
+ |
+LL | foo::<u32>(42_u8 as u16);
+ | ---------- ^^^^^^^^^^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert a `u16` to a `u32`
+ |
+LL | foo::<u32>((42_u8 as u16).into());
+ | + ++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-suffix.rs:423:16
+ |
+LL | foo::<i32>(-42_i8);
+ | ---------- ^^^^^^ expected `i32`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/numeric-suffix.rs:3:4
+ |
+LL | fn foo<N>(_x: N) {}
+ | ^^^ -----
+help: you can convert an `i8` to an `i32`
+ |
+LL | foo::<i32>((-42_i8).into());
+ | + ++++++++
+
+error: aborting due to 68 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/issue-27060-rpass.rs:15:13
+ |
+LL | let _ = &good.data; // ok
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-27060-rpass.rs:11:9
+ |
+LL | #[allow(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/issue-27060-rpass.rs:16:13
+ |
+LL | let _ = &good.data2[0]; // ok
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-27060-rpass.rs:11:9
+ |
+LL | #[allow(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/issue-27060-rpass.rs:18:13
+ |
+LL | let _ = &good.data;
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-27060-rpass.rs:11:9
+ |
+LL | #[allow(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/issue-27060-rpass.rs:19:13
+ |
+LL | let _ = &good.data2[0];
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-27060-rpass.rs:11:9
+ |
+LL | #[allow(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
aligned: [u8; 32],
}
-#[deny(unaligned_references)]
fn main() {
let good = Good {
data: &0,
error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:16:13
+ --> $DIR/issue-27060.rs:15:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/issue-27060.rs:8:8
- |
-LL | #[deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:18:13
+ --> $DIR/issue-27060.rs:17:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:21:13
+ --> $DIR/issue-27060.rs:20:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:23:13
+ --> $DIR/issue-27060.rs:22:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
+Future incompatibility report: Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:15:13
+ |
+LL | let _ = &good.data;
+ | ^^^^^^^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:17:13
+ |
+LL | let _ = &good.data2[0];
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:20:13
+ |
+LL | let _ = &good.data;
+ | ^^^^^^^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+error: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:22:13
+ |
+LL | let _ = &good.data2[0];
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(unaligned_references)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
// run-pass
#![allow(dead_code)]
-#![deny(unaligned_references)]
#![feature(raw_ref_op)]
// ignore-emscripten weird assertion?
baz: usize
}
+#[warn(unaligned_references)]
pub fn main() {
let foo = Foo4C { bar: 1, baz: 2 };
let brw = &foo.baz; //~WARN reference to packed field is unaligned
warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element-64bit.rs:14:15
+ --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = note: `#[warn(unaligned_references)]` on by default
+note: the lint level is defined here
+ --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
+ |
+LL | #[warn(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
= 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
warning: 1 warning emitted
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
+ |
+LL | let brw = &foo.baz;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
+ |
+LL | #[warn(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
baz: usize
}
+#[warn(unaligned_references)]
pub fn main() {
let foo = Foo1 { bar: 1, baz: 2 };
let brw = &foo.baz; //~WARN reference to packed field is unaligned
warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:25:15
+ --> $DIR/packed-struct-borrow-element.rs:26:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = note: `#[warn(unaligned_references)]` on by default
+note: the lint level is defined here
+ --> $DIR/packed-struct-borrow-element.rs:23:8
+ |
+LL | #[warn(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
= 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:30:15
+ --> $DIR/packed-struct-borrow-element.rs:31:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
warning: 2 warnings emitted
+Future incompatibility report: Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:26:15
+ |
+LL | let brw = &foo.baz;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/packed-struct-borrow-element.rs:23:8
+ |
+LL | #[warn(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+Future breakage diagnostic:
+warning: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:31:15
+ |
+LL | let brw = &foo.baz;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/packed-struct-borrow-element.rs:23:8
+ |
+LL | #[warn(unaligned_references)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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 #82523 <https://github.com/rust-lang/rust/issues/82523>
+ = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+ = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
-pub fn f(
+pub fn f( //~ NOTE function defined here
/// Comment
//~^ ERROR documentation comments cannot be applied to function parameters
//~| NOTE doc comments are not allowed here
+ //~| NOTE
id: u8,
/// Other
//~^ ERROR documentation comments cannot be applied to function parameters
//~| NOTE doc comments are not allowed here
+ //~| NOTE
a: u8,
) {}
fn bar(id: #[allow(dead_code)] i32) {}
//~^ ERROR attributes cannot be applied to a function parameter's type
//~| NOTE attributes are not allowed here
+//~| NOTE function defined here
+//~| NOTE
fn main() {
// verify that the parser recovered and properly typechecked the args
f("", "");
- //~^ ERROR mismatched types
+ //~^ ERROR arguments to this function are incorrect
//~| NOTE expected `u8`, found `&str`
- //~| ERROR mismatched types
//~| NOTE expected `u8`, found `&str`
bar("");
//~^ ERROR mismatched types
+ //~| NOTE arguments to this function are incorrect
//~| NOTE expected `i32`, found `&str`
}
error: attributes cannot be applied to a function parameter's type
- --> $DIR/fn-arg-doc-comment.rs:12:12
+ --> $DIR/fn-arg-doc-comment.rs:14:12
|
LL | fn bar(id: #[allow(dead_code)] i32) {}
| ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
| ^^^^^^^^^^^ doc comments are not allowed here
error: documentation comments cannot be applied to function parameters
- --> $DIR/fn-arg-doc-comment.rs:6:5
+ --> $DIR/fn-arg-doc-comment.rs:7:5
|
LL | /// Other
| ^^^^^^^^^ doc comments are not allowed here
-error[E0308]: mismatched types
- --> $DIR/fn-arg-doc-comment.rs:18:7
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/fn-arg-doc-comment.rs:22:5
|
LL | f("", "");
- | ^^ expected `u8`, found `&str`
-
-error[E0308]: mismatched types
- --> $DIR/fn-arg-doc-comment.rs:18:11
+ | ^ -- -- expected `u8`, found `&str`
+ | |
+ | expected `u8`, found `&str`
|
-LL | f("", "");
- | ^^ expected `u8`, found `&str`
+note: function defined here
+ --> $DIR/fn-arg-doc-comment.rs:1:8
+ |
+LL | pub fn f(
+ | ^
+LL | / /// Comment
+LL | |
+LL | |
+LL | |
+LL | | id: u8,
+ | |__________-
+LL | / /// Other
+LL | |
+LL | |
+LL | |
+LL | | a: u8,
+ | |_________-
error[E0308]: mismatched types
- --> $DIR/fn-arg-doc-comment.rs:23:9
+ --> $DIR/fn-arg-doc-comment.rs:26:9
|
LL | bar("");
- | ^^ expected `i32`, found `&str`
+ | --- ^^ expected `i32`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/fn-arg-doc-comment.rs:14:4
+ |
+LL | fn bar(id: #[allow(dead_code)] i32) {}
+ | ^^^ ---------------------------
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+fn main() {
+ (if foobar) //~ ERROR expected `{`, found `)`
+}
--- /dev/null
+error: expected `{`, found `)`
+ --> $DIR/issue-61858.rs:2:15
+ |
+LL | (if foobar)
+ | -- ^ expected `{`
+ | |
+ | this `if` expression has a condition, but no block
+
+error: aborting due to previous error
+
--> $DIR/pattern-error-continue.rs:28:7
|
LL | f(true);
- | ^^^^ expected `char`, found `bool`
+ | - ^^^^ expected `char`, found `bool`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/pattern-error-continue.rs:13:4
+ |
+LL | fn f(_c: char) {}
+ | ^ --------
error: aborting due to 5 previous errors
|
= note: expected fn pointer `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
found fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+note: associated function defined here
+ --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
+ |
+LL | pub const fn custom_derive(
+ | ^^^^^^^^^^^^^
error: aborting due to previous error
--> $DIR/issue-54505-no-literals.rs:16:16
|
LL | take_range(std::ops::Range { start: 0, end: 1 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `std::ops::Range`
- | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `std::ops::Range`
+ | | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `std::ops::Range<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:21:16
|
LL | take_range(::std::ops::Range { start: 0, end: 1 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `std::ops::Range`
- | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `std::ops::Range`
+ | | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `std::ops::Range<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:26:16
|
LL | take_range(std::ops::RangeFrom { start: 1 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeFrom`
- | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeFrom`
+ | | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFrom<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:31:16
|
LL | take_range(::std::ops::RangeFrom { start: 1 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeFrom`
- | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeFrom`
+ | | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFrom<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:36:16
|
LL | take_range(std::ops::RangeFull {});
- | ^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeFull`
- | help: consider borrowing here: `&std::ops::RangeFull {}`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeFull`
+ | | help: consider borrowing here: `&std::ops::RangeFull {}`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFull`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:41:16
|
LL | take_range(::std::ops::RangeFull {});
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeFull`
- | help: consider borrowing here: `&::std::ops::RangeFull {}`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeFull`
+ | | help: consider borrowing here: `&::std::ops::RangeFull {}`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFull`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:46:16
|
LL | take_range(std::ops::RangeInclusive::new(0, 1));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeInclusive`
- | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeInclusive`
+ | | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:51:16
|
LL | take_range(::std::ops::RangeInclusive::new(0, 1));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeInclusive`
- | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeInclusive`
+ | | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:56:16
|
LL | take_range(std::ops::RangeTo { end: 5 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeTo`
- | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeTo`
+ | | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeTo<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:61:16
|
LL | take_range(::std::ops::RangeTo { end: 5 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeTo`
- | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeTo`
+ | | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeTo<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:66:16
|
LL | take_range(std::ops::RangeToInclusive { end: 5 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeToInclusive`
- | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeToInclusive`
+ | | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeToInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-literals.rs:71:16
|
LL | take_range(::std::ops::RangeToInclusive { end: 5 });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `RangeToInclusive`
- | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+ | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `RangeToInclusive`
+ | | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeToInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-literals.rs:12:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error: aborting due to 12 previous errors
--> $DIR/issue-54505-no-std.rs:27:16
|
LL | take_range(0..1);
- | ^^^^
- | |
- | expected reference, found struct `Range`
- | help: consider borrowing here: `&(0..1)`
+ | ---------- ^^^^
+ | | |
+ | | expected reference, found struct `Range`
+ | | help: consider borrowing here: `&(0..1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `Range<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-std.rs:32:16
|
LL | take_range(1..);
- | ^^^
- | |
- | expected reference, found struct `RangeFrom`
- | help: consider borrowing here: `&(1..)`
+ | ---------- ^^^
+ | | |
+ | | expected reference, found struct `RangeFrom`
+ | | help: consider borrowing here: `&(1..)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFrom<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-std.rs:37:16
|
LL | take_range(..);
- | ^^
- | |
- | expected reference, found struct `RangeFull`
- | help: consider borrowing here: `&(..)`
+ | ---------- ^^
+ | | |
+ | | expected reference, found struct `RangeFull`
+ | | help: consider borrowing here: `&(..)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFull`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-std.rs:42:16
|
LL | take_range(0..=1);
- | ^^^^^
- | |
- | expected reference, found struct `RangeInclusive`
- | help: consider borrowing here: `&(0..=1)`
+ | ---------- ^^^^^
+ | | |
+ | | expected reference, found struct `RangeInclusive`
+ | | help: consider borrowing here: `&(0..=1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-std.rs:47:16
|
LL | take_range(..5);
- | ^^^
- | |
- | expected reference, found struct `RangeTo`
- | help: consider borrowing here: `&(..5)`
+ | ---------- ^^^
+ | | |
+ | | expected reference, found struct `RangeTo`
+ | | help: consider borrowing here: `&(..5)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeTo<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505-no-std.rs:52:16
|
LL | take_range(..=42);
- | ^^^^^
- | |
- | expected reference, found struct `RangeToInclusive`
- | help: consider borrowing here: `&(..=42)`
+ | ---------- ^^^^^
+ | | |
+ | | expected reference, found struct `RangeToInclusive`
+ | | help: consider borrowing here: `&(..=42)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeToInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505-no-std.rs:23:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error: aborting due to 7 previous errors
--> $DIR/issue-54505.rs:14:16
|
LL | take_range(0..1);
- | ^^^^
- | |
- | expected reference, found struct `std::ops::Range`
- | help: consider borrowing here: `&(0..1)`
+ | ---------- ^^^^
+ | | |
+ | | expected reference, found struct `std::ops::Range`
+ | | help: consider borrowing here: `&(0..1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `std::ops::Range<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505.rs:19:16
|
LL | take_range(1..);
- | ^^^
- | |
- | expected reference, found struct `RangeFrom`
- | help: consider borrowing here: `&(1..)`
+ | ---------- ^^^
+ | | |
+ | | expected reference, found struct `RangeFrom`
+ | | help: consider borrowing here: `&(1..)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFrom<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505.rs:24:16
|
LL | take_range(..);
- | ^^
- | |
- | expected reference, found struct `RangeFull`
- | help: consider borrowing here: `&(..)`
+ | ---------- ^^
+ | | |
+ | | expected reference, found struct `RangeFull`
+ | | help: consider borrowing here: `&(..)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeFull`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505.rs:29:16
|
LL | take_range(0..=1);
- | ^^^^^
- | |
- | expected reference, found struct `RangeInclusive`
- | help: consider borrowing here: `&(0..=1)`
+ | ---------- ^^^^^
+ | | |
+ | | expected reference, found struct `RangeInclusive`
+ | | help: consider borrowing here: `&(0..=1)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505.rs:34:16
|
LL | take_range(..5);
- | ^^^
- | |
- | expected reference, found struct `RangeTo`
- | help: consider borrowing here: `&(..5)`
+ | ---------- ^^^
+ | | |
+ | | expected reference, found struct `RangeTo`
+ | | help: consider borrowing here: `&(..5)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeTo<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error[E0308]: mismatched types
--> $DIR/issue-54505.rs:39:16
|
LL | take_range(..=42);
- | ^^^^^
- | |
- | expected reference, found struct `RangeToInclusive`
- | help: consider borrowing here: `&(..=42)`
+ | ---------- ^^^^^
+ | | |
+ | | expected reference, found struct `RangeToInclusive`
+ | | help: consider borrowing here: `&(..=42)`
+ | arguments to this function are incorrect
|
= note: expected reference `&_`
found struct `RangeToInclusive<{integer}>`
+note: function defined here
+ --> $DIR/issue-54505.rs:10:4
+ |
+LL | fn take_range(_r: &impl RangeBounds<i8>) {}
+ | ^^^^^^^^^^ -------------------------
error: aborting due to 6 previous errors
--> $DIR/issue-73553-misinterp-range-literal.rs:12:10
|
LL | demo(tell(1)..tell(10));
- | ^^^^^^^^^^^^^^^^^
- | |
- | expected reference, found struct `std::ops::Range`
- | help: consider borrowing here: `&(tell(1)..tell(10))`
+ | ---- ^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected reference, found struct `std::ops::Range`
+ | | help: consider borrowing here: `&(tell(1)..tell(10))`
+ | arguments to this function are incorrect
|
= note: expected reference `&std::ops::Range<usize>`
found struct `std::ops::Range<usize>`
+note: function defined here
+ --> $DIR/issue-73553-misinterp-range-literal.rs:3:4
+ |
+LL | fn demo(r: &Range) {
+ | ^^^^ ---------
error[E0308]: mismatched types
--> $DIR/issue-73553-misinterp-range-literal.rs:14:10
|
LL | demo(1..10);
- | ^^^^^
- | |
- | expected reference, found struct `std::ops::Range`
- | help: consider borrowing here: `&(1..10)`
+ | ---- ^^^^^
+ | | |
+ | | expected reference, found struct `std::ops::Range`
+ | | help: consider borrowing here: `&(1..10)`
+ | arguments to this function are incorrect
|
= note: expected reference `&std::ops::Range<usize>`
found struct `std::ops::Range<{integer}>`
+note: function defined here
+ --> $DIR/issue-73553-misinterp-range-literal.rs:3:4
+ |
+LL | fn demo(r: &Range) {
+ | ^^^^ ---------
error: aborting due to 2 previous errors
| ^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:22:5
| ^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:28:5
| ^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:35:5
| ^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
+ = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
error: aborting due to 4 previous errors
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5
|
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `U: 'static`...
+ | ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5
|
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `U: 'static`...
+ | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5
|
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `U: 'static`...
+ | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error: lifetime may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:5
error[E0310]: the parameter type `U` may not live long enough
--> $DIR/regions-close-object-into-object-4.rs:9:14
|
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `U: 'static`
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^
- |
- = help: consider adding an explicit lifetime bound `U: 'static`...
+ | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds
error: aborting due to 6 previous errors
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-5.rs:17:5
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:14
|
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | // oh dear!
LL | Box::new(B(&*v)) as Box<dyn X>
- | ^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 5 previous errors
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
+LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
+ | -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | Box::new(v) as Box<dyn SomeTrait + 'static>
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `A: 'static`...
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
+LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
+ | -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | Box::new(v) as Box<dyn SomeTrait + 'b>
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `A: 'b`...
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error: aborting due to 2 previous errors
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:6:5
|
+LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
LL | Box::new(v)
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:12:5
|
+LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+...
LL | Box::new(v)
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:18:5
|
+LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | Box::new(v)
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-close-param-into-object.rs:24:5
|
+LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
+ | - help: consider adding an explicit lifetime bound...: `T: 'a`
+...
LL | Box::new(v)
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'a`...
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 4 previous errors
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regions-implied-bounds-projection-gap-1.rs:16:5
|
+LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
+ | -- help: consider adding an explicit lifetime bound...: `T: 'x +`
+LL | {
LL | wf::<&'x T>();
- | ^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `T: 'x`...
+ | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to previous error
| ^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
+ = note: ...so that the type `Self` will meet its required lifetime bounds
error: aborting due to previous error
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:33:5
|
+LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
+ | - help: consider adding an explicit lifetime bound...: `A: 'a`
LL | check_bound(x, a)
- | ^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `A: 'a`...
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-infer-bound-from-trait.rs:37:5
|
+LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
+ | -- help: consider adding an explicit lifetime bound...: `A: 'a +`
LL | check_bound(x, a)
- | ^^^^^^^^^^^^^^^^^
- |
- = help: consider adding an explicit lifetime bound `A: 'a`...
+ | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error: aborting due to 2 previous errors
-struct Foo<'static> { //~ ERROR invalid lifetime parameter name: `'static`
- x: &'static isize
+struct Foo<'static> {
+ //~^ ERROR invalid lifetime parameter name: `'static`
+ x: &'static isize,
}
fn main() {}
let y: &'a isize = x;
// &'a is not visible to *items*:
- type X = Option<&'a isize>; //~ ERROR undeclared lifetime
+ type X = Option<&'a isize>; //~ ERROR can't use generic parameters from outer item
enum E {
- E1(&'a isize) //~ ERROR undeclared lifetime
+ E1(&'a isize) //~ ERROR can't use generic parameters from outer item
}
struct S {
- f: &'a isize //~ ERROR undeclared lifetime
+ f: &'a isize //~ ERROR can't use generic parameters from outer item
}
- fn f(a: &'a isize) { } //~ ERROR undeclared lifetime
+ fn f(a: &'a isize) { } //~ ERROR can't use generic parameters from outer item
// &'a CAN be declared on functions and used then:
fn g<'a>(a: &'a isize) { } // OK
-error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/regions-name-undeclared.rs:28:13
- |
-LL | enum E {
- | - help: consider introducing lifetime `'a` here: `<'a>`
-LL | E1(&'a isize)
- | ^^ undeclared lifetime
-
-error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/regions-name-undeclared.rs:31:13
- |
-LL | struct S {
- | - help: consider introducing lifetime `'a` here: `<'a>`
-LL | f: &'a isize
- | ^^ undeclared lifetime
-
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:16:24
|
|
help: consider introducing lifetime `'b` here
|
-LL | impl<'b, 'a> Foo<'a> {
- | +++
-help: consider introducing lifetime `'b` here
- |
LL | fn m4<'b>(&self, arg: &'b isize) { }
| ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:17:12
|
help: consider introducing lifetime `'b` here
|
-LL | impl<'b, 'a> Foo<'a> {
- | +++
-help: consider introducing lifetime `'b` here
- |
LL | fn m5<'b>(&'b self) { }
| ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:18:27
|
help: consider introducing lifetime `'b` here
|
-LL | impl<'b, 'a> Foo<'a> {
- | +++
-help: consider introducing lifetime `'b` here
- |
LL | fn m6<'b>(&self, arg: Foo<'b>) { }
| ++++
+help: consider introducing lifetime `'b` here
+ |
+LL | impl<'b, 'a> Foo<'a> {
+ | +++
-error[E0261]: use of undeclared lifetime name `'a`
+error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:26:22
|
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
LL | type X = Option<&'a isize>;
- | - ^^ undeclared lifetime
+ | - ^^ use of generic parameter from outer item
| |
| help: consider introducing lifetime `'a` here: `<'a>`
-error[E0261]: use of undeclared lifetime name `'a`
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:28:13
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | enum E {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | E1(&'a isize)
+ | ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
+ --> $DIR/regions-name-undeclared.rs:31:13
+ |
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
+LL | struct S {
+ | - help: consider introducing lifetime `'a` here: `<'a>`
+LL | f: &'a isize
+ | ^^ use of generic parameter from outer item
+
+error[E0401]: can't use generic parameters from outer item
--> $DIR/regions-name-undeclared.rs:33:14
|
+LL | fn bar<'a>(x: &'a isize) {
+ | -- lifetime parameter from outer item
+...
LL | fn f(a: &'a isize) { }
- | - ^^ undeclared lifetime
+ | - ^^ use of generic parameter from outer item
| |
| help: consider introducing lifetime `'a` here: `<'a>`
| ^^ undeclared lifetime
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+ | +++
help: consider introducing lifetime `'b` here
|
LL | fn fn_types<'b>(a: &'a isize,
| ++++
-help: consider making the bound lifetime-generic with a new `'b` lifetime
- |
-LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
- | ++++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/regions-name-undeclared.rs:46:36
LL | ... &'b isize)>,
| ^^ undeclared lifetime
|
- = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | b: Box<dyn for<'b, 'a> FnOnce(&'a isize,
+ | +++
help: consider introducing lifetime `'b` here
|
LL | fn fn_types<'b>(a: &'a isize,
| ++++
-help: consider making the bound lifetime-generic with a new `'b` lifetime
- |
-LL | b: Box<dyn for<'a, 'b> FnOnce(&'a isize,
- | ++++
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/regions-name-undeclared.rs:47:17
|
help: consider introducing lifetime `'a` here
|
-LL | impl<'a> Bug {
- | ++++
-help: consider introducing lifetime `'a` here
- |
LL | async fn buggy<'a>(&self) -> &'a str {
| ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | impl<'a> Bug {
+ | ++++
error: aborting due to 12 previous errors
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0401.
+For more information about an error, try `rustc --explain E0261`.
--> $DIR/resolve-primitive-fallback.rs:3:5
|
LL | std::mem::size_of(u16);
- | ^^^^^^^^^^^^^^^^^ --- supplied 1 argument
- | |
- | expected 0 arguments
+ | ^^^^^^^^^^^^^^^^^ --- argument unexpected
|
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();
+ | ~~~~~~~~~~~~~~~~~~~
error: aborting due to 3 previous errors
pub struct Int(i32);
impl const std::ops::Add for i32 { //~ ERROR type annotations needed
- //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
+ //~^ ERROR only traits defined in the current crate can be implemented for primitive types
type Output = Self;
fn add(self, rhs: Self) -> Self {
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/const-and-non-const-impl.rs:5:1
|
LL | impl const std::ops::Add for i32 {
error: implementation of `FnOnce` is not general enough
- --> $DIR/rfc1623.rs:36:8
+ --> $DIR/rfc1623.rs:32:8
|
LL | f: &id,
| ^^^ implementation of `FnOnce` is not general enough
error[E0308]: mismatched types
- --> $DIR/rfc1623.rs:29:35
+ --> $DIR/rfc1623.rs:32:8
|
-LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
- | ___________________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | };
- | |_^ one type is more general than the other
+LL | f: &id,
+ | ^^^ one type is more general than the other
|
= note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
found type `Fn<(&Foo<'_>,)>`
error[E0308]: mismatched types
- --> $DIR/rfc1623.rs:29:35
+ --> $DIR/rfc1623.rs:32:8
|
-LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
- | ___________________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | };
- | |_^ one type is more general than the other
+LL | f: &id,
+ | ^^^ one type is more general than the other
|
= note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>`
found type `Fn<(&Foo<'_>,)>`
error: implementation of `FnOnce` is not general enough
- --> $DIR/rfc1623.rs:29:35
+ --> $DIR/rfc1623.rs:32:8
|
-LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
- | ___________________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | };
- | |_^ implementation of `FnOnce` is not general enough
+LL | f: &id,
+ | ^^^ implementation of `FnOnce` is not general enough
|
= note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2`
error: implementation of `FnOnce` is not general enough
- --> $DIR/rfc1623.rs:29:35
+ --> $DIR/rfc1623.rs:32:8
|
-LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
- | ___________________________________^
-LL | |
-LL | |
-LL | |
-... |
-LL | |
-LL | | };
- | |_^ implementation of `FnOnce` is not general enough
+LL | f: &id,
+ | ^^^ implementation of `FnOnce` is not general enough
|
= note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2`
}
static SOME_STRUCT: &SomeStruct = &SomeStruct {
- //[nll]~^ ERROR mismatched types
- //[nll]~| ERROR mismatched types
- //[nll]~| ERROR implementation of `FnOnce` is not general enough
- //[nll]~| ERROR implementation of `FnOnce` is not general enough
foo: &Foo { bools: &[false, true] },
bar: &Bar { bools: &[true, true] },
f: &id,
//[base]~^ ERROR implementation of `FnOnce` is not general enough
+ //[nll]~^^ ERROR mismatched types
+ //[nll]~| ERROR mismatched types
+ //[nll]~| ERROR implementation of `FnOnce` is not general enough
+ //[nll]~| ERROR implementation of `FnOnce` is not general enough
};
// very simple test for a 'static static with default lifetime
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:52
+ |
+LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+ | ---- ---- ^ ...but data from `f` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:82
+ |
+LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+ | ---- ----------------- ^ ...but data from `f` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
+ |
+LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+ | ------ --- ^^^ ...but data from `arg` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:52
|
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
| - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| let's call the lifetime of this reference `'2`
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:15:75
|
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
| - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| let's call the lifetime of this reference `'2`
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:22:64
|
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
| -- - ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
use std::pin::Pin;
impl Foo {
async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
- //~^ ERROR lifetime mismatch
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ lifetime may not live long enough
async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- //~^ ERROR lifetime mismatch
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ lifetime may not live long enough
}
type Alias<T> = Pin<T>;
impl Foo {
- async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+ async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+ //[base]~^ ERROR E0623
+ //[nll]~^^ lifetime may not live long enough
}
fn main() {}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
- |
-LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
- | ---- ---- ^ ...but data from `f` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
-
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:82
- |
-LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- | ---- ----------------- ^ ...but data from `f` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
-
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
- |
-LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
- | ------ --- ^^^ ...but data from `arg` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:46
+ |
+LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+ | ---- ---- ^ ...but data from `f` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:14:76
+ |
+LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+ | ---- ----------------- ^ ...but data from `f` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:58
+ |
+LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+ | ------ --- ^^^ ...but data from `arg` is returned here
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:46
|
LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
| - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| let's call the lifetime of this reference `'2`
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:14:69
|
LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
| - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| let's call the lifetime of this reference `'2`
error: lifetime may not live long enough
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
+ --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:21:58
|
LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
| -- ---- has type `Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
use std::pin::Pin;
struct Foo;
impl Foo {
- fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } //~ ERROR E0623
+ fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+ //[base]~^ ERROR E0623
+ //[nll]~^^ lifetime may not live long enough
- fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
+ fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+ //[base]~^ ERROR E0623
+ //[nll]~^^ lifetime may not live long enough
}
type Alias<T> = Pin<T>;
impl Foo {
- fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+ fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+ //[base]~^ ERROR E0623
+ //[nll]~^^ lifetime may not live long enough
}
fn main() {}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
- |
-LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
- | ---- ---- ^ ...but data from `f` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:76
- |
-LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- | ---- ----------------- ^ ...but data from `f` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
- |
-LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
- | ------ --- ^^^ ...but data from `arg` is returned here
- | |
- | this parameter and the return type are declared with different lifetimes...
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:16:9
+ |
+LL | async fn ref_self(&self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:24:9
+ |
+LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:30:9
+ |
+LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:36:9
+ |
+LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:42:9
+ |
+LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self-async.rs:48:9
+ |
+LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:13:9
+ --> $DIR/lt-ref-self-async.rs:16:9
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:19:9
+ --> $DIR/lt-ref-self-async.rs:24:9
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:23:9
+ --> $DIR/lt-ref-self-async.rs:30:9
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:27:9
+ --> $DIR/lt-ref-self-async.rs:36:9
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:31:9
+ --> $DIR/lt-ref-self-async.rs:42:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:35:9
+ --> $DIR/lt-ref-self-async.rs:48:9
|
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
#![allow(non_snake_case)]
// Test using `&self` sugar:
async fn ref_self(&self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&Self` explicitly:
async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:13:9
- |
-LL | async fn ref_self(&self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:19:9
- |
-LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:23:9
- |
-LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:27:9
- |
-LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:31:9
- |
-LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:35:9
- |
-LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:15:9
+ |
+LL | fn ref_self(&self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:23:9
+ |
+LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:29:9
+ |
+LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:35:9
+ |
+LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:41:9
+ |
+LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/lt-ref-self.rs:47:9
+ |
+LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:11:9
+ --> $DIR/lt-ref-self.rs:15:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:17:9
+ --> $DIR/lt-ref-self.rs:23:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:21:9
+ --> $DIR/lt-ref-self.rs:29:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:25:9
+ --> $DIR/lt-ref-self.rs:35:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:29:9
+ --> $DIR/lt-ref-self.rs:41:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:33:9
+ --> $DIR/lt-ref-self.rs:47:9
|
LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
#![allow(non_snake_case)]
use std::pin::Pin;
// Test using `&self` sugar:
fn ref_self(&self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&Self` explicitly:
fn ref_Self(self: &Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:11:9
- |
-LL | fn ref_self(&self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:17:9
- |
-LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:21:9
- |
-LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:25:9
- |
-LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:29:9
- |
-LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:33:9
- |
-LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:16:9
+ |
+LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:24:9
+ |
+LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:30:9
+ |
+LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:36:9
+ |
+LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:42:9
+ |
+LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self-async.rs:48:9
+ |
+LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:13:9
+ --> $DIR/ref-mut-self-async.rs:16:9
|
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:19:9
+ --> $DIR/ref-mut-self-async.rs:24:9
|
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:23:9
+ --> $DIR/ref-mut-self-async.rs:30:9
|
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:27:9
+ --> $DIR/ref-mut-self-async.rs:36:9
|
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:31:9
+ --> $DIR/ref-mut-self-async.rs:42:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:35:9
+ --> $DIR/ref-mut-self-async.rs:48:9
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
#![allow(non_snake_case)]
// Test using `&mut self` sugar:
async fn ref_self(&mut self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&mut Self` explicitly:
async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:13:9
- |
-LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:19:9
- |
-LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:23:9
- |
-LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:27:9
- |
-LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:31:9
- |
-LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:35:9
- |
-LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:15:9
+ |
+LL | fn ref_self(&mut self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:23:9
+ |
+LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:29:9
+ |
+LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:35:9
+ |
+LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:41:9
+ |
+LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-self.rs:47:9
+ |
+LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:11:9
+ --> $DIR/ref-mut-self.rs:15:9
|
LL | fn ref_self(&mut self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:17:9
+ --> $DIR/ref-mut-self.rs:23:9
|
LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:21:9
+ --> $DIR/ref-mut-self.rs:29:9
|
LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:25:9
+ --> $DIR/ref-mut-self.rs:35:9
|
LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:29:9
+ --> $DIR/ref-mut-self.rs:41:9
|
LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:33:9
+ --> $DIR/ref-mut-self.rs:47:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
#![allow(non_snake_case)]
use std::pin::Pin;
// Test using `&mut self` sugar:
fn ref_self(&mut self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&mut Self` explicitly:
fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:11:9
- |
-LL | fn ref_self(&mut self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:17:9
- |
-LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:21:9
- |
-LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:25:9
- |
-LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:29:9
- |
-LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:33:9
- |
-LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct-async.rs:16:9
+ |
+LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct-async.rs:22:9
+ |
+LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct-async.rs:28:9
+ |
+LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct-async.rs:34:9
+ |
+LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct-async.rs:40:9
+ |
+LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:13:9
+ --> $DIR/ref-mut-struct-async.rs:16:9
|
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:17:9
+ --> $DIR/ref-mut-struct-async.rs:22:9
|
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:21:9
+ --> $DIR/ref-mut-struct-async.rs:28:9
|
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:25:9
+ --> $DIR/ref-mut-struct-async.rs:34:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:29:9
+ --> $DIR/ref-mut-struct-async.rs:40:9
|
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
#![allow(non_snake_case)]
// Test using `&mut Struct` explicitly:
async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:13:9
- |
-LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:17:9
- |
-LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:21:9
- |
-LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:25:9
- |
-LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:29:9
- |
-LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct.rs:15:9
+ |
+LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct.rs:21:9
+ |
+LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct.rs:27:9
+ |
+LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct.rs:33:9
+ |
+LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-mut-struct.rs:39:9
+ |
+LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:11:9
+ --> $DIR/ref-mut-struct.rs:15:9
|
LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:15:9
+ --> $DIR/ref-mut-struct.rs:21:9
|
LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:19:9
+ --> $DIR/ref-mut-struct.rs:27:9
|
LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:23:9
+ --> $DIR/ref-mut-struct.rs:33:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:27:9
+ --> $DIR/ref-mut-struct.rs:39:9
|
LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
#![allow(non_snake_case)]
use std::pin::Pin;
// Test using `&mut Struct` explicitly:
fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:11:9
- |
-LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:15:9
- |
-LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:19:9
- |
-LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:23:9
- |
-LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:27:9
- |
-LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:26:9
+ |
+LL | async fn ref_self(&self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:34:9
+ |
+LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:40:9
+ |
+LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:46:9
+ |
+LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:52:9
+ |
+LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:58:9
+ |
+LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self-async.rs:64:9
+ |
+LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+ | --- ---
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:23:9
+ --> $DIR/ref-self-async.rs:26:9
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:29:9
+ --> $DIR/ref-self-async.rs:34:9
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:33:9
+ --> $DIR/ref-self-async.rs:40:9
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:37:9
+ --> $DIR/ref-self-async.rs:46:9
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:41:9
+ --> $DIR/ref-self-async.rs:52:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:45:9
+ --> $DIR/ref-self-async.rs:58:9
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:49:9
+ --> $DIR/ref-self-async.rs:64:9
|
LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| - - let's call the lifetime of this reference `'1`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
#![allow(non_snake_case)]
#![feature(arbitrary_self_types)]
// Test using `&self` sugar:
async fn ref_self(&self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&Self` explicitly:
async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:23:9
- |
-LL | async fn ref_self(&self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:29:9
- |
-LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:33:9
- |
-LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:37:9
- |
-LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:41:9
- |
-LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:45:9
- |
-LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:49:9
- |
-LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- | --- ---
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:25:9
+ |
+LL | fn ref_self(&self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:33:9
+ |
+LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:39:9
+ |
+LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:45:9
+ |
+LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:51:9
+ |
+LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:57:9
+ |
+LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-self.rs:63:9
+ |
+LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+ | --- ---
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+ | ++++ ++ ++
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:21:9
+ --> $DIR/ref-self.rs:25:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:27:9
+ --> $DIR/ref-self.rs:33:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:31:9
+ --> $DIR/ref-self.rs:39:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:35:9
+ --> $DIR/ref-self.rs:45:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:39:9
+ --> $DIR/ref-self.rs:51:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:43:9
+ --> $DIR/ref-self.rs:57:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-self.rs:47:9
+ --> $DIR/ref-self.rs:63:9
|
LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| - - let's call the lifetime of this reference `'1`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
// Test using `&self` sugar:
fn ref_self(&self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
// Test using `&Self` explicitly:
fn ref_Self(self: &Self, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:21:9
- |
-LL | fn ref_self(&self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:27:9
- |
-LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:31:9
- |
-LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:35:9
- |
-LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:39:9
- |
-LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:43:9
- |
-LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-self.rs:47:9
- |
-LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- | --- ---
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
- | ++++ ++ ++
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct-async.rs:16:9
+ |
+LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct-async.rs:22:9
+ |
+LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct-async.rs:28:9
+ |
+LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct-async.rs:34:9
+ |
+LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct-async.rs:40:9
+ |
+LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:13:9
+ --> $DIR/ref-struct-async.rs:16:9
|
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:17:9
+ --> $DIR/ref-struct-async.rs:22:9
|
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:21:9
+ --> $DIR/ref-struct-async.rs:28:9
|
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:25:9
+ --> $DIR/ref-struct-async.rs:34:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:29:9
+ --> $DIR/ref-struct-async.rs:40:9
|
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
// edition:2018
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
#![allow(non_snake_case)]
// Test using `&Struct` explicitly:
async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:13:9
- |
-LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:17:9
- |
-LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:21:9
- |
-LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:25:9
- |
-LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:29:9
- |
-LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct.rs:15:9
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct.rs:21:9
+ |
+LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct.rs:27:9
+ |
+LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct.rs:33:9
+ |
+LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/ref-struct.rs:39:9
+ |
+LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+ | ---- ----
+ | |
+ | this parameter and the return type are declared with different lifetimes...
+LL | f
+ | ^ ...but data from `f` is returned here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+ |
+LL | fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+ | ++++ ++ ++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:11:9
+ --> $DIR/ref-struct.rs:15:9
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:15:9
+ --> $DIR/ref-struct.rs:21:9
|
LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:19:9
+ --> $DIR/ref-struct.rs:27:9
|
LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:23:9
+ --> $DIR/ref-struct.rs:33:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:27:9
+ --> $DIR/ref-struct.rs:39:9
|
LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
+// revisions: base nll
+// ignore-compare-mode-nll
+//[nll] compile-flags: -Z borrowck=mir
+
#![allow(non_snake_case)]
use std::pin::Pin;
// Test using `&Struct` explicitly:
fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
- f //~ ERROR lifetime mismatch
+ f
+ //[base]~^ ERROR lifetime mismatch
+ //[nll]~^^ ERROR lifetime may not live long enough
}
}
+++ /dev/null
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:11:9
- |
-LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:15:9
- |
-LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:19:9
- |
-LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:23:9
- |
-LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:27:9
- |
-LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
- | ---- ----
- | |
- | this parameter and the return type are declared with different lifetimes...
-LL | f
- | ^ ...but data from `f` is returned here
- |
- = note: each elided lifetime in input position becomes a distinct lifetime
-help: consider introducing a named lifetime parameter and update trait if needed
- |
-LL | fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
- | ++++ ++ ++
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0623`.
--> $DIR/issue-61882.rs:4:27
|
LL | const B: A<u8> = Self(0);
- | ^ expected `bool`, found integer
+ | ---- ^ expected `bool`, found integer
+ | |
+ | arguments to this function are incorrect
+ |
+note: tuple struct defined here
+ --> $DIR/issue-61882.rs:1:8
+ |
+LL | struct A<T>(T);
+ | ^
error[E0308]: mismatched types
--> $DIR/issue-61882.rs:4:22
--- /dev/null
+fn main() {
+ let f = |x| x * 3;
+ let a = f(); //~ ERROR E0057
+ let b = f(4);
+ let c = f(2, 3); //~ ERROR E0057
+}
--- /dev/null
+error[E0057]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/E0057.rs:3:13
+ |
+LL | let a = f();
+ | ^-- an argument is missing
+ |
+help: provide the argument
+ |
+LL | let a = f({_});
+ | ~~~~~~
+
+error[E0057]: this function takes 1 argument but 2 arguments were supplied
+ --> $DIR/E0057.rs:5:13
+ |
+LL | let c = f(2, 3);
+ | ^ - argument unexpected
+ |
+help: remove the extra argument
+ |
+LL | let c = f(2);
+ | ~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0057`.
--> $DIR/coerce-suggestions.rs:12:10
|
LL | test(&y);
- | ^^ types differ in mutability
+ | ---- ^^ types differ in mutability
+ | |
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut String`
found reference `&String`
+note: function defined here
+ --> $DIR/coerce-suggestions.rs:1:4
+ |
+LL | fn test(_x: &mut String) {}
+ | ^^^^ ---------------
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:14:11
|
LL | test2(&y);
- | ^^ types differ in mutability
+ | ----- ^^ types differ in mutability
+ | |
+ | arguments to this function are incorrect
|
= note: expected mutable reference `&mut i32`
found reference `&String`
+note: function defined here
+ --> $DIR/coerce-suggestions.rs:3:4
+ |
+LL | fn test2(_x: &mut i32) {}
+ | ^^^^^ ------------
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:17:9
--> $DIR/issue-34264.rs:7:5
|
LL | foo(Some(42), 2, "");
- | ^^^ -------- - -- supplied 3 arguments
- | |
- | expected 2 arguments
+ | ^^^ -- argument unexpected
|
note: function defined here
--> $DIR/issue-34264.rs:1:4
|
LL | fn foo(Option<i32>, String) {}
| ^^^ ----------- ------
+help: remove the extra argument
+ |
+LL | foo(Some(42), 2);
+ | ~~~~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-34264.rs:8:13
|
LL | bar("", "");
- | ^^ expected `usize`, found `&str`
+ | --- ^^ expected `usize`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-34264.rs:3:4
+ |
+LL | fn bar(x, y: usize) {}
+ | ^^^ - --------
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/issue-34264.rs:10:5
|
LL | bar(1, 2, 3);
- | ^^^ - - - supplied 3 arguments
- | |
- | expected 2 arguments
+ | ^^^ - argument unexpected
|
note: function defined here
--> $DIR/issue-34264.rs:3:4
|
LL | fn bar(x, y: usize) {}
| ^^^ - --------
+help: remove the extra argument
+ |
+LL | bar(1, 2);
+ | ~~~~~~~~~
error: aborting due to 6 previous errors
--> $DIR/missing-unit-argument.rs:11:33
|
LL | let _: Result<(), String> = Ok();
- | ^^-- supplied 0 arguments
+ | ^^-- an argument of type `()` is missing
|
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
|
LL | let _: Result<(), String> = Ok(());
- | ++
+ | ~~~~~~
error[E0061]: this function takes 2 arguments but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:12:5
|
LL | foo();
- | ^^^-- supplied 0 arguments
- | |
- | expected 2 arguments
+ | ^^^-- two arguments of type `()` and `()` are missing
|
note: function defined here
--> $DIR/missing-unit-argument.rs:1:4
|
LL | fn foo(():(), ():()) {}
| ^^^ ----- -----
+help: provide the arguments
+ |
+LL | foo((), ());
+ | ~~~~~~~~~~~
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/missing-unit-argument.rs:13:5
|
LL | foo(());
- | ^^^ -- supplied 1 argument
- | |
- | expected 2 arguments
+ | ^^^---- an argument of type `()` is missing
|
note: function defined here
--> $DIR/missing-unit-argument.rs:1:4
|
LL | fn foo(():(), ():()) {}
| ^^^ ----- -----
+help: provide the argument
+ |
+LL | foo((), ());
+ | ~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:14:5
|
LL | bar();
- | ^^^-- supplied 0 arguments
+ | ^^^-- an argument of type `()` is missing
|
note: function defined here
--> $DIR/missing-unit-argument.rs:2:4
|
LL | fn bar(():()) {}
| ^^^ -----
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
|
LL | bar(());
- | ++
+ | ~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:15:7
|
LL | S.baz();
- | ^^^- supplied 0 arguments
+ | ^^^-- an argument of type `()` is missing
|
note: associated function defined here
--> $DIR/missing-unit-argument.rs:6:8
|
LL | fn baz(self, (): ()) { }
| ^^^ ---- ------
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
|
LL | S.baz(());
- | ++
+ | ~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/missing-unit-argument.rs:16:7
|
LL | S.generic::<()>();
- | ^^^^^^^------ supplied 0 arguments
+ | ^^^^^^^^^^^^^-- an argument of type `()` is missing
|
note: associated function defined here
--> $DIR/missing-unit-argument.rs:7:8
|
LL | fn generic<T>(self, _: T) { }
| ^^^^^^^ ---- ----
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
|
LL | S.generic::<()>(());
- | ++
+ | ~~~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors
static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
//~| WARN: previously accepted
-//~| ERROR undefined behavior to use this value
+//~| ERROR could not evaluate static initializer
//~| WARN: type `Void` does not permit zero-initialization
static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
//~| WARN: previously accepted
-//~| ERROR undefined behavior to use this value
+//~| ERROR could not evaluate static initializer
//~| WARN: type `Void` does not permit zero-initialization
fn main() {}
= note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
= note: uninhabited statics cannot be initialized, and any access would be an immediate error
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/uninhabited-static.rs:12:1
+error[E0080]: could not evaluate static initializer
+ --> $DIR/uninhabited-static.rs:12:31
|
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
- |
- = 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: 0, align: 1) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/uninhabited-static.rs:16:1
+error[E0080]: could not evaluate static initializer
+ --> $DIR/uninhabited-static.rs:16:32
|
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Void
- |
- = 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: 0, align: 1) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
warning: the type `Void` does not permit zero-initialization
--> $DIR/uninhabited-static.rs:12:31
--> $DIR/args-instead-of-tuple-errors.rs:6:34
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
- | ^^^^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^ - - argument unexpected
+ | |
+ | expected tuple, found integer
+ |
+ = note: expected tuple `(i32, bool)`
+ found type `{integer}`
+help: remove the extra argument
+ |
+LL | let _: Option<(i32, bool)> = Some({(i32, bool)});
+ | ~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:8:5
|
LL | int_bool(1, 2);
- | ^^^^^^^^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^^^^^ - - argument unexpected
+ | |
+ | expected tuple, found integer
|
+ = note: expected tuple `(i32, bool)`
+ found type `{integer}`
note: function defined here
--> $DIR/args-instead-of-tuple-errors.rs:21:4
|
LL | fn int_bool(_: (i32, bool)) {
| ^^^^^^^^ --------------
+help: remove the extra argument
+ |
+LL | int_bool({(i32, bool)});
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:11:28
|
LL | let _: Option<(i8,)> = Some();
- | ^^^^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^^^-- an argument of type `(i8,)` is missing
+ |
+help: provide the argument
+ |
+LL | let _: Option<(i8,)> = Some({(i8,)});
+ | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:14:34
|
LL | let _: Option<(i32,)> = Some(5_usize);
- | ^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^ expected tuple, found `usize`
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected tuple `(i32,)`
found type `usize`
--> $DIR/args-instead-of-tuple-errors.rs:17:34
|
LL | let _: Option<(i32,)> = Some((5_usize));
- | ^^^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^^^ expected tuple, found `usize`
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected tuple `(i32,)`
found type `usize`
--> $DIR/args-instead-of-tuple.rs:7:36
|
LL | let _: Result<(i32, i8), ()> = Ok(1, 2);
- | ^^ - - supplied 2 arguments
+ | ^^
|
help: use parentheses to construct a tuple
|
--> $DIR/args-instead-of-tuple.rs:9:46
|
LL | let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi");
- | ^^^^ - - ---- supplied 3 arguments
+ | ^^^^
|
help: use parentheses to construct a tuple
|
--> $DIR/args-instead-of-tuple.rs:11:25
|
LL | let _: Option<()> = Some();
- | ^^^^-- supplied 0 arguments
+ | ^^^^-- an argument of type `()` is missing
|
-help: expected the unit value `()`; create it with empty parentheses
+help: provide the argument
|
LL | let _: Option<()> = Some(());
- | ++
+ | ~~~~~~~~
error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:14:34
|
LL | let _: Option<(i32,)> = Some(3);
- | ^ expected tuple, found integer
+ | ---- ^ expected tuple, found integer
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected tuple `(i32,)`
found type `{integer}`
--> $DIR/args-instead-of-tuple.rs:17:34
|
LL | let _: Option<(i32,)> = Some((3));
- | ^^^ expected tuple, found integer
+ | ---- ^^^ expected tuple, found integer
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected tuple `(i32,)`
found type `{integer}`
--> $DIR/args-instead-of-tuple.rs:20:5
|
LL | two_ints(1, 2);
- | ^^^^^^^^ - - supplied 2 arguments
+ | ^^^^^^^^
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:25:4
--> $DIR/args-instead-of-tuple.rs:22:5
|
LL | with_generic(3, 4);
- | ^^^^^^^^^^^^ - - supplied 2 arguments
+ | ^^^^^^^^^^^^
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:28:4
--> $DIR/args-instead-of-tuple.rs:31:9
|
LL | with_generic(a, b);
- | ^^^^^^^^^^^^ - - supplied 2 arguments
+ | ^^^^^^^^^^^^
|
note: function defined here
--> $DIR/args-instead-of-tuple.rs:28:4
--> $DIR/as-ref.rs:7:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- ^^^ expected `&Foo`, found struct `Foo`
- | |
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
error[E0308]: mismatched types
--> $DIR/as-ref.rs:8:39
|
LL | opt.and_then(|arg| Some(takes_ref(arg)));
- | -------- ^^^ expected `&Foo`, found struct `Foo`
- | |
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
error[E0308]: mismatched types
--> $DIR/as-ref.rs:10:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- ^^^ expected `&Foo`, found struct `Foo`
- | |
+ | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
error[E0308]: mismatched types
--> $DIR/as-ref.rs:11:37
|
LL | opt.and_then(|arg| Ok(takes_ref(arg)));
- | -------- ^^^ expected `&Foo`, found struct `Foo`
- | |
+ | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | | |
+ | | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
+ |
+note: function defined here
+ --> $DIR/as-ref.rs:3:4
+ |
+LL | fn takes_ref(_: &Foo) {}
+ | ^^^^^^^^^ -------
error[E0308]: mismatched types
--> $DIR/as-ref.rs:13:29
--> $DIR/boxed-variant-field.rs:9:31
|
LL | Ty::List(elem) => foo(elem),
- | ^^^^ expected enum `Ty`, found struct `Box`
+ | --- ^^^^ expected enum `Ty`, found struct `Box`
+ | |
+ | arguments to this function are incorrect
|
= note: expected enum `Ty`
found struct `Box<Ty>`
+note: function defined here
+ --> $DIR/boxed-variant-field.rs:6:4
+ |
+LL | fn foo(x: Ty) -> Ty {
+ | ^^^ -----
help: consider unboxing the value
|
LL | Ty::List(elem) => foo(*elem),
LL | Pin::new(x)
| -------- ^ expected struct `Box`, found type parameter `F`
| |
+ | arguments to this function are incorrect
| help: use `Box::pin` to pin and box this expression: `Box::pin`
|
= note: expected struct `Box<dyn Future<Output = i32> + Send>`
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:5
| ^^ undeclared lifetime
|
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
-help: consider introducing lifetime `'a` here
- |
-LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
- | +++
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
LL | struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
| +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F);
+ | +++
error[E0106]: missing lifetime specifier
--> $DIR/fn-missing-lifetime-in-item.rs:2:32
--- /dev/null
+fn main() {
+ let items = vec![1, 2, 3];
+ let ref_items: &[i32] = &items;
+ let items_clone: Vec<i32> = ref_items.clone();
+//~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let items_clone_2:Vec<i32> = items.clone();
+
+ let s = "hi";
+ let string: String = s.clone();
+//~^ ERROR mismatched types
+
+ // in that case no suggestion will be triggered
+ let s2 = "hi";
+ let string_2: String = s2.to_string();
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-53692.rs:4:37
+ |
+LL | let items_clone: Vec<i32> = ref_items.clone();
+ | -------- ^^^^^^^^^^^^^^^^^
+ | | |
+ | | expected struct `Vec`, found `&[i32]`
+ | | help: try using a conversion method: `ref_items.to_vec()`
+ | expected due to this
+ |
+ = note: expected struct `Vec<i32>`
+ found reference `&[i32]`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-53692.rs:11:30
+ |
+LL | let string: String = s.clone();
+ | ------ ^^^^^^^^^
+ | | |
+ | | expected struct `String`, found `&str`
+ | | help: try using a conversion method: `s.to_string()`
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
|
LL | foo((Some(3)));
- | ^^^^^^^^^ expected tuple, found enum `Option`
+ | --- ^^^^^^^^^ expected tuple, found enum `Option`
+ | |
+ | arguments to this function are incorrect
|
= note: expected tuple `(_,)`
found enum `Option<{integer}>`
+note: function defined here
+ --> $DIR/issue-86100-tuple-paren-comma.rs:5:4
+ |
+LL | fn foo<T>(_t: (T,)) {}
+ | ^^^ --------
help: use a trailing comma to create a tuple with one element
|
LL | foo((Some(3),));
--> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19
|
LL | Self::foo(None)
- | ^^^^ expected struct `Box`, found enum `Option`
+ | --------- ^^^^ expected struct `Box`, found enum `Option`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Box<Option<S>>`
found enum `Option<_>`
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+note: associated function defined here
+ --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:7:8
+ |
+LL | fn foo(_: Box<Option<S>>) {}
+ | ^^^ -----------------
help: store this in the heap by calling `Box::new`
|
LL | Self::foo(Box::new(None))
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/missing-lifetimes-in-signature-2.rs:20:5
|
+LL | fn func<T: Test>(foo: &Foo, t: T) {
+ | -- help: consider adding an explicit lifetime bound...: `T: 'a +`
LL | / foo.bar(move |_| {
LL | |
LL | | t.test();
|
LL | fn func<T: Test>(foo: &Foo, t: T) {
| ^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature-2.rs:20:5
+ |
+LL | / foo.bar(move |_| {
+LL | |
+LL | | t.test();
+LL | | });
+ | |______^
error: aborting due to previous error
--- /dev/null
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/missing-lifetimes-in-signature.rs:38:11
+ |
+LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `'a,`
+
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:19:5
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+ | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
+...
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:32:5
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:26:26
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:32:5
+ |
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:55:5
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | -- help: consider adding an explicit lifetime bound...: `G: 'b +`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:49:34
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:55:5
+ |
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:65:9
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | -- help: consider adding an explicit lifetime bound...: `G: 'c +`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_________^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:62:47
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:65:9
+ |
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_________^
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:77:5
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | -- help: consider adding an explicit lifetime bound...: `G: 'b +`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:72:34
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ^^^^^^
+note: ...so that the type `G` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:77:5
+ |
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+
+error[E0621]: explicit lifetime required in the type of `dest`
+ --> $DIR/missing-lifetimes-in-signature.rs:77:5
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^ lifetime `'a` required
+
+error[E0309]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:89:5
+ |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+ | - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | / move || {
+LL | | *dest = g.get();
+LL | | }
+ | |_____^ ...so that the type `G` will meet its required lifetime bounds
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0261, E0309, E0621, E0700.
+For more information about an error, try `rustc --explain E0261`.
fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
where
- G: Get<T>
+ G: Get<T>,
{
move || {
+ //~^ ERROR hidden type for `impl Trait` captures lifetime
*dest = g.get();
}
}
// After applying suggestion for `foo`:
fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
where
- G: Get<T>
+ G: Get<T>,
{
+ //~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
}
-
// After applying suggestion for `bar`:
-fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime
+fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR undeclared lifetime name `'a`
where
- G: Get<T>
+ G: Get<T>,
{
move || {
*dest = g.get();
// After applying suggestion for `baz`:
fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
where
- G: Get<T>
+ G: Get<T>,
{
+ //~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
// Same as above, but show that we pay attention to lifetime names from parent item
impl<'a> Foo {
fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ //~^ ERROR the parameter type `G` may not live long enough
+ //~| ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
// After applying suggestion for `qux`:
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+//~^ ERROR explicit lifetime required in the type of `dest`
where
- G: Get<T>
+ G: Get<T>,
{
move || {
*dest = g.get();
// Potential incorrect attempt:
fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+//~^ ERROR the parameter type `G` may not live long enough
where
- G: Get<T>
+ G: Get<T>,
{
+ //~^ ERROR the parameter type `G` may not live long enough
move || {
*dest = g.get();
}
}
-
// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
where
- G: Get<T>
+ G: Get<T>,
{
move || {
*dest = g.get();
// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
where
- G: Get<T>
+ G: Get<T>,
{
move || {
*dest = g.get();
error[E0261]: use of undeclared lifetime name `'a`
- --> $DIR/missing-lifetimes-in-signature.rs:36:11
+ --> $DIR/missing-lifetimes-in-signature.rs:38:11
|
LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| - ^^ undeclared lifetime
| |
| help: consider introducing lifetime `'a` here: `'a,`
-error: aborting due to previous error
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:19:5
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+ | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 22:6]` captures the anonymous lifetime defined here
+...
+LL | / move || {
+LL | |
+LL | | *dest = g.get();
+LL | | }
+ | |_____^
+ |
+help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+ |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:26:37
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:26:26
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:26:37
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+ |
+LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ~~~~~ ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:30:1
+ |
+LL | / {
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:26:26
+ |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:32:5: 34:6]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:30:1
+ |
+LL | / {
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_^
+help: consider introducing an explicit lifetime bound
+ |
+LL ~ fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL |
+LL | where
+LL | G: Get<T>,
+LL | {
+LL |
+ ...
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:49:45
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:49:34
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:49:45
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+ |
+LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
+ | +++ ~~~~~~~ ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:53:1
+ |
+LL | / {
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:49:34
+ |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:55:5: 57:6]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:53:1
+ |
+LL | / {
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_^
+help: consider introducing an explicit lifetime bound
+ |
+LL ~ fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL |
+LL | where
+LL | G: Get<T>,
+LL | {
+LL |
+ ...
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:62:58
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:62:47
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:62:58
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+ |
+LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
+ | +++ ~~~~~~~ ++++
+
+error[E0311]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:62:77
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | _____________________________________________________________________________^
+LL | |
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_____^
+ |
+note: the parameter type `G` must be valid for the anonymous lifetime defined here...
+ --> $DIR/missing-lifetimes-in-signature.rs:62:47
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | ^^^^^^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:65:9: 67:10]` will meet its required lifetime bounds
+ --> $DIR/missing-lifetimes-in-signature.rs:62:77
+ |
+LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+ | _____________________________________________________________________________^
+LL | |
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_____^
+help: consider introducing an explicit lifetime bound
+ |
+LL ~ fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+LL |
+LL |
+LL | move || {
+LL | *dest = g.get();
+LL | }
+ ...
+
+error[E0621]: explicit lifetime required in the type of `dest`
+ --> $DIR/missing-lifetimes-in-signature.rs:72:45
+ |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
+ | |
+ | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+
+error[E0309]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:83:44
+ |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+ | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
+ | |
+ | help: consider adding an explicit lifetime bound...: `G: 'a`
+
+error[E0309]: the parameter type `G` may not live long enough
+ --> $DIR/missing-lifetimes-in-signature.rs:87:1
+ |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+ | - help: consider adding an explicit lifetime bound...: `G: 'a`
+...
+LL | / {
+LL | |
+LL | | move || {
+LL | | *dest = g.get();
+LL | | }
+LL | | }
+ | |_^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:89:5: 91:6]` will meet its required lifetime bounds
+
+error: aborting due to 11 previous errors
-For more information about this error, try `rustc --explain E0261`.
+Some errors have detailed explanations: E0261, E0309, E0621, E0700.
+For more information about an error, try `rustc --explain E0261`.
--- /dev/null
+use std::ops::Deref;
+
+struct Foo {
+ v: Vec<u32>,
+}
+
+struct Bar {
+ v: Vec<u32>,
+}
+
+impl Deref for Bar {
+ type Target = Vec<u32>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.v
+ }
+}
+
+fn f(foo: &Foo) {
+ match foo {
+ Foo { v: [1, 2] } => {}
+ //~^ ERROR expected an array or slice, found `Vec<u32>
+ _ => {}
+ }
+}
+
+fn bar(bar: &Bar) {
+ match bar {
+ Bar { v: [1, 2] } => {}
+ //~^ ERROR expected an array or slice, found `Vec<u32>
+ _ => {}
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0529]: expected an array or slice, found `Vec<u32>`
+ --> $DIR/pattern-struct-with-slice-vec-field.rs:21:18
+ |
+LL | Foo { v: [1, 2] } => {}
+ | ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error[E0529]: expected an array or slice, found `Vec<u32>`
+ --> $DIR/pattern-struct-with-slice-vec-field.rs:29:18
+ |
+LL | Bar { v: [1, 2] } => {}
+ | ^^^^^^ pattern cannot match with input type `Vec<u32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0529`.
--> $DIR/recover-from-semicolon-trailing-item.rs:14:9
|
LL | foo("");
- | ^^ expected `usize`, found `&str`
+ | --- ^^ expected `usize`, found `&str`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/recover-from-semicolon-trailing-item.rs:6:4
+ |
+LL | fn foo(a: usize) {};
+ | ^^^ --------
error: aborting due to 6 previous errors
error[E0310]: the parameter type `impl Debug` may not live long enough
--> $DIR/suggest-impl-trait-lifetime.rs:7:5
|
+LL | fn foo(d: impl Debug) {
+ | ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static`
+LL |
LL | bar(d);
- | ^^^^^^
- |
- = help: consider adding an explicit lifetime bound `impl Debug: 'static`...
+ | ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds
error: aborting due to previous error
--> $DIR/suggest-ref-macro.rs:15:11
|
LL | x(123);
- | ^^^
- | |
- | expected `&mut i32`, found integer
- | help: consider mutably borrowing here: `&mut 123`
+ | - ^^^
+ | | |
+ | | expected `&mut i32`, found integer
+ | | help: consider mutably borrowing here: `&mut 123`
+ | arguments to this function are incorrect
...
LL | bla!();
| ------ in this macro invocation
|
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:11:4
+ |
+LL | fn x(_: &mut i32) {}
+ | ^ -----------
= note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/suggest-ref-macro.rs:26:10
|
+LL | x($v)
+ | - arguments to this function are incorrect
+...
LL | bla!(456);
| ^^^
| |
| expected `&mut i32`, found integer
| help: consider mutably borrowing here: `&mut 456`
+ |
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:11:4
+ |
+LL | fn x(_: &mut i32) {}
+ | ^ -----------
error[E0308]: mismatched types
--> $DIR/suggest-ref-macro.rs:8:1
|
LL | #[hello]
- | ^^^^^^^^ expected `&mut i32`, found integer
+ | ^^^^^^^^
+ | |
+ | expected `&mut i32`, found integer
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/suggest-ref-macro.rs:8:1
|
+LL | #[hello]
+ | _-^^^^^^^
+LL | | fn abc() {}
+LL | |
+LL | | fn x(_: &mut i32) {}
+LL | |
+LL | | macro_rules! bla {
+ | |_____________-
= note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait<A = usize>, _: T) {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait>::A` to `usize`
|
LL | fn ban<T>(x: T) where T: Trait<A = usize> {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait<A = usize>, _: T) {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait>::A` to `usize`
|
LL | fn bar<T: Trait<A = usize>>(x: T) {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
|
LL | fn foo2(x: impl Trait<i32, A = usize>) {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
|
LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
--> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait>::A` to `usize`
|
LL | fn ban<T>(x: T) where T: Trait<A = usize> {
--> $DIR/trait-with-missing-associated-type-restriction.rs:14:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo(_: impl Trait, x: impl Trait<A = usize>) {
--> $DIR/trait-with-missing-associated-type-restriction.rs:18:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait>::A` to `usize`
|
LL | fn bar<T: Trait<A = usize>>(x: T) {
--> $DIR/trait-with-missing-associated-type-restriction.rs:22:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<impl Trait<i32> as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<impl Trait<i32> as Trait<i32>>::A` to `usize`
|
LL | fn foo2(x: impl Trait<i32, A = usize>) {
--> $DIR/trait-with-missing-associated-type-restriction.rs:26:12
|
LL | x.funk(3);
- | ^ expected associated type, found integer
+ | ---- ^ expected associated type, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected associated type `<T as Trait<i32>>::A`
found type `{integer}`
LL | fn funk(&self, _: Self::A);
LL | fn funq(&self) -> Self::A {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq`
+note: associated function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
+ |
+LL | fn funk(&self, _: Self::A);
+ | ^^^^
help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
|
LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
--> $DIR/trait-with-missing-associated-type-restriction.rs:27:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait<i32>>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait<i32>>::A` to `usize`
|
LL | fn bar2<T: Trait<i32, A = usize>>(x: T) {
LL | fn baz<D: std::fmt::Debug, T: Trait<A = D>>(x: T) {
| - this type parameter
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found type parameter `D`
+ | --- ^^^^^^^^ expected `usize`, found type parameter `D`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found type parameter `D`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
error[E0308]: mismatched types
--> $DIR/trait-with-missing-associated-type-restriction.rs:35:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found `()`
+ | --- ^^^^^^^^ expected `usize`, found `()`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
error[E0308]: mismatched types
--> $DIR/trait-with-missing-associated-type-restriction.rs:39:9
|
LL | qux(x.func())
- | ^^^^^^^^ expected `usize`, found associated type
+ | --- ^^^^^^^^ expected `usize`, found associated type
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found associated type `<T as Trait>::A`
+note: function defined here
+ --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4
+ |
+LL | fn qux(_: usize) {}
+ | ^^^ --------
help: consider constraining the associated type `<T as Trait>::A` to `usize`
|
LL | fn ban<T>(x: T) where T: Trait<A = usize> {
--> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
|
LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
- | ^ ------------ help: remove these generic arguments
- | |
- | expected 2 generic arguments
+ | ^ expected 2 generic arguments
|
note: trait defined here, with 2 generic parameters: `X`, `Y`
--> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11
|
LL | pub trait T<X, Y> {
| ^ - -
+help: replace the generic bounds with the associated types
+ |
+LL | i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
+ | ~~~~~~~~~ ~~~~~~~~~
error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified
--> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
...
LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified
- |
-help: specify the associated types
- |
-LL | i: Box<dyn T<usize, usize, A = usize, C = usize, B=usize>>,
- | ~~~~~~~~~ ~~~~~~~~~
error: aborting due to 2 previous errors
fn main() {
let _: () = 42;
- //~^ ERROR mismatched types
+ //~^ ERROR arguments to this function are incorrect
}
--> $DIR/terr-in-field.rs:13:14
|
LL | want_foo(b);
- | ^ expected struct `Foo`, found struct `Bar`
+ | -------- ^ expected struct `Foo`, found struct `Bar`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/terr-in-field.rs:11:4
+ |
+LL | fn want_foo(f: Foo) {}
+ | ^^^^^^^^ ------
error: aborting due to previous error
--> $DIR/terr-sorts.rs:10:14
|
LL | want_foo(b);
- | ^ expected struct `Foo`, found struct `Box`
+ | -------- ^ expected struct `Foo`, found struct `Box`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo`
found struct `Box<Foo>`
+note: function defined here
+ --> $DIR/terr-sorts.rs:8:4
+ |
+LL | fn want_foo(f: Foo) {}
+ | ^^^^^^^^ ------
help: consider unboxing the value
|
LL | want_foo(*b);
--- /dev/null
+// Check that #[thread_local] attribute is rejected on non-static items.
+#![feature(thread_local)]
+
+#[thread_local]
+//~^ ERROR attribute should be applied to a static
+const A: u32 = 0;
+
+#[thread_local]
+//~^ ERROR attribute should be applied to a static
+fn main() {
+ #[thread_local] || {};
+ //~^ ERROR attribute should be applied to a static
+}
+
+struct S {
+ #[thread_local]
+ //~^ ERROR attribute should be applied to a static
+ a: String,
+ b: String,
+}
+
+#[thread_local]
+// Static. OK.
+static B: u32 = 0;
+
+extern "C" {
+ #[thread_local]
+ // Foreign static. OK.
+ static C: u32;
+}
--- /dev/null
+error: attribute should be applied to a static
+ --> $DIR/non-static.rs:4:1
+ |
+LL | #[thread_local]
+ | ^^^^^^^^^^^^^^^
+LL |
+LL | const A: u32 = 0;
+ | ----------------- not a static
+
+error: attribute should be applied to a static
+ --> $DIR/non-static.rs:8:1
+ |
+LL | #[thread_local]
+ | ^^^^^^^^^^^^^^^
+LL |
+LL | / fn main() {
+LL | | #[thread_local] || {};
+LL | |
+LL | | }
+ | |_- not a static
+
+error: attribute should be applied to a static
+ --> $DIR/non-static.rs:11:5
+ |
+LL | #[thread_local] || {};
+ | ^^^^^^^^^^^^^^^ ----- not a static
+
+error: attribute should be applied to a static
+ --> $DIR/non-static.rs:16:5
+ |
+LL | #[thread_local]
+ | ^^^^^^^^^^^^^^^
+LL |
+LL | a: String,
+ | --------- not a static
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+
+struct Foo;
+
+impl Drop for Foo {
+ fn drop(&mut self) {
+ println!("test2");
+ }
+}
+
+thread_local!(static FOO: Foo = Foo);
+
+fn main() {
+ // Off the main thread due to #28129, be sure to initialize FOO first before
+ // calling `println!`
+ thread::spawn(|| {
+ FOO.with(|_| {});
+ println!("test1");
+ }).join().unwrap();
+}
--> $DIR/sugar.rs:12:7
|
LL | a(x);
- | ^ expected trait `Foo + Send`, found trait `Foo + Sync`
+ | - ^ expected trait `Foo + Send`, found trait `Foo + Sync`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Box<(dyn Foo + Send + 'static)>`
found struct `Box<(dyn Foo + Sync + 'static)>`
+note: function defined here
+ --> $DIR/sugar.rs:5:4
+ |
+LL | fn a(_x: Box<dyn Foo + Send>) {
+ | ^ -----------------------
error: aborting due to previous error
LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: required because it appears within the type `*const SalsaStorage`
+ = note: required because it appears within the type `PhantomData<SalsaStorage>`
= note: required because it appears within the type `Unique<SalsaStorage>`
= note: required because it appears within the type `Box<SalsaStorage>`
note: required because it appears within the type `Runtime<RootDatabase>`
--- /dev/null
+// run-pass
+#![allow(unused)]
+
+fn main() {
+}
+
+fn foo() {
+ let b = mk::<
+ Forward<(Box<dyn Future<Error = u32>>,)>,
+ >();
+ b.map_err(|_| ()).join();
+}
+
+fn mk<T>() -> T {
+ loop {}
+}
+
+impl<I: Future<Error = E>, E> Future for (I,) {
+ type Error = E;
+}
+
+struct Forward<T: Future> {
+ _a: T,
+}
+
+impl<T: Future> Future for Forward<T>
+where
+ T::Error: From<u32>,
+{
+ type Error = T::Error;
+}
+
+trait Future {
+ type Error;
+
+ fn map_err<F, E>(self, _: F) -> (Self, F)
+ where
+ F: FnOnce(Self::Error) -> E,
+ Self: Sized,
+ {
+ loop {}
+ }
+
+ fn join(self) -> (MaybeDone<Self>, ())
+ where
+ Self: Sized,
+ {
+ loop {}
+ }
+}
+
+impl<S: ?Sized + Future> Future for Box<S> {
+ type Error = S::Error;
+}
+
+enum MaybeDone<A: Future> {
+ _Done(A::Error),
+}
+
+impl<U, A: Future, F> Future for (A, F)
+where
+ F: FnOnce(A::Error) -> U,
+{
+ type Error = U;
+}
| - this type parameter
...
LL | builder.push(output);
- | ^^^^^^ expected type parameter `F`, found struct `Class`
+ | ---- ^^^^^^ expected type parameter `F`, found struct `Class`
+ | |
+ | arguments to this function are incorrect
|
- = note: expected type parameter `F`
- found struct `Class<P>`
+ = note: expected type `F`
+ found struct `Class<P>`
+note: associated function defined here
+ --> $DIR/issue-52893.rs:11:8
+ |
+LL | fn push(self, other: T) -> Self::PushRes;
+ | ^^^^
error: aborting due to previous error
--- /dev/null
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::marker::Unsize;
+use std::ops::DispatchFromDyn;
+
+#[allow(unused)]
+struct Foo<'a, T: ?Sized> {
+ _inner: &'a &'a T,
+}
+
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
+//~| NOTE all implementations of `Unsize` are provided automatically by the compiler
+//~| NOTE required because of the requirements on the impl
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied
+ --> $DIR/issue-71036.rs:11:1
+ |
+LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
+ |
+ = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
+ = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--> $DIR/multidispatch-bad.rs:19:17
|
LL | test(22i32, 44i32);
- | ^^^^^ expected `u32`, found `i32`
+ | ---- ^^^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
|
+note: function defined here
+ --> $DIR/multidispatch-bad.rs:13:4
+ |
+LL | fn test<T,U>(_: T, _: U)
+ | ^^^^ ---- ----
help: change the type of the numeric literal from `i32` to `u32`
|
LL | test(22i32, 44u32);
--> $DIR/tuple-arity-mismatch.rs:6:20
|
LL | let y = first ((1,2.0,3));
- | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+ | ----- ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+ | |
+ | arguments to this function are incorrect
|
= note: expected tuple `(isize, f64)`
found tuple `(isize, f64, {integer})`
+note: function defined here
+ --> $DIR/tuple-arity-mismatch.rs:3:4
+ |
+LL | fn first((value, _): (isize, f64)) -> isize { value }
+ | ^^^^^ ------------------------
error[E0308]: mismatched types
--> $DIR/tuple-arity-mismatch.rs:12:20
|
LL | let y = first ((1,));
- | ^^^^ expected a tuple with 2 elements, found one with 1 element
+ | ----- ^^^^ expected a tuple with 2 elements, found one with 1 element
+ | |
+ | arguments to this function are incorrect
|
= note: expected tuple `(isize, f64)`
found tuple `(isize,)`
+note: function defined here
+ --> $DIR/tuple-arity-mismatch.rs:3:4
+ |
+LL | fn first((value, _): (isize, f64)) -> isize { value }
+ | ^^^^^ ------------------------
error: aborting due to 2 previous errors
--> $DIR/wrong_argument_ice-2.rs:13:5
|
LL | test(x.qux(), x.qux());
- | ^^^^ ------- ------- supplied 2 arguments
+ | ^^^^
|
note: function defined here
--> $DIR/wrong_argument_ice-2.rs:1:4
--> $DIR/wrong_argument_ice-3.rs:9:16
|
LL | groups.push(new_group, vec![process]);
- | ^^^^ --------- ------------- supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^ --------- ------------- argument unexpected
+ | |
+ | expected tuple, found struct `Vec`
|
+ = note: expected tuple `(Vec<String>, Vec<Process>)`
+ 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>)});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
|
LL | (|| {})(|| {
| _____^^^^^^^_-
- | | |
- | | expected 0 arguments
LL | |
LL | | let b = 1;
LL | | });
- | |_____- supplied 1 argument
+ | |_____- argument unexpected
+ |
+help: remove the extra argument
+ |
+LL | (|| {})();
+ | ~~~~~~~~~
error: aborting due to previous error
--> $DIR/wrong_argument_ice.rs:11:18
|
LL | self.acc.push_back(self.current_provides, self.current_requires);
- | ^^^^^^^^^ --------------------- --------------------- supplied 2 arguments
+ | ^^^^^^^^^
|
note: associated function defined here
--> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
| - this type parameter
LL | fn ts_variant() {
LL | Self::TSVariant(());
- | ^^ expected type parameter `T`, found `()`
+ | --------------- ^^ expected type parameter `T`, found `()`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found unit type `()`
+note: tuple variant defined here
+ --> $DIR/enum-variant-generic-args.rs:7:16
+ |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+ | ^^^^^^^^^
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:15:27
| - this type parameter
...
LL | Self::<()>::TSVariant(());
- | ^^ expected type parameter `T`, found `()`
+ | --------------------- ^^ expected type parameter `T`, found `()`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type parameter `T`
found unit type `()`
+note: tuple variant defined here
+ --> $DIR/enum-variant-generic-args.rs:7:16
+ |
+LL | enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
+ | ^^^^^^^^^
error[E0109]: type arguments are not allowed for this type
--> $DIR/enum-variant-generic-args.rs:20:16
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
|
LL | <E>::V();
- | ^^^^^^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^^^^^-- an argument of type `u8` is missing
|
note: tuple variant defined here
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
|
LL | V(u8)
| ^
+help: provide the argument
+ |
+LL | <E>::V({u8});
+ | ~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generic_type_does_not_live_long_enough.rs:18:5
|
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | t
- | ^
- |
- = help: consider adding an explicit lifetime bound `T: 'static`...
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error: aborting due to 3 previous errors
trait Animal { }
fn main() {
- pub type ServeFut = /*impl Trait*/;
+ type ServeFut = /*impl Trait*/;
}
//~^ ERROR use of undeclared lifetime name `'a`
fn my_fun() -> Return<()> {}
+//~^ ERROR non-defining opaque type use in defining scope
+//~| ERROR non-defining opaque type use in defining scope
fn main() {}
--> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
|
LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
- | - ^^ undeclared lifetime
- | |
- | help: consider introducing lifetime `'a` here: `'a,`
+ | ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | type Return<A> = impl for<'a> WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+ | +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+ | +++
+
+error: non-defining opaque type use in defining scope
+ --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
+ |
+LL | fn my_fun() -> Return<()> {}
+ | ^^
+ |
+note: used non-generic type `()` for generic parameter
+ --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
+ |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+ | ^
+
+error: non-defining opaque type use in defining scope
+ --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27
+ |
+LL | fn my_fun() -> Return<()> {}
+ | ^^
+ |
+note: used non-generic type `()` for generic parameter
+ --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13
+ |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+ | ^
-error: aborting due to previous error
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0261`.
--> $DIR/type-ascription-instead-of-initializer.rs:2:12
|
LL | let x: Vec::with_capacity(10, 20);
- | ^^^^^^^^^^^^^^^^^^ -- -- supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^^^^^^^^^^^^^^^ -- argument unexpected
|
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);
+ | ~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
--> $DIR/type-mismatch-same-crate-name.rs:16:20
|
LL | a::try_foo(foo2);
- | ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+ | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: perhaps two different versions of crate `crate_a1` are being used?
+note: function defined here
+ --> $DIR/auxiliary/crate_a1.rs:10:8
+ |
+LL | pub fn try_foo(x: Foo){}
+ | ^^^^^^^
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:20:20
|
LL | a::try_bar(bar2);
- | ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
+ | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Box<(dyn main::a::Bar + 'static)>`
found struct `Box<dyn main::a::Bar>`
= note: perhaps two different versions of crate `crate_a1` are being used?
+note: function defined here
+ --> $DIR/auxiliary/crate_a1.rs:11:8
+ |
+LL | pub fn try_bar(x: Box<Bar>){}
+ | ^^^^^^^
error: aborting due to 2 previous errors
--> $DIR/type-mismatch.rs:17:17
|
LL | want::<foo>(f);
- | ^ expected struct `foo`, found `usize`
+ | ----------- ^ expected struct `foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:18:17
|
LL | want::<bar>(f);
- | ^ expected struct `bar`, found `usize`
+ | ----------- ^ expected struct `bar`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:19:24
|
LL | want::<Foo<usize>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | ------------------ ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:20:27
|
LL | want::<Foo<usize, B>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | --------------------- ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, B>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:21:22
|
LL | want::<Foo<foo>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<foo>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:22:25
|
LL | want::<Foo<foo, B>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<foo, B>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:23:22
|
LL | want::<Foo<bar>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:24:25
|
LL | want::<Foo<bar, B>>(f);
- | ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected struct `Foo`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, B>`
found type `usize`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:28:19
|
LL | want::<usize>(f);
- | ^ expected `usize`, found struct `foo`
+ | ------------- ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:29:17
|
LL | want::<bar>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ----------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:30:24
|
LL | want::<Foo<usize>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | ------------------ ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:31:27
|
LL | want::<Foo<usize, B>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | --------------------- ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, B>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:32:22
|
LL | want::<Foo<foo>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<foo>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:33:25
|
LL | want::<Foo<foo, B>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<foo, B>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:34:22
|
LL | want::<Foo<bar>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:35:25
|
LL | want::<Foo<bar, B>>(f);
- | ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, B>`
found struct `foo`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:39:19
|
LL | want::<usize>(f);
- | ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:40:17
|
LL | want::<foo>(f);
- | ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected struct `foo`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `foo`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:41:17
|
LL | want::<bar>(f);
- | ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected struct `bar`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `bar`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:42:24
|
LL | want::<Foo<usize>>(f);
- | ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize>`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:43:27
|
LL | want::<Foo<usize, B>>(f);
- | ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, B>`
found struct `Foo<foo, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:44:25
|
LL | want::<Foo<foo, B>>(f);
- | ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected struct `B`, found struct `A`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<_, B>`
found struct `Foo<_, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:45:22
|
LL | want::<Foo<bar>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar>`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:46:25
|
LL | want::<Foo<bar, B>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, B>`
found struct `Foo<foo, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:47:23
|
LL | want::<&Foo<foo>>(f);
- | ^
- | |
- | expected `&Foo<foo>`, found struct `Foo`
- | help: consider borrowing here: `&f`
+ | ----------------- ^
+ | | |
+ | | expected `&Foo<foo>`, found struct `Foo`
+ | | help: consider borrowing here: `&f`
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo>`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:48:26
|
LL | want::<&Foo<foo, B>>(f);
- | ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo, B>`
found struct `Foo<foo>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:52:19
|
LL | want::<usize>(f);
- | ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:53:17
|
LL | want::<foo>(f);
- | ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected struct `foo`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `foo`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:54:17
|
LL | want::<bar>(f);
- | ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected struct `bar`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `bar`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:55:24
|
LL | want::<Foo<usize>>(f);
- | ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, A>`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:56:27
|
LL | want::<Foo<usize, B>>(f);
- | ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, _>`
found struct `Foo<foo, _>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:57:22
|
LL | want::<Foo<foo>>(f);
- | ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected struct `A`, found struct `B`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<_, A>`
found struct `Foo<_, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:58:22
|
LL | want::<Foo<bar>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, A>`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:59:25
|
LL | want::<Foo<bar, B>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, _>`
found struct `Foo<foo, _>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:60:23
|
LL | want::<&Foo<foo>>(f);
- | ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo>`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:61:26
|
LL | want::<&Foo<foo, B>>(f);
- | ^
- | |
- | expected `&Foo<foo, B>`, found struct `Foo`
- | help: consider borrowing here: `&f`
+ | -------------------- ^
+ | | |
+ | | expected `&Foo<foo, B>`, found struct `Foo`
+ | | help: consider borrowing here: `&f`
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo, B>`
found struct `Foo<foo, B>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:65:19
|
LL | want::<usize>(f);
- | ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected type `usize`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:66:17
|
LL | want::<foo>(f);
- | ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected struct `foo`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `foo`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:67:17
|
LL | want::<bar>(f);
- | ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected struct `bar`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `bar`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:68:24
|
LL | want::<Foo<usize>>(f);
- | ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, A, B>`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:69:27
|
LL | want::<Foo<usize, B>>(f);
- | ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `usize`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<usize, _, B>`
found struct `Foo<foo, _, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:70:22
|
LL | want::<Foo<foo>>(f);
- | ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected struct `A`, found struct `B`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<_, A, B>`
found struct `Foo<_, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:71:25
|
LL | want::<Foo<foo, B>>(f);
- | ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected struct `B`, found struct `A`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<_, _, B>`
found struct `Foo<_, _, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:72:22
|
LL | want::<Foo<bar>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, A, B>`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:73:25
|
LL | want::<Foo<bar, B>>(f);
- | ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected struct `bar`, found struct `foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected struct `Foo<bar, _, B>`
found struct `Foo<foo, _, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:74:23
|
LL | want::<&Foo<foo>>(f);
- | ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo>`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:75:26
|
LL | want::<&Foo<foo, B>>(f);
- | ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | |
+ | arguments to this function are incorrect
|
= note: expected reference `&Foo<foo, B>`
found struct `Foo<foo, B, A>`
+note: function defined here
+ --> $DIR/type-mismatch.rs:14:4
+ |
+LL | fn want<T>(t: T) {}
+ | ^^^^ ----
error: aborting due to 47 previous errors
--> $DIR/issue-46112.rs:9:21
|
LL | fn main() { test(Ok(())); }
- | ^^ expected enum `Option`, found `()`
+ | -- ^^ expected enum `Option`, found `()`
+ | |
+ | arguments to this enum variant are incorrect
|
= note: expected enum `Option<()>`
found unit type `()`
--> $DIR/issue-84768.rs:7:42
|
LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
- | ^ expected tuple, found integer
+ | --------------------------------- ^ expected tuple, found integer
+ | |
+ | arguments to this function are incorrect
|
= note: expected tuple `(&mut u8,)`
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
--> $DIR/issue-89856.rs:6:20
|
LL | take_str_maybe(option);
- | ^^^^^^ expected `str`, found struct `String`
+ | -------------- ^^^^^^ expected `str`, found struct `String`
+ | |
+ | arguments to this function are incorrect
|
= note: expected enum `Option<&str>`
found enum `Option<&String>`
+note: function defined here
+ --> $DIR/issue-89856.rs:1:4
+ |
+LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+ | ^^^^^^^^^^^^^^ ---------------
help: try converting the passed type into a `&str`
|
LL | take_str_maybe(option.map(|x| &**x));
--> $DIR/struct-enum-wrong-args.rs:6:13
|
LL | let _ = Some(3, 2);
- | ^^^^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^ - argument unexpected
+ |
+help: remove the extra argument
+ |
+LL | let _ = Some(3);
+ | ~~~~~~~
error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:7:13
|
LL | let _ = Ok(3, 6, 2);
- | ^^ - - - supplied 3 arguments
- | |
- | expected 1 argument
+ | ^^ - - argument unexpected
+ | |
+ | argument unexpected
+ |
+help: remove the extra arguments
+ |
+LL | let _ = Ok(3);
+ | ~~~~~
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:8:13
|
LL | let _ = Ok();
- | ^^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^-- an argument is missing
+ |
+help: provide the argument
+ |
+LL | let _ = Ok({_});
+ | ~~~~~~~
error[E0061]: this struct takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:9:13
|
LL | let _ = Wrapper();
- | ^^^^^^^-- supplied 0 arguments
- | |
- | expected 1 argument
+ | ^^^^^^^-- an argument of type `i32` is missing
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:2:8
|
LL | struct Wrapper(i32);
| ^^^^^^^
+help: provide the argument
+ |
+LL | let _ = Wrapper({i32});
+ | ~~~~~~~~~~~~~~
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:10:13
|
LL | let _ = Wrapper(5, 2);
- | ^^^^^^^ - - supplied 2 arguments
- | |
- | expected 1 argument
+ | ^^^^^^^ - argument unexpected
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:2:8
|
LL | struct Wrapper(i32);
| ^^^^^^^
+help: remove the extra argument
+ |
+LL | let _ = Wrapper(5);
+ | ~~~~~~~~~~
error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:11:13
|
LL | let _ = DoubleWrapper();
- | ^^^^^^^^^^^^^-- supplied 0 arguments
- | |
- | expected 2 arguments
+ | ^^^^^^^^^^^^^-- two arguments of type `i32` and `i32` are missing
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:3:8
|
LL | struct DoubleWrapper(i32, i32);
| ^^^^^^^^^^^^^
+help: provide the arguments
+ |
+LL | let _ = DoubleWrapper({i32}, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this struct takes 2 arguments but 1 argument was supplied
--> $DIR/struct-enum-wrong-args.rs:12:13
|
LL | let _ = DoubleWrapper(5);
- | ^^^^^^^^^^^^^ - supplied 1 argument
- | |
- | expected 2 arguments
+ | ^^^^^^^^^^^^^--- an argument of type `i32` is missing
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:3:8
|
LL | struct DoubleWrapper(i32, i32);
| ^^^^^^^^^^^^^
+help: provide the argument
+ |
+LL | let _ = DoubleWrapper(5, {i32});
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:13:13
|
LL | let _ = DoubleWrapper(5, 2, 7);
- | ^^^^^^^^^^^^^ - - - supplied 3 arguments
- | |
- | expected 2 arguments
+ | ^^^^^^^^^^^^^ - argument unexpected
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:3:8
|
LL | struct DoubleWrapper(i32, i32);
| ^^^^^^^^^^^^^
+help: remove the extra argument
+ |
+LL | let _ = DoubleWrapper(5, 2);
+ | ~~~~~~~~~~~~~~~~~~~
error: aborting due to 8 previous errors
LL | impl DefaultedTrait for Box<C> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate
-error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:22:1
|
LL | impl DefaultedTrait for lib::Something<C> { }
impl Clone for Test9 {
fn clone(&self) -> _ { Test9 }
- //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
fn clone_from(&mut self, other: _) { *self = Test9; }
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
impl Clone for FnTest9 {
fn clone(&self) -> _ { FnTest9 }
- //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
fn clone_from(&mut self, other: _) { *self = FnTest9; }
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
LL | fn test10<T>(&self, _x : T) { }
| +++ ~
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/typeck_type_placeholder_item.rs:59:24
|
LL | fn clone(&self) -> _ { Test9 }
- | ^
- | |
- | not allowed in type signatures
- | help: replace with the correct return type: `Test9`
+ | ^ not allowed in type signatures
+ |
+help: try replacing `_` with the type in the corresponding trait method signature
+ |
+LL | fn clone(&self) -> Test9 { Test9 }
+ | ~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/typeck_type_placeholder_item.rs:62:37
LL | fn clone_from(&mut self, other: _) { *self = Test9; }
| ^ not allowed in type signatures
|
-help: use type parameters instead
+help: try replacing `_` with the type in the corresponding trait method signature
|
-LL | fn clone_from<T>(&mut self, other: T) { *self = Test9; }
- | +++ ~
+LL | fn clone_from(&mut self, other: &Test9) { *self = Test9; }
+ | ~~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/typeck_type_placeholder_item.rs:107:31
LL | fn fn_test10<T>(&self, _x : T) { }
| +++ ~
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/typeck_type_placeholder_item.rs:115:28
|
LL | fn clone(&self) -> _ { FnTest9 }
- | ^
- | |
- | not allowed in type signatures
- | help: replace with the correct return type: `FnTest9`
+ | ^ not allowed in type signatures
+ |
+help: try replacing `_` with the type in the corresponding trait method signature
+ |
+LL | fn clone(&self) -> FnTest9 { FnTest9 }
+ | ~~~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/typeck_type_placeholder_item.rs:118:41
LL | fn clone_from(&mut self, other: _) { *self = FnTest9; }
| ^ not allowed in type signatures
|
-help: use type parameters instead
+help: try replacing `_` with the type in the corresponding trait method signature
|
-LL | fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
- | +++ ~
+LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; }
+ | ~~~~~~~~
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
--> $DIR/typeck_type_placeholder_item.rs:201:14
--> $DIR/ufcs-qpath-self-mismatch.rs:6:28
|
LL | <i32 as Add<i32>>::add(1u32, 2);
- | ^^^^ expected `i32`, found `u32`
+ | ---------------------- ^^^^ expected `i32`, found `u32`
+ | |
+ | arguments to this function are incorrect
|
+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);
--> $DIR/ufcs-qpath-self-mismatch.rs:8:31
|
LL | <i32 as Add<i32>>::add(1, 2u32);
- | ^^^^ expected `i32`, found `u32`
+ | ---------------------- ^^^^ expected `i32`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+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);
--> $DIR/unboxed-closures-type-mismatch.rs:5:15
|
LL | let z = f(1_usize, 2);
- | ^^^^^^^ expected `isize`, found `usize`
+ | - ^^^^^^^ expected `isize`, found `usize`
+ | |
+ | arguments to this function are incorrect
|
help: change the type of the numeric literal from `usize` to `isize`
|
//~^ ERROR `'_` cannot be used here
struct Struct<'_> {
-//~^ ERROR `'_` cannot be used here
+ //~^ ERROR `'_` cannot be used here
v: Vec<&'static char>
}
enum Enum<'_> {
-//~^ ERROR `'_` cannot be used here
+ //~^ ERROR `'_` cannot be used here
Variant
}
union Union<'_> {
-//~^ ERROR `'_` cannot be used here
+ //~^ ERROR `'_` cannot be used here
a: u32
}
trait Trait<'_> {
-//~^ ERROR `'_` cannot be used here
+ //~^ ERROR `'_` cannot be used here
}
fn foo<'_>() {
--- /dev/null
+// Verifies that MIR building for a call expression respects
+// privacy when checking if a call return type is uninhabited.
+
+pub mod widget {
+ enum Unimplemented {}
+ pub struct Widget(Unimplemented);
+
+ impl Widget {
+ pub fn new() -> Widget {
+ todo!();
+ }
+ }
+
+ pub fn f() {
+ let x: &mut u32;
+ Widget::new();
+ // Ok. Widget type returned from new is known to be uninhabited
+ // and the following code is considered unreachable.
+ *x = 1;
+ }
+}
+
+fn main() {
+ let y: &mut u32;
+ widget::Widget::new();
+ // Error. Widget type is not known to be uninhabited here,
+ // so the following code is considered reachable.
+ *y = 2; //~ ERROR use of possibly-uninitialized variable
+}
--- /dev/null
+error[E0381]: use of possibly-uninitialized variable: `y`
+ --> $DIR/privately-uninhabited-mir-call.rs:28:5
+ |
+LL | *y = 2;
+ | ^^^^^^ use of possibly-uninitialized `y`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
- --> $DIR/issue-45087-unreachable-unsafe.rs:6:5
+ --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
|
LL | *(1 as *mut u32) = 42;
| ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-error: aborting due to previous error
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+ |
+LL | *a = 1;
+ | ^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+ |
+LL | *b = 1;
+ | ^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0133`.
+// Verify that unreachable code undergoes unsafety checks.
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
*(1 as *mut u32) = 42;
//~^ ERROR dereference of raw pointer is unsafe
}
+
+fn panic() -> ! {
+ panic!();
+}
+
+fn f(a: *mut u32) {
+ panic();
+ *a = 1;
+ //~^ ERROR dereference of raw pointer is unsafe
+}
+
+enum Void {}
+
+fn uninhabited() -> Void {
+ panic!();
+}
+
+fn g(b: *mut u32) {
+ uninhabited();
+ *b = 1;
+ //~^ ERROR dereference of raw pointer is unsafe
+}
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
- --> $DIR/issue-45087-unreachable-unsafe.rs:6:5
+ --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
|
LL | *(1 as *mut u32) = 42;
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-error: aborting due to previous error
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+ |
+LL | *a = 1;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+ |
+LL | *b = 1;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+/* //~ ERROR E0758
+/* */
+/*
+*/
--- /dev/null
+error[E0758]: unterminated block comment
+ --> $DIR/unterminated-nested-comment.rs:1:1
+ |
+LL | /*
+ | ^-
+ | |
+ | _unterminated block comment
+ | |
+LL | | /* */
+LL | | /*
+ | | --
+ | | |
+ | | ...as last nested comment starts here, maybe you want to close this instead?
+LL | | */
+ | |_--^
+ | |
+ | ...and last nested comment terminates here.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0758`.
+++ /dev/null
-// --extern-location with bad location type
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=badloc:in-the-test-file -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
+++ /dev/null
-error: unknown location type `badloc`: use `raw` or `json`
-
+++ /dev/null
-// Default extern location from name and path if one isn't specified
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--error-format json
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
+++ /dev/null
-{"message":"external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":146,"byte_end":146,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":154,"byte_end":179,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"name":"bar"}}],"rendered":"warning: external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`
- --> $DIR/extern-loc-defl-json.rs:7:1
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^
- |
-note: the lint level is defined here
- --> $DIR/extern-loc-defl-json.rs:7:9
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
+++ /dev/null
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:[{"malformed -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
+++ /dev/null
-error: `--extern-location`: malformed json location `[{"malformed`
-
+++ /dev/null
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:{"key":123,"value":{}} --error-format json -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
+++ /dev/null
-{"message":"external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":189,"byte_end":189,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":197,"byte_end":222,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"key":123,"value":{}}}],"rendered":"warning: external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`
- --> $DIR/extern-loc-json-json.rs:7:1
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^
- |
-note: the lint level is defined here
- --> $DIR/extern-loc-json-json.rs:7:9
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
+++ /dev/null
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=json:{"key":123,"value":{}} -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
+++ /dev/null
-warning: external crate `bar` unused in `extern_loc_json`: remove the dependency or add `use bar as _;`
- --> $DIR/extern-loc-json.rs:7:1
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^
- |
-note: the lint level is defined here
- --> $DIR/extern-loc-json.rs:7:9
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar`
-
-warning: 1 warning emitted
-
+++ /dev/null
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar -Zunstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
+++ /dev/null
-error: `--extern-location`: specify location for extern crate `bar`
-
+++ /dev/null
-// --extern-location with no type
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=missing-loc-type -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
+++ /dev/null
-error: unknown location type `missing-loc-type`: use `raw` or `json`
-
+++ /dev/null
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw:in-the-test-file --error-format json -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
+++ /dev/null
-{"message":"external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":182,"byte_end":182,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":190,"byte_end":215,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar` at `in-the-test-file`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"raw extern location","code":null,"level":"help","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":null,"suggested_replacement":"in-the-test-file","suggestion_applicability":"Unspecified","expansion":null}],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":"in-the-test-file"}],"rendered":"warning: external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`
- --> $DIR/extern-loc-raw-json.rs:7:1
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^
- |
-note: the lint level is defined here
- --> $DIR/extern-loc-raw-json.rs:7:9
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar` at `in-the-test-file`
-
-"}
-{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
-
-"}
+++ /dev/null
-// --extern-location with a raw reference
-
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-
-fn main() {}
+++ /dev/null
-error: `--extern-location`: missing `raw` location
-
+++ /dev/null
-// --extern-location with a raw reference
-
-// check-pass
-// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar=raw:in-the-test-file -Z unstable-options
-
-#![warn(unused_crate_dependencies)]
-//~^ WARNING external crate `bar` unused in
-
-fn main() {}
+++ /dev/null
-warning: external crate `bar` unused in `extern_loc_raw`: remove the dependency or add `use bar as _;`
- --> $DIR/extern-loc-raw.rs:7:1
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^
- |
-note: the lint level is defined here
- --> $DIR/extern-loc-raw.rs:7:9
- |
-LL | #![warn(unused_crate_dependencies)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar` at `in-the-test-file`
-
-warning: 1 warning emitted
-
| ^
|
= note: requested on the command line with `-W unused-crate-dependencies`
- = help: remove unnecessary dependency `bar`
warning: 1 warning emitted
|
LL | #![warn(unused_crate_dependencies)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `barbar`
warning: 1 warning emitted
|
LL | #![warn(unused_crate_dependencies)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove unnecessary dependency `bar`
warning: 1 warning emitted
| ^
|
= note: requested on the command line with `-W unused-crate-dependencies`
- = help: remove unnecessary dependency `bar`
warning: 1 warning emitted
| ^
|
= note: requested on the command line with `-W unused-crate-dependencies`
- = help: remove unnecessary dependency `bar`
warning: 1 warning emitted
pub fn g() {
use ::super::main; //~ ERROR global paths cannot start with `super`
- main(); //~ ERROR cannot find function `main` in this scope
+ main();
}
}
LL | use ::super::main;
| ^^^^^ global paths cannot start with `super`
-error[E0425]: cannot find function `main` in this scope
- --> $DIR/use-super-global-path.rs:12:9
- |
-LL | main();
- | ^^^^ not found in this scope
- |
-help: consider importing this function
- |
-LL | use main;
- |
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0425, E0433.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0433`.
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16
|
LL | impl Trait for Ref {}
- | ^^^- help: indicate the anonymous lifetime: `<'_>`
+ | ^^^ expected lifetime parameter
|
= note: assuming a `'static` lifetime...
+help: indicate the anonymous lifetime
+ |
+LL | impl Trait for Ref<'_> {}
+ | ++++
error: incompatible lifetime on type
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
error[E0261]: use of undeclared lifetime name `'a`
--> $DIR/where-lifetime-resolution.rs:6:38
|
-LL | fn f() where
- | - help: consider introducing lifetime `'a` here: `<'a>`
-LL | for<'a> dyn Trait1<'a>: Trait1<'a>, // OK
LL | (dyn for<'a> Trait1<'a>): Trait1<'a>,
| ^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | (dyn for<'a> Trait1<'a>): for<'a> Trait1<'a>,
+ | +++++++
+help: consider making the bound lifetime-generic with a new `'a` lifetime
+ |
+LL | for<'a> (dyn for<'a> Trait1<'a>): Trait1<'a>,
+ | +++++++
+help: consider introducing lifetime `'a` here
+ |
+LL | fn f<'a>() where
+ | ++++
error[E0261]: use of undeclared lifetime name `'b`
--> $DIR/where-lifetime-resolution.rs:8:52
|
-LL | fn f() where
- | - help: consider introducing lifetime `'b` here: `<'b>`
-...
LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
| ^^ undeclared lifetime
+ |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | for<'a> dyn for<'b> Trait2<'a, 'b>: for<'b> Trait2<'a, 'b>,
+ | +++++++
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+ |
+LL | for<'b, 'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>,
+ | +++
+help: consider introducing lifetime `'b` here
+ |
+LL | fn f<'b>() where
+ | ++++
error: aborting due to 2 previous errors
-Subproject commit dba5baf4345858c591517b24801902a062c399f8
+Subproject commit edffc4ada3d77799e5a04eeafd9b2f843d29fc23
if rust_cc > self.limit.limit() {
let fn_span = match kind {
- FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
+ FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
FnKind::Closure => {
let header_span = body_span.with_hi(decl.output.span().lo());
let pos = snippet_opt(cx, header_span).and_then(|snip| {
}
// The `module_name_repetitions` lint should only trigger if the item has the module in its
// name. Having the same name is accepted.
- if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
+ if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() {
let matching = count_match_start(mod_camel, &item_camel);
let rmatching = count_match_end(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then {
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
- if v.fields().iter().any(|f| !f.vis.node.is_pub()) {
+ if v.fields().iter().any(|f| {
+ let def_id = cx.tcx.hir().local_def_id(f.hir_id);
+ !cx.tcx.visibility(def_id).is_public()
+ }) {
// skip structs with private fields
return;
}
hir_id: hir::HirId,
) {
let unsafety = match kind {
- intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
- intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
+ intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
+ intravisit::FnKind::Method(_, sig) => sig.header.unsafety,
intravisit::FnKind::Closure => return,
};
header: hir::FnHeader { abi: Abi::Rust, .. },
..
},
- _,
)
- | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => check_arg_number(
+ | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }) => check_arg_number(
cx,
decl,
span.with_hi(decl.output.span().hi()),
.iter()
.map(|(o, _)| match o {
InlineAsmOperand::In { expr, .. }
- | InlineAsmOperand::InOut { expr, .. }
- | InlineAsmOperand::Sym { expr } => never_loop_expr(expr, main_loop_id),
+ | InlineAsmOperand::InOut { expr, .. } => never_loop_expr(expr, main_loop_id),
InlineAsmOperand::Out { expr, .. } => never_loop_expr_all(&mut expr.iter(), main_loop_id),
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
never_loop_expr_all(&mut once(in_expr).chain(out_expr.iter()), main_loop_id)
},
- InlineAsmOperand::Const { .. } => NeverLoopResult::Otherwise,
+ InlineAsmOperand::Const { .. }
+ | InlineAsmOperand::SymFn { .. }
+ | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
})
.fold(NeverLoopResult::Otherwise, combine_both),
ExprKind::Struct(_, _, None)
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, DefIdTree};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Span;
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == sym::main {
- let def_key = cx.tcx.hir().def_key(it.def_id);
- if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
+ let at_root = cx.tcx.local_parent(it.def_id) == Some(CRATE_DEF_ID);
+ if at_root {
return;
}
}
}
match kind {
- FnKind::ItemFn(.., header, _) => {
+ FnKind::ItemFn(.., header) => {
let attrs = cx.tcx.hir().attrs(hir_id);
if header.abi != Abi::Rust || requires_exact_signature(attrs) {
return;
}
match kind {
- FnKind::ItemFn(.., header, _) => {
+ FnKind::ItemFn(.., header) => {
if header.abi != Abi::Rust {
return;
}
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
-use rustc_hir::{Item, ItemKind, VisibilityKind};
+use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::CRATE_DEF_ID;
declare_clippy_lint! {
/// ### What it does
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
- if let VisibilityKind::Crate { .. } = item.vis.node {
+ if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()) {
if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false) {
let span = item.span.with_hi(item.ident.span.hi());
let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
&format!("pub(crate) {} inside private module", descr),
|diag| {
diag.span_suggestion(
- item.vis.span,
+ item.vis_span,
"consider using",
"pub".to_string(),
Applicability::MachineApplicable,
) {
if_chain! {
// We are only interested in methods, not in functions or associated functions.
- if matches!(kind, FnKind::Method(_, _, _));
+ if matches!(kind, FnKind::Method(_, _));
if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id);
if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
// We don't want this method to be te implementation of a trait because the
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
let mut map = FxHashMap::<Res, ExistingName>::default();
- for item in cx.tcx.hir().items() {
+ for id in cx.tcx.hir().items() {
+ if !matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+ continue;
+ }
+
+ let item = cx.tcx.hir().item(id);
if let ItemKind::Impl(Impl {
items,
of_trait,
span: Span,
hir_id: HirId,
) {
- if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }, _) = &fn_kind {
+ if let FnKind::ItemFn(_, _, FnHeader { asyncness, .. }) = &fn_kind {
if matches!(asyncness, IsAsync::Async) {
let mut visitor = AsyncFnVisitor { cx, found_await: false };
walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), span, hir_id);
use rustc_ast::ast::{Attribute, InlineAsmTemplatePiece};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty;
use rustc_session::Session;
use rustc_session::{declare_lint_pass, declare_tool_lint};
return;
}
println!("impl item `{}`", item.ident.name);
- match item.vis.node {
- hir::VisibilityKind::Public => println!("public"),
- hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
- hir::VisibilityKind::Restricted { path, .. } => println!(
- "visible in module `{}`",
- rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
- ),
- hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
+ match cx.tcx.visibility(item.def_id) {
+ ty::Visibility::Public => println!("public"),
+ ty::Visibility::Restricted(def_id) => {
+ if def_id.is_top_level_module() {
+ println!("visible crate wide")
+ } else {
+ println!("visible in module `{}`", cx.tcx.def_path_str(def_id))
+ }
+ },
+ ty::Visibility::Invisible => println!("invisible"),
}
match item.kind {
hir::ImplItemKind::Const(_, body_id) => {
for (op, _op_sp) in asm.operands {
match op {
hir::InlineAsmOperand::In { expr, .. }
- | hir::InlineAsmOperand::InOut { expr, .. }
- | hir::InlineAsmOperand::Sym { expr } => print_expr(cx, expr, indent + 1),
+ | hir::InlineAsmOperand::InOut { expr, .. } => {
+ print_expr(cx, expr, indent + 1);
+ }
hir::InlineAsmOperand::Out { expr, .. } => {
if let Some(expr) = expr {
print_expr(cx, expr, indent + 1);
print_expr(cx, out_expr, indent + 1);
}
},
- hir::InlineAsmOperand::Const { anon_const } => {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => {
println!("{}anon_const:", ind);
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
},
+ hir::InlineAsmOperand::SymStatic { path, .. } => {
+ match path {
+ hir::QPath::Resolved(ref ty, path) => {
+ println!("{}Resolved Path, {:?}", ind, ty);
+ println!("{}path: {:?}", ind, path);
+ },
+ hir::QPath::TypeRelative(ty, seg) => {
+ println!("{}Relative Path, {:?}", ind, ty);
+ println!("{}seg: {:?}", ind, seg);
+ },
+ hir::QPath::LangItem(lang_item, ..) => {
+ println!("{}Lang Item Path, {:?}", ind, lang_item.name());
+ },
+ }
+ }
}
}
},
fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
let did = item.def_id;
println!("item `{}`", item.ident.name);
- match item.vis.node {
- hir::VisibilityKind::Public => println!("public"),
- hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
- hir::VisibilityKind::Restricted { path, .. } => println!(
- "visible in module `{}`",
- rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false))
- ),
- hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
+ match cx.tcx.visibility(item.def_id) {
+ ty::Visibility::Public => println!("public"),
+ ty::Visibility::Restricted(def_id) => {
+ if def_id.is_top_level_module() {
+ println!("visible crate wide")
+ } else {
+ println!("visible in module `{}`", cx.tcx.def_path_str(def_id))
+ }
+ },
+ ty::Visibility::Invisible => println!("invisible"),
}
match item.kind {
hir::ItemKind::ExternCrate(ref _renamed_from) => {
Item, ItemKind, PathSegment, UseKind,
};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::kw;
use rustc_span::{sym, BytePos};
if is_test_module_or_function(cx.tcx, item) {
self.test_modules_deep = self.test_modules_deep.saturating_add(1);
}
- if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() {
+ let module = cx.tcx.parent_module_from_def_id(item.def_id);
+ if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
return;
}
if_chain! {
}
},
InlineAsmOperand::Const { anon_const } => self.hash_body(anon_const.body),
- InlineAsmOperand::Sym { expr } => self.hash_expr(expr),
+ InlineAsmOperand::SymFn { anon_const } => self.hash_body(anon_const.body),
+ InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
}
}
},
/// Checks if the given function kind is an async function.
pub fn is_async_fn(kind: FnKind<'_>) -> bool {
- matches!(kind, FnKind::ItemFn(_, _, header, _) if header.asyncness == IsAsync::Async)
+ matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness == IsAsync::Async)
}
/// Peels away all the compiler generated code surrounding the body of an async function,
LL | fn foo() {}
| ^^^^^^^^^^^
+error: method's name is the same as an existing method in a trait
+ --> $DIR/same_name_method.rs:34:13
+ |
+LL | fn clone() {}
+ | ^^^^^^^^^^^^^
+ |
+note: existing `clone` defined here
+ --> $DIR/same_name_method.rs:30:18
+ |
+LL | #[derive(Clone)]
+ | ^^^^^
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
error: method's name is the same as an existing method in a trait
--> $DIR/same_name_method.rs:44:13
|
LL | impl T1 for S {}
| ^^^^^^^^^^^^^^^^
-error: method's name is the same as an existing method in a trait
- --> $DIR/same_name_method.rs:34:13
- |
-LL | fn clone() {}
- | ^^^^^^^^^^^^^
- |
-note: existing `clone` defined here
- --> $DIR/same_name_method.rs:30:18
- |
-LL | #[derive(Clone)]
- | ^^^^^
- = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
error: aborting due to 5 previous errors
error: unneeded unit return type
- --> $DIR/unused_unit.rs:19:28
+ --> $DIR/unused_unit.rs:19:58
|
LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
- | ^^^^^^ help: remove the `-> ()`
+ | ^^^^^^ help: remove the `-> ()`
|
note: the lint level is defined here
--> $DIR/unused_unit.rs:12:9
| ^^^^^^^^^^^^^^^^^^^
error: unneeded unit return type
- --> $DIR/unused_unit.rs:20:18
+ --> $DIR/unused_unit.rs:19:28
|
-LL | where G: Fn() -> () {
- | ^^^^^^ help: remove the `-> ()`
+LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
+ | ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
- --> $DIR/unused_unit.rs:19:58
+ --> $DIR/unused_unit.rs:20:18
|
-LL | pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
- | ^^^^^^ help: remove the `-> ()`
+LL | where G: Fn() -> () {
+ | ^^^^^^ help: remove the `-> ()`
error: unneeded unit return type
--> $DIR/unused_unit.rs:21:26
/// The rust-demangler executable.
pub rust_demangler_path: Option<PathBuf>,
- /// The Python executable to use for LLDB.
- pub lldb_python: String,
-
- /// The Python executable to use for htmldocck.
- pub docck_python: String,
+ /// The Python executable to use for LLDB and htmldocck.
+ pub python: String,
/// The jsondocck executable.
pub jsondocck_path: Option<String>,
pub should_ice: bool,
// If true, the stderr is expected to be different across bit-widths.
pub stderr_per_bitwidth: bool,
+ // The MIR opt to unit test, if any
+ pub mir_unit_test: Option<String>,
}
mod directives {
pub const STDERR_PER_BITWIDTH: &'static str = "stderr-per-bitwidth";
pub const INCREMENTAL: &'static str = "incremental";
pub const KNOWN_BUG: &'static str = "known-bug";
+ pub const MIR_UNIT_TEST: &'static str = "unit-test";
// This isn't a real directive, just one that is probably mistyped often
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
}
assembly_output: None,
should_ice: false,
stderr_per_bitwidth: false,
+ mir_unit_test: None,
}
}
config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth);
config.set_name_directive(ln, INCREMENTAL, &mut self.incremental);
config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug);
+ config.set_name_value_directive(ln, MIR_UNIT_TEST, &mut self.mir_unit_test, |s| {
+ s.trim().to_string()
+ });
});
}
"--compile-lib-path=",
"--run-lib-path=",
"--rustc-path=",
- "--lldb-python=",
- "--docck-python=",
+ "--python=",
"--jsondocck-path=",
"--src-base=",
"--build-base=",
.reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
.optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
.optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH")
- .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH")
- .reqopt("", "docck-python", "path to python to use for doc tests", "PATH")
+ .reqopt("", "python", "path to python to use for doc tests", "PATH")
.optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH")
.optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
.optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
rustc_path: opt_path(matches, "rustc-path"),
rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from),
- lldb_python: matches.opt_str("lldb-python").unwrap(),
- docck_python: matches.opt_str("docck-python").unwrap(),
+ python: matches.opt_str("python").unwrap(),
jsondocck_path: matches.opt_str("jsondocck-path"),
valgrind_path: matches.opt_str("valgrind-path"),
force_valgrind: matches.opt_present("force-valgrind"),
}
Some(Debugger::Lldb) => {
- config.lldb_python.hash(&mut hash);
+ config.python.hash(&mut hash);
config.lldb_python_dir.hash(&mut hash);
env::var_os("PATH").hash(&mut hash);
env::var_os("PYTHONPATH").hash(&mut hash);
// Prepare the lldb_batchmode which executes the debugger script
let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
self.cmd2procres(
- Command::new(&self.config.lldb_python)
+ Command::new(&self.config.python)
.arg(&lldb_script_path)
.arg(test_executable)
.arg(debugger_script)
rustc.args(&[
"-Copt-level=1",
"-Zdump-mir=all",
- "-Zmir-opt-level=4",
"-Zvalidate-mir",
"-Zdump-mir-exclude-pass-number",
]);
+ if let Some(pass) = &self.props.mir_unit_test {
+ rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]);
+ } else {
+ rustc.arg("-Zmir-opt-level=4");
+ }
let mir_dump_dir = self.get_mir_dump_dir();
let _ = fs::remove_dir_all(&mir_dump_dir);
self.check_rustdoc_test_option(proc_res);
} else {
let root = self.config.find_rust_src_root().unwrap();
- let mut cmd = Command::new(&self.config.docck_python);
+ let mut cmd = Command::new(&self.config.python);
cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
if self.config.bless {
cmd.arg("--bless");
let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
json_out.set_extension("json");
let res = self.cmd2procres(
- Command::new(&self.config.docck_python)
+ Command::new(&self.config.python)
.arg(root.join("src/etc/check_missing_items.py"))
.arg(&json_out),
);
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.env("TARGET", &self.config.target)
- .env("PYTHON", &self.config.docck_python)
+ .env("PYTHON", &self.config.python)
.env("S", src_root)
.env("RUST_BUILD_STAGE", &self.config.stage_id)
.env("RUSTC", cwd.join(&self.config.rustc_path))
-Subproject commit c568f32f165d86aba51ec544756c3c833acbabd7
+Subproject commit edd4858846003dc96020a0de07a1499e3224e633
-Subproject commit 46d7ee68f26285db26b2640f2c07d6332380c756
+Subproject commit 24cf957627d5ede1b395f92ff871fd7a281d49a4
env_logger = "0.7.1"
[dependencies.mdbook]
-version = "0.4.14"
+version = "0.4.18"
default-features = false
features = ["search"]
} while (pos < content.length && content[pos] !== '/' && content[pos - 1] !== '*');
// Eat quoted strings
- } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
+ } else if ((content[pos] === '"' || content[pos] === "'" || content[pos] === "`") &&
+ (pos === 0 || content[pos - 1] !== '/')) {
stop = content[pos];
do {
if (content[pos] === '\\') {
// execQuery last parameter is built in buildIndex.
// buildIndex requires the hashmap from search-index.
var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
- "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch",
- "removeEmptyStringsFromArray"];
+ "buildIndex", "execQuery", "parseQuery", "createQueryResults",
+ "isWhitespace", "isSpecialStartCharacter", "isStopCharacter",
+ "parseInput", "getItemsBefore", "getNextElem", "createQueryElement",
+ "isReturnArrow", "isPathStart", "getStringElem", "newParsedQuery",
+ "itemTypeFromName", "isEndCharacter", "isErrorCharacter",
+ "isIdentCharacter", "isSeparatorCharacter", "getIdentEndPosition",
+ "checkExtraTypeFilterCharacters", "isWhitespaceCharacter"];
const functions = ["hasOwnPropertyRustdoc", "onEach"];
ALIASES = {};
return [loaded, index];
}
+// This function checks if `expected` has all the required fields needed for the checks.
+function checkNeededFields(fullPath, expected, error_text, queryName, position) {
+ let fieldsToCheck;
+ if (fullPath.length === 0) {
+ fieldsToCheck = [
+ "foundElems",
+ "original",
+ "returned",
+ "typeFilter",
+ "userQuery",
+ "error",
+ ];
+ } else if (fullPath.endsWith("elems") || fullPath.endsWith("generics")) {
+ fieldsToCheck = [
+ "name",
+ "fullPath",
+ "pathWithoutLast",
+ "pathLast",
+ "generics",
+ ];
+ } else {
+ fieldsToCheck = [];
+ }
+ for (var i = 0; i < fieldsToCheck.length; ++i) {
+ const field = fieldsToCheck[i];
+ if (!expected.hasOwnProperty(field)) {
+ let text = `${queryName}==> Mandatory key \`${field}\` is not present`;
+ if (fullPath.length > 0) {
+ text += ` in field \`${fullPath}\``;
+ if (position != null) {
+ text += ` (position ${position})`;
+ }
+ }
+ error_text.push(text);
+ }
+ }
+}
+
+function valueCheck(fullPath, expected, result, error_text, queryName) {
+ if (Array.isArray(expected)) {
+ for (var i = 0; i < expected.length; ++i) {
+ checkNeededFields(fullPath, expected[i], error_text, queryName, i);
+ if (i >= result.length) {
+ error_text.push(`${queryName}==> EXPECTED has extra value in array from field ` +
+ `\`${fullPath}\` (position ${i}): \`${JSON.stringify(expected[i])}\``);
+ } else {
+ valueCheck(fullPath + '[' + i + ']', expected[i], result[i], error_text, queryName);
+ }
+ }
+ for (; i < result.length; ++i) {
+ error_text.push(`${queryName}==> RESULT has extra value in array from field ` +
+ `\`${fullPath}\` (position ${i}): \`${JSON.stringify(result[i])}\` ` +
+ 'compared to EXPECTED');
+ }
+ } else if (expected !== null && typeof expected !== "undefined" &&
+ expected.constructor == Object)
+ {
+ for (const key in expected) {
+ if (!expected.hasOwnProperty(key)) {
+ continue;
+ }
+ if (!result.hasOwnProperty(key)) {
+ error_text.push('==> Unknown key "' + key + '"');
+ break;
+ }
+ const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
+ valueCheck(obj_path, expected[key], result[key], error_text, queryName);
+ }
+ } else {
+ expectedValue = JSON.stringify(expected);
+ resultValue = JSON.stringify(result);
+ if (expectedValue != resultValue) {
+ error_text.push(`${queryName}==> Different values for field \`${fullPath}\`:\n` +
+ `EXPECTED: \`${expectedValue}\`\nRESULT: \`${resultValue}\``);
+ }
+ }
+}
+
+function runParser(query, expected, loaded, loadedFile, queryName) {
+ var error_text = [];
+ checkNeededFields("", expected, error_text, queryName, null);
+ if (error_text.length === 0) {
+ valueCheck('', expected, loaded.parseQuery(query), error_text, queryName);
+ }
+ return error_text;
+}
+
function runSearch(query, expected, index, loaded, loadedFile, queryName) {
const filter_crate = loadedFile.FILTER_CRATE;
const ignore_order = loadedFile.ignore_order;
const exact_check = loadedFile.exact_check;
- var results = loaded.execSearch(loaded.getQuery(query), index, filter_crate);
+ var results = loaded.execQuery(loaded.parseQuery(query), index, filter_crate);
var error_text = [];
for (var key in expected) {
return 1;
}
-function runChecks(testFile, loaded, index) {
- var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;';
- if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
- testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;";
- } else {
- testFileContent += "exports.FILTER_CRATE = null;";
- }
- var loadedFile = loadContent(testFileContent);
-
- const expected = loadedFile.EXPECTED;
+function runCheck(loadedFile, key, callback) {
+ const expected = loadedFile[key];
const query = loadedFile.QUERY;
if (Array.isArray(query)) {
if (!Array.isArray(expected)) {
console.log("FAILED");
- console.log("==> If QUERY variable is an array, EXPECTED should be an array too");
+ console.log(`==> If QUERY variable is an array, ${key} should be an array too`);
return 1;
} else if (query.length !== expected.length) {
console.log("FAILED");
- console.log("==> QUERY variable should have the same length as EXPECTED");
+ console.log(`==> QUERY variable should have the same length as ${key}`);
return 1;
}
for (var i = 0; i < query.length; ++i) {
- var error_text = runSearch(query[i], expected[i], index, loaded, loadedFile,
- "[ query `" + query[i] + "`]");
+ var error_text = callback(query[i], expected[i], "[ query `" + query[i] + "`]");
if (checkResult(error_text, loadedFile, false) !== 0) {
return 1;
}
}
console.log("OK");
- return 0;
+ } else {
+ var error_text = callback(query, expected, "");
+ if (checkResult(error_text, loadedFile, true) !== 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+function runChecks(testFile, loaded, index) {
+ var checkExpected = false;
+ var checkParsed = false;
+ var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;';
+
+ if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
+ testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;";
+ } else {
+ testFileContent += "exports.FILTER_CRATE = null;";
+ }
+
+ if (testFileContent.indexOf("\nconst EXPECTED") !== -1) {
+ testFileContent += 'exports.EXPECTED = EXPECTED;';
+ checkExpected = true;
+ }
+ if (testFileContent.indexOf("\nconst PARSED") !== -1) {
+ testFileContent += 'exports.PARSED = PARSED;';
+ checkParsed = true;
+ }
+ if (!checkParsed && !checkExpected) {
+ console.log("FAILED");
+ console.log("==> At least `PARSED` or `EXPECTED` is needed!");
+ return 1;
+ }
+
+ const loadedFile = loadContent(testFileContent);
+ var res = 0;
+
+ if (checkExpected) {
+ res += runCheck(loadedFile, "EXPECTED", (query, expected, text) => {
+ return runSearch(query, expected, index, loaded, loadedFile, text);
+ });
+ }
+ if (checkParsed) {
+ res += runCheck(loadedFile, "PARSED", (query, expected, text) => {
+ return runParser(query, expected, loaded, loadedFile, text);
+ });
}
- var error_text = runSearch(query, expected, index, loaded, loadedFile, "");
- return checkResult(error_text, loadedFile, true);
+ return res;
}
function load_files(doc_folder, resource_suffix, crate) {
pub(crate) fn from_fn_kind(
fn_kind: &'a visit::FnKind<'_>,
- generics: &'a ast::Generics,
decl: &'a ast::FnDecl,
defaultness: ast::Defaultness,
) -> FnSig<'a> {
match *fn_kind {
- visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt {
+ visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, generics, _) => match fn_ctxt {
visit::FnCtxt::Assoc(..) => {
let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
fn_sig.defaultness = defaultness;
let inner_attrs = inner_attributes(&self.attrs);
let fn_ctxt = visit::FnCtxt::Foreign;
visitor.visit_fn(
- visit::FnKind::Fn(fn_ctxt, self.ident, sig, &self.vis, Some(body)),
- generics,
+ visit::FnKind::Fn(
+ fn_ctxt,
+ self.ident,
+ sig,
+ &self.vis,
+ generics,
+ Some(body),
+ ),
&sig.decl,
self.span,
defaultness,
pub(crate) fn visit_fn(
&mut self,
fk: visit::FnKind<'_>,
- generics: &ast::Generics,
fd: &ast::FnDecl,
s: Span,
defaultness: ast::Defaultness,
let indent = self.block_indent;
let block;
let rewrite = match fk {
- visit::FnKind::Fn(_, ident, _, _, Some(ref b)) => {
+ visit::FnKind::Fn(_, ident, _, _, _, Some(ref b)) => {
block = b;
self.rewrite_fn_before_block(
indent,
ident,
- &FnSig::from_fn_kind(&fk, generics, fd, defaultness),
+ &FnSig::from_fn_kind(&fk, fd, defaultness),
mk_sp(s.lo(), b.span.lo()),
)
}
_ => visit::FnCtxt::Foreign,
};
self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, item.ident, sig, &item.vis, Some(body)),
- generics,
+ visit::FnKind::Fn(
+ fn_ctxt,
+ item.ident,
+ sig,
+ &item.vis,
+ generics,
+ Some(body),
+ ),
&sig.decl,
item.span,
defaultness,
let inner_attrs = inner_attributes(&ai.attrs);
let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
- generics,
+ visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)),
&sig.decl,
ai.span,
defaultness,
("self_cell", "Apache-2.0"), // rustc (fluent translations)
// FIXME: this dependency violates the documentation comment above:
("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target
+ ("dunce", "CC0-1.0"), // cargo (dev dependency)
+ ("similar", "Apache-2.0"), // cargo (dev dependency)
+ ("normalize-line-endings", "Apache-2.0"), // cargo (dev dependency)
];
const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 986;
-const ISSUES_ENTRY_LIMIT: usize = 2310;
+const ISSUES_ENTRY_LIMIT: usize = 2292;
fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))